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