|
|
1.1 root 1: /* @(#)uucp.c 1.6
2: */
3: #include "uucp.h"
4: VERSION(@(#)uucp.c 1.6);
5:
6: /*
7: * uucp
8: * user id
9: * make a copy in spool directory
10: */
11: int Copy = 0;
12: static int _Transfer = 0;
13: char Nuser[32];
14: char *Ropt = " ";
15: char Optns[10];
16: char Uopts[BUFSIZ];
17: char Grade = 'N';
18:
19: char Sfile[MAXFULLNAME];
20: #ifndef V7
21: long ulimit();
22: #endif
23:
24: main(argc, argv, envp)
25: char *argv[];
26: char **envp;
27: {
28: int ret;
29: int errors = 0;
30: char *fopt;
31: char sys1[MAXFULLNAME], sys2[MAXFULLNAME];
32: char fwd1[MAXFULLNAME], fwd2[MAXFULLNAME];
33: char file1[MAXFULLNAME], file2[MAXFULLNAME];
34: short jflag = 0; /* -j flag Jobid printout */
35:
36: void split();
37: #ifndef V7
38: long limit, dummy;
39: char msg[100];
40: #endif V7
41:
42:
43: /* this fails in some versions, but it doesn't hurt */
44: Uid = getuid();
45: Euid = geteuid();
46: if (Uid == 0)
47: (void) setuid(UUCPUID);
48:
49: /* choose LOGFILE */
50: (void) strcpy(Logfile, LOGUUCP);
51:
52: Env = envp;
53: fopt = NULL;
54: (void) strcpy(Progname, "uucp");
55: Pchar = 'U';
56: *Uopts = NULLCHAR;
57:
58: /*
59: * find name of local system
60: */
61: uucpname(Myname);
62: Optns[0] = '-';
63: Optns[1] = 'd';
64: Optns[2] = 'c';
65: Optns[3] = Nuser[0] = Sfile[0] = NULLCHAR;
66:
67: /*
68: * find id of user who spawned command to
69: * determine
70: */
71: (void) guinfo(Uid, User);
72:
73: while ((ret = getopt(argc, argv, "Ccdfg:jmn:rs:x:")) != EOF) {
74: switch (ret) {
75:
76: /*
77: * make a copy of the file in the spool
78: * directory.
79: */
80: case 'C':
81: Copy = 1;
82: Optns[2] = 'C';
83: break;
84:
85: /*
86: * not used (default)
87: */
88: case 'c':
89: break;
90:
91: /*
92: * not used (default)
93: */
94: case 'd':
95: break;
96: case 'f':
97: Optns[1] = 'f';
98: break;
99:
100: /*
101: * set service grade
102: */
103: case 'g':
104: Grade = *optarg;
105: break;
106:
107: case 'j': /* job id */
108: jflag = 1;
109: break;
110:
111: /*
112: * send notification to local user
113: */
114: case 'm':
115: (void) strcat(Optns, "m");
116: break;
117:
118: /*
119: * send notification to user on remote
120: * if no user specified do not send notification
121: */
122: case 'n':
123: (void) strcat(Optns, "n");
124: (void) sprintf(Nuser, "%.8s", optarg);
125: (void) sprintf(Uopts+strlen(Uopts), "-n%s ", Nuser);
126: break;
127:
128: /*
129: * create JCL files but do not start uucico
130: */
131: case 'r':
132: Ropt = "-r";
133: break;
134:
135: /*
136: * return status file
137: */
138: case 's':
139: fopt = optarg;
140: /* "m" needed for compatability */
141: (void) strcat(Optns, "mo");
142: break;
143:
144: /*
145: * turn on debugging
146: */
147: case 'x':
148: Debug = atoi(optarg);
149: if (Debug <= 0)
150: Debug = 1;
151: break;
152:
153: default:
154: printf("unknown flag %s\n", argv[1]);
155: break;
156: }
157: }
158: DEBUG(4, "\n\n** %s **\n", "START");
159: gwd(Wrkdir);
160: if (fopt) {
161: if (*fopt != '/')
162: (void) sprintf(Sfile, "%s/%s", Wrkdir, fopt);
163: else
164: (void) sprintf(Sfile, "%s", fopt);
165:
166: }
167: /*
168: * work in WORKSPACE directory
169: */
170: ret = chdir(WORKSPACE);
171: if (ret != 0) {
172: (void) fprintf(stderr, "No work directory - %s - get help\n",
173: WORKSPACE);
174: cleanup(-12);
175: }
176:
177: if (Nuser[0] == NULLCHAR)
178: (void) strcpy(Nuser, User);
179: (void) strcpy(Loginuser, User);
180: DEBUG(4, "UID %d, ", Uid);
181: DEBUG(4, "User %s\n", User);
182: if (argc - optind < 2) {
183: (void) fprintf(stderr, "usage uucp from ... to\n");
184: cleanup(-2);
185: }
186:
187: /*
188: * set up "to" system and file names
189: */
190:
191: split(argv[argc - 1], sys2, fwd2, file2);
192: if (*sys2 != NULLCHAR) {
193: if (versys(sys2, 0) != 0) {
194: (void) fprintf(stderr, "bad system: %s\n", sys2);
195: cleanup(-11);
196: }
197: }
198: else
199: (void) strcpy(sys2, Myname);
200:
201: (void) strncpy(Rmtname, sys2, MAXBASENAME);
202: Rmtname[MAXBASENAME] = NULLCHAR;
203:
204: DEBUG(9, "sys2: %s, ", sys2);
205: DEBUG(9, "fwd2: %s, ", fwd2);
206: DEBUG(9, "file2: %s\n", file2);
207:
208: /*
209: * if there are more than 2 argsc, file2 is a directory
210: */
211: if (argc - optind > 2)
212: (void) strcat(file2, "/");
213:
214: /*
215: * do each from argument
216: */
217:
218: for ( ; optind < argc - 1; optind++) {
219: split(argv[optind], sys1, fwd1, file1);
220: if (*sys1 != NULLCHAR) {
221: if (versys(sys1, 0) != 0) {
222: (void) fprintf(stderr, "bad system: %s\n", sys1);
223: cleanup(-11);
224: }
225: }
226:
227: /* source files can have at most one ! */
228: if (*fwd1 != NULLCHAR) {
229: /* syntax error */
230: (void) fprintf(stderr, "illegal syntax %s\n", argv[optind]);
231: exit(2);
232: }
233:
234: /*
235: * check for required remote expansion of file names -- generate
236: * and execute a uux command
237: * e.g.
238: * uucp owl!~/dan/* ~/dan/
239: *
240: * NOTE: The source file part must be full path name.
241: * If ~ it will be expanded locally - it assumes the remote
242: * names are the same.
243: */
244:
245: if (*sys1 != NULLCHAR)
246: if ((strchr(file1, '*') != NULL
247: || strchr(file1, '?') != NULL
248: || strchr(file1, '[') != NULL)) {
249: /* do a uux command */
250: if (ckexpf(file1) == FAIL)
251: exit(6);
252: ruux(sys1, sys1, file1, sys2, fwd2, file2);
253: continue;
254: }
255:
256: /*
257: * check for forwarding -- generate and execute a uux command
258: * e.g.
259: * uucp uucp.c raven!owl!~/dan/
260: */
261:
262: if (*fwd2 != NULLCHAR) {
263: ruux(sys2, sys1, file1, "", fwd2, file2);
264: continue;
265: }
266:
267: /*
268: * check for both source and destination on other systems --
269: * generate and execute a uux command
270: */
271:
272: if (*sys1 != NULLCHAR )
273: if ( (!EQUALS(Myname, sys1))
274: && *sys2 != NULLCHAR
275: && (!EQUALS(sys2, Myname)) ) {
276: ruux(sys2, sys1, file1, "", fwd2, file2);
277: continue;
278: }
279:
280:
281: if (*sys1 == NULLCHAR)
282: (void) strcpy(sys1, Myname);
283: else {
284: (void) strncpy(Rmtname, sys1, MAXBASENAME);
285: Rmtname[MAXBASENAME] = NULLCHAR;
286: }
287:
288: DEBUG(4, "sys1 - %s, ", sys1);
289: DEBUG(4, "file1 - %s, ", file1);
290: DEBUG(4, "Rmtname - %s\n", Rmtname);
291: if (copy(sys1, file1, sys2, file2))
292: errors++;
293: }
294:
295: /* move the work files to their proper places */
296: commitall();
297:
298: /*
299: * do not spawn daemon if -r option specified
300: */
301: #ifndef V7
302: limit = ulimit(1, dummy);
303: #endif V7
304: if (*Ropt != '-')
305: #ifndef V7
306: if (limit < MINULIMIT) {
307: (void) sprintf(msg,
308: "ULIMIT (%ld) < MINULIMIT (%ld)", limit, MINULIMIT);
309: logent(msg, "Low-ULIMIT");
310: }
311: else
312: #endif
313: xuucico(Rmtname);
314: if (jflag)
315: printf("%s\n", Jobid);
316: cleanup(errors);
317: }
318:
319: /*
320: * cleanup lock files before exiting
321: */
322: cleanup(code)
323: register int code;
324: {
325: rmlock(CNULL);
326: if (code != 0)
327: wfabort(); /* this may be extreme -- abort all work */
328: if (code < 0) {
329: (void) fprintf(stderr, "uucp failed completely (%d)\n", (-code));
330: exit(-code);
331: }
332: else if (code > 0) {
333: (void) fprintf(stderr,
334: "uucp failed partially: %d file(s) sent; %d error(s)\n ",
335: _Transfer, code);
336: exit(code);
337: }
338: exit(code);
339: }
340:
341: /*
342: * generate copy files for s1!f1 -> s2!f2
343: * Note: only one remote machine, other situations
344: * have been taken care of in main.
345: * return:
346: * 0 -> success
347: * Non-zero -> failure
348: */
349:
350: copy(s1, f1, s2, f2)
351: char *s1, *f1, *s2, *f2;
352: {
353: FILE *cfp, *syscfile();
354: struct stat stbuf, stbuf1;
355: int type, statret;
356: char dfile[NAMESIZE];
357: char cfile[NAMESIZE];
358: char file1[MAXFULLNAME], file2[MAXFULLNAME];
359: char msg[BUFSIZ];
360:
361: type = 0;
362: (void) strcpy(file1, f1);
363: (void) strcpy(file2, f2);
364: if (!EQUALS(s1, Myname))
365: type = 1;
366: if (!EQUALS(s2, Myname))
367: type = 2;
368:
369: switch (type) {
370: case 0:
371:
372: /*
373: * all work here
374: */
375: DEBUG(4, "all work here %d\n", type);
376:
377: /*
378: * check access control permissions
379: */
380: if (ckexpf(file1))
381: return(-6);
382: if (ckexpf(file2))
383: return(-7);
384: if (uidstat(file1, &stbuf) != 0) {
385: (void) fprintf(stderr,
386: "can't get file status %s\n copy failed\n", file1);
387: return(8);
388: }
389: statret = uidstat(file2, &stbuf1);
390: if (statret == 0
391: && stbuf.st_ino == stbuf1.st_ino
392: && stbuf.st_dev == stbuf1.st_dev) {
393: (void) fprintf(stderr,
394: "%s %s - same file; can't copy\n", file1, file2);
395: return(5);
396: }
397: if (chkperm(file1, file2, strchr(Optns, 'd')) ) {
398: (void) fprintf(stderr, "permission denied\n");
399: cleanup(1);
400: }
401: if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
402: (void) fprintf(stderr, "directory name illegal - %s\n",
403: file1);
404: return(9);
405: }
406: /* see if I can read this file as read uid, gid */
407: if ( !(stbuf.st_mode & ANYREAD)
408: && !(stbuf.st_uid == Uid && stbuf.st_mode & 0400)
409: && !(stbuf.st_gid == getgid() && stbuf.st_mode & 0040)
410: ) {
411: (void) fprintf(stderr,
412: "uucp can't read (%s) mode (%o)\n",
413: file1, stbuf.st_mode);
414: (void) fprintf(stderr, "use cp command\n");
415: return(3);
416: }
417: if (statret == 0 && (stbuf1.st_mode & ANYWRITE) == 0) {
418: (void) fprintf(stderr,
419: "can't write file (%s) mode (%o)\n",
420: file2, stbuf1.st_mode);
421: return(4);
422: }
423:
424: /*
425: * copy file locally
426: */
427: DEBUG(2, "local copy: uidxcp(%s, ", file1);
428: DEBUG(2, "%s\n", file2);
429:
430: /* do copy as Uid, but the file will be owned by uucp */
431: if (uidxcp(file1, file2) == FAIL) {
432: (void) fprintf(stderr,
433: "can't copy file (%s) errno %d\n", file2, errno);
434: return(5);
435: }
436: (void) chmod(file2, (int) (stbuf.st_mode | 0666));
437: return(0);
438: case 1:
439:
440: /*
441: * receive file
442: */
443: DEBUG(4, "receive file - %d\n", type);
444:
445: /*
446: * expand source and destination file names
447: * and check access permissions
448: */
449: if (file1[0] != '~')
450: if (ckexpf(file1))
451: return(6);
452: if (ckexpf(file2))
453: return(7);
454:
455: /*
456: * insert JCL card in file
457: */
458: cfp = syscfile(cfile, s1);
459: (void) fprintf(cfp,
460: "R %s %s %s %s %s %o %s\n", file1, file2,
461: User, Optns,
462: *Sfile ? Sfile : "dummy",
463: 0777, Nuser);
464: (void) fclose(cfp);
465: (void) sprintf(msg, "%s!%s --> %s!%s", Rmtname, file1,
466: Myname, file2);
467: logent(msg, "QUEUED");
468: break;
469: case 2:
470:
471: /*
472: * send file
473: */
474: if (ckexpf(file1))
475: return(6);
476: /* XQTDIR hook enables 3rd party uux requests (cough) */
477: if (file2[0] != '~' && !EQUALS(Wrkdir, XQTDIR))
478: if (ckexpf(file2))
479: return(7);
480: DEBUG(4, "send file - %d\n", type);
481:
482: if (uidstat(file1, &stbuf) != 0) {
483: (void) fprintf(stderr,
484: "can't get status for file %s\n", file1);
485: return(8);
486: }
487: if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
488: (void) fprintf(stderr,
489: "directory name illegal - %s\n", file1);
490: return(9);
491: }
492:
493: /*
494: * make a copy of file in spool directory
495: */
496: if (Copy || !READANY(file1) ) {
497: gename(DATAPRE, s2, Grade, dfile);
498:
499: if (uidxcp(file1, dfile))
500: return(5);
501:
502: (void) chmod(dfile, DFILEMODE);
503: wfcommit(dfile, dfile, s2);
504: } else {
505:
506: /*
507: * make a dummy D. name
508: * cntrl.c knows names < 6 chars are dummy D. files
509: */
510: (void) strcpy(dfile, "D.0");
511: }
512:
513: /*
514: * insert JCL card in file
515: */
516: cfp = syscfile(cfile, s2);
517: (void) fprintf(cfp, "S %s %s %s %s %s %o %s %s\n",
518: file1, file2, User, Optns, dfile,
519: stbuf.st_mode & 0777, Nuser, Sfile);
520: (void) fclose(cfp);
521: (void) sprintf(msg, "%s!%s --> %s!%s", Myname, file1,
522: Rmtname, file2);
523: logent(msg, "QUEUED");
524: break;
525: }
526: _Transfer++;
527: return(0);
528: }
529:
530:
531: /*
532: * syscfile(file, sys)
533: * char *file, *sys;
534: *
535: * get the cfile for system sys (creat if need be)
536: * return stream pointer
537: *
538: * returns
539: * stream pointer to open cfile
540: *
541: */
542:
543: static FILE *
544: syscfile(file, sys)
545: char *file, *sys;
546: {
547: FILE *cfp;
548:
549: if (gtcfile(file, sys) == FAIL) {
550: gename(CMDPRE, sys, Grade, file);
551: ASSERT(access(file, 0) != 0, Fl_EXISTS, file, errno);
552: cfp = fdopen(creat(file, CFILEMODE), "w");
553: svcfile(file, sys);
554: } else
555: cfp = fopen(file, "a");
556: /* set Jobid -- C.jobid */
557: (void) strncpy(Jobid, BASENAME(file, '.'), NAMESIZE);
558: Jobid[NAMESIZE-1] = '\0';
559: ASSERT(cfp != NULL, Ct_OPEN, file, errno);
560: return(cfp);
561: }
562:
563:
564: /*
565: * split - split the name into parts:
566: * sys - system name
567: * fwd - intermediate destinations
568: * file - file part
569: */
570:
571: static
572: void
573: split(arg, sys, fwd, file)
574: char *arg, *sys, *fwd, *file;
575: {
576: register char *cl, *cr, *n;
577: *sys = *fwd = *file = NULLCHAR;
578:
579: for (n=arg ;; n=cl+1) {
580: cl = strchr(n, '!');
581: if ( cl == NULL) {
582: /* no ! in n */
583: (void) strcpy(file, n);
584: return;
585: }
586:
587: if (PREFIX(Myname, n))
588: continue;
589:
590: cr = strrchr(n, '!');
591: (void) strcpy(file, cr+1);
592: (void) strncpy(sys, n, cl-n);
593: sys[cl-n] = NULLCHAR;
594:
595: if (cr != cl) {
596: /* more than one ! */
597: (void) strncpy(fwd, cl+1, cr-cl-1);
598: fwd[cr-cl-1] = NULLCHAR;
599: }
600: return;
601: }
602: /*NOTREACHED*/
603: }
604:
605:
606: /*
607: * generate and execute a uux command
608: */
609:
610: ruux(rmt, sys1, file1, sys2, fwd2, file2)
611: char *rmt, *sys1, *file1, *sys2, *fwd2, *file2;
612: {
613: char cmd[BUFSIZ];
614:
615: if (*Uopts != NULLCHAR)
616: (void) sprintf(cmd, "uux -C %s %s!uucp -C \\(%s\\) ", Ropt, rmt, Uopts);
617: else
618: (void) sprintf(cmd, "uux -C %s %s!uucp -C ", Ropt, rmt);
619:
620: if (*sys1 == NULLCHAR || EQUALS(sys1, Myname)) {
621: if (ckexpf(file1))
622: exit(6);
623: (void) sprintf(cmd+strlen(cmd), " %s!%s ", sys1, file1);
624: }
625: else
626: if (!EQUALS(rmt, sys1))
627: (void) sprintf(cmd+strlen(cmd), " \\(%s!%s\\) ", sys1, file1);
628: else
629: (void) sprintf(cmd+strlen(cmd), " \\(%s\\) ", file1);
630:
631: if (*fwd2 != NULLCHAR) {
632: if (*sys2 != NULLCHAR)
633: (void) sprintf(cmd+strlen(cmd),
634: " \\(%s!%s!%s\\) ", sys2, fwd2, file2);
635: else
636: (void) sprintf(cmd+strlen(cmd), " \\(%s!%s\\) ", fwd2, file2);
637: }
638: else {
639: if (*sys2 == NULLCHAR || EQUALS(sys2, Myname))
640: if (ckexpf(file2))
641: exit(7);
642: (void) sprintf(cmd+strlen(cmd), " \\(%s!%s\\) ", sys2, file2);
643: }
644:
645: DEBUG(2, "cmd: %s\n", cmd);
646: logent(cmd, "QUEUED");
647: system(cmd);
648: return;
649: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.