home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / dmail / sendmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-29  |  9.6 KB  |  513 lines

  1. /*
  2.  *  SENDMAIL.C
  3.  *
  4.  *  (C) Copyright 1985-1990 by Matthew Dillon,    All Rights Reserved.
  5.  *
  6.  *  Global Routines:    DO_REPLY()
  7.  *            DO_ASK()
  8.  *
  9.  *  Static Routines:    WORD_SIZE()
  10.  *            FOPEN_SCRATCH()
  11.  *            FCLOSE_SCRATCH()
  12.  *            RUN_VI()
  13.  *            SEND_MAIL()
  14.  *            ARCHIVE_MAIL()
  15.  *            COPY_HEADER()
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <sys/file.h>
  23. #ifdef UNIX
  24. #include <sys/ioctl.h>
  25. #endif
  26. #include <sys/time.h>
  27. #include <signal.h>
  28. #include "dmail.h"
  29. #include "config.h"
  30.  
  31. FILE *fi;
  32. char file[64];
  33.  
  34. Prototype int  do_reply (char *garbage, int itext);
  35. Prototype int  do_ask (void);
  36.  
  37. Local void copy_header (FILE *fi, char *var);
  38. Local void fopen_scratch (void);
  39. Local void fclose_scratch (void);
  40. Local int  word_size (register char *str);
  41. Local int  run_vi (void);
  42. Local void send_mail (void);
  43. Local int  archive_mail (char *ptr);
  44.  
  45. int
  46. do_reply (char *garbage, int itext)
  47. {
  48.     int i, j;
  49.     int anyargs  = 0;
  50.     int len;
  51.     char *ptr;
  52.     static char buf[1024];
  53.     char *istr;
  54.  
  55.     if (!(istr = get_var(LEVEL_SET, "_headchar")))
  56.     istr = ">";
  57.     if (push_base()) {
  58.     push_break();
  59.     pop_base();
  60.     fclose_scratch();
  61.     puts ("ABORTED, no mail sent");
  62.     unlink(file);
  63.     pop_break();
  64.     return (-1);
  65.     }
  66.     fopen_scratch();
  67.     strcpy (buf, "To: ");
  68.     for (i = 1; i < ac; ++i) {
  69.     char *tail;
  70.     long msgNo = strtol(av[i], &tail, 0);
  71.  
  72.     if (msgNo > 0 && *tail == 0) {
  73.         if ((j = indexof(msgNo)) < 0) {
  74.         puts ("No such message");
  75.         fclose_scratch();
  76.         unlink(file);
  77.         pop_break();
  78.         return (-1);
  79.         }
  80.         Current = j;
  81.     } else {
  82.         if (anyargs)
  83.         strcat (buf, ", ");
  84.         anyargs = 1;
  85.         strcat (buf, av[i]);
  86.     }
  87.     }
  88.     len = strlen(buf);
  89.     switch (itext) {
  90.     case R_FORWARD:
  91.     case R_FWDINCL:
  92.     strcat (buf, "\n");
  93.     fputs (buf, fi);
  94.     fputs ("Subject: \n", fi);
  95.     break;
  96.     case R_INCLUDE:
  97.     case R_REPLY:
  98.     if (anyargs) {
  99.         strcat (buf, ", ");
  100.         len = strlen(buf);
  101.     }
  102.     buf[len] = 0;
  103.     if (Current >= 0) {
  104.         char *rf = get_var(LEVEL_SET, "replyfields");
  105.         if (rf == NULL)
  106.         rf = "";
  107.         while (*rf) {    /* attempt to find the fields listed */
  108.         char *re;
  109.         char *ptr;
  110.         char c;
  111.         for (re = rf; *re && *re != ' ' && *re != 9; ++re);
  112.         c = *re;
  113.         *re = 0;
  114.         ptr = get_field(rf);
  115.         if (*ptr) {
  116.             *re = c;
  117.             sprintf (buf + len, "%s\n", ptr);
  118.             break;
  119.         }
  120.         *re = c;
  121.         while (*re == ' ' || *re == 9)
  122.             ++re;
  123.         rf = re;
  124.         }
  125.         if (*rf == 0) {
  126.         sprintf (buf + len, "%.*s\n",
  127.             word_size(Entry[Current].from), Entry[Current].from);
  128.         }
  129.     }
  130.     fputs (buf, fi);
  131.  
  132.     fputs ("Cc: ", fi);
  133.     ptr = get_field ("Cc:");
  134.     if (*ptr)
  135.         fputs (ptr, fi);
  136.  
  137.     fputs ("\nSubject: Re: ", fi);
  138.     {
  139.         char *ptr = get_field("Subject:");
  140.         for (;;) {                    /*    skip multiple Re:'s */
  141.         while (*ptr == ' ' || *ptr == '\t')
  142.             ++ptr;
  143.         if (strnicmp(ptr, "re:", 3) == 0) {
  144.             ptr += 3;
  145.             continue;
  146.         }
  147.         break;
  148.         }
  149.         fputs(ptr, fi);
  150.     }
  151.     fputs ("\n", fi);
  152.     break;
  153.     case R_MAIL:
  154.     fputs (buf, fi);
  155.     fputs ("\n", fi);
  156.     fputs ("Cc: \n", fi);
  157.     fputs ("Bcc: \n", fi);
  158.     fputs ("Subject: \n", fi);
  159.     break;
  160.     default:
  161.     puts ("INTERNAL STUPID MAIL ERROR: REPLY");
  162.     break;
  163.     }
  164.     copy_header (fi, "headfile");
  165.     fputs ("\n\n", fi);
  166.     if (itext == R_FORWARD || itext == R_FWDINCL || itext == R_INCLUDE) {
  167.     position_current();
  168.     if (itext == R_FORWARD || itext == R_FWDINCL) {
  169.         if (Current >= 0)
  170.         fprintf (fi, "ORIGINALLY From %s\n", Entry[Current].from);
  171.     } else {
  172.         skip_to_data (m_fi);
  173.     }
  174.     while ((fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) && !isfrom(Buf)) {
  175.         if (itext == R_INCLUDE || itext == R_FWDINCL)
  176.         fputs(istr, fi);
  177.         fputs (Buf, fi);
  178.     }
  179.     fputs ("\n", fi);
  180.     }
  181.     copy_header (fi, "sigfile");
  182.     fclose_scratch();
  183.     if (itext != R_MAIL) {
  184.     push_break();
  185.     if (Current >= 0) {
  186.         Entry[Current].status |= ST_SCR;
  187.         write_file("t:Original", O_CREAT | O_TRUNC, ST_SCR, 0);
  188.         Entry[Current].status &= ~ST_SCR;
  189.     }
  190.     pop_break();
  191.     }
  192.     j = -1;
  193. loop:
  194.     ++j;
  195.     if (run_vi() || j) {
  196.     push_break();
  197.     switch (do_ask()) {
  198.     case 1:
  199.         puts ("SENDING.. wait");
  200.         send_mail();
  201.         {
  202.         FILE *li = fopen(file, "r");
  203.         char buf[128], *ptr = NULL;
  204.  
  205.         if (li) {
  206.             while (fgets(buf, 128, li) && buf[0] != '\n') {
  207.             if (strncmp(buf, "Farchive:", 9) == 0) {
  208.                 buf[strlen(buf)-1] = '\0';
  209.                 for (ptr = buf + 9; *ptr == ' '; ++ptr);
  210.                 if (ptr[0] == '$')
  211.                 ptr = get_var(LEVEL_SET, ptr+1);
  212.                 break;
  213.             }
  214.             }
  215.             fclose(li);
  216.         }
  217.         archive_mail(ptr);
  218.         }
  219.         unlink(file);
  220.         break;
  221.     case 2:
  222.         pop_break();
  223.         goto loop;
  224.     default:
  225.         unlink (file);
  226.         break;
  227.     }
  228.     pop_base();
  229.     pop_break();
  230.     } else {
  231.     puts ("File not modified or ABORTED, no mail sent");
  232.     unlink(file);
  233.     pop_base();
  234.     }
  235.     unlink ("T:Original");
  236. }
  237.  
  238. int
  239. do_ask (void)
  240. {
  241.     char in[256];
  242.  
  243.     if (!S_ask)
  244.     return (1);
  245.     fputs ("\n(Send, Vi, Quit) ?", stdout);
  246.     fflush(stdout);
  247.     gets (in);
  248.     switch (in[0]) {
  249.     case 's':
  250.     case 'S':
  251.     return (1);
  252.     case 'q':
  253.     case 'Q':
  254.     puts ("ABORT, no mail sent");
  255.     return (3);
  256.     case 'v':
  257.     case 'V':
  258.     default:
  259.     return (2);
  260.     }
  261. }
  262.  
  263. static void
  264. copy_header (FILE *fi, char *var)
  265. {
  266.     FILE *fs;
  267.     char *ptr;
  268.     char *tmp = NULL;
  269.  
  270.     if (ptr = get_var (LEVEL_SET, var)) {
  271.     push_break();
  272.     fs = fopen(ptr, "r");
  273.     if (fs == NULL) {   /*    check uulib:    */
  274.         tmp = xmalloc(strlen(ptr) + strlen(MakeConfigPath(UULIB, "")) + 1);
  275.         sprintf(tmp, "%s%s", MakeConfigPath(UULIB, ""), ptr);
  276.         fs = fopen(tmp, "r");
  277.     }
  278.     if (fs) {
  279.         while (fgets (Buf, MAXFIELDSIZE, fs) != NULL)
  280.         fputs (Buf, fi);
  281.         fclose (fs);
  282.     } else {
  283.         printf ("Cannot open header file %d %s\n", strlen(ptr), ptr);
  284.         perror ("fopen");
  285.     }
  286.     if (tmp)
  287.         free(tmp);
  288.     pop_break();
  289.     }
  290. }
  291.  
  292. static void
  293. fopen_scratch (void)
  294. {
  295.     static int c;
  296.     int fd;
  297.  
  298.     sprintf(file, "t:dmt%d%d", getpid(), c++);
  299.     fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0700);
  300.     if (fd < 0) {
  301.     perror ("Dmail, cannot open scratch file");
  302.     done (30);
  303.     }
  304. #ifdef AMIGA        /*    fix bug in Lattice C fdopen */
  305. #ifndef _DCC
  306.     fi = fopen("nil:", "w");
  307.     fclose(fi);
  308. #endif
  309. #endif
  310.     fi = fdopen(fd, "w+");
  311. }
  312.  
  313. static void
  314. fclose_scratch (void)
  315. {
  316.     if (fi != NULL) {
  317.     fflush (fi);
  318.     fclose (fi);
  319.     fi = NULL;
  320.     }
  321. }
  322.  
  323. static int
  324. word_size (register char *str)
  325. {
  326.     register int size = 0;
  327.  
  328.     while (*str) {
  329.     if (*str == ' ')
  330.         return (size);
  331.     ++str;
  332.     ++size;
  333.     }
  334.     return (size);
  335. }
  336.  
  337. static int
  338. run_vi (void)
  339. {
  340. #ifdef UNIX
  341.     char buf[64];
  342.     int ret;
  343.     volatile int pid = 0;
  344. #endif
  345.     struct stat stat1, stat2;
  346.     char *argv[3];
  347.  
  348.     argv[0] = visual;
  349.     argv[1] = file;
  350.     argv[2] = NULL;
  351.     if (push_base()) {
  352.     push_break();
  353.     pop_base();
  354. #ifdef UNIX
  355.     if (pid) {
  356.         kill (pid, SIGKILL);
  357.         sprintf (buf, "t:Ex%d", pid); unlink (buf);
  358.         sprintf (buf, "t:Rx%d", pid); unlink (buf);
  359.         wait(0);
  360.         system ("clear; reset ; clear");
  361.         pid = 0;
  362.     }
  363. #endif
  364.     pop_break();
  365.     return (0);
  366.     }
  367.     stat1.st_mtime = stat2.st_mtime = stat1.st_ctime = stat2.st_ctime = 0;
  368.     stat (file, &stat1);
  369.     if (S_novibreak)
  370.     push_break();
  371.  
  372. #ifdef UNIX
  373.     pid = vfork();
  374.     if (!pid) {
  375.     execv (visual, argv);
  376.     printf ("Cannot exec visual: %s\n", visual);
  377.     _exit (1);  /* ifdef UNIX */
  378.     }
  379.     while ((ret = wait(0)) > 0) {
  380.     if (ret == pid)
  381.         break;
  382.     }
  383. #endif
  384. #ifdef AMIGA
  385.     {
  386.     short
  387.         i;
  388.     static char
  389.         buf [128];
  390.  
  391.     strcpy (buf, argv [0]);
  392.     for (i = 1; argv [i]; ++i) {
  393.         strcat (buf, " ");
  394.         strcat (buf, argv [i]);
  395.     }
  396.     if (DOSBase->dl_lib.lib_Version >= 36)
  397.         SystemTags (buf,
  398.             SYS_UserShell, 1,
  399.             TAG_DONE);
  400.     else
  401.         Execute (buf, 0, 0);
  402.     }
  403. #endif
  404.     if (S_novibreak)
  405.     pop_break();
  406.     stat (file, &stat2);
  407.     pop_base();
  408.     return (!(stat1.st_mtime==stat2.st_mtime));
  409. }
  410.  
  411.  
  412. #ifdef UNIX
  413. static void
  414. send_mail (void)
  415. {
  416.     int fd, stdin_fd;
  417.     char *argv[6];
  418.  
  419.     push_break();
  420.     argv[0] = S_sendmail;
  421.     argv[1] = "-t";
  422.     argv[2] = "-oem";
  423.     argv[3] = "-i";
  424.     if (S_verbose) {
  425.     argv[4] = "-v";
  426.     argv[5] = NULL;
  427.     } else {
  428.     argv[4] = NULL;
  429.     }
  430.  
  431.     fd = open (file, O_RDONLY, 0);
  432.     if (fd < 0) {
  433.     perror ("Dmail, Cannot open scratch file");
  434.     done (30);
  435.     }
  436.     lseek(fd, 0L, 0);
  437.  
  438.     stdin_fd = dup (0);
  439.     dup2 (fd, 0);    /* STDIN = message file */
  440.     close(fd);        /* don't need message file anymore  */
  441.     if (!fork()) {
  442.     int fd = open("/dev/tty", O_RDWR, 0);
  443.     if (fd >= 0) {
  444.         ioctl(fd, TIOCNOTTY, 0);
  445.         close(fd);
  446.         freopen("/dev/null", "w", stdout);
  447.         freopen("/dev/null", "w", stderr);
  448.     }
  449.     execv (S_sendmail, argv);
  450.     printf ("Unable to exec sendmail: %s\n", S_sendmail);
  451.     _exit (1);  /* ifdef UNIX */
  452.     }
  453.     dup2 (stdin_fd, 0);     /* restore STDIN    */
  454.     close(stdin_fd);
  455.     if (S_verbose) {
  456.     puts ("Waiting for sendmail...");
  457.     wait (0);
  458.     puts ("Sendmail done");
  459.     }
  460.     pop_break();
  461. }
  462.  
  463. #endif
  464. #ifdef AMIGA
  465.  
  466. static void
  467. send_mail (void)
  468. {
  469.     static char Buf[256];
  470.  
  471.     push_break();
  472.     sprintf(Buf, "%s < %s%s -f %s", S_sendmail, file, (S_verbose ? " -v" : ""), user_name);
  473.  
  474.     printf("Sending\n", Buf);
  475.     if (Execute(Buf, 0, 0) == 0)
  476.     printf("Unable to run: %s\n", Buf);
  477.  
  478.     pop_break();
  479. }
  480. #endif
  481.  
  482. static int
  483. archive_mail (char *ptr)
  484. {
  485.     FILE *ifi, *ofi;
  486.     long tim = time(NULL);
  487.  
  488.     if (!ptr)
  489.     ptr = get_var(LEVEL_SET, "archive");
  490.     if (ptr == NULL || *ptr == '\0')
  491.     return(-1);
  492.     ifi = fopen(file, "r");
  493.     if (ifi == NULL) {
  494.     puts ("Cannot open scratch file");
  495.     return(-1);
  496.     }
  497.     ofi = fopen(ptr, "a");
  498.     if (ofi == NULL) {
  499.     puts ("Cannot open archive file");
  500.     fclose(ifi);
  501.     return(-1);
  502.     }
  503.     sprintf (Buf, "\nFrom %s (ARCHIVE)\n", user_name);
  504.     fputs (Buf, ofi);
  505.     sprintf (Buf, "Date: %s\n", atime(&tim));
  506.     fputs (Buf, ofi);
  507.     while (fgets (Buf, MAXFIELDSIZE, ifi))
  508.     fputs (Buf, ofi);
  509.     fclose(ofi);
  510.     fclose(ifi);
  511.     return (1);
  512. }
  513.