|
|
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.