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