Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / realpath.ultrix.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: realpath.ultrix.c /main/3 1995/10/23 09:50:04 rswiston $                                                     */
28
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/param.h>
33 #include <strings.h>
34
35 char *
36 realpath(pathname, finalpath)
37 char *pathname;
38 char *finalpath;
39 {
40   struct stat sbuf;
41   char curpath[MAXPATHLEN],
42   workpath[MAXPATHLEN],
43   linkpath[MAXPATHLEN],
44   namebuf[MAXPATHLEN],
45   *where,
46   *ptr,
47   *last;
48   int len;
49
50    strcpy(curpath, pathname);
51
52    if (*pathname != '/') {
53 #if defined(__STDC__) && defined(hp)
54       if (!getcwd(workpath)) {
55 #else
56       if (!getwd(workpath)) {
57 #endif
58          strcpy(finalpath, ".");
59          return(NULL);
60        }
61     } else *workpath = NULL;
62
63    /* curpath is the path we're still resolving      */
64    /* linkpath is the path a symbolic link points to */
65    /* workpath is the path we've resolved            */
66
67  loop:
68    where = curpath;
69    while (*where != NULL) {
70       if (!strcmp(where, ".")) {
71          where++;
72          continue;
73        }
74
75       /* deal with "./" */
76       if (!strncmp(where, "./", 2)) {
77          where += 2;
78          continue;
79        }
80
81       /* deal with "../" */
82       if (!strncmp(where, "../", 3)) {
83          where += 3;
84          ptr = last = workpath;
85          while (*ptr) {
86             if (*ptr == '/') last = ptr;
87             ptr++;
88           }
89          *last = NULL;
90          continue;
91        }
92
93       ptr = strchr(where, '/');
94       if (!ptr)
95          ptr = where + strlen(where) - 1;
96       else
97          *ptr = NULL;
98
99       strcpy(namebuf, workpath);
100       for (last = namebuf; *last; last++) continue;
101       /* tack on a trailing, or leading, `/` */
102       if (last == namebuf || *--last != '/') {
103         strcat(namebuf, "/");
104       }
105       strcat(namebuf, where);
106
107       where = ++ptr;
108       if (lstat(namebuf, &sbuf) == -1) {
109          strcpy(finalpath, namebuf);
110          return(NULL);
111        }
112
113       if ((sbuf.st_mode & S_IFLNK) == S_IFLNK) {
114          len = readlink(namebuf, linkpath, MAXPATHLEN);
115          if (len == 0) {
116             strcpy(finalpath, namebuf);
117             return(NULL);
118           }
119          *(linkpath + len) = NULL; /* readlink doesn't null-terminate result */
120          if (*linkpath == '/') *workpath = NULL;
121          if (*where) {
122             strcat(linkpath, "/");
123             strcat(linkpath, where);
124           }
125          strcpy(curpath, linkpath);
126          goto loop;
127        }
128
129       if ((sbuf.st_mode & S_IFDIR) == S_IFDIR) {
130          strcpy(workpath, namebuf);
131          continue;
132        }
133
134       if (*where) {
135          strcpy(finalpath, namebuf);
136          return(NULL);  /* path/notadir/morepath */
137        } else
138          strcpy(workpath, namebuf);
139     }
140    strcpy(finalpath, workpath);
141    return(finalpath);
142
143 }
144