1: /* inc.c - incorporate messages from a maildrop into a folder */ 2: 3: #include "../h/mh.h" 4: #ifdef POP 5: #include "../h/dropsbr.h" 6: #endif POP 7: #include "../h/formatsbr.h" 8: #include "../h/scansbr.h" 9: #include "../zotnet/tws.h" 10: #include <stdio.h> 11: #include "../zotnet/mts.h" 12: #include <errno.h> 13: #include <signal.h> 14: #include <sys/types.h> 15: #include <sys/stat.h> 16: 17: /* */ 18: 19: static struct swit switches[] = { 20: #define AUDSW 0 21: "audit audit-file", 0, 22: #define NAUDSW 1 23: "noaudit", 0, 24: 25: #define CHGSW 2 26: "changecur", 0, 27: #define NCHGSW 3 28: "nochangecur", 0, 29: 30: #define DECRSW 4 31: "decrypt", 32: #ifndef TMA 33: -7, 34: #else TMA 35: 0, 36: #endif TMA 37: #define NDECRSW 5 38: "nodecrypt", 39: #ifndef TMA 40: -9, 41: #else TMA 42: 0, 43: #endif TMA 44: 45: #define MSW 6 46: "file name", 0, 47: 48: #define FORMSW 7 49: "form formatfile", 0, 50: #define FMTSW 8 51: "format string", 5, 52: 53: #define HOSTSW 9 54: "host host", 55: #ifndef POP 56: -4, 57: #else POP 58: 0, 59: #endif POP 60: #define USERSW 10 61: "user user", 62: #ifndef POP 63: -4, 64: #else POP 65: 0, 66: #endif POP 67: #define PACKSW 11 68: "pack file", 69: #ifndef POP 70: -4, 71: #else POP 72: 0, 73: #endif POP 74: #define NPACKSW 12 75: "nopack", 76: #ifndef POP 77: -6, 78: #else POP 79: 0, 80: #endif POP 81: #define RPOPSW 13 82: "rpop", 83: #ifndef RPOP 84: -4, 85: #else RPOP 86: 0, 87: #endif RPOP 88: #define NRPOPSW 14 89: "norpop", 90: #ifndef RPOP 91: -6, 92: #else RPOP 93: 0, 94: #endif RPOP 95: 96: #define SILSW 15 97: "silent", 0, 98: #define NSILSW 16 99: "nosilent", 0, 100: 101: #define TRNCSW 17 102: "truncate", 0, 103: #define NTRNCSW 18 104: "notruncate", 0, 105: 106: #define UUCPSW 19 107: "uucp", 108: #ifndef MF 109: -4, 110: #else MF 111: 0, 112: #endif MF 113: #define NUUCPSW 20 114: "nouucp", 115: #ifndef MF 116: -6, 117: #else MF 118: 0, 119: #endif MF 120: 121: #define WIDSW 21 122: "width columns", 0, 123: 124: #define HELPSW 22 125: "help", 4, 126: 127: NULL, NULL 128: }; 129: 130: /* */ 131: 132: extern int errno; 133: 134: #ifdef POP 135: int snoop = 0; 136: extern char response[]; 137: 138: static char *file = NULL; 139: static int size; 140: static long pos; 141: static long start; 142: static long stop; 143: 144: static int pd = NOTOK; 145: static FILE *pf = NULL; 146: 147: int pop_action (), pop_pack (); 148: #endif POP 149: 150: /* * / 151: 152: /* ARGSUSED */ 153: 154: main (argc, argv) 155: int argc; 156: char *argv[]; 157: { 158: int chgflag = 1, 159: trnflag = 1, 160: decflag = 1, 161: noisy = 1, 162: width = 0, 163: uucp = 1, 164: locked = 0, 165: #ifdef POP 166: nmsgs, 167: nbytes, 168: p, 169: #endif POP 170: rpop = 1, 171: i, 172: hghnum, 173: msgnum; 174: char *cp, 175: *maildir, 176: *folder = NULL, 177: *form = NULL, 178: *format = NULL, 179: *audfile = NULL, 180: *from = NULL, 181: *host = NULL, 182: *user = NULL, 183: #ifdef POP 184: *pass = NULL, 185: #endif POP 186: *newmail, 187: buf[100], 188: **ap, 189: **argp, 190: *nfs, 191: *arguments[MAXARGS]; 192: struct msgs *mp; 193: struct stat st, 194: s1; 195: FILE *in, *aud; 196: #ifdef MHE 197: FILE *mhe; 198: #endif MHE 199: 200: invo_name = r1bindex (argv[0], '/'); 201: mts_init (invo_name); 202: #ifdef POP 203: if (pophost && *pophost) 204: host = pophost; 205: if ((cp = getenv ("MHPOPDEBUG")) && *cp) 206: snoop++; 207: #endif POP 208: if ((cp = m_find (invo_name)) != NULL) { 209: ap = brkstring (cp = getcpy (cp), " ", "\n"); 210: ap = copyip (ap, arguments); 211: } 212: else 213: ap = arguments; 214: (void) copyip (argv + 1, ap); 215: argp = arguments; 216: 217: /* */ 218: 219: while (cp = *argp++) { 220: if (*cp == '-') 221: switch (smatch (++cp, switches)) { 222: case AMBIGSW: 223: ambigsw (cp, switches); 224: done (1); 225: case UNKWNSW: 226: adios (NULLCP, "-%s unknown", cp); 227: case HELPSW: 228: (void) sprintf (buf, "%s [+folder] [switches]", invo_name); 229: help (buf, switches); 230: done (1); 231: 232: case AUDSW: 233: if (!(cp = *argp++) || *cp == '-') 234: adios (NULLCP, "missing argument to %s", argp[-2]); 235: audfile = getcpy (m_maildir (cp)); 236: continue; 237: case NAUDSW: 238: audfile = NULL; 239: continue; 240: 241: case CHGSW: 242: chgflag++; 243: continue; 244: case NCHGSW: 245: chgflag = 0; 246: continue; 247: 248: case TRNCSW: 249: trnflag++; 250: continue; 251: case MSW: 252: if (!(cp = *argp++) || *cp == '-') 253: adios (NULLCP, "missing argument to %s", argp[-2]); 254: from = path (cp, TFILE);/* fall */ 255: case NTRNCSW: 256: trnflag = 0; 257: continue; 258: 259: case SILSW: 260: noisy = 0; 261: continue; 262: case NSILSW: 263: noisy++; 264: continue; 265: 266: case FORMSW: 267: if (!(form = *argp++) || *form == '-') 268: adios (NULLCP, "missing argument to %s", argp[-2]); 269: format = NULL; 270: continue; 271: case FMTSW: 272: if (!(format = *argp++) || *format == '-') 273: adios (NULLCP, "missing argument to %s", argp[-2]); 274: form = NULL; 275: continue; 276: 277: case WIDSW: 278: if (!(cp = *argp++) || *cp == '-') 279: adios (NULLCP, "missing argument to %s", argp[-2]); 280: width = atoi (cp); 281: continue; 282: 283: case DECRSW: 284: decflag++; 285: continue; 286: case NDECRSW: 287: decflag = 0; 288: continue; 289: 290: case UUCPSW: 291: uucp++; 292: continue; 293: case NUUCPSW: 294: uucp = 0; 295: continue; 296: 297: case HOSTSW: 298: if (!(host = *argp++) || *host == '-') 299: adios (NULLCP, "missing argument to %s", argp[-2]); 300: continue; 301: case USERSW: 302: if (!(user = *argp++) || *user == '-') 303: adios (NULLCP, "missing argument to %s", argp[-2]); 304: continue; 305: case PACKSW: 306: #ifndef POP 307: if (!(cp = *argp++) || *cp == '-') 308: adios (NULLCP, "missing argument to %s", argp[-2]); 309: #else POP 310: if (!(file = *argp++) || *file == '-') 311: adios (NULLCP, "missing argument to %s", argp[-2]); 312: #endif POP 313: continue; 314: case NPACKSW: 315: #ifdef POP 316: file = NULLCP; 317: #endif POP 318: continue; 319: case RPOPSW: 320: rpop++; 321: continue; 322: case NRPOPSW: 323: rpop = 0; 324: continue; 325: } 326: if (*cp == '+' || *cp == '@') { 327: if (folder) 328: adios (NULLCP, "only one folder at a time!"); 329: else 330: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); 331: } 332: else 333: adios (NULLCP, "usage: %s [+folder] [switches]", invo_name); 334: } 335: 336: /* */ 337: 338: #ifdef POP 339: if (host && !*host) 340: host = NULL; 341: if (from || !host || !rpop) 342: (void) setuid (getuid ()); 343: #endif POP 344: if (from) { 345: newmail = from; 346: #ifdef POP 347: host = NULL; 348: #endif POP 349: if (stat (newmail, &s1) == NOTOK || s1.st_size == 0) 350: adios (NULLCP, "no mail to incorporate"); 351: } 352: #ifdef POP 353: else if (host) { 354: if (rpop) { 355: if (user == NULL) 356: user = getusr (); 357: pass = getusr (); 358: } 359: else 360: ruserpass (host, &user, &pass); 361: 362: if (pop_init (host, user, pass, snoop, rpop) == NOTOK 363: || pop_stat (&nmsgs, &nbytes) == NOTOK) 364: adios (NULLCP, "%s", response); 365: if (rpop) 366: (void) setuid (getuid ()); 367: if (nmsgs == 0) { 368: (void) pop_quit (); 369: adios (NULLCP, "no mail to incorporate"); 370: } 371: } 372: #endif POP 373: else { 374: if (((newmail = getenv ("MAILDROP")) && *newmail) 375: || ((newmail = m_find ("maildrop")) && *newmail)) 376: newmail = m_mailpath (newmail); 377: else { 378: #ifdef MF 379: if (uucp && umincproc && *umincproc) 380: get_uucp_mail (); 381: #endif MF 382: newmail = concat (MAILDIR, "/", MAILFIL, NULLCP); 383: } 384: if (stat (newmail, &s1) == NOTOK || s1.st_size == 0) 385: adios (NULLCP, "no mail to incorporate"); 386: } 387: 388: #ifdef POP 389: if (host && file) 390: goto go_to_it; 391: #endif POP 392: if (!m_find ("path")) 393: free (path ("./", TFOLDER)); 394: if (!folder) 395: folder = defalt; 396: maildir = m_maildir (folder); 397: 398: if (stat (maildir, &st) == NOTOK) { 399: if (errno != ENOENT) 400: adios (maildir, "error on folder"); 401: cp = concat ("Create folder \"", maildir, "\"? ", NULLCP); 402: if (noisy && !getanswer (cp)) 403: done (1); 404: free (cp); 405: if (!makedir (maildir)) 406: adios (NULLCP, "unable to create folder %s", maildir); 407: } 408: 409: if (chdir (maildir) == NOTOK) 410: adios (maildir, "unable to change directory to"); 411: if (!(mp = m_gmsg (folder))) 412: adios (NULLCP, "unable to read folder %s", folder); 413: 414: /* */ 415: 416: #ifdef POP 417: go_to_it: ; 418: if (host == NULL) 419: #endif POP 420: if (access (newmail, 02) == NOTOK) { 421: trnflag = 0; 422: if ((in = fopen (newmail, "r")) == NULL) 423: adios (newmail, "unable to read"); 424: } 425: else { 426: locked++; 427: if (trnflag) { 428: (void) signal (SIGHUP, SIG_IGN); 429: (void) signal (SIGINT, SIG_IGN); 430: (void) signal (SIGQUIT, SIG_IGN); 431: (void) signal (SIGTERM, SIG_IGN); 432: } 433: if ((in = lkfopen (newmail, "r")) == NULL) 434: adios (NULLCP, "unable to lock and fopen %s", newmail); 435: (void) fstat (fileno(in), &s1); 436: } 437: 438: if (audfile) { 439: if ((i = stat (audfile, &st)) == NOTOK) 440: advise (NULLCP, "Creating Receive-Audit: %s", audfile); 441: if ((aud = fopen (audfile, "a")) == NULL) 442: adios (audfile, "unable to append to"); 443: else 444: if (i == NOTOK) 445: (void) chmod (audfile, m_gmprot ()); 446: #ifndef POP 447: fprintf (aud, from ? "<<inc>> %s -ms %s\n" : "<<inc>> %s\n", 448: dtimenow (), from); 449: #else POP 450: fprintf (aud, from ? "<<inc>> %s -ms %s\n" 451: : host ? "<<inc>> %s -host %s -user %s%s\n" 452: : "<<inc>> %s\n", 453: dtimenow (), from ? from : host, user, rpop ? " -rpop" : ""); 454: #endif POP 455: } 456: 457: #ifdef MHE 458: if (m_find ("mhe")) { 459: cp = concat (maildir, "/++", NULLCP); 460: i = stat (cp, &st); 461: if ((mhe = fopen (cp, "a")) == NULL) 462: admonish (cp, "unable to append to"); 463: else 464: if (i == NOTOK) 465: (void) chmod (cp, m_gmprot ()); 466: free (cp); 467: } 468: #endif MHE 469: 470: nfs = new_fs (form, format, FORMAT); 471: 472: if (noisy) { 473: printf ("Incorporating new mail into %s...\n\n", folder); 474: (void) fflush (stdout); 475: } 476: 477: /* */ 478: 479: #ifdef POP 480: if (host) { 481: if (file) { 482: file = path (file, TFILE); 483: if (stat (file, &st) == NOTOK) { 484: if (errno != ENOENT) 485: adios (file, "error on file"); 486: cp = concat ("Create file \"", file, "\"? ", NULLCP); 487: if (noisy && !getanswer (cp)) 488: done (1); 489: free (cp); 490: } 491: msgnum = map_count (); 492: if ((pd = mbx_open (file, getuid (), getgid (), m_gmprot ())) 493: == NOTOK) 494: adios (file, "unable to open"); 495: if ((pf = fdopen (pd, "w+")) == NULL) 496: adios (NULLCP, "unable to fdopen %s", file); 497: } 498: else { 499: hghnum = msgnum = mp -> hghmsg; 500: if ((mp = m_remsg (mp, 0, mp -> hghmsg + nmsgs)) == NULL) 501: adios (NULLCP, "unable to allocate folder storage"); 502: } 503: 504: for (i = 1; i <= nmsgs; i++) { 505: msgnum++; 506: if (file) { 507: (void) fseek (pf, 0L, 1); 508: pos = ftell (pf); 509: size = 0; 510: (void) fwrite (mmdlm1, 1, strlen (mmdlm1), pf); 511: start = ftell (pf); 512: 513: if (pop_retr (i, pop_pack) == NOTOK) 514: adios (NULLCP, "%s", response); 515: 516: (void) fseek (pf, 0L, 1); 517: stop = ftell (pf); 518: if (fflush (pf)) 519: adios (file, "write error on"); 520: (void) fseek (pf, start, 0); 521: } 522: else { 523: cp = getcpy (m_name (msgnum)); 524: if ((pf = fopen (cp, "w+")) == NULL) 525: adios (cp, "unable to write"); 526: (void) chmod (cp, m_gmprot ()); 527: start = stop = 0L; 528: 529: if (pop_retr (i, pop_action) == NOTOK) 530: adios (NULLCP, "%s", response); 531: 532: if (fflush (pf)) 533: adios (cp, "write error on"); 534: (void) fseek (pf, 0L, 0); 535: } 536: switch (p = scan (pf, msgnum, 0, nfs, width, 537: file ? 0 : msgnum == mp -> hghmsg + 1 && chgflag, 538: 0, stop - start, noisy)) { 539: case SCNEOF: 540: printf ("%*d empty\n", DMAXFOLDER, msgnum); 541: break; 542: 543: case SCNERR: 544: case SCNNUM: 545: break; 546: 547: case SCNMSG: 548: case SCNENC: 549: default: 550: if (aud) 551: fputs (scanl, aud); 552: #ifdef MHE 553: if (mhe) 554: fputs (scanl, mhe); 555: #endif MHE 556: if (noisy) 557: (void) fflush (stdout); 558: if (!file) { 559: mp -> msgstats[msgnum] = EXISTS; 560: #ifdef TMA 561: if (p == SCNENC) { 562: if (mp -> lowsel == 0 || msgnum < mp -> lowsel) 563: mp -> lowsel = msgnum; 564: if (mp -> hghsel == 0 || msgnum > mp -> hghsel) 565: mp -> hghsel = msgnum; 566: mp -> numsel++; 567: mp -> msgstats[msgnum] |= SELECTED; 568: } 569: #endif TMA 570: mp -> msgstats[msgnum] |= UNSEEN; 571: mp -> msgflags |= SEQMOD; 572: } 573: break; 574: } 575: if (file) { 576: (void) fseek (pf, stop, 0); 577: (void) fwrite (mmdlm2, 1, strlen (mmdlm2), pf); 578: if (fflush (pf)) 579: adios (file, "write error on"); 580: (void) map_write (file, pd, 0, start, stop, pos, size, noisy); 581: } 582: else { 583: (void) fclose (pf); 584: free (cp); 585: } 586: 587: if (trnflag && pop_dele (i) == NOTOK) 588: adios (NULLCP, "%s", response); 589: } 590: if (pop_quit () == NOTOK) 591: adios (NULLCP, "%s", response); 592: if (file) { 593: (void) mbx_close (file, pd); 594: pd = NOTOK; 595: } 596: } 597: else { 598: #endif POP 599: 600: /* */ 601: 602: m_unknown (in); /* the MAGIC invocation... */ 603: hghnum = msgnum = mp -> hghmsg; 604: for (;;) { 605: if (msgnum >= mp -> hghoff) 606: if ((mp = m_remsg (mp, 0, mp -> hghoff + MAXFOLDER)) == NULL) 607: adios (NULLCP, "unable to allocate folder storage"); 608: 609: switch (i = scan (in, msgnum + 1, msgnum + 1, nfs, width, 610: msgnum == hghnum && chgflag, 611: 0, 612: 0L, 613: noisy)) { 614: case SCNEOF: 615: break; 616: 617: case SCNERR: 618: if (aud) 619: fputs ("inc aborted!\n", aud); 620: adios (NULLCP, "aborted!"); 621: 622: case SCNNUM: 623: adios (NULLCP, "more than %d messages in folder %s, %s not zero'd", 624: MAXFOLDER, folder, newmail); 625: 626: default: 627: adios (NULLCP, "scan() botch (%d)", i); 628: 629: case SCNMSG: 630: case SCNENC: 631: if (aud) 632: fputs (scanl, aud); 633: #ifdef MHE 634: if (mhe) 635: fputs (scanl, mhe); 636: #endif MHE 637: if (noisy) 638: (void) fflush (stdout); 639: 640: msgnum++, mp -> hghmsg++; 641: mp -> msgstats[msgnum] = EXISTS; 642: #ifdef TMA 643: if (i == SCNENC) { 644: if (mp -> lowsel == 0 || mp -> lowsel > msgnum) 645: mp -> lowsel = msgnum; 646: if (mp -> hghsel == 0 || mp -> hghsel < msgnum) 647: mp -> hghsel = msgnum; 648: mp -> numsel++; 649: mp -> msgstats[msgnum] |= SELECTED; 650: } 651: #endif TMA 652: mp -> msgstats[msgnum] |= UNSEEN; 653: mp -> msgflags |= SEQMOD; 654: continue; 655: } 656: break; 657: } 658: #ifdef POP 659: } 660: #endif POP 661: 662: if (aud) 663: (void) fclose (aud); 664: #ifdef MHE 665: if (mhe) 666: (void) fclose (mhe); 667: #endif MHE 668: if (noisy) 669: (void) fflush (stdout); 670: #ifdef POP 671: if (host && file) 672: done (0); 673: #endif POP 674: 675: /* */ 676: 677: #ifdef POP 678: if (host == NULL) 679: #endif POP 680: if (trnflag) { 681: if (stat (newmail, &st) != NOTOK && s1.st_mtime != st.st_mtime) 682: advise (NULLCP, "new messages have arrived!\007"); 683: else { 684: if ((i = creat (newmail, 0600)) != NOTOK) 685: (void) close (i); 686: else 687: admonish (newmail, "error zero'ing"); 688: (void) unlink (map_name (newmail)); 689: } 690: } 691: else 692: if (noisy) 693: printf ("%s not zero'd\n", newmail); 694: 695: if (msgnum == hghnum) 696: admonish (NULLCP, "no messages incorporated"); 697: else { 698: m_replace (pfolder, folder); 699: if (chgflag) 700: mp -> curmsg = hghnum + 1; 701: mp -> hghmsg = msgnum; 702: if (mp -> lowmsg == 0) 703: mp -> lowmsg = 1; 704: if (chgflag) /* sigh... */ 705: m_setcur (mp, mp -> curmsg); 706: } 707: 708: #ifdef POP 709: if (host == NULL) 710: #endif POP 711: if (locked) 712: (void) lkfclose (in, newmail); 713: else 714: (void) fclose (in); 715: 716: m_setvis (mp, 0); 717: m_sync (mp); 718: m_update (); 719: 720: #ifdef TMA 721: if (decflag && mp -> numsel > 0) { 722: if (noisy) { 723: printf ("\nIncorporating encrypted mail into %s...\n\n", folder); 724: (void) fflush (stdout); 725: } 726: 727: tmastart (); 728: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 729: if (mp -> msgstats[msgnum] & SELECTED && decipher (msgnum) == OK) { 730: if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) { 731: admonish (cp, "unable to open message"); 732: free (cp); 733: continue; 734: } 735: switch (scan (in, msgnum, 0, nfs, width, 736: msgnum == mp -> curmsg, 737: 0, 738: fstat (fileno (in), &st) != NOTOK ? (long) st.st_size 739: : 0L, 740: noisy)) { 741: case SCNEOF: 742: printf ("%*d empty\n", DMAXFOLDER, msgnum); 743: break; 744: 745: default: 746: break; 747: } 748: (void) fclose (in); 749: free (cp); 750: } 751: tmastop (); 752: 753: if (noisy) 754: (void) fflush (stdout); 755: } 756: #endif TMA 757: 758: done (0); 759: } 760: 761: /* */ 762: 763: #ifdef POP 764: void done (status) 765: int status; 766: { 767: if (file && pd != NOTOK) 768: (void) mbx_close (file, pd); 769: 770: exit (status); 771: } 772: #endif POP 773: /* */ 774: 775: #ifdef MF 776: get_uucp_mail () { 777: int child_id; 778: char buffer[BUFSIZ]; 779: struct stat st; 780: 781: (void) sprintf (buffer, "%s/%s", UUCPDIR, UUCPFIL); 782: if (stat (buffer, &st) == NOTOK || st.st_size == 0) 783: return; 784: 785: switch (child_id = vfork ()) { 786: case NOTOK: 787: admonish ("fork", "unable to"); 788: break; 789: 790: case OK: 791: execlp (umincproc, r1bindex (umincproc, '/'), NULLCP); 792: fprintf (stderr, "unable to exec "); 793: perror (umincproc); 794: _exit (-1); 795: 796: default: 797: (void) pidXwait (child_id, umincproc); 798: break; 799: } 800: } 801: #endif MF 802: 803: /* */ 804: 805: #ifdef POP 806: static int pop_action (s) 807: register char *s; 808: { 809: fprintf (pf, "%s\n", s); 810: stop += strlen (s) + 1; 811: } 812: 813: 814: static int pop_pack (s) 815: register char *s; 816: { 817: register int j; 818: char buffer[BUFSIZ]; 819: 820: (void) sprintf (buffer, "%s\n", s); 821: for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++) 822: continue; 823: for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++) 824: continue; 825: fputs (buffer, pf); 826: size += strlen (buffer) + 1; 827: } 828: 829: static int map_count () { 830: int md; 831: char *cp; 832: struct drop d; 833: struct stat st; 834: 835: if (stat (file, &st) == NOTOK) 836: return 0; 837: if ((md = open (cp = map_name (file), 0)) == NOTOK 838: || map_chk (cp, md, &d, (long) st.st_size, 1)) { 839: if (md != NOTOK) 840: (void) close (md); 841: return 0; 842: } 843: (void) close (md); 844: return (d.d_id); 845: } 846: #endif POP