1 #ifndef lint 2 static char sccsid[] = "@(#)uucp.c 5.8 (Berkeley) 4/24/88"; 3 #endif 4 5 #include "uucp.h" 6 #include <sys/stat.h> 7 #include "uust.h" 8 9 /* 10 * uucp command 11 */ 12 13 int Uid; 14 char *Ropt = " "; 15 char Path[100], Optns[10], Ename[MAXBASENAME+1]; 16 char Grade = 'n'; 17 #ifdef DONTCOPY 18 int Copy = 0; 19 #else !DONTCOPY 20 int Copy = 1; 21 #endif !DONTCOPY 22 char Nuser[32]; 23 struct timeb Now; 24 25 /* variables used to check if talking to more than one system. */ 26 int xsflag = -1; 27 char xsys[MAXBASENAME+1]; 28 29 long Nbytes = 0; 30 #define MAXBYTES 50000 /* maximun number of bytes of data per C. file */ 31 #define MAXCOUNT 15 /* maximun number of files per C. file */ 32 33 main(argc, argv) 34 int argc; 35 char **argv; 36 { 37 char *sysfile1, *sysfl2; 38 register char *cp; 39 char file1[MAXFULLNAME], file2[MAXFULLNAME]; 40 int avoidgwd = 0, c; 41 extern char *optarg; 42 extern int optind; 43 44 strcpy(Progname, "uucp"); 45 uucpname(Myname); 46 umask(WFMASK); 47 Optns[0] = '-'; 48 Optns[1] = 'd'; 49 #ifdef DONTCOPY 50 Optns[2] = 'c'; 51 #else !DONTCOPY 52 Optns[2] = 'C'; 53 #endif !DONTCOPY 54 Ename[0] = Nuser[0] = Optns[3] = '\0'; 55 while((c = getopt(argc, argv, "aCcdfe:g:mn:rs:x:")) != EOF) 56 switch(c) { 57 case 'a': 58 /* efficiency hack; avoid gwd call */ 59 avoidgwd = 1; 60 break; 61 case 'C': 62 Copy = 1; 63 Optns[2] = 'C'; 64 break; 65 case 'c': 66 Copy = 0; 67 Optns[2] = 'c'; 68 break; 69 case 'd': 70 break; 71 case 'f': 72 Optns[1] = 'f'; 73 break; 74 case 'e': 75 strncpy(Ename, optarg, MAXBASENAME); 76 break; 77 case 'g': 78 Grade = *optarg; 79 break; 80 case 'm': 81 strcat(Optns, "m"); 82 break; 83 case 'n': 84 sprintf(Nuser, "%.31s", optarg); 85 break; 86 case 'r': 87 Ropt = argv[optind-1]; 88 break; 89 case 's': 90 Spool = optarg; 91 break; 92 case 'x': 93 chkdebug(); 94 Debug = atoi(optarg); 95 if (Debug <= 0) 96 Debug = 1; 97 fprintf(stderr, "DEBUG %d\n", Debug); 98 break; 99 case '?': 100 default: 101 fprintf(stderr, "unknown flag %s\n", argv[optind-1]); 102 break; 103 } 104 105 DEBUG(4, "\n\n** %s **\n", "START"); 106 if (!avoidgwd) { 107 cp = getwd(Wrkdir); 108 if (cp == NULL) { 109 syslog(LOG_WARNING, "getwd failed"); 110 cleanup(1); 111 } 112 } 113 if (subchdir(Spool) < 0) { 114 syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool); 115 cleanup(1); 116 } 117 118 Uid = getuid(); 119 if (guinfo(Uid, User, Path) != SUCCESS) { 120 syslog(LOG_WARNING, "Can't find username for uid %d", Uid); 121 DEBUG(1, "Using username", "uucp"); 122 strcpy(User, "uucp"); 123 } 124 DEBUG(4, "UID %d, ", Uid); 125 DEBUG(4, "User %s,", User); 126 DEBUG(4, "Ename (%s) ", Ename); 127 DEBUG(4, "PATH %s\n", Path); 128 if (optind > (argc-2)) { 129 fprintf(stderr, "usage: uucp [flags] from... to\n"); 130 cleanup(1); 131 } 132 133 134 /* set up "to" system and file names */ 135 if ((cp = index(argv[--argc], '!')) != NULL) { 136 sysfl2 = argv[argc]; 137 *cp = '\0'; 138 if (*sysfl2 == '\0') 139 sysfl2 = Myname; 140 else 141 strncpy(Rmtname, sysfl2, MAXBASENAME); 142 if (versys(&sysfl2) != 0) { 143 fprintf(stderr, "bad system name: %s\n", sysfl2); 144 cleanup(1); 145 } 146 if (Rmtname[0] != '\0') 147 strncpy(Rmtname, sysfl2, MAXBASENAME); 148 /* block multi-hop requests immediately */ 149 if (index(cp+1, '!') != NULL) { 150 fprintf(stderr, "uucp handles only adjacent sites.\n"); 151 fprintf(stderr, "Try uusend for multi-hop delivery.\n"); 152 cleanup(1); 153 } 154 strcpy(file2, cp + 1); 155 } else { 156 sysfl2 = Myname; 157 strcpy(file2, argv[argc]); 158 } 159 if (strlen(sysfl2) > MAXBASENAME) 160 sysfl2[MAXBASENAME] = '\0'; 161 162 163 /* do each from argument */ 164 while (optind < argc) { 165 if ((cp = index(argv[optind], '!')) != NULL) { 166 sysfile1 = argv[optind]; 167 *cp = '\0'; 168 if (strlen(sysfile1) > MAXBASENAME) 169 sysfile1[MAXBASENAME] = '\0'; 170 if (*sysfile1 == '\0') 171 sysfile1 = Myname; 172 else 173 strncpy(Rmtname, sysfile1, MAXBASENAME); 174 if (versys(&sysfile1) != 0) { 175 fprintf(stderr, "bad system name: %s\n", sysfile1); 176 cleanup(1); 177 } 178 if (Rmtname[0] != '\0') 179 strncpy(Rmtname, sysfl2, MAXBASENAME); 180 strcpy(file1, cp + 1); 181 } else { 182 sysfile1 = Myname; 183 strcpy(file1, argv[optind]); 184 } 185 DEBUG(4, "file1 - %s\n", file1); 186 copy(sysfile1, file1, sysfl2, file2); 187 optind++; 188 } 189 190 clscfile(); 191 if (*Ropt != '-' && xsflag >= 0) 192 xuucico(xsys); 193 cleanup(0); 194 } 195 196 cleanup(code) 197 int code; 198 { 199 logcls(); 200 rmlock(CNULL); 201 if (code) 202 fprintf(stderr, "uucp failed. code %d\n", code); 203 exit(code); 204 } 205 206 207 /* 208 * generate copy files 209 * 210 * return codes 0 | FAIL 211 */ 212 213 copy(s1, f1, s2, f2) 214 register char *s1, *f1, *s2, *f2; 215 { 216 int type, statret; 217 struct stat stbuf, stbuf1; 218 char dfile[NAMESIZE]; 219 char file1[MAXFULLNAME], file2[MAXFULLNAME]; 220 FILE *cfp, *gtcfile(); 221 char opts[100]; 222 223 type = 0; 224 opts[0] = '\0'; 225 strcpy(file1, f1); 226 strcpy(file2, f2); 227 if (strcmp(s1, Myname) != SAME) 228 type = 1; 229 if (strcmp(s2, Myname) != SAME) 230 type += 2; 231 if (type & 01) 232 if ((index(f1, '*') != NULL 233 || index(f1, '?') != NULL 234 || index(f1, '[') != NULL)) 235 type = 4; 236 237 switch (type) { 238 case 0: 239 /* all work here */ 240 DEBUG(4, "all work here %d\n", type); 241 if (ckexpf(file1)) 242 return FAIL; 243 if (ckexpf(file2)) 244 return FAIL; 245 if (stat(subfile(file1), &stbuf) != 0) { 246 fprintf(stderr, "can't get file status %s \n copy failed\n", 247 file1); 248 return SUCCESS; 249 } 250 statret = stat(subfile(file2), &stbuf1); 251 if (statret == 0 252 && stbuf.st_ino == stbuf1.st_ino 253 && stbuf.st_dev == stbuf1.st_dev) { 254 fprintf(stderr, "%s %s - same file; can't copy\n", file1, file2); 255 return SUCCESS; 256 } 257 if (chkpth(User, "", file1) != 0 258 || chkperm(file2, index(Optns, 'd')) 259 || chkpth(User, "", file2) != 0) { 260 fprintf(stderr, "permission denied\n"); 261 cleanup(1); 262 } 263 if ((stbuf.st_mode & ANYREAD) == 0) { 264 fprintf(stderr, "can't read file (%s) mode (%o)\n", 265 file1, (int)stbuf.st_mode); 266 return FAIL; 267 } 268 if (statret == 0 && (stbuf1.st_mode & ANYWRITE) == 0) { 269 fprintf(stderr, "can't write file (%s) mode (%o)\n", 270 file2, (int)stbuf.st_mode); 271 return FAIL; 272 } 273 xcp(file1, file2); 274 /* With odd umask() might not be able to read it himself */ 275 (void) chmod(file2, 0666); 276 logent("WORK HERE", "DONE"); 277 return SUCCESS; 278 case 1: 279 /* receive file */ 280 DEBUG(4, "receive file - %d\n", type); 281 chsys(s1); 282 if (file1[0] != '~') 283 if (ckexpf(file1)) 284 return FAIL; 285 if (ckexpf(file2)) 286 return FAIL; 287 if (chkpth(User, "", file2) != 0) { 288 fprintf(stderr, "permission denied\n"); 289 return FAIL; 290 } 291 if (Ename[0] != '\0') { 292 /* execute uux - remote uucp */ 293 xuux(Ename, s1, file1, s2, file2, opts); 294 return SUCCESS; 295 } 296 297 cfp = gtcfile(s1); 298 fprintf(cfp, "R %s %s %s %s\n", file1, file2, User, Optns); 299 break; 300 case 2: 301 /* send file */ 302 if (ckexpf(file1)) 303 return FAIL; 304 if (file2[0] != '~') 305 if (ckexpf(file2)) 306 return FAIL; 307 DEBUG(4, "send file - %d\n", type); 308 chsys(s2); 309 310 if (chkpth(User, "", file1) != 0) { 311 fprintf(stderr, "permission denied %s\n", file1); 312 return FAIL; 313 } 314 if (stat(subfile(file1), &stbuf) != 0) { 315 fprintf(stderr, "can't get status for file %s\n", file1); 316 return FAIL; 317 } 318 if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 319 fprintf(stderr, "directory name illegal - %s\n", 320 file1); 321 return FAIL; 322 } 323 if ((stbuf.st_mode & ANYREAD) == 0) { 324 fprintf(stderr, "can't read file (%s) mode (%o)\n", 325 file1, (int)stbuf.st_mode); 326 return FAIL; 327 } 328 if ((Nuser[0] != '\0') && (index(Optns, 'n') == NULL)) 329 strcat(Optns, "n"); 330 if (Ename[0] != '\0') { 331 /* execute uux - remote uucp */ 332 if (Nuser[0] != '\0') 333 sprintf(opts, "-n%s", Nuser); 334 xuux(Ename, s1, file1, s2, file2, opts); 335 return SUCCESS; 336 } 337 Nbytes += stbuf.st_size; 338 if (Copy) { 339 gename(DATAPRE, Myname, Grade, dfile); 340 if (xcp(file1, dfile) != 0) { 341 fprintf(stderr, "can't copy %s\n", file1); 342 return FAIL; 343 } 344 } 345 else { 346 /* make a dummy D. name */ 347 /* cntrl.c knows names < 6 chars are dummy D. files */ 348 strcpy(dfile, "D.0"); 349 } 350 cfp = gtcfile(s2); 351 fprintf(cfp, "S %s %s %s %s %s %o %s\n", file1, file2, 352 User, Optns, dfile, (int)stbuf.st_mode & 0777, Nuser); 353 break; 354 case 3: 355 case 4: 356 /* send uucp command for execution on s1 */ 357 DEBUG(4, "send uucp command - %d\n", type); 358 chsys(s1); 359 if (strcmp(s2, Myname) == SAME) { 360 if (ckexpf(file2)) 361 return FAIL; 362 if (chkpth(User, "", file2) != 0) { 363 fprintf(stderr, "permission denied\n"); 364 return FAIL; 365 } 366 } 367 if (Ename[0] != '\0') { 368 /* execute uux - remote uucp */ 369 xuux(Ename, s1, file1, s2, file2, opts); 370 return SUCCESS; 371 } 372 cfp = gtcfile(s1); 373 fprintf(cfp, "X %s %s!%s %s %s\n", file1, s2, file2, User, Optns); 374 break; 375 } 376 return SUCCESS; 377 } 378 379 /* 380 * execute uux for remote uucp 381 * 382 * return code - none 383 */ 384 385 xuux(ename, s1, f1, s2, f2, opts) 386 char *ename, *s1, *s2, *f1, *f2, *opts; 387 { 388 char cmd[200]; 389 390 DEBUG(4, "Ropt(%s) ", Ropt); 391 DEBUG(4, "ename(%s) ", ename); 392 DEBUG(4, "s1(%s) ", s1); 393 DEBUG(4, "f1(%s) ", f1); 394 DEBUG(4, "s2(%s) ", s2); 395 DEBUG(4, "f2(%s)\n", f2); 396 sprintf(cmd, "uux %s %s!uucp %s %s!%s \\(%s!%s\\)", 397 Ropt, ename, opts, s1, f1, s2, f2); 398 DEBUG(4, "cmd (%s)\n", cmd); 399 system(cmd); 400 return; 401 } 402 403 FILE *Cfp = NULL; 404 char Cfile[NAMESIZE]; 405 406 /* 407 * get a Cfile descriptor 408 * 409 * return an open file descriptor 410 */ 411 412 FILE * 413 gtcfile(sys) 414 register char *sys; 415 { 416 static char presys[8] = ""; 417 static int cmdcount = 0; 418 register int savemask; 419 420 if (strcmp(presys, sys) != SAME /* this is !SAME on first call */ 421 || Nbytes > MAXBYTES 422 || ++cmdcount > MAXCOUNT) { 423 cmdcount = 1; 424 Nbytes = 0; 425 if (presys[0] != '\0') { 426 clscfile(); 427 } 428 gename(CMDPRE, sys, Grade, Cfile); 429 #ifdef VMS 430 savemask = umask(~0600); /* vms must have read permission */ 431 #else !VMS 432 savemask = umask(~0200); 433 #endif !VMS 434 Cfp = fopen(subfile(Cfile), "w"); 435 umask(savemask); 436 if (Cfp == NULL) { 437 syslog(LOG_WARNING, "fopen(%s) failed: %m", 438 subfile(Cfile)); 439 cleanup(1); 440 } 441 strcpy(presys, sys); 442 } 443 return Cfp; 444 } 445 446 /* 447 * close cfile 448 * 449 * return code - none 450 */ 451 452 clscfile() 453 { 454 if (Cfp == NULL) 455 return; 456 fclose(Cfp); 457 chmod(subfile(Cfile), ~WFMASK & 0777); 458 logent(Cfile, "QUE'D"); 459 US_CRS(Cfile); 460 Cfp = NULL; 461 } 462 463 /* 464 * compile a list of all systems we are referencing 465 */ 466 chsys(s1) 467 register char *s1; 468 { 469 if (xsflag < 0) 470 xsflag = 0; 471 else if (xsflag > 0) 472 return; 473 474 if (xsys[0] == '\0') { 475 strncpy(xsys, s1, MAXBASENAME); 476 return; 477 } 478 479 if (strncmp(xsys, s1, MAXBASENAME) == SAME) 480 return; 481 482 xsflag++; 483 xsys[0] = '\0'; 484 } 485