|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)uusend.c 5.3 (Berkeley) 5/11/89"; ! 3: #endif ! 4: ! 5: /* ! 6: * uusend: primitive operation to allow uucp like copy of binary files ! 7: * but handle indirection over systems. ! 8: * ! 9: * usage: uusend [-r] [-m ooo] localfile sysname1!sysname2!...!destfile ! 10: * uusend [-r] [-m ooo] - sysname1!sysname2!...!destfile ! 11: * ! 12: * Author: Mark Horton, May 1980. ! 13: * ! 14: * "-r" switch added. Has same effect as "-r" in uux. 11/82 CCW ! 15: * ! 16: * Error recovery (a la uucp) added & ifdefs for ruusend (as in rmail). ! 17: * Checks for illegal access to /usr/lib/uucp. ! 18: * February 1983 Christopher Woodbury ! 19: * Fixed mode set[ug]id loophole. 4/8/83 CCW ! 20: * ! 21: * Add '-f' to make uusend syntax more similar to UUCP. "destname" ! 22: * can now be a directory. June 1983 CCW ! 23: */ ! 24: ! 25: #include <sys/types.h> ! 26: #include <sys/stat.h> ! 27: #include <stdio.h> ! 28: #include <pwd.h> ! 29: ! 30: /* ! 31: * define RECOVER to permit requests like 'uusend file sys1!sys2!~uucp' ! 32: * (abbreviation for 'uusend file sys1!sys2!~uucp/file'). ! 33: * define DEBUG to keep log of uusend uusage. ! 34: * define RUUSEND if neighboring sites permit 'ruusend', ! 35: * which they certainly should to avoid security holes ! 36: */ ! 37: #define RECOVER ! 38: /*#define DEBUG "/usr/spool/uucp/uusend.log"/**/ ! 39: ! 40: FILE *in, *out; ! 41: FILE *dout; ! 42: ! 43: extern FILE *popen(); ! 44: extern char *index(), *strcpy(), *strcat(), *ctime(); ! 45: ! 46: #ifdef RUUSEND ! 47: int rsend; ! 48: #endif RUUSEND ! 49: int mode = -1; /* mode to chmod new file to */ ! 50: char *nextsys; /* next system in the chain */ ! 51: char dnbuf[200]; /* buffer for result of ~user/file */ ! 52: char cmdbuf[256]; /* buffer to build uux command in */ ! 53: char *rflg = ""; /* default value of rflg ccw -- 1 Nov '82 */ ! 54: ! 55: struct passwd *user; /* entry in /etc/passwd for ~user */ ! 56: struct passwd *getpwnam(); ! 57: struct stat stbuf; ! 58: ! 59: char *excl; /* location of first ! in destname */ ! 60: char *sl; /* location of first / in destname */ ! 61: char *sourcename; /* argv[1] */ ! 62: char *destname; /* argv[2] */ ! 63: char *UULIB = "/usr/lib/uucp"; /* UUCP lib directory */ ! 64: ! 65: #ifdef RECOVER ! 66: char *UUPUB = "/usr/spool/uucppublic/"; /* public UUCP directory */ ! 67: char *filename; /* file name from end of destname */ ! 68: char *getfname(); /* routine to get filename from destname */ ! 69: int fflg; ! 70: char f[100]; /* name of default output file */ ! 71: #else !RECOVER ! 72: char *f = ""; /* so we waste a little space */ ! 73: #endif !RECOVER ! 74: ! 75: main(argc, argv) ! 76: int argc; ! 77: char **argv; ! 78: { ! 79: register int c; ! 80: long count; ! 81: extern char **environ; ! 82: ! 83: #ifdef DEBUG ! 84: long t; ! 85: umask(022); ! 86: dout = fopen(DEBUG, "a"); ! 87: if (dout == NULL) { ! 88: printf("Cannot append to %s\n", DEBUG); ! 89: exit(1); ! 90: } ! 91: freopen(DEBUG, "a", stdout); ! 92: fprintf(dout, "\nuusend run: "); ! 93: for (c=0; c<argc; c++) ! 94: fprintf(dout, "%s ", argv[c]); ! 95: time(&t); ! 96: fprintf(dout, "%s", ctime(&t)); ! 97: #endif DEBUG ! 98: ! 99: #ifdef RUUSEND ! 100: if(argv[0][0] == 'r') ! 101: rsend++; ! 102: #endif RUUSEND ! 103: while (argc > 1 && argv[1][0] == '-' && argv[1][1]) { ! 104: switch(argv[1][1]) { ! 105: case 'm': ! 106: sscanf(argv[2], "%o", &mode); ! 107: mode &= 0777; /* fix set[ug]id loophole */ ! 108: argc--; argv++; ! 109: break; ! 110: case 'r': /* -r flag for uux */ ! 111: rflg = "-r "; ! 112: break; ! 113: #ifdef RECOVER ! 114: case 'f': ! 115: fflg++; ! 116: strcpy(f, argv[1]); ! 117: break; ! 118: #endif RECOVER ! 119: default: ! 120: fprintf(stderr, "Bad flag: %s\n", argv[1]); ! 121: break; ! 122: } ! 123: argc--; argv++; ! 124: } ! 125: ! 126: if (argc != 3) { ! 127: fprintf(stderr, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n"); ! 128: exit(1); ! 129: } ! 130: ! 131: sourcename = argv[1]; ! 132: destname = argv[2]; ! 133: ! 134: if (sourcename[0] == '-') ! 135: in = stdin; ! 136: else { ! 137: #ifdef RUUSEND ! 138: if (rsend) { ! 139: fprintf(stderr, "illegal input\n"); ! 140: exit(2); ! 141: } ! 142: #endif RUUSEND ! 143: in = fopen(sourcename, "r"); ! 144: if (in == NULL) { ! 145: perror(argv[1]); ! 146: exit(2); ! 147: } ! 148: if (!fflg || f[2] == '\0') { ! 149: strcpy(f, "-f"); ! 150: strcat(f, getfname(sourcename)); ! 151: fflg++; ! 152: } ! 153: } ! 154: ! 155: excl = index(destname, '!'); ! 156: if (excl) { ! 157: /* ! 158: * destname is on a remote system. ! 159: */ ! 160: nextsys = destname; ! 161: *excl++ = 0; ! 162: destname = excl; ! 163: if (mode < 0) { ! 164: fstat(fileno(in), &stbuf); ! 165: mode = stbuf.st_mode & 0777; ! 166: } ! 167: #ifdef RUUSEND ! 168: sprintf(cmdbuf,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"", ! 169: #else !RUUSEND ! 170: sprintf(cmdbuf, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"", ! 171: #endif !RUUSEND ! 172: rflg, nextsys, f, mode, destname); ! 173: #ifdef DEBUG ! 174: fprintf(dout, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys, destname, cmdbuf); ! 175: #endif DEBUG ! 176: out = popen(cmdbuf, "w"); ! 177: } else { ! 178: /* ! 179: * destname is local. ! 180: */ ! 181: if (destname[0] == '~') { ! 182: #ifdef DEBUG ! 183: fprintf(dout, "before ~: '%s'\n", destname); ! 184: fflush(dout); ! 185: #endif DEBUG ! 186: sl = index(destname, '/'); ! 187: #ifdef RECOVER ! 188: if (sl == NULL && !fflg) { ! 189: fprintf(stderr, "Illegal ~user\n"); ! 190: exit(3); ! 191: } ! 192: for (sl = destname; *sl != '\0'; sl++) ! 193: ; /* boy, is this a hack! */ ! 194: #else !RECOVER ! 195: if (sl == NULL) { ! 196: fprintf(stderr, "Illegal ~user\n"); ! 197: exit(3); ! 198: } ! 199: *sl++ = 0; ! 200: #endif !RECOVER ! 201: user = getpwnam(destname+1); ! 202: if (user == NULL) { ! 203: fprintf(stderr, "No such user as %s\n", ! 204: destname); ! 205: #ifdef RECOVER ! 206: if ((filename =getfname(sl)) == NULL && ! 207: !fflg) ! 208: exit(4); ! 209: strcpy(dnbuf, UUPUB); ! 210: if (fflg) ! 211: strcat(dnbuf, &f[2]); ! 212: else ! 213: strcat(dnbuf, filename); ! 214: } ! 215: else { ! 216: strcpy(dnbuf, user->pw_dir); ! 217: strcat(dnbuf, "/"); ! 218: strcat(dnbuf, sl); ! 219: } ! 220: #else !RECOVER ! 221: exit(4); ! 222: } ! 223: strcpy(dnbuf, user->pw_dir); ! 224: strcat(dnbuf, "/"); ! 225: strcat(dnbuf, sl); ! 226: #endif !RECOVER ! 227: destname = dnbuf; ! 228: } ! 229: #ifdef RECOVER ! 230: else ! 231: destname = strcpy(dnbuf, destname); ! 232: #endif !RECOVER ! 233: if(strncmp(UULIB, destname, strlen(UULIB)) == 0) { ! 234: fprintf(stderr, "illegal file: %s", destname); ! 235: exit(4); ! 236: } ! 237: #ifdef RECOVER ! 238: if (stat(destname, &stbuf) == 0 && ! 239: (stbuf.st_mode & S_IFMT) == S_IFDIR && ! 240: fflg) { ! 241: strcat(destname, "/"); ! 242: strcat(destname, &f[2]); ! 243: } ! 244: #endif RECOVER ! 245: out = fopen(destname, "w"); ! 246: #ifdef DEBUG ! 247: fprintf(dout, "local, file='%s'\n", destname); ! 248: #endif DEBUG ! 249: if (out == NULL) { ! 250: perror(destname); ! 251: #ifdef RECOVER ! 252: if (strncmp(destname,UUPUB,strlen(UUPUB)) == 0) ! 253: exit(5); /* forget it! */ ! 254: filename = getfname(destname); ! 255: if (destname == dnbuf) /* cmdbuf is scratch */ ! 256: filename = strcpy(cmdbuf, filename); ! 257: destname = strcpy(dnbuf, UUPUB); ! 258: if (user != NULL) { ! 259: strcat(destname, user->pw_name); ! 260: if (stat(destname, &stbuf) == -1) { ! 261: mkdir(destname, 0777); ! 262: } ! 263: strcat(destname, "/"); ! 264: } ! 265: if (fflg) ! 266: strcat(destname, &f[2]); ! 267: else ! 268: strcat(destname, filename); ! 269: if ((out = fopen(destname, "w")) == NULL) ! 270: exit(5); /* all for naught! */ ! 271: #else !RECOVER ! 272: exit(5); ! 273: #endif !RECOVER ! 274: } ! 275: if (mode > 0) ! 276: chmod(destname, mode); /* don't bother to check it */ ! 277: } ! 278: ! 279: /* ! 280: * Now, in any case, copy from in to out. ! 281: */ ! 282: ! 283: count = 0; ! 284: while ((c=getc(in)) != EOF) { ! 285: putc(c, out); ! 286: count++; ! 287: } ! 288: #ifdef DEBUG ! 289: fprintf(dout, "count %ld bytes\n", count); ! 290: fclose(dout); ! 291: #endif DEBUG ! 292: ! 293: fclose(in); ! 294: fclose(out); /* really should pclose in that case */ ! 295: exit(0); ! 296: } ! 297: ! 298: /* ! 299: * Return the ptr in sp at which the character c appears; ! 300: * NULL if not found. Included so I don't have to fight the ! 301: * index/strchr battle. ! 302: */ ! 303: ! 304: #define NULL 0 ! 305: ! 306: char * ! 307: index(sp, c) ! 308: register char *sp, c; ! 309: { ! 310: do { ! 311: if (*sp == c) ! 312: return(sp); ! 313: } while (*sp++); ! 314: return(NULL); ! 315: } ! 316: ! 317: #ifdef RECOVER ! 318: char * ! 319: getfname(p) ! 320: register char *p; ! 321: { ! 322: register char *s; ! 323: s = p; ! 324: while (*p != '\0') ! 325: p++; ! 326: if (p == s) ! 327: return (NULL); ! 328: for (;p != s; p--) ! 329: if (*p == '/') { ! 330: p++; ! 331: break; ! 332: } ! 333: return (p); ! 334: } ! 335: ! 336: #ifndef BSD4_2 ! 337: makedir(dirname, mode) ! 338: char *dirname; ! 339: int mode; ! 340: { ! 341: register int pid; ! 342: int retcode, status; ! 343: switch ((pid = fork())) { ! 344: case -1: /* error */ ! 345: return (-1); ! 346: case 0: /* child */ ! 347: umask(0); ! 348: execl("/bin/mkdir", "mkdir", dirname, (char *)0); ! 349: exit(1); ! 350: /* NOTREACHED */ ! 351: default: /* parent */ ! 352: while ((retcode=wait(&status)) != pid && retcode != -1) ! 353: ; ! 354: if (retcode == -1) ! 355: return -1; ! 356: else { ! 357: chmod(dirname, mode); ! 358: return status; ! 359: } ! 360: } ! 361: /* NOTREACHED */ ! 362: } ! 363: #endif !BSD4_2 ! 364: #endif RECOVER
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.