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