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