1 #ifndef lint 2 static char sccsid[] = "@(#)uux.c 5.14 (Berkeley) 10/27/88"; 3 #endif 4 5 #include "uucp.h" 6 #include <sys/stat.h> 7 #include <sysexits.h> 8 9 #define NOSYSPART 0 10 #define HASSYSPART 1 11 12 #define LQUOTE '(' 13 #define RQUOTE ')' 14 15 #define APPCMD(d) {\ 16 register char *p; for (p = d; *p != '\0';)\ 17 {*cmdp++ = *p++;\ 18 if(cmdp>(sizeof(cmd)+&cmd[0])){\ 19 fprintf(stderr,"argument list too long\n");\ 20 cleanup(EX_SOFTWARE);\ 21 }\ 22 }\ 23 *cmdp++ = ' '; *cmdp = '\0';} 24 25 #define GENSEND(f, a, b, c, d, e) {\ 26 fprintf(f, "S %s %s %s -%s %s 0666\n", a, b, c, d, e); } 27 #define GENRCV(f, a, b, c) {fprintf(f, "R %s %s %s - \n", a, b, c);} 28 29 struct timeb Now; 30 31 main(argc, argv) 32 int argc; 33 char **argv; 34 { 35 char cfile[NAMESIZE]; /* send commands for files from here */ 36 char dfile[NAMESIZE]; /* used for all data files from here */ 37 char rxfile[NAMESIZE]; /* to be sent to xqt file (X. ...) */ 38 char tfile[NAMESIZE]; /* temporary file name */ 39 char tcfile[NAMESIZE]; /* temporary file name */ 40 char t2file[NAMESIZE]; /* temporary file name */ 41 int cflag = 0; /* commands in C. file flag */ 42 int rflag = 0; /* C. files for receiving flag */ 43 #ifdef DONTCOPY 44 int Copy = 0; /* Don't Copy spool files */ 45 #else !DONTCOPY 46 int Copy = 1; /* Copy spool files */ 47 #endif !DONTCOPY 48 int Linkit = 0; /* Try link before copy */ 49 char buf[2*BUFSIZ]; 50 char inargs[2*BUFSIZ]; 51 int pipein = 0; 52 int startjob = 1; 53 char Grade = 'A'; 54 long Gradedelta = 100000000L; /* "huge number" */ 55 long size = 0L; 56 char path[MAXFULLNAME]; 57 char cmd[2*BUFSIZ]; 58 char *ap, *cmdp; 59 char prm[2*BUFSIZ]; 60 char syspart[MAXBASENAME+1], rest[MAXFULLNAME]; 61 char Xsys[MAXBASENAME+1], local[MAXBASENAME+1]; 62 char *xsys = Xsys; 63 FILE *fprx, *fpc, *fpd, *fp; 64 extern char *getprm(), *lastpart(); 65 extern FILE *ufopen(); 66 int uid, ret, c; 67 char redir = '\0'; 68 int nonoti = 0; 69 int nonzero = 0; 70 int link_failed; 71 char *ReturnTo = NULL; 72 extern int LocalOnly; 73 extern char *optarg; 74 extern int optind; 75 76 strcpy(Progname, "uux"); 77 uucpname(Myname); 78 umask(WFMASK); 79 Ofn = 1; 80 Ifn = 0; 81 #ifdef VMS 82 arg_fix(argc, argv); 83 #endif 84 while (((c = getopt(argc, argv, "-prclCg:x:nzLa:")) != EOF) || 85 (optind < argc && (c = *argv[optind]) == '-' && ++optind)) 86 switch (c) { 87 case '-': 88 /* FALLTHROUGH */ 89 case 'p': 90 pipein = 1; 91 break; 92 case 'r': 93 startjob = 0; 94 break; 95 case 'c': 96 Copy = 0; 97 Linkit = 0; 98 break; 99 case 'l': 100 Copy = 0; 101 Linkit = 1; 102 break; 103 case 'C': 104 Copy = 1; 105 Linkit = 0; 106 break; 107 case 'g': 108 Grade = *optarg; 109 Gradedelta = atol(optarg+1); 110 break; 111 case 'x': 112 chkdebug(); 113 Debug = atoi(optarg); 114 if (Debug <= 0) 115 Debug = 1; 116 break; 117 case 'n': 118 nonoti = 1; 119 break; 120 case 'z': 121 nonzero = 1; 122 break; 123 case 'L': 124 LocalOnly++; 125 break; 126 case 'a': 127 ReturnTo = optarg; 128 if (prefix(Myname, ReturnTo) && ReturnTo[strlen(Myname)] == '!') 129 ReturnTo = index(ReturnTo, '!') + 1; 130 break; 131 case '?': 132 default: 133 break; 134 } 135 136 ap = getwd(Wrkdir); 137 if (ap == 0) { 138 fprintf(stderr, "can't get working directory; will try to continue\n"); 139 strcpy(Wrkdir, "/UNKNOWN"); 140 } 141 142 DEBUG(4, "\n\n** %s **\n", "START"); 143 144 inargs[0] = '\0'; 145 while (optind < argc) { 146 DEBUG(4, "arg - %s:", argv[optind]); 147 strcat(inargs, " "); 148 strcat(inargs, argv[optind++]); 149 } 150 DEBUG(4, "arg - %s\n", inargs); 151 if (subchdir(Spool) < 0) { 152 syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool); 153 cleanup(1); 154 } 155 uid = getuid(); 156 if (guinfo(uid, User, path) != SUCCESS) { 157 syslog(LOG_WARNING, "Can't find username for uid %d", uid); 158 DEBUG(1, "Using username", "uucp"); 159 strcpy(User, "uucp"); 160 } 161 162 strncpy(local, Myname, MAXBASENAME); 163 cmdp = cmd; 164 *cmdp = '\0'; 165 gename(DATAPRE, local, 'X', rxfile); 166 fprx = ufopen(rxfile, "w"); 167 if (fprx == NULL) { 168 syslog(LOG_WARNING, "fopen(%s) failed: %m", rxfile); 169 cleanup(1); 170 } 171 gename(DATAPRE, local, 'T', tcfile); 172 fpc = ufopen(tcfile, "w"); 173 if (fpc == NULL) { 174 syslog(LOG_WARNING, "fopen(%s) failed: %m", tcfile); 175 cleanup(1); 176 } 177 fprintf(fprx, "%c %s %s\n", X_USER, User, local); 178 if (nonoti) 179 fprintf(fprx, "%c\n", X_NONOTI); 180 if (nonzero) 181 fprintf(fprx, "%c\n", X_NONZERO); 182 if (ReturnTo == NULL || *ReturnTo == '\0') 183 ReturnTo = User; 184 fprintf(fprx, "%c %s\n", X_RETURNTO, ReturnTo); 185 186 /* find remote system name */ 187 ap = inargs; 188 xsys[0] = '\0'; 189 while ((ap = getprm(ap, prm)) != NULL) { 190 if (prm[0] == '>' || prm[0] == '<') { 191 ap = getprm(ap, prm); 192 continue; 193 } 194 195 split(prm, xsys, rest); 196 break; 197 } 198 if (xsys[0] == '\0') 199 strcpy(xsys, local); 200 if (versys(&xsys) != 0) { 201 /* bad system name */ 202 fprintf(stderr, "bad system name: %s\n", xsys); 203 fclose(fprx); 204 fclose(fpc); 205 cleanup(EX_NOHOST); 206 } 207 208 strncpy(Rmtname, xsys, MAXBASENAME); 209 DEBUG(4, "xsys %s\n", xsys); 210 211 if (pipein) { 212 gename(DATAPRE, local, 'B', dfile); 213 fpd = ufopen(dfile, "w"); 214 if (fpd == NULL) { 215 syslog(LOG_WARNING, "fopen(%s) failed: %m", dfile); 216 cleanup(1); 217 } 218 while (!feof(stdin)) { 219 ret = fread(buf, 1, BUFSIZ, stdin); 220 fwrite(buf, 1, ret, fpd); 221 if (ferror(stdin)) { 222 perror("stdin"); 223 cleanup(EX_IOERR); 224 } 225 if (ferror(fpd)) { 226 perror(dfile); 227 cleanup(EX_IOERR); 228 } 229 size += ret; 230 } 231 fclose(fpd); 232 strcpy(tfile, dfile); 233 if (strcmp(local, xsys) != SAME) { 234 register int Len = strlen(local); 235 if (Len > SYSNSIZE) 236 Len = SYSNSIZE; 237 tfile[Len + 2] = 'S'; 238 GENSEND(fpc, dfile, tfile, User, "", dfile); 239 cflag++; 240 } 241 fprintf(fprx, "%c %s\n", X_RQDFILE, tfile); 242 fprintf(fprx, "%c %s\n", X_STDIN, tfile); 243 } 244 /* parse command */ 245 ap = inargs; 246 while ((ap = getprm(ap, prm)) != NULL) { 247 DEBUG(4, "prm - %s\n", prm); 248 if (prm[0] == '>' || prm[0] == '<') { 249 redir = prm[0]; 250 continue; 251 } 252 253 if (prm[0] == ';') { 254 APPCMD(prm); 255 continue; 256 } 257 258 if (prm[0] == '|' || prm[0] == '^') { 259 if (cmdp != cmd) 260 APPCMD(prm); 261 continue; 262 } 263 264 /* process command or file or option */ 265 ret = split(prm, syspart, rest); 266 DEBUG(4, "s - %s, ", syspart); 267 DEBUG(4, "r - %s, ", rest); 268 DEBUG(4, "ret - %d\n", ret); 269 if (syspart[0] == '\0') 270 strcpy(syspart, local); 271 272 if (cmdp == cmd && redir == '\0') { 273 /* command */ 274 APPCMD(rest); 275 continue; 276 } 277 278 /* process file or option */ 279 DEBUG(4, "file s- %s, ", syspart); 280 DEBUG(4, "local - %s\n", local); 281 /* process file */ 282 if (redir == '>') { 283 if (rest[0] != '~') 284 if (ckexpf(rest)) 285 cleanup(EX_CANTCREAT); 286 fprintf(fprx, "%c %s %s\n", X_STDOUT, rest, 287 syspart); 288 redir = '\0'; 289 continue; 290 } 291 292 if (ret == NOSYSPART && redir == '\0') { 293 /* option */ 294 APPCMD(rest); 295 continue; 296 } 297 298 if (rest[0] != '\0') { 299 struct stat stbuf; 300 if (stat(rest, &stbuf) < 0) 301 DEBUG(4, "Can't stat %s\n", rest); 302 else 303 size += stbuf.st_size; 304 DEBUG(4, "size = %ld\n", size); 305 } 306 307 if (strcmp(xsys, local) == SAME 308 && strcmp(xsys, syspart) == SAME) { 309 if (ckexpf(rest)) 310 cleanup(EX_CANTCREAT); 311 if (redir == '<') 312 fprintf(fprx, "%c %s\n", X_STDIN, rest); 313 else 314 APPCMD(rest); 315 redir = '\0'; 316 continue; 317 } 318 319 if (strcmp(syspart, local) == SAME) { 320 /* generate send file */ 321 if (ckexpf(rest)) 322 cleanup(EX_CANTCREAT); 323 gename(DATAPRE, local, 'A', dfile); 324 DEBUG(4, "rest %s\n", rest); 325 if ((chkpth(User, "", rest) || anyread(rest)) != 0) { 326 fprintf(stderr, "permission denied %s\n", rest); 327 cleanup(EX_NOINPUT); 328 } 329 link_failed = 0; 330 if (Linkit) { 331 if (link(subfile(rest), subfile(dfile)) != 0) 332 link_failed++; 333 else 334 GENSEND(fpc, rest, dfile, User, "", dfile); 335 } 336 if (Copy || link_failed) { 337 if (xcp(rest, dfile) != 0) { 338 fprintf(stderr, "can't copy %s to %s\n", rest, dfile); 339 cleanup(EX_NOINPUT); 340 } 341 GENSEND(fpc, rest, dfile, User, "", dfile); 342 } 343 if (!Copy && !Linkit) { 344 GENSEND(fpc, rest, dfile, User, "c", "D.0"); 345 } 346 cflag++; 347 if (redir == '<') { 348 fprintf(fprx, "%c %s\n", X_STDIN, dfile); 349 fprintf(fprx, "%c %s\n", X_RQDFILE, dfile); 350 } else { 351 APPCMD(lastpart(rest)); 352 fprintf(fprx, "%c %s %s\n", X_RQDFILE, 353 dfile, lastpart(rest)); 354 } 355 redir = '\0'; 356 continue; 357 } 358 359 if (strcmp(local, xsys) == SAME) { 360 /* generate local receive */ 361 gename(CMDPRE, syspart, 'R', tfile); 362 strcpy(dfile, tfile); 363 dfile[0] = DATAPRE; 364 fp = ufopen(tfile, "w"); 365 if (fp == NULL) { 366 syslog(LOG_WARNING, "fopen(%s) failed: %m", 367 tfile); 368 cleanup(1); 369 } 370 if (ckexpf(rest)) 371 cleanup(EX_CANTCREAT); 372 GENRCV(fp, rest, dfile, User); 373 fclose(fp); 374 rflag++; 375 if (rest[0] != '~') 376 if (ckexpf(rest)) 377 cleanup(EX_CANTCREAT); 378 if (redir == '<') { 379 fprintf(fprx, "%c %s\n", X_RQDFILE, dfile); 380 fprintf(fprx, "%c %s\n", X_STDIN, dfile); 381 } else { 382 fprintf(fprx, "%c %s %s\n", X_RQDFILE, dfile, 383 lastpart(rest)); 384 APPCMD(lastpart(rest)); 385 } 386 387 redir = '\0'; 388 continue; 389 } 390 391 if (strcmp(syspart, xsys) != SAME) { 392 /* generate remote receives */ 393 gename(DATAPRE, syspart, 'R', dfile); 394 strcpy(tfile, dfile); 395 tfile[0] = CMDPRE; 396 fpd = ufopen(dfile, "w"); 397 if (fpd == NULL) { 398 syslog(LOG_WARNING, "fopen(%s) failed: %m", 399 dfile); 400 cleanup(1); 401 } 402 gename(DATAPRE, local, 'T', t2file); 403 GENRCV(fpd, rest, t2file, User); 404 fclose(fpd); 405 GENSEND(fpc, dfile, tfile, User, "", dfile); 406 cflag++; 407 if (redir == '<') { 408 fprintf(fprx, "%c %s\n", X_RQDFILE, t2file); 409 fprintf(fprx, "%c %s\n", X_STDIN, t2file); 410 } else { 411 fprintf(fprx, "%c %s %s\n", X_RQDFILE, t2file, 412 lastpart(rest)); 413 APPCMD(lastpart(rest)); 414 } 415 redir = '\0'; 416 continue; 417 } 418 419 /* file on remote system */ 420 if (rest[0] != '~') 421 if (ckexpf(rest)) 422 cleanup(EX_CANTCREAT); 423 if (redir == '<') 424 fprintf(fprx, "%c %s\n", X_STDIN, rest); 425 else 426 APPCMD(rest); 427 redir = '\0'; 428 continue; 429 430 } 431 /* 432 * clean up trailing ' ' in command. 433 */ 434 if (cmdp > cmd && cmdp[0] == '\0' && cmdp[-1] == ' ') 435 *--cmdp = '\0'; 436 /* block multi-hop uux, which doesn't work */ 437 for (ap = cmd; *ap && *ap != ' '; ap++) 438 if (*ap == '!') { 439 fprintf(stderr, "uux handles only adjacent sites.\n"); 440 fprintf(stderr, "Try uusend for multi-hop delivery.\n"); 441 cleanup(EX_USAGE); 442 } 443 444 fprintf(fprx, "%c %s\n", X_CMD, cmd); 445 if (ferror(fprx)) { 446 logent(cmd, "COULD NOT QUEUE XQT"); 447 cleanup(EX_IOERR); 448 } else 449 logent(cmd, "XQT QUE'D"); 450 fclose(fprx); 451 452 if (size > 0 && Gradedelta > 0) { 453 DEBUG (4, "Grade changed from %c ", Grade); 454 Grade += size/Gradedelta; 455 if (Grade > 'z') 456 Grade = 'z'; 457 DEBUG(4, "to %c\n", Grade); 458 } 459 gename(XQTPRE, local, Grade, tfile); 460 if (strcmp(xsys, local) == SAME) { 461 /* rti!trt: xmv() works across filesystems, link(II) doesnt */ 462 xmv(rxfile, tfile); 463 if (startjob) 464 if (rflag) 465 xuucico(xsys); 466 else 467 xuuxqt(); 468 } 469 else { 470 GENSEND(fpc, rxfile, tfile, User, "", rxfile); 471 cflag++; 472 } 473 474 if (ferror(fpc)) 475 cleanup(EX_IOERR); 476 fclose(fpc); 477 if (cflag) { 478 gename(CMDPRE, xsys, Grade, cfile); 479 /* rti!trt: use xmv() rather than link(II) */ 480 xmv(tcfile, cfile); 481 if (startjob) 482 xuucico(xsys); 483 cleanup(0); 484 } 485 else 486 unlink(subfile(tcfile)); 487 exit(0); 488 } 489 490 #define FTABSIZE 30 491 char Fname[FTABSIZE][NAMESIZE]; 492 int Fnamect = 0; 493 494 /* 495 * cleanup and unlink if error 496 * 497 * return - none - do exit() 498 */ 499 500 cleanup(code) 501 int code; 502 { 503 int i; 504 505 logcls(); 506 rmlock(CNULL); 507 if (code) { 508 for (i = 0; i < Fnamect; i++) 509 unlink(subfile(Fname[i])); 510 fprintf(stderr, "uux failed. code %d\n", code); 511 } 512 DEBUG(1, "exit code %d\n", code); 513 exit(code); 514 } 515 516 /* 517 * open file and record name 518 * 519 * return file pointer. 520 */ 521 522 FILE *ufopen(file, mode) 523 char *file, *mode; 524 { 525 if (Fnamect < FTABSIZE) 526 strcpy(Fname[Fnamect++], file); 527 else 528 logent("Fname", "TABLE OVERFLOW"); 529 return fopen(subfile(file), mode); 530 } 531 #ifdef VMS 532 /* 533 * EUNICE bug: 534 * quotes are not stripped from DCL. Do it here. 535 * Note if we are running under Unix shell we don't 536 * do the right thing. 537 */ 538 arg_fix(argc, argv) 539 char **argv; 540 { 541 register char *cp, *tp; 542 543 for (; argc > 0; --argc, argv++) { 544 cp = *argv; 545 if (cp == (char *)0 || *cp++ != '"') 546 continue; 547 tp = cp; 548 while (*tp++) ; 549 tp -= 2; 550 if (*tp == '"') { 551 *tp = '\0'; 552 *argv = cp; 553 } 554 } 555 } 556 #endif VMS 557 558 /* 559 * split into system and file part 560 * 561 * return codes: 562 * NOSYSPART 563 * HASSYSPART 564 */ 565 566 split(name, sys, rest) 567 register char *name, *rest; 568 char *sys; 569 { 570 register char *c; 571 572 if (*name == LQUOTE) { 573 if ((c = index(name + 1, RQUOTE)) != NULL) { 574 /* strip off quotes */ 575 name++; 576 while (c != name) 577 *rest++ = *name++; 578 *rest = '\0'; 579 *sys = '\0'; 580 return NOSYSPART; 581 } 582 } 583 584 if ((c = index(name, '!')) == NULL) { 585 strcpy(rest, name); 586 *sys = '\0'; 587 return NOSYSPART; 588 } 589 590 *c++ = '\0'; 591 strncpy(sys, name, MAXBASENAME); 592 sys[MAXBASENAME] = '\0'; 593 594 strcpy(rest, c); 595 return HASSYSPART; 596 } 597