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