|
|
1.1 root 1: /* /sccs/src/cmd/uucp/s.expfile.c
2: expfile.c 1.4 8/30/84 17:37:18
3: */
4: #include "uucp.h"
5: VERSION(@(#)expfile.c 1.4);
6:
7: /*
8: * expand file name expansion is based on first characters
9: * / -> fully qualified pathname. no
10: * processing necessary
11: * ~ -> prepended with login directory
12: * ~/ -> prepended with Pubdir
13: * default -> prepended with current directory
14: * file -> filename to expand
15: * returns:
16: * 0 -> ok
17: * FAIL -> no Wrkdir name available
18: */
19: expfile(file)
20: register char *file;
21: {
22: register char *fpart, *up;
23: int uid;
24: char user[NAMESIZE], save[MAXFULLNAME];
25:
26: strcpy(save, file);
27: if (*file == '/')
28: ;
29: else if (*file == '~') {
30: /* find / and copy user part */
31: for (fpart = save + 1, up = user; *fpart != '\0'
32: && *fpart != '/'; fpart++)
33: *up++ = *fpart;
34: *up = '\0';
35: if ((user[0]=='\0') || (gninfo(user, &uid, file) != 0)){
36: (void) strcpy(file, Pubdir);
37: }
38: (void) strcat(file, fpart);
39: }
40: else {
41: (void) sprintf(file, "%s/%s", Wrkdir, save);
42: if (Wrkdir[0] == '\0')
43: return(FAIL);
44: }
45:
46: if (canPath(file) != 0) { /* I don't think this will ever fail */
47: (void) strcpy(file, CORRUPTDIR);
48: return(FAIL);
49: }
50: else
51: return(0);
52: }
53:
54:
55: /*
56: * make all necessary directories
57: * name -> directory to make
58: * return:
59: * 0 -> success
60: * FAIL -> failure
61: */
62: mkdirs(name)
63: register char *name;
64: {
65: register char *p;
66: char dir[MAXFULLNAME];
67:
68: strcpy(dir, name);
69: if (*LASTCHAR(dir) != '/')
70: (void) strcat(dir, "/");
71: p = dir + 1;
72: while (1) {
73: if ((p = strchr(p, '/')) == NULL)
74: return(0);
75: *p = '\0';
76: DEBUG(4, "mkdir - %s\n", dir);
77: if (mkdirs2(dir, 0) == FAIL)
78: return (FAIL);
79: *p++ = '/';
80: }
81: }
82:
83:
84: #ifdef ATTSV
85: /*
86: * Make name a directory if it is not already a directory
87: * ATTSV handling of setuid is less than convenient ...
88: * return:
89: * 0 -> ok
90: * FAIL -> failed
91: */
92:
93: mkdirs2(name, mask)
94: register char *name;
95: register int mask;
96: {
97: int ret, pid, status;
98: char *tail, nmbuf[MAXFULLNAME], *parent;
99: struct stat statbuf;
100:
101: if (DIRECTORY(name))
102: return(0); /* directory exists */
103:
104: /* in ATTSV the parent directory has to be writeable by real uid */
105: (void) strcpy(nmbuf, name);
106:
107: /* get pathname of parent */
108: tail = nmbuf + strlen(nmbuf) - 1; /* last char in nmbuf */
109: while (*tail == '/' && tail > nmbuf) /* kill trailing slashes */
110: *tail-- = '\0';
111:
112: /* is parent "."? */
113: if ((tail = strrchr(nmbuf, '/')) != NULL) {
114: *tail = '\0';
115: parent = nmbuf;
116: } else
117: parent = ".";
118:
119: /* save mode of parent */
120: if (stat(parent, &statbuf) != 0) {
121: DEBUG(5, "CAN'T STAT PARENT DIRECTORY %s ", parent);
122: DEBUG(5, "errno %d\n", errno);
123: return(FAIL);
124: }
125:
126: /* if it's already 0xx7 we don't have to change it */
127: if ((statbuf.st_mode & 0777) != 0777) {
128: /* make parent writable by all (thus by real uid) */
129: if (chmod(parent, 0777) != 0) {
130: DEBUG(5, "CAN'T CHMOD PARENT DIRECTORY %s ", parent);
131: DEBUG(5, "errno %d\n", errno);
132: return(FAIL);
133: }
134: }
135:
136: switch (pid = fork()) {
137: case 0: /* child */
138: umask(0);
139: /* close stdout and stderr to fail quietly */
140: close(1);
141: close(2);
142: execl("/bin/mkdir", "mkdir", name, 0);
143: _exit(1);
144:
145: case -1: /* fork failed */
146: ASSERT(pid != -1, Ct_FORK, "mkdir", errno);
147:
148: default: /* parent */
149: break;
150: }
151:
152: while ((ret = wait(&status)) != pid );
153:
154: if (status != 0) {
155: errent(Ct_CREATE, name, ret, sccsid, __FILE__, __LINE__);
156: return(FAIL);
157: }
158:
159:
160: if ((statbuf.st_mode & 0777) != 0777) {
161: /* restore mode of parent directory */
162: if (chmod(parent, statbuf.st_mode & 0777) != 0) {
163: errent(Ct_CHMOD, parent, errno, sccsid, __FILE__, __LINE__);
164: DEBUG(5, "CAN'T CHMOD PARENT %s\n", parent);
165: return(FAIL);
166: }
167: }
168:
169: if (Uid != 0) {
170: if (setuid(Uid) != 0) {
171: DEBUG(5, "CAN'T SETUID %d\n", Uid);
172: return(FAIL);
173: }
174: if ( chmod(name, (mask ^ 0777) & 0777) != 0) {
175: errent(Ct_CHMOD, name, errno, sccsid, __FILE__, __LINE__);
176: return(FAIL);
177: };
178: if (chown(name, UUCPUID, getgid()) != 0) {
179: DEBUG(5, "CHOWN FAILED %s ", name);
180: DEBUG(5, "errno %d\n", errno);
181: errent(Ct_CHOWN, name, errno, sccsid, __FILE__, __LINE__);
182: setuid(Euid);
183: return(FAIL);
184: }
185: setuid(Euid);
186: }
187: return(0);
188: }
189: #endif ATTSV
190:
191: #ifdef V7
192: mkdirs2(name, mask)
193: register char *name;
194: register int mask;
195: {
196: int ret;
197:
198: if (DIRECTORY(name))
199: return(0); /* directory exists */
200:
201: if (fork() == 0) {
202: setuid(Euid); /* this makes it trivial in V7 */
203: umask(mask);
204: /* close stdout and stderr to fail quietly */
205: close(1);
206: close(2);
207: execl("/bin/mkdir", "mkdir", name, 0);
208: _exit(1);
209: }
210: wait(&ret);
211:
212: if (ret != 0) /* why should we abort if some remote tries */
213: return(FAIL); /* to make a garbage directory */
214:
215: return(0);
216: }
217: #endif V7
218:
219: /*
220: * expand file name and check return
221: * print error if it failed.
222: * file -> file name to check
223: * returns:
224: * 0 -> ok
225: * FAIL -> if expfile failed
226: */
227: ckexpf(file)
228: char *file;
229: {
230: if (expfile(file) == 0)
231: return(0);
232:
233: fprintf(stderr, "Illegal filename (%s).\n", file);
234: return(FAIL);
235: }
236:
237:
238: /*
239: * make canonical path out of path passed as argument.
240: *
241: * Eliminate redundant self-references like // or /./
242: * (A single terminal / will be preserved, however.)
243: * Dispose of references to .. in the path names.
244: * In relative path names, this means that .. or a/../..
245: * will be treated as an illegal reference.
246: * In full paths, .. is always allowed, with /.. treated as /
247: *
248: * returns:
249: * 0 -> path is now in canonical form
250: * FAIL -> relative path contained illegal .. reference
251: */
252:
253: int
254: canPath(path)
255: register char *path; /* path is modified in place */
256: {
257: register char *to, *fr;
258:
259: to = fr = path;
260: if (*fr == '/') *to++ = *fr++;
261: for (;;) {
262: /* skip past references to self and validate references to .. */
263: for (;;) {
264: if (*fr == '/') {
265: fr++;
266: continue;
267: }
268: if ((strncmp(fr, "./", 2) == SAME) || EQUALS(fr, ".")) {
269: fr++;
270: continue;
271: }
272: if ((strncmp(fr, "../", 3) == SAME) || EQUALS(fr, "..")) {
273: fr += 2;
274: /* /.. is / */
275: if (((to - 1) == path) && (*path == '/')) continue;
276: /* error if no previous component */
277: if (to <= path) return (FAIL);
278: /* back past previous component */
279: while ((--to > path) && (to[-1] != '/'));
280: continue;
281: }
282: break;
283: }
284: /*
285: * What follows is a legitimate component,
286: * terminated by a null or a /
287: */
288: if (*fr == '\0') break;
289: while ((*to++ = *fr) && (*fr++ != '/'));
290: }
291: /* null path is . */
292: if (to == path) *to++ = '.';
293: *to = '\0';
294: return (0);
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.