|
|
1.1 root 1: /* @(#)uucleanup.c 1.6
2:
3: * uucleanup - This is a program based on the heuristics
4: * by Brian Redman for cleaning up and doing something
5: * useful with old files left in the uucp queues.
6: * It also will send warning messags to users where requests are not
7: * going out due to failure to contact the remote system.
8: *
9: * This program knows a lot about the construction and
10: * contents of the C., D. and X. files. In addition, it
11: * thinks it knows what mail and netnews data files look like.
12: *
13: * At present, this is what is done:
14: * For WARNING messages:
15: * C. files of age given by -W option are read, looking for
16: * either user files to be sent or received, or
17: * mail to be sent. (Other remote execution that
18: * does not involve sending user files is not checked
19: * for now.) In either of the cases, the user is
20: * informed by mail that the request is not being
21: * processed due to lack of communications with the remote
22: * system, and the request will be deleted in the future
23: * if it the condition remains for several more days.
24: *
25: * For DELETIONS:
26: * C. files - if they reference only D. files, the C. is
27: * merely deleted, because the D. files are usually
28: * mail or news, and the later D. processing will
29: * take care of them.
30: * - if they reference files from the file system,
31: * a message is constructed that will contain a
32: * lines like
33: * We can't contact the remote.
34: *
35: * local!file -> remote!otherfile
36: *
37: * can't be executed.
38: * X. files - merely deleted at present - D.s will be taken
39: * care of later. Besides, some of the D.s are
40: * missing or else the X. wouldn't be left around.
41: * D. files - mail type data is sent to a local person if that
42: * is where it originated. If not, it is returned to the
43: * sender -- assumed to be from the first From line. If
44: * a sender can't be determing, the file is merely deleted.
45: * - rnews: if locally generated, just delete. If remote,
46: * the X. got lost, so execute rnews.
47: * other files - just delete them.
48: *
49: * Deletions and executions are logged in
50: * (CLEANUPLOG)--/usr/spool/uucp/.Admin/uucleanup
51: */
52:
53: #include "uucp.h"
54: VERSION(@(#)uucleanup.c 1.6);
55:
56: #ifdef V7
57: #define O_RDONLY 0
58: #endif
59:
60: #define USAGE "[-oDAYS] [-mSTRING] [-Cdays] [-Ddays] [-Wdays] [-Xdays] [-xLEVEL] [-sSYSTEM]"
61:
62: extern int _age(); /* find the age of a file */
63: extern void oprocess(), xprocess(), cprocess();
64: extern void dXprocess(), dNprocess(), dMprocess(), dDprocess(), wprocess();
65: extern int toWho(), sendMail(), execRnews();
66: extern void logit();
67:
68: /* need these dummys to satisy some .o files */
69: cleanup(){}
70: void systat(){}
71: void logent(){}
72:
73:
74: /* types of D. files */
75: #define D_MAIL 1
76: #define D_NEWS 2
77: #define D_XFILE 3
78: #define D_DATA 4
79: #define FULLNAME(full,dir,file) (void) sprintf(full, "%s/%s", dir, file);
80:
81: int _Ddays = 7; /* D. limit */
82: int _Cdays = 7; /* C. limit */
83: int _Xdays = 2; /* X. limit */
84: int _Odays = 2; /* O. limit */
85: int _Wdays = 1; /* Warning limit for C. files */
86: char _ShortLocal[6]; /* 5 char or less version of local name */
87:
88: char *_Undeliverable[] = {
89: "Subject: Undeliverable Mail\n",
90: "This mail message is undeliverable.\n",
91: "(Probably to or from system '%s')\n",
92: "It was sent to you or by you.\n",
93: "Sorry for the inconvenience.\n",
94: "",
95: };
96:
97: #define CANT1 2 /* first line to fill in */
98: #define CANT2 3 /* second line to fill in */
99: char *_CantContact[] = {
100: "Subject: Job Killed By uucp\n",
101: "We can't contact machine '%s'.\n",
102: " ", /* uucleanup will fill in variable text here */
103: " ", /* fill in jobid of killed job */
104: "",
105: };
106:
107: #define WARN1 2
108: #define WARN2 5
109: #define WARN3 6
110: char *_Warning[] = {
111: "Subject: Warning From uucp\n",
112: "We have been unable to contact machine '%s' since you queued your job.\n",
113: " ", /* wprocess FILLS IN THIS LINE OF TEXT */
114: "The job will be deleted in several days if the problem is not corrected.\n",
115: "If you care to kill the job, execute the following command:\n",
116: " ", /* wprocess FILLS IN THIS LINE WITH: uustat -kJOBid */
117: " ", /* FILL IN THE -m STRING IF SPECIFIED */
118: "",
119: };
120:
121: main(argc, argv, envp)
122: char *argv[];
123: char **envp;
124: {
125: DIR *spooldir, *subdir;
126: char f[MAXFULLNAME], subf[MAXFULLNAME];
127: char fullname[MAXFULLNAME];
128: int pass = 0; /* pass counter - multi passes through directory */
129: char soptName[MAXFULLNAME]; /* name from -s option */
130: int i, value;
131:
132: soptName[0] = NULLCHAR;
133: (void) strcpy(Logfile, CLEANUPLOGFILE);
134: uucpname(Myname);
135: (void) strncpy(_ShortLocal, Myname, 5);
136: _ShortLocal[5] = NULLCHAR;
137: (void) strcpy(Progname, "uucleanup");
138: while ((i = getopt(argc, argv, "C:D:W:X:m:o:s:x:")) != EOF) {
139: switch(i){
140: case 's': /* for debugging - choose system */
141: (void) strcpy(soptName, optarg);
142: break;
143: case 'x':
144: Debug = atoi(optarg);
145: if (Debug <= 0)
146: Debug = 1;
147: break;
148: case 'm':
149: _Warning[WARN3] = optarg;
150: break;
151: default:
152: (void) fprintf(stderr, "\tusage: %s %s\n",
153: Progname, USAGE);
154: exit(1);
155:
156: case 'C':
157: case 'D':
158: case 'W':
159: case 'X':
160: case 'o':
161: value = atoi(optarg);
162: if (value < 1) {
163: fprintf(stderr," Options: CDWXo require value > 0\n");
164: exit(1);
165: }
166: switch(i) {
167: case 'C':
168: _Cdays = value;
169: break;
170: case 'D':
171: _Ddays = value;
172: break;
173: case 'W':
174: _Wdays = value;
175: break;
176: case 'X':
177: _Xdays = value;
178: break;
179: case 'o':
180: _Odays = value;
181: break;
182: }
183: break;
184: }
185: }
186:
187: if (argc != optind) {
188: (void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE);
189: exit(1);
190: }
191:
192: DEBUG(5, "Progname (%s): STARTED\n", Progname);
193: DEBUG(5, "Myname (%s), ", Myname);
194: DEBUG(5, "_ShortLocal (%s)\n", _ShortLocal);
195: DEBUG(5, "Days C.(%d), ", _Cdays);
196: DEBUG(5, "D.(%d), ", _Ddays);
197: DEBUG(5, "W.(%d), ", _Wdays);
198: DEBUG(5, "X.(%d), ", _Xdays);
199: DEBUG(5, "other (%d)\n", _Odays);
200:
201: if (chdir(SPOOL) != 0) {
202: (void) fprintf(stderr, "CAN'T CHDIR (%s): errno (%d)\n",
203: SPOOL, errno);
204: exit(1);
205: }
206: if ( (spooldir = opendir(SPOOL)) == NULL) {
207: (void) fprintf(stderr, "CAN'T OPEN (%s): errno (%d)\n",
208: SPOOL, errno);
209: exit(1);
210: }
211:
212: while (gnamef(spooldir, f) == TRUE) {
213: if (EQUALSN("LCK..", f, 5))
214: continue;
215:
216: if (*soptName && !EQUALS(soptName, f))
217: continue;
218:
219: if (DIRECTORY(f)) {
220: (void) strcpy(Rmtname, f);
221: pass = 0;
222: /*
223: * pass 1 - process old C. and X. files
224: * pass 2 - process D.s that are going to X.
225: * pass 3 - processs D. mail and netnews and other D.s
226: * pass 4 - process other
227: */
228: while ( (++pass < 5) && (subdir = opendir(f)) ) {
229: DEBUG(7, "Directory: %s\n", f);
230: while (gnamef(subdir, subf) == TRUE) {
231: DEBUG(9, "file: %s\n", subf);
232: FULLNAME(fullname, f, subf);
233: switch (pass) {
234: case 1:
235: if (EQUALSN(subf, "C.", 2)
236: && _age(fullname) >=_Cdays)
237: cprocess(fullname);
238: else if (EQUALSN(subf, "C.", 2)
239: && _age(fullname) ==_Wdays)
240: wprocess(f, subf);
241: else if (EQUALSN(subf, "X.", 2)
242: && _age(fullname) >=_Xdays)
243: xprocess(fullname);
244: break;
245:
246: case 2: /* pass 2 */
247: if (EQUALSN(subf, "D.", 2)
248: && _age(fullname) >= _Ddays
249: && dType(fullname) == D_XFILE)
250: dXprocess(fullname);
251: break;
252:
253: case 3: /* pass 3 */
254: if (EQUALSN(subf, "D.", 2)
255: && _age(fullname) >= _Ddays)
256: switch (dType(fullname)) {
257: case D_MAIL:
258: dMprocess(f, subf);
259: break;
260: case D_NEWS:
261: dNprocess(f, subf);
262: break;
263: case D_DATA:
264: dDprocess(fullname);
265: break;
266: default: /* do nothing */
267: break;
268: }
269: break;
270: case 4:
271: if ( _age(fullname) >= _Odays
272: && !EQUALSN(subf, "C.", 2)
273: && !EQUALSN(subf, "D.", 2)
274: && !EQUALSN(subf, "X.", 2) )
275: oprocess(fullname);
276: break;
277: }
278: }
279: closedir(subdir);
280: }
281: }
282: }
283: exit(0);
284: }
285:
286: /* xprocess - X. file processing -- just remove the X. for now */
287:
288: void
289: xprocess(fullname)
290: char *fullname;
291: {
292: char text[BUFSIZ];
293:
294: DEBUG(5, "xprocess(%s), ", fullname);
295: DEBUG(5, "unlink(%s)\n", fullname);
296: (void) sprintf(text, "xprocess: unlink(%s)", fullname);
297: errno = 0;
298: (void) unlink(fullname);
299: logit(text, errno);
300: }
301:
302: /*
303: * cprocess - Process old C. files
304: *
305: */
306:
307: #define CMFMT "\n\t%s!%s -> %s!%s (Date %2.2d/%2.2d)\n\nCan't be executed."
308: #define XFMT "\n\t%s!%s (Date %2.2d/%2.2d)\n"
309: #define WFMT "\n\t%s!%s -> %s!%s (Date %2.2d/%2.2d)\n"
310: void
311: cprocess(fullname)
312: char *fullname;
313: {
314: struct stat s;
315: register struct tm *tp;
316: char buf[BUFSIZ], user[9];
317: char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
318: char text[BUFSIZ], text1[BUFSIZ], text2[BUFSIZ];
319: FILE *fp;
320: int ret;
321:
322: DEBUG(5, "cprocess(%s)\n", fullname);
323:
324:
325: fp = fopen(fullname, "r");
326: if (fp == NULL) {
327: DEBUG(5, "Can't open file (%s), ", fullname);
328: DEBUG(5, "errno=%d -- skip it!\n", errno);
329: return;
330: }
331: if (fstat(fileno(fp), &s) != 0) {
332: /* can't happen; _age() did stat of this file and file is opened */
333: (void) fclose(fp);
334: return;
335: }
336: tp = localtime(&s.st_mtime);
337:
338: if (s.st_size == 0) { /* dummy C. for polling */
339: DEBUG(5, "dummy C. -- unlink(%s)\n", fullname);
340: (void) sprintf(text, "dDprocess: dummy C. unlinked(%s)",
341: fullname);
342: errno = 0;
343: (void) unlink(fullname);
344: logit(text, errno);
345: (void) fclose(fp);
346: return;
347: }
348:
349: /* Read the C. file and process it */
350: while (fgets(buf, BUFSIZ, fp) != NULL) {
351: buf[strlen(buf)-1] = NULLCHAR; /* remove \n */
352: if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
353: user, opt, file3) <5) {
354: (void) sprintf(text, "cprocess: Bad C. %s, unlink(%s)",
355: buf, fullname);
356: break;
357: }
358:
359: *text = NULLCHAR;
360: ret = 0;
361: /* fill in line 3 of text */
362: (void) sprintf(text2, "Job (%s) killed!\n",
363: BASENAME(fullname, '/')+2);
364: _CantContact[CANT2] = text2;
365: if (*type == 'S') {
366: if (EQUALSN(file1, "D.", 2))
367: /* generated file (mail/news) I think */
368: /* D. processing will return it later */
369: continue;
370:
371: /* some data was requested -- tell user */
372:
373: (void) sprintf(text1, CMFMT, Myname, file1, Rmtname, file2,
374: tp->tm_mon + 1, tp->tm_mday);
375: _CantContact[CANT1] = text1;
376: ret = sendMail((char *) NULL, user, "", _CantContact);
377: }
378: else if (*type == 'R') {
379: (void) sprintf(text1, CMFMT, Rmtname, file1, Myname, file2,
380: tp->tm_mon + 1, tp->tm_mday);
381: _CantContact[CANT1] = text1;
382: ret = sendMail((char *) NULL, user, "", _CantContact);
383: }
384: }
385:
386: if (!*text) {
387: (void) sprintf(text,
388: "cprocess: C. %s, mail returned (%d), unlink(%s)",
389: buf, ret, fullname);
390: }
391: DEBUG(3, "text (%s)\n", text);
392:
393: errno = 0;
394: (void) unlink(fullname);
395: logit(text, errno);
396:
397: (void) fclose(fp);
398: return;
399: }
400:
401: /*
402: * wprocess - send warning messages for C. == Wdays
403: */
404:
405: void
406: wprocess(dir, file)
407: char *dir, *file;
408: {
409: struct stat s;
410: register struct tm *tp;
411: char fullname[BUFSIZ], xfile[BUFSIZ], xF_file[BUFSIZ];
412: char buf[BUFSIZ], user[BUFSIZ];
413: char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
414: char text[BUFSIZ], text1[BUFSIZ], text2[BUFSIZ];
415: char *realuser, uline_m[NAMESIZE], uline_u[BUFSIZ], retaddr[BUFSIZ];
416: FILE *fp, *xfp;
417: int ret;
418:
419: FULLNAME(fullname, dir, file);
420: DEBUG(5, "wprocess(%s)\n", fullname);
421:
422: fp = fopen(fullname, "r");
423: if (fp == NULL) {
424: DEBUG(4, "Can't open file (%s), ", fullname);
425: DEBUG(4, "errno=%d -- skip it!\n", errno);
426: return;
427: }
428: if (fstat(fileno(fp), &s) != 0) {
429: /* can't happen; _age() did stat of this file and file is opened */
430: (void) fclose(fp);
431: return;
432: }
433: tp = localtime(&s.st_mtime);
434:
435: if (s.st_size == 0) { /* dummy C. for polling */
436: DEBUG(5, "dummy C. -- skip(%s)\n", fullname);
437: (void) fclose(fp);
438: return;
439: }
440:
441: /* read C. and process it */
442: while (fgets(buf, BUFSIZ, fp) != NULL) {
443: buf[strlen(buf)-1] = NULLCHAR; /* remove \n */
444: if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
445: user, opt, file3) <5) {
446: DEBUG(5, "short line (%s): ", buf);
447: DEBUG(5, "bad D. -- skip(%s)\n", fullname);
448: (void) fclose(fp);
449: return;
450: }
451:
452: /* set up the 6th text line of the mail message */
453: (void) sprintf(text2,
454: "\n\tuustat -k%s\n", BASENAME(fullname, '/')+2);
455:
456: _Warning[WARN2] = text2;
457: if (*type == 'S') { /* Send type C. file processing */
458: if (EQUALSN(file2, "X.", 2)) {
459: /* this is a uux job - tell user about it */
460: FULLNAME(xfile, dir, file1);
461: if ( (xfp = fopen(xfile, "r")) == NULL) {
462: /* Can't read X. file ??? - just skip */
463: DEBUG(3, "Can't read %s\n", xfile);
464: break;
465: }
466: *retaddr = *uline_u = *uline_m = *text = NULLCHAR;
467: while (fgets(buf, BUFSIZ, xfp) != NULL) {
468: buf[strlen(buf)-1] = NULLCHAR; /* remove \n */
469: switch(*buf) {
470: case 'F': /* save the file name */
471: FULLNAME(xF_file, dir, &buf[2]);
472: break;
473: case 'R': /* save return address */
474: sscanf(buf+2, "%s", retaddr);
475: DEBUG(7, "retaddr (%s)\n", retaddr);
476: break;
477: case 'U': /* save machine, user */
478: sscanf(buf+2, "%s%s", uline_u, uline_m);
479: break;
480: }
481: if (buf[0] != 'C')
482: continue;
483: realuser = uline_u;
484: if (*retaddr != NULLCHAR)
485: realuser = retaddr;
486: if (*realuser == NULLCHAR)
487: strcpy(realuser, user);
488: if (!EQUALS(uline_m, Myname))
489: sprintf(user, "%s!%s", uline_m, realuser);
490: else
491: strcpy(user, realuser);
492:
493: (void) sprintf(text1, XFMT, Rmtname,
494: EQUALSN(&buf[2], "rmail", 5) ? &buf[3] : &buf[2],
495: tp->tm_mon + 1, tp->tm_mday);
496: _Warning[WARN1] = text1;
497: if (EQUALSN(&buf[2], "rmail", 5) )
498: /* this is mail; append user mail (xF_file) */
499: ret = sendMail((char *) NULL, user, xF_file, _Warning);
500: else
501: ret = sendMail((char *) NULL, user, "", _Warning);
502: break;
503: }
504: (void) fclose(xfp);
505: break;
506: }
507:
508: if (EQUALSN(file1, "D.", 2))
509: /* generated file (mail/news) I think */
510: /* D. processing will return it later */
511: continue;
512:
513: /* some data was requested -- tell user */
514:
515: /* set up the 2nd text line of the mail message */
516: (void) sprintf(text1, WFMT, Myname, file1, Rmtname, file2,
517: tp->tm_mon + 1, tp->tm_mday);
518: _Warning[WARN1] = text1;
519: ret = sendMail((char *) NULL, user, "", _Warning);
520: }
521:
522: else if (*type == 'R') { /* Receive C. file processing */
523: if (EQUALSN(file1, "D.", 2) && EQUALSN(file2, "D.", 2))
524: continue;
525: (void) sprintf(text1, WFMT, Rmtname, file1, Myname, file2,
526: tp->tm_mon + 1, tp->tm_mday);
527: _Warning[WARN1] = text1;
528: ret = sendMail((char *) NULL, user, "", _Warning);
529: }
530: } /* end while - read C. lines loop */
531:
532: (void) sprintf(text,
533: "wprocess: %s: %s, warning message sent to %s, returned (%d)",
534: fullname, buf, user, ret);
535: DEBUG(3, "text (%s)\n", text);
536:
537: logit(text, errno);
538:
539: (void) fclose(fp);
540: return;
541: }
542: /*
543: * oprocess - some unknown file just remove the file
544: */
545:
546: void
547: oprocess(fullname)
548: char *fullname;
549: {
550:
551: char text[BUFSIZ];
552:
553: DEBUG(5, "oprocess(%s), ", fullname);
554: DEBUG(5, "unlink(%s)\n", fullname);
555: (void) sprintf(text, "oprocess: unlink(%s)", fullname);
556: errno = 0;
557: (void) unlink(fullname);
558: logit(text, errno);
559: }
560:
561: /*
562: * dDprocess - random D. file (not mail or rnews)
563: *--just delete it for now
564: */
565:
566: void
567: dDprocess(fullname)
568: char *fullname;
569: {
570: char text[BUFSIZ];
571:
572: DEBUG(5, "dDprocess(%s), ", fullname);
573: DEBUG(5, "unlink(%s)\n", fullname);
574: (void) sprintf(text, "dDprocess: unlink(%s)", fullname);
575: errno = 0;
576: (void) unlink(fullname);
577: logit(text, errno);
578: }
579:
580: /*
581: * dXprocess - process D. files that are destined for X. on remote
582: * --for now just delete it
583: */
584:
585: void
586: dXprocess(fullname)
587: char *fullname;
588: {
589: char text[BUFSIZ];
590:
591: DEBUG(5, "dXprocess(%s), ", fullname);
592: DEBUG(5, " unlink(%s)\n", fullname);
593: (void) sprintf(text, "dXprocess: unlink(%s)", fullname);
594: errno = 0;
595: (void) unlink(fullname);
596: logit(text, errno);
597: }
598:
599: /*
600: * dMprocess - process ophan D. mail files
601: * There are two types: ones generated locally and
602: * others that are from remotes. They can be identified
603: * by the system name following the D.
604: * Local ones have the local name.
605: */
606:
607: void
608: dMprocess(dir, file)
609: char *dir, *file;
610: {
611: int ret;
612: char fullname[MAXFULLNAME];
613: char *toUser, *toSystem;
614: char text[BUFSIZ];
615:
616: (void) sprintf(fullname, "%s/%s", dir, file);
617: DEBUG(5, "dMprocess(%s)\n", fullname);
618:
619:
620: if (PREFIX(_ShortLocal, &file[2])) {
621: DEBUG(5, " Local file %s: ", file);
622: }
623: else {
624: DEBUG(5, " Remote file %s: ", file);
625: }
626: if (toWho(fullname, &toUser, &toSystem)) {
627: DEBUG(5, "toUser %s, ", toUser);
628: DEBUG(5, "toSystem %s ", toSystem);
629: ret = sendMail(toSystem, toUser, fullname, _Undeliverable);
630: DEBUG(5, "Mail sent, unlink(%s)\n", fullname);
631: (void) sprintf(text,
632: "dMprocess: mail %s to %s!%s, returned (%d), unlink(%s)",
633: fullname, toSystem, toUser, ret, fullname);
634: errno = 0;
635: (void) unlink(fullname);
636: logit(text, errno);
637: }
638: }
639:
640: /*
641: * dNprocess - process ophan D. netnews files
642: * There are two types: ones generated locally and
643: * others that are from remotes. They can be identified
644: * by the system name following the D.
645: * Local ones have the local name.
646: */
647:
648: void
649: dNprocess(dir, file)
650: char *dir, *file;
651: {
652: char fullname[MAXFULLNAME];
653: char text[BUFSIZ];
654: int ret;
655:
656: (void) sprintf(fullname, "%s/%s", dir, file);
657: DEBUG(5, "dNprocess(%s)\n", fullname);
658:
659:
660: if (PREFIX(_ShortLocal, &file[2])) {
661: /* just delete it, the C. is gone */
662: DEBUG(5, " Local file %s, ", file);
663: DEBUG(5, "unlink(%s)\n", fullname);
664: (void) unlink(fullname);
665: (void) sprintf(text, "dNprocess: Local news item unlink(%s)",
666: fullname);
667: errno = 0;
668: (void) unlink(fullname);
669: logit(text, errno);
670: }
671: else {
672: /* execute rnews with this file - the X. is missing */
673: DEBUG(5, " Remote file %s, ", file);
674: DEBUG(5, "exec rnews(%s), ", fullname);
675: ret = execRnews(fullname);
676: DEBUG(5, "unlink(%s)\n", fullname);
677: (void) sprintf(text,
678: "dNprocess: Remote - exec rnews %s: returned (%d), unlink(%s)",
679: fullname, ret, fullname);
680: errno = 0;
681: (void) unlink(fullname);
682: logit(text, errno);
683: }
684:
685: }
686:
687:
688:
689: static long _sec_per_day = 86400L;
690:
691: /*
692: * _age - find the age of "file" in days
693: * return:
694: * age of file
695: * 0 - if stat fails
696: */
697:
698: int
699: _age(fullname)
700: char *fullname;
701: {
702: static time_t ptime = 0;
703: time_t time();
704: struct stat stbuf;
705:
706: if (!ptime)
707: (void) time(&ptime);
708: if (stat(fullname, &stbuf) != -1) {
709: return ((int)((ptime - stbuf.st_mtime)/_sec_per_day));
710: }
711: else
712: return(0);
713: }
714:
715: /*
716: * dType - return the type of D. file
717: * return:
718: * FAIL - can't read D. file
719: * D_MAIL - mail message D. file
720: * D_NEWS - netnews D. file
721: * D_DATA - other kind of D. file
722: * D_XFILE - destined for X. on destination machine
723: */
724:
725: /* NLINES - number of lines of D. file to read to determine type */
726: #define NLINES 10
727:
728: int
729: dType(fullname)
730: char *fullname;
731: {
732: char buf[BUFSIZ];
733: FILE *fp;
734: int i, type;
735:
736: fp = fopen(fullname, "r");
737: if (fp == NULL) {
738: DEBUG(4, "Can't open file (%s), ", fullname);
739: DEBUG(4, "errno=%d -- skip it!\n", errno);
740: return(FAIL);
741: }
742: type = D_DATA;
743:
744: /* read first NLINES lines to determine file type */
745: for (i=0; i<NLINES; i++) {
746: DEBUG(9, "buf: %s\n", buf);
747: if (fgets(buf, BUFSIZ, fp) == NULL)
748: break; /* no more lines */
749: if (EQUALSN(buf, "From ", 5)) {
750: type = D_MAIL;
751: break;
752: }
753: if (EQUALSN(buf, "U ", 2)) {
754: type = D_XFILE;
755: break;
756: }
757: if (EQUALSN(buf, "Newsgroups: ", 12)) {
758: type = D_NEWS;
759: break;
760: }
761: }
762:
763: (void) fclose(fp);
764: return(type);
765: }
766:
767: /*
768: * sendMail - send mail file and message to user (local or remote)
769: * return:
770: * the return from the pclose - mail exit status
771: */
772: static char *salute[] = {
773: "Frankly,",
774: "Honestly,",
775: "Candidly,",
776: "Guilelessly,",
777: "Purely,",
778: "Scrupulously,",
779: "Ingenuously,",
780: "Innocently,",
781: "Childishly,",
782: "Artlessly,",
783: "Bluntly,",
784: "Naively,",
785: "Sympathetically,",
786: "Sufferingly,",
787: "Enduringly,",
788: "Pathetically,",
789: "Gustily,",
790: "Heartily,",
791: "Warmly,",
792: "Passionately,",
793: "Profoundly,",
794: "Wistfully,",
795: "Rabidly,",
796: "Hysterically,",
797: "Impetously,",
798: "Feverishly,",
799: };
800:
801: sendMail(system, user, file, mtext)
802: char *system, *user, *file;
803: char *mtext[];
804: {
805: register FILE *fp, *fi;
806: char cmd[BUFSIZ];
807: static int rstart = 0;
808: long time();
809:
810: DEBUG(5, "Mail %s to ", file);
811: DEBUG(5, "%s\n", user);
812:
813: if (system != NULL && *system != '\0')
814: (void) sprintf(cmd, "%s mail %s!%s", PATH, system, user);
815: else
816: (void) sprintf(cmd, "%s mail %s", PATH, user);
817: DEBUG(7, "sendMail: %s\n", cmd);
818: if ((fp = popen(cmd, "w")) == NULL)
819: return(-errno);
820: while (*mtext[0] )
821: (void) fprintf(fp, *mtext++, Rmtname);
822:
823: if (rstart == 0) {
824: srand((int)time((long *)0));
825: rstart = 1;
826: }
827: (void) fprintf(fp, "\n\t%s\n\t%s!uucp\n",
828: salute[rand()%sizeof(salute)/sizeof(salute[0])], Myname);
829: if (*file) {
830: if ((fi= fopen(file, "r")) == NULL) /* never happen;I read once */
831: return(pclose(fp));
832: (void) fprintf(fp,
833: "##### Data File: ############################\n");
834: xfappend(fi, fp);
835: (void) fclose(fi);
836: }
837: return(pclose(fp));
838: }
839:
840: /*
841: * execRnews - execute rnews command with stdin file
842: * return:
843: * the return from the pclose - rnews exit status
844: */
845:
846: execRnews(file)
847: char *file;
848: {
849: register FILE *fp, *fi;
850: char cmd[BUFSIZ];
851:
852: DEBUG(5, "Rnews %s\n", file);
853:
854: (void) sprintf(cmd, "%s rnews ", PATH);
855: if ((fp = popen(cmd, "w")) == NULL)
856: return(-errno);
857:
858: if ( (fi = fopen(file, "r")) == NULL) /* never happen - I read once */
859: return(pclose(fp));
860: xfappend(fi, fp);
861: (void) fclose(fi);
862:
863: return(pclose(fp));
864: }
865:
866: /*
867: * toWho - figure out who to send this dead mail to
868: * It is a guess;
869: * If there is a local address, send it there.
870: * If not, send it back where it came from.
871: * return:
872: * 0 - could not find system and user information
873: * 1 - found it
874: */
875:
876: int
877: toWho(file, user, system)
878: char *file; /* the D. mail message file */
879: char **system; /* pointer to the system name */
880: char **user; /* pointer to the user name */
881: {
882: char buf[BUFSIZ];
883: FILE *fp;
884: int i;
885: static char fuser[BUFSIZ], fsystem[MAXBASENAME+1]; /* from first From */
886: static char luser[BUFSIZ], lsystem[MAXBASENAME+1]; /* from other From */
887:
888: *fuser = NULLCHAR;
889: DEBUG(5, "toWho(%s)\n", file);
890: fp = fopen(file, "r");
891: for (i=0; i<NLINES; i++) {
892: if (fgets(buf, BUFSIZ, fp) == NULL)
893: break; /* no more lines */
894: DEBUG(9, "buf: %s\n", buf);
895: if (!analFrom(buf, luser, lsystem))
896: continue;
897: if ( !*fuser) {
898: (void) strcpy(fuser, luser);
899: (void) strcpy(fsystem, lsystem);
900: }
901: if (EQUALS(Myname, lsystem)) {
902: *user = luser;
903: *system = lsystem;
904: (void) fclose(fp);
905: return(1);
906: }
907: }
908:
909: /* could not find local user - use first line */
910: (void) fclose(fp);
911: if (!*fuser) /* didn't find all information */
912: return(0);
913: *user = fuser;
914: *system = fsystem;
915: return(1);
916: }
917:
918: /* analFrom - analyze From line
919: * return:
920: * 0 - didn't find both from and remote from info
921: * 1 - found info.
922: */
923:
924: int
925: analFrom(line, user, system)
926: char *line, *user, *system;
927: {
928: char *s;
929: int i;
930:
931: if (!PREFIX("From ", line) && !PREFIX(">From ", line))
932: return(0);
933:
934: s = strchr(line, ' ') + 1;
935: for (i = 0; *s && *s != ' ' && *s != '\n'; i++)
936: user[i] = *s++;
937: user[i] = NULLCHAR;
938:
939: /* look for "remote from" */
940: while (*s && ((s = strchr(s, ' ')) != NULL)) {
941: s++;
942: if (PREFIX("remote from ", s)) { /* found it */
943: s = s + strlen("remote from ");
944: for (i = 0; (i<MAXBASENAME) && *s && *s != ' ' && *s != '\n'; i++)
945: system[i] = *s++;
946: system[i] = NULLCHAR;
947: return(1);
948: }
949: }
950: return(0);
951: }
952:
953:
954:
955: static FILE *_Lf = NULL;
956:
957: /*
958: * Make log entry
959: * text -> ptr to text string
960: * status errno number
961: * Returns:
962: * none
963: */
964:
965: void
966: logit(text, status)
967: register char *text;
968: int status;
969: {
970:
971: if (Nstat.t_pid == 0)
972: Nstat.t_pid = getpid();
973:
974: if (_Lf == NULL) {
975: _Lf = fopen(Logfile, "a");
976: if (_Lf == NULL)
977: return;
978: setbuf(_Lf, CNULL);
979: }
980: (void) fseek(_Lf, 0L, 2);
981: (void) fprintf(_Lf, "%s ", Rmtname);
982: (void) fprintf(_Lf, "(%s,%d,%d) ", timeStamp(), Nstat.t_pid, Seqn);
983: (void) fprintf(_Lf, "%s (%d)\n", text, status);
984: return;
985: }
986:
987:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.