|
|
1.1 root 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50: typedef unsigned char u_char;
51: typedef unsigned short u_short;
52: typedef unsigned int u_int;
53: typedef unsigned long u_long;
54: typedef unsigned short ushort;
55:
56:
57:
58: typedef struct _physadr { int r[1]; } * physadr;
59:
60:
61:
62:
63: typedef struct label_t {
64: int val[12];
65: } label_t;
66:
67: typedef struct _quad { long val[2]; } quad;
68: typedef long daddr_t;
69: typedef char * caddr_t;
70: typedef u_long ino_t;
71: typedef long swblk_t;
72: typedef long size_t;
73: typedef long time_t;
74: typedef short dev_t;
75: typedef long off_t;
76: typedef u_short uid_t;
77: typedef u_short gid_t;
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90: typedef long fd_mask;
91:
92:
93:
94:
95:
96: typedef struct fd_set {
97: fd_mask fds_bits[ (((256)+(( (sizeof( fd_mask) * 8 ) )-1))/( (sizeof( fd_mask) * 8 ) ))];
98: } fd_set;
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143: extern struct _iobuf {
144: int _cnt;
145:
146: unsigned char *_ptr;
147: unsigned char *_base;
148:
149: int _bufsiz;
150: short _flag;
151: char _file;
152:
153: char *_name;
154:
155: } _iob[];
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194: struct _iobuf * fopen();
195: struct _iobuf * fdopen();
196: struct _iobuf * freopen();
197: long ftell();
198: char * fgets();
199:
200: struct _iobuf * popen();
201: char * gets();
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259: extern char _ctype_[];
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393: int (* signal())();
394:
395:
396:
397:
398:
399: struct sigvec {
400: int (*sv_handler)();
401: int sv_mask;
402: int sv_flags;
403: };
404:
405:
406:
407:
408:
409:
410:
411: struct sigstack {
412: char *ss_sp;
413: int ss_onstack;
414: };
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426: struct sigcontext {
427:
428:
429:
430:
431: int sc_onstack;
432: int sc_mask;
433: int sc_pc;
434:
435:
436:
437: int sc_regs[32];
438: int sc_mdlo;
439: int sc_mdhi;
440:
441:
442:
443: int sc_ownedfp;
444: int sc_fpregs[32];
445: int sc_fpc_csr;
446: int sc_fpc_eir;
447:
448:
449:
450:
451:
452:
453:
454: int sc_cause;
455: int sc_badvaddr;
456: int sc_badpaddr;
457: };
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556: struct stat
557: {
558: dev_t st_dev;
559: ino_t st_ino;
560: unsigned short st_mode;
561: short st_nlink;
562: uid_t st_uid;
563: gid_t st_gid;
564: dev_t st_rdev;
565: off_t st_size;
566: time_t st_atime;
567: int st_spare1;
568: time_t st_mtime;
569: int st_spare2;
570: time_t st_ctime;
571: int st_spare3;
572: long st_blksize;
573: long st_blocks;
574: long st_spare4[2];
575: };
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:
631:
632:
633:
634:
635:
636:
637:
638:
639:
640:
641:
642:
643:
644:
645:
646:
647:
648:
649:
650:
651:
652:
653:
654:
655:
656:
657:
658:
659:
660:
661:
662:
663:
664:
665:
666:
667:
668:
669:
670:
671:
672:
673:
674:
675:
676:
677:
678:
679:
680:
681:
682:
683:
684:
685:
686:
687:
688:
689:
690:
691:
692:
693:
694:
695:
696:
697:
698:
699:
700:
701:
702:
703:
704:
705:
706:
707:
708:
709:
710:
711:
712:
713:
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736:
737:
738:
739:
740:
741:
742: extern char *strcat();
743: extern char *strncat();
744: extern char *strcpy();
745: extern char *strncpy();
746: extern int strlen();
747: extern int strcmp();
748: extern int strncmp();
749: extern char *strchr();
750: extern char *strrchr();
751:
752:
753: typedef struct string {
754: char *base;
755: char *end;
756: char *ptr;
757: } string;
758:
759:
760:
761:
762:
763:
764:
765:
766:
767:
768: extern string *s_new();
769: extern void s_free();
770: extern string *s_append();
771: extern string *s_nappend();
772: extern string *s_array();
773: extern string *s_copy();
774: extern string *s_seq_read();
775: extern char *s_read_line();
776: extern int s_read_to_eof();
777: extern string *s_parse();
778:
779:
780:
781:
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793: typedef struct namelist namelist;
794: struct namelist {
795: namelist *next;
796: char *name;
797: };
798:
799:
800:
801:
802:
803:
804:
805:
806:
807:
808:
809:
810:
811:
812:
813:
814:
815:
816:
817:
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
830:
831:
832:
833:
834:
835:
836:
837:
838:
839:
840:
841:
842:
843:
844:
845:
846:
847:
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915:
916:
917:
918:
919:
920:
921:
922:
923:
924:
925:
926:
927:
928:
929:
930:
931:
932:
933:
934:
935:
936:
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
949:
950:
951:
952:
953:
954:
955:
956:
957:
958:
959:
960:
961:
962:
963:
964:
965:
966:
967:
968:
969:
970:
971:
972:
973:
974:
975:
976:
977:
978:
979:
980:
981:
982:
983:
984:
985:
986:
987:
988:
989:
990:
991:
992:
993:
994:
995:
996:
997:
998:
999:
1000:
1001:
1002:
1003:
1004:
1005:
1006:
1007:
1008:
1009:
1010:
1011:
1012:
1013:
1014:
1015:
1016:
1017:
1018:
1019:
1020:
1021:
1022:
1023:
1024:
1025:
1026:
1027:
1028:
1029:
1030:
1031:
1032:
1033:
1034:
1035:
1036:
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059:
1060:
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091:
1092:
1093:
1094:
1095:
1096:
1097:
1098:
1099:
1100:
1101:
1102:
1103:
1104:
1105:
1106:
1107:
1108:
1109:
1110:
1111:
1112:
1113:
1114:
1115:
1116:
1117:
1118:
1119:
1120:
1121:
1122:
1123:
1124:
1125:
1126:
1127:
1128:
1129:
1130:
1131:
1132:
1133:
1134:
1135:
1136:
1137:
1138:
1139:
1140:
1141:
1142:
1143:
1144:
1145:
1146:
1147:
1148:
1149:
1150:
1151:
1152:
1153:
1154:
1155:
1156:
1157:
1158:
1159:
1160:
1161:
1162:
1163:
1164:
1165:
1166:
1167:
1168:
1169:
1170:
1171:
1172:
1173:
1174:
1175:
1176:
1177:
1178:
1179:
1180:
1181:
1182:
1183:
1184:
1185:
1186:
1187:
1188:
1189:
1190:
1191:
1192:
1193:
1194:
1195:
1196:
1197:
1198:
1199:
1200:
1201:
1202:
1203:
1204:
1205:
1206:
1207:
1208:
1209:
1210:
1211:
1212:
1213:
1214:
1215:
1216:
1217:
1218:
1219:
1220:
1221:
1222:
1223:
1224:
1225:
1226:
1227:
1228:
1229:
1230:
1231:
1232:
1233:
1234:
1235:
1236:
1237:
1238:
1239:
1240:
1241:
1242:
1243:
1244:
1245:
1246:
1247:
1248:
1249:
1250:
1251:
1252:
1253:
1254:
1255:
1256:
1257:
1258:
1259:
1260:
1261:
1262:
1263:
1264:
1265:
1266:
1267:
1268:
1269:
1270:
1271:
1272:
1273:
1274:
1275:
1276:
1277:
1278:
1279:
1280:
1281:
1282:
1283:
1284:
1285:
1286:
1287:
1288:
1289:
1290:
1291:
1292:
1293:
1294:
1295:
1296:
1297:
1298:
1299:
1300:
1301:
1302:
1303:
1304:
1305:
1306:
1307:
1308:
1309:
1310:
1311:
1312: struct direct {
1313: u_long d_fileno;
1314: u_short d_reclen;
1315: u_short d_namlen;
1316: char d_name[255 + 1];
1317: };
1318:
1319:
1320:
1321:
1322:
1323:
1324:
1325:
1326:
1327:
1328:
1329:
1330:
1331:
1332:
1333:
1334:
1335: typedef struct _dirdesc {
1336: int dd_fd;
1337: long dd_loc;
1338: long dd_size;
1339: long dd_bbase;
1340: long dd_entno;
1341: long dd_bsize;
1342: char *dd_buf;
1343: } DIR;
1344:
1345:
1346: extern DIR * opendir();
1347: extern struct direct * readdir();
1348: extern long telldir();
1349: extern void seekdir();
1350:
1351: extern void closedir();
1352:
1353:
1354:
1355:
1356:
1357:
1358:
1359:
1360:
1361:
1362:
1363:
1364:
1365:
1366:
1367:
1368:
1369:
1370:
1371:
1372:
1373:
1374:
1375:
1376:
1377:
1378:
1379:
1380:
1381: typedef int (*SIG_TYP)();
1382:
1383:
1384:
1385:
1386:
1387:
1388:
1389:
1390:
1391:
1392:
1393:
1394:
1395:
1396:
1397: extern char *UPASROOT;
1398: int warn = -1;
1399: int remove = -1;
1400: int cleanup;
1401: int verbose;
1402: int testmode;
1403: int Xonly;
1404: int Conly;
1405: string *replyaddr;
1406: string *dest;
1407: int mypid;
1408: char **getcmd();
1409:
1410:
1411:
1412: struct {
1413: string *dest;
1414: time_t time;
1415: } destlist[50 ];
1416: int ndest = 0;
1417:
1418: int debug;
1419:
1420:
1421:
1422:
1423:
1424:
1425:
1426:
1427:
1428:
1429:
1430:
1431:
1432:
1433:
1434:
1435:
1436:
1437:
1438:
1439:
1440: usage()
1441: {
1442: fprintf((& _iob[2]), "smtpsched [-cvt] [-w #days] [-r #days] [-s #scheds] [dir]\n");
1443: exit(1);
1444: }
1445:
1446: main(ac, av)
1447: int ac;
1448: char *av[];
1449: {
1450: direct *dirp;
1451: direct d;
1452: direct *dp;
1453: int max=0;
1454: int c;
1455: extern int optind;
1456: extern char *optarg;
1457:
1458: mypid = getpid();
1459:
1460:
1461:
1462:
1463: signal(13 , (int (*)())1);
1464: signal(1 , (int (*)())1);
1465:
1466: while ((c = getopt(ac, av, "XCcvtr:w:s:d")) != (-1))
1467: switch (c) {
1468: case 'X':
1469: Xonly = 1;
1470: break;
1471: case 'C':
1472: Conly = 1;
1473: break;
1474: case 't':
1475: testmode = 1;
1476: break;
1477: case 'v':
1478: verbose = 1;
1479: break;
1480: case 'c':
1481: cleanup = 1;
1482: break;
1483: case 'r':
1484: remove = atoi(optarg);
1485: break;
1486: case 's':
1487: max = atoi(optarg);
1488: break;
1489: case 'w':
1490: warn = atoi(optarg);
1491: break;
1492: case 'd':
1493: debug = 1;
1494: break;
1495: default:
1496: usage();
1497: }
1498: openlog();
1499:
1500:
1501:
1502:
1503: if(chdir("/usr/spool/smtpq")<0){
1504: log("can't chdir to %s\n", "/usr/spool/smtpq");
1505: exit(1);
1506: }
1507:
1508:
1509:
1510:
1511: if(max && toomany(max)<0)
1512: exit(0);
1513:
1514:
1515:
1516:
1517:
1518: if(optind!=ac){
1519: for(; optind<ac; optind++)
1520: while(dodir(av[optind], 1 ) && !warn && !remove)
1521: ;
1522: return 0;
1523: }
1524:
1525:
1526:
1527:
1528:
1529:
1530:
1531: dirp = opendir(".");
1532: if(dirp<0){
1533: log("couldn't read %s\n", "/usr/spool/smtpq");
1534: exit(1);
1535: }
1536: while(dp = readdir(dirp)){
1537: d = *dp;
1538: if(strcmp(d.d_name, ".")!=0 && strcmp(d.d_name, "..")!=0)
1539: dodir(d.d_name, (warn>=0 || remove>=0) ? 2 : 1 );
1540: }
1541: closedir(dirp);
1542: return 0;
1543: }
1544:
1545:
1546:
1547:
1548: dodir(dname, action)
1549: char *dname;
1550: {
1551: int i;
1552:
1553: i = dodirdir(dname, action, "X.");
1554: i += dodirdir(dname, action, "C.");
1555: return i;
1556: }
1557:
1558:
1559:
1560:
1561:
1562: dodirdir(dname, action, direction)
1563: char *dname;
1564: char *direction;
1565: {
1566: DIR *dirp;
1567: direct *dp;
1568: int i;
1569: int changed=0;
1570: int ents=0;
1571: static string *ds;
1572: static string *ls;
1573: extern int errno;
1574:
1575: ds = (ds ? (*(ds->ptr = ds->base) = '\0' , ds) : s_new());
1576: s_append(ds, dname);
1577: ls = (ls ? (*(ls->ptr = ls->base) = '\0' , ls) : s_new());
1578: s_append(ls, direction);
1579: s_append(ls, dname);
1580:
1581:
1582:
1583:
1584: switch(action){
1585: case 0 :
1586: for(i=0; i<3; i++){
1587: if(lock( ls->base)==0)
1588: break;
1589: sleep(5);
1590: }
1591: if(i==3)
1592: return changed;
1593: break;
1594: case 1 :
1595: if(lock( ls->base)<0){
1596: log("couldn't lock %s\n", dname);
1597: return changed;
1598: }
1599: break;
1600: case 2 :
1601: break;
1602: }
1603:
1604:
1605:
1606:
1607:
1608: if(chdir( ds->base)<0){
1609: if(action != 2 )
1610: unlock( ls->base);
1611: return changed;
1612: }
1613:
1614:
1615:
1616:
1617: dirp = opendir(".");
1618: if(dirp<0){
1619: log("couldn't read directory %s\n", dname);
1620: if(chdir("..")<0){
1621: log("can't chdir ..\n");
1622: fflush((& _iob[1]));
1623: exit(1);
1624: }
1625: if(action != 2 )
1626: unlock( ls->base);
1627: return changed;
1628: }
1629: while(dp = readdir(dirp)){
1630: if(strcmp(dp->d_name, ".")!=0 && strcmp(dp->d_name, "..")!=0
1631: && dp->d_name[0] == *direction) {
1632: switch(dofile(dname, dp->d_name)){
1633: case 0:
1634:
1635: changed = 1;
1636: break;
1637: case 1:
1638:
1639: ents += 1;
1640: break;
1641: }
1642: }
1643: }
1644: closedir(dirp);
1645:
1646:
1647:
1648:
1649: if(chdir("..")<0){
1650: log("can't chdir ..\n");
1651: fflush((& _iob[1]));
1652: exit(1);
1653: }
1654:
1655:
1656:
1657:
1658: if(cleanup && ents==0){
1659: log("%s empty\n", ds->base);
1660: if(rmdir( ds->base)<0)
1661: log("can't unlink: %d\n", errno);
1662: }
1663:
1664: if(action != 2 )
1665: unlock( ls->base);
1666: return changed;
1667: }
1668:
1669:
1670:
1671:
1672:
1673:
1674:
1675: dofile(dname, name)
1676: char *dname;
1677: char *name;
1678: {
1679: int rv;
1680: int fd, ofd;
1681: char *ef;
1682: extern char *fileoftype();
1683: struct stat sb;
1684: time_t now, Edate, Cdate;
1685:
1686: rv = -1;
1687:
1688:
1689:
1690:
1691: if(cleanup && inconsistent(name)){
1692: log("%s/%s inconsistent\n", dname, name);
1693: unlink(name);
1694: return 0;
1695: }
1696:
1697:
1698:
1699:
1700: if(name[1]!='.' || (name[0]!='C' && name[0]!='X'))
1701: return 1;
1702:
1703:
1704:
1705:
1706:
1707: if(warn>=0 || remove>=0) {
1708: if(checkage(name)==0) {
1709: log("%s/%s too old\n", dname, name);
1710: doremove(name);
1711: return 0;
1712: }
1713: return 1;
1714: }
1715:
1716:
1717:
1718:
1719: if(cleanup)
1720: return 1;
1721:
1722:
1723:
1724:
1725: ef = fileoftype('E', name);
1726: if (name[0]=='C') {
1727: now = time((time_t *)0);
1728: Cdate = now;
1729: Edate = now-4*3600L -1;
1730: if (stat(name, &sb)==0)
1731: Cdate = sb.st_ctime;
1732: if (stat(ef, &sb)==0)
1733: Edate = sb.st_mtime;
1734: if (now-Cdate>6*3600L && now-Edate<4*3600L
1735: || now-Cdate>1*3600L && now-Edate<1*3600L ) {
1736: if (verbose)
1737: log("ignore %s/%s: not time yet\n", dname, name);
1738: if (debug==0)
1739: return 1;
1740: }
1741: }
1742:
1743:
1744:
1745:
1746: if (testmode) {
1747: log("would process %s/%s\n", dname, name);
1748: return 1;
1749: }
1750:
1751:
1752:
1753: ofd = dup(2);
1754: close(2);
1755: fd = open(ef, 1);
1756: if(fd<0)
1757: fd = creat(ef, 0666);
1758: if(fd>=0){
1759: lseek(fd, 0l, 2);
1760:
1761:
1762:
1763:
1764: if(name[0]=='C') {
1765: rv = dosmtp(dname, name);
1766: } else if(name[0]=='X') {
1767: rv = dormail(dname, name);
1768: }
1769:
1770:
1771:
1772:
1773: close(2);
1774: (void) dup(ofd);
1775: close(ofd);
1776: }
1777:
1778:
1779:
1780:
1781: if(rv==0) {
1782: doremove(name);
1783: return 0;
1784: }
1785: return 1;
1786: }
1787:
1788:
1789:
1790:
1791: doremove(ctl)
1792: char *ctl;
1793: {
1794: fflush((& _iob[1]));
1795: unlink(fileoftype('E', ctl));
1796: unlink(ctl);
1797: unlink(fileoftype('D', ctl));
1798: }
1799:
1800:
1801:
1802:
1803:
1804: dormail(dname, ctl)
1805: char *dname;
1806: char *ctl;
1807: {
1808: char **av;
1809:
1810: log("dormail %s/%s\n", dname, ctl);
1811:
1812:
1813:
1814:
1815: av = getcmd(ctl, "/bin/rmail");
1816: if(av && docmd(ctl, av)==0){
1817: log("success\n");
1818: return 0;
1819: } else {
1820: log("failure\n");
1821: return -1;
1822: }
1823: }
1824:
1825:
1826:
1827:
1828:
1829: dosmtp(dname, ctl)
1830: char *dname;
1831: char *ctl;
1832: {
1833: static string *cmd;
1834: int status, i;
1835: char **av;
1836: time_t t0, t1;
1837:
1838: log("dosmtp %s/%s\n", dname, ctl);
1839:
1840:
1841:
1842:
1843: cmd = (cmd ? (*(cmd->ptr = cmd->base) = '\0' , cmd) : s_new());
1844: s_append(cmd, UPASROOT);
1845: s_append(cmd, "/smtp");
1846: av = getcmd(ctl, cmd->base);
1847: if (av==0) {
1848: log("cmdfail\n", 0);
1849: return -1;
1850: }
1851:
1852:
1853:
1854:
1855: for (i=0; i<ndest; i++) {
1856: if (strcmp( dest->base, destlist[i].dest->base)==0) {
1857: if (destlist[i].time > 5*60 ) {
1858: log("passed %s (%d sec)\n", dest->base, destlist[i].time);
1859: fprintf((& _iob[2]), "can't contact destination\n");
1860: return -1;
1861: }
1862: break;
1863: }
1864: }
1865: if (i==ndest) {
1866: if (ndest<50 )
1867: ndest++;
1868: else
1869: i = 0;
1870: destlist[i].dest = s_copy( dest->base);
1871: destlist[i].time = 0;
1872: }
1873: if (debug)
1874: log("time %d for %s\n", destlist[i].time, dest->base);
1875: time(&t0);
1876: switch(status=docmd(ctl, av)){
1877: case 0:
1878: log("success\n");
1879: destlist[i].time = 0;
1880: return 0;
1881:
1882: case 69 :
1883: case 77 :
1884: case 67 :
1885: case 68 :
1886: log("fail %d\n", status);
1887: returnmail(ctl, 1);
1888: destlist[i].time = 0;
1889: return 0;
1890:
1891: case 73 :
1892: case 74 :
1893: case 71 :
1894: case 72 :
1895: case 70 :
1896: case 64 :
1897: case 65 :
1898: case 66 :
1899: case 76 :
1900: case 75 :
1901: log("fail %d\n", status);
1902: time(&t1);
1903: destlist[i].time += t1-t0;
1904: return -1;
1905:
1906: default:
1907: log("fail %d\n", status);
1908: time(&t1);
1909: destlist[i].time += t1-t0;
1910: return -1;
1911: }
1912: }
1913:
1914:
1915:
1916:
1917:
1918:
1919:
1920: struct _iobuf *
1921: parseline1(ctl)
1922: char *ctl;
1923: {
1924: struct _iobuf *fp;
1925: static string *line;
1926:
1927: fp = fopen(ctl, "r");
1928: if(fp==0)
1929: return 0;
1930:
1931:
1932:
1933:
1934: line = (line ? (*(line->ptr = line->base) = '\0' , line) : s_new());
1935: if(s_read_line(fp, line)==0){
1936: fprintf((& _iob[2]), "smtpsched: error reading ctl file %s\n", ctl);
1937: fclose(fp);
1938: return 0;
1939: }
1940: replyaddr = s_parse( (line->ptr = line->base , line), (replyaddr ? (*(replyaddr->ptr = replyaddr->base) = '\0' , replyaddr) : s_new()));
1941: dest = s_parse(line, (dest ? (*(dest->ptr = dest->base) = '\0' , dest) : s_new()));
1942: return fp;
1943: }
1944:
1945:
1946:
1947:
1948:
1949:
1950:
1951:
1952: char **
1953: getcmd(ctl, cmd)
1954: char *cmd;
1955: {
1956: static string *args;
1957: struct _iobuf *fp;
1958: static char *av[1024];
1959: int ac=0;
1960: char *cp;
1961:
1962: fp = parseline1(ctl);
1963: if (fp==0)
1964: return 0;
1965:
1966:
1967:
1968:
1969: av[ac++] = cmd;
1970: args = (args ? (*(args->ptr = args->base) = '\0' , args) : s_new());
1971: if(s_read_line(fp, args)==0){
1972: fprintf((& _iob[2]), "smtpsched: error reading ctl file %s\n", ctl);
1973: fclose(fp);
1974: return 0;
1975: }
1976: fclose(fp);
1977: for(cp = args->base; *cp && ac<1023;){
1978: av[ac++] = cp++;
1979: while(*cp && ! (( _ctype_+1)[*cp]&010))
1980: cp++;
1981: while( (( _ctype_+1)[*cp]&010))
1982: *cp++ = 0;
1983: }
1984: av[ac] = 0;
1985: return av;
1986: }
1987:
1988:
1989:
1990:
1991: docmd(ctl, av)
1992: char *ctl;
1993: char **av;
1994: {
1995: int fd;
1996: int pid, status;
1997: int n;
1998:
1999:
2000:
2001:
2002: switch(pid = fork()){
2003: case -1:
2004: return 1;
2005: case 0:
2006:
2007:
2008:
2009: close(0);
2010: fd = open(fileoftype('D', ctl), 0);
2011: if(fd<0){
2012: perror("smtpsched: error reading data file:\n");
2013: exit(1);
2014: }
2015:
2016:
2017:
2018:
2019: close(1);
2020: fd = dup(2);
2021:
2022:
2023:
2024:
2025: execvp(av[0], av);
2026: exit(1);
2027: default:
2028:
2029:
2030:
2031: while((n = wait(&status))>=0)
2032: if(n == pid)
2033: break;
2034: if(status&0xff)
2035: return -1;
2036: else
2037: return (status>>8)&0xff;
2038: }
2039:
2040: }
2041:
2042:
2043:
2044:
2045:
2046:
2047:
2048: toomany(max)
2049: int max;
2050: {
2051: struct _iobuf *ifp=0;
2052: struct _iobuf *ofp=0;
2053: int cur=0;
2054: int pid;
2055:
2056:
2057:
2058:
2059: if(lock(".smtpscheds")<0)
2060: return -1;
2061:
2062:
2063:
2064:
2065: ofp = fopen(".nsmtpscheds", "w");
2066: if(ofp==0){
2067: fprintf((& _iob[2]), "can't open %s\n", ".nsmtpscheds");
2068: goto error;
2069: }
2070: ifp = fopen(".smtpscheds", "r");
2071: if(ifp!=0){
2072:
2073:
2074:
2075: while(fscanf(ifp, "%d", &pid)==1){
2076: if(kill(pid, 0) == 0){
2077: cur++;
2078: if(fprintf(ofp, "%d\n", pid)<0){
2079: fprintf((& _iob[2]), "error writing %s\n", ".nsmtpscheds");
2080: goto error;
2081: }
2082: }
2083: }
2084: if(cur >= max)
2085: goto error;
2086: }
2087:
2088:
2089:
2090:
2091: if(fprintf(ofp, "%d\n", getpid())<0){
2092: fprintf((& _iob[2]), "error writing %s\n", ".nsmtpscheds");
2093: goto error;
2094: }
2095: if(ifp!=0)
2096: fclose(ifp);
2097: if(fclose(ofp)==(-1))
2098: goto error;
2099: unlink(".smtpscheds");
2100: if(link(".nsmtpscheds", ".smtpscheds")<0)
2101: fprintf((& _iob[2]), "can't link %s to %s file\n", ".smtpscheds", ".nsmtpscheds");
2102: unlink(".nsmtpscheds");
2103: unlock(".smtpscheds");
2104: return 0;
2105: error:
2106:
2107:
2108:
2109: if(ifp!=0)
2110: fclose(ifp);
2111: if(ofp!=0)
2112: fclose(ofp);
2113: unlink(".nsmtpscheds");
2114: unlock(".smtpscheds");
2115: return -1;
2116: }
2117:
2118:
2119:
2120:
2121:
2122:
2123:
2124:
2125: inconsistent(file)
2126: char *file;
2127: {
2128: struct stat s;
2129: int days;
2130:
2131:
2132:
2133:
2134: switch(file[0]){
2135: case 'C':
2136: case 'X':
2137:
2138:
2139:
2140: if(stat(fileoftype('D', file), &s)<0)
2141: return 1;
2142: break;
2143: case 'E':
2144:
2145:
2146:
2147: if(stat(fileoftype('X', file), &s)<0
2148: && stat(fileoftype('C', file), &s)<0)
2149: return 1;
2150:
2151:
2152:
2153:
2154: if(stat(fileoftype('D', file), &s)<0)
2155: return 1;
2156: break;
2157: case 'D':
2158:
2159:
2160:
2161: if(stat(fileoftype('X', file), &s)==0
2162: || stat(fileoftype('C', file), &s)==0)
2163: break;
2164:
2165:
2166:
2167:
2168: if(stat(file, &s)<0)
2169: return 0;
2170: days = (time((long *)0) - s.st_ctime)/(24*60*60);
2171: if(days>0)
2172: return 1;
2173: break;
2174: default:
2175: break;
2176: }
2177: return 0;
2178: }
2179:
2180:
2181:
2182:
2183:
2184: checkage(ctl)
2185: char *ctl;
2186: {
2187: struct stat s;
2188: int days;
2189: char buf[256];
2190: struct _iobuf *fp;
2191:
2192:
2193:
2194:
2195: if(stat(ctl, &s)<0)
2196: return -1;
2197: days = (time((long *)0) - s.st_ctime)/(24*60*60);
2198:
2199:
2200:
2201:
2202: if(remove>=0 && days>=remove){
2203: fp = parseline1(ctl);
2204: if(fp==0)
2205: return -1;
2206: fclose(fp);
2207:
2208: log("r %d %d\n", days, remove);
2209: return returnmail(ctl, 1);
2210: }
2211:
2212:
2213:
2214:
2215: if(warn>=0 && days>=warn){
2216: fp = parseline1(ctl);
2217: if(fp==0)
2218: return -1;
2219: fclose(fp);
2220:
2221: log("w %d %d\n", days, warn);
2222: returnmail(ctl, 0);
2223: }
2224:
2225: return -1;
2226: }
2227:
2228:
2229:
2230:
2231: returnmail(ctl, warn)
2232: char *ctl;
2233: {
2234: int pid, status;
2235: string *cmd;
2236: int pfd[2];
2237: char buf[132];
2238: int fd, n;
2239: int reads;
2240: struct _iobuf *fp;
2241: struct _iobuf *ifp;
2242: long now;
2243: char asct[27];
2244:
2245: log("returnmail %s to %s about %s\n", ctl, replyaddr->base,
2246: dest->base);
2247:
2248: if(pipe(pfd)<0)
2249: return -1;
2250:
2251: switch(pid=fork()){
2252: case -1:
2253: close(pfd[0]);
2254: close(pfd[1]);
2255: return -1;
2256: case 0:
2257:
2258:
2259:
2260: close(0);
2261: dup(pfd[0]);
2262: close(pfd[1]);
2263: execl("/bin/rmail", "/bin/rmail", replyaddr->base, 0);
2264: exit(1);
2265: default:
2266:
2267:
2268:
2269: close(pfd[0]);
2270: fp = fdopen(pfd[1], "w");
2271: if(fp==0) {
2272: close(pfd[1]);
2273: break;
2274: }
2275:
2276:
2277:
2278:
2279: now = time((long *)0);
2280: strcpy(asct, ctime(&now));
2281: asct[24] = 0;
2282: fprintf(fp, "From postmaster %s remote from \n", asct);
2283:
2284:
2285:
2286:
2287: if(warn) {
2288: fprintf(fp, "Subject: smtp mail failed\n\n");
2289: fprintf(fp, "Your mail to %s is undeliverable.\n",
2290: dest->base);
2291: } else {
2292: fprintf(fp, "Subject: smtp mail warning\n\n");
2293: fprintf(fp, "Your mail to %s is not yet delivered.\n",
2294: dest->base);
2295: fprintf(fp, "Delivery attempts continue.\n");
2296: }
2297:
2298:
2299:
2300:
2301: fprintf(fp, "---------- diagnosis ----------\n");
2302: ifp = fopen(fileoftype('E', ctl), "r");
2303: if(ifp!=0){
2304: for(reads=0; reads<20; reads++) {
2305: if(fgets(buf, sizeof(buf), ifp)==0)
2306: break;
2307: fputs(buf, fp);
2308: }
2309: fclose(ifp);
2310: }
2311:
2312:
2313:
2314:
2315: fprintf(fp, "---------- unsent mail ----------\n");
2316: ifp = fopen(fileoftype('D', ctl), "r");
2317: if(ifp!=0){
2318: for(reads=0; reads<50; reads++) {
2319: if(fgets(buf, sizeof(buf), ifp)==0)
2320: break;
2321: fputs(buf, fp);
2322: }
2323: fclose(ifp);
2324: }
2325: fclose(fp);
2326:
2327:
2328:
2329:
2330: while((n = wait(&status))>=0)
2331: if(n == pid)
2332: break;
2333: return status ? -1 : 0;
2334: }
2335: close(pfd[1]);
2336: return -1;
2337: }
2338:
2339: openlog()
2340: {
2341: string *f;
2342:
2343: if (debug)
2344: return;
2345: f = s_new();
2346: s_append(f, "/usr/spool/smtpq");
2347: s_append(f, "/smtpsched.log");
2348: close(0);
2349: if(open("/dev/null", 0)==0){
2350: close(1);
2351: close(2);
2352: close(3);
2353: if(open( f->base, 2)==1
2354: || creat( f->base, 0666)==1){
2355: lseek(1, 0L, 2);
2356: dup(1);
2357: dup(1);
2358: }
2359: }
2360: s_free(f);
2361: }
2362:
2363: log(f, a, b, c)
2364: char *f;
2365: {
2366: char *dp;
2367: struct tm *bp;
2368: long thetime;
2369: extern struct tm *localtime();
2370: extern char *asctime();
2371: extern long time();
2372:
2373: thetime = time((long *)0);
2374: bp = localtime(&thetime);
2375: dp = asctime(bp);
2376:
2377: lseek(1, 0L, 2);
2378: printf("%d %.12s: ", mypid, dp+4);
2379: printf(f, a, b, c);
2380: fflush((& _iob[1]));
2381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.