home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / com / utils / elm / sources / fastmail.c < prev    next >
C/C++ Source or Header  |  1992-10-04  |  10KB  |  347 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: fastmail.c,v 4.1.1.3 90/12/06 10:38:55 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.3 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    fastmail.c,v $
  17.  * Revision 4.1.1.3  90/12/06  10:38:55  syd
  18.  * Fix getlogin returning null causing a core dump
  19.  * From: Nigel Metheringham <nigelm@ohm.york.ac.uk>
  20.  *
  21.  * Revision 4.1.1.2  90/10/07  20:56:25  syd
  22.  * Add ifndef NO_XHEADER to X-Mailer
  23.  * From: syd via request of Frank Elsner
  24.  *
  25.  * Revision 4.1.1.1  90/06/26  20:30:22  syd
  26.  * Fix boundary check on argument count
  27.  * From: Syd
  28.  *
  29.  * Revision 4.1  90/04/28  22:44:39  syd
  30.  * checkin of Elm 2.3 as of Release PL0
  31.  *
  32.  *
  33.  ******************************************************************************/
  34.  
  35. /** This program is specifically written for group mailing lists and
  36.     such batch type mail processing.  It does NOT use aliases at all,
  37.     it does NOT read the /etc/password file to find the From: name
  38.     of the user and does NOT expand any addresses.  It is meant
  39.     purely as a front-end for either /bin/mail or /usr/lib/sendmail
  40.     (according to what is available on the current system).
  41.  
  42.          **** This program should be used with CAUTION *****
  43.  
  44. **/
  45.  
  46. /** The calling sequence for this program is:
  47.  
  48.     fastmail {args}  filename full-email-address
  49.  
  50.    where args could be any (or all) of;
  51.  
  52.        -b bcc-list        (Blind carbon copies to)
  53.        -c cc-list        (carbon copies to)
  54.        -d            (debug on)
  55.        -f from         (from name)
  56.        -F from-addr        (the actual address to be put in the From: line)
  57.        -r reply-to-address     (Reply-To:)
  58.        -s subject         (subject of message)
  59. **/
  60.  
  61. #include <stdio.h>
  62. #include "defs.h"
  63. #include "patchlevel.h"
  64.  
  65. #ifdef I_TIME
  66. #  include <time.h>
  67. #endif
  68. #ifdef I_SYSTIME
  69. #  include <sys/time.h>
  70. #endif
  71. #ifdef BSD
  72. #  include <sys/types.h>
  73. #  include <sys/timeb.h>
  74. #endif
  75.  
  76. static char ident[] = { WHAT_STRING };
  77.  
  78. char *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
  79.           "Fri", "Sat", "" };
  80.  
  81. char *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  82.           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
  83.  
  84. char *get_arpa_date();
  85.  
  86. #if defined(BSD) && !defined(_POSIX_SOURCE)
  87.   char *timezone();
  88. #else
  89. #ifndef OS2
  90.   extern char *tzname[];
  91. #endif
  92. #endif
  93.  
  94. main(argc, argv)
  95. int argc;
  96. char *argv[];
  97. {
  98.  
  99.     extern char *optarg;
  100.     extern int optind;
  101.     FILE *tempfile, *mailpipe;
  102.     char hostname[NLEN], username[NLEN], from_string[SLEN], subject[SLEN];
  103.     char filename[SLEN], tempfilename[SLEN], command_buffer[256];
  104.     char replyto[SLEN], cc_list[SLEN], bcc_list[SLEN], to_list[SLEN];
  105.     char from_addr[SLEN], buffer[SLEN];
  106.     char *tmplogname;
  107.     int  c, sendmail_available, debug = 0;
  108.  
  109.         initpaths();
  110.  
  111.     from_string[0] = '\0';
  112.     subject[0] = '\0';
  113.     replyto[0] = '\0';
  114.     cc_list[0] = '\0';
  115.     bcc_list[0] = '\0';
  116.     to_list[0] = '\0';
  117.     from_addr[0] = '\0';
  118.  
  119.     while ((c = getopt(argc, argv, "b:c:df:F:r:s:")) != EOF) {
  120.       switch (c) {
  121.         case 'b' : strcpy(bcc_list, optarg);        break;
  122.         case 'c' : strcpy(cc_list, optarg);        break;
  123.         case 'd' : debug++;                    break;
  124.         case 'f' : strcpy(from_string, optarg);    break;
  125.         case 'F' : strcpy(from_addr, optarg);        break;
  126.         case 'r' : strcpy(replyto, optarg);        break;
  127.         case 's' : strcpy(subject, optarg);        break;
  128.         case '?' :
  129.           usage();
  130.        }
  131.     }
  132.  
  133.     if (optind >= argc)
  134.       usage();
  135.  
  136.     strcpy(filename, argv[optind++]);
  137.  
  138.     if (optind >= argc)
  139.           usage();
  140.  
  141. #ifdef HOSTCOMPILED
  142.     strncpy(hostname, HOSTNAME, sizeof(hostname));
  143. #else
  144.     gethostname(hostname, sizeof(hostname));
  145.     gethostdomain(buffer, sizeof(buffer));
  146.         strcat(hostname, buffer);
  147. #endif
  148.  
  149.     tmplogname = getenv("LOGNAME");
  150.     if (tmplogname != NULL)
  151.       strcpy(username, tmplogname);
  152.     else
  153.       username[0] = '\0';
  154.  
  155. #ifndef OS2
  156.     if (strlen(username) == 0)
  157.       cuserid(username);
  158. #endif
  159.  
  160.     if (access(filename, READ_ACCESS) == -1) {
  161.       fprintf(stderr, "Error: can't find file %s!\n", filename);
  162.       exit(1);
  163.     }
  164.  
  165.     sprintf(tempfilename, "%s%d.fm", tempdir, getpid());
  166.  
  167.     if ((tempfile = fopen(tempfilename, "w")) == NULL) {
  168.       fprintf(stderr, "Couldn't open temp file %s\n", tempfilename);
  169.       exit(1);
  170.     }
  171.  
  172.     /** Subject must appear even if "null" and must be first
  173.         at top of headers for mail because the
  174.         pure System V.3 mailer, in its infinite wisdom, now
  175.         assumes that anything the user sends is part of the
  176.         message body unless either:
  177.         1. the "-s" flag is used (although it doesn't seem
  178.            to be supported on all implementations??)
  179.         2. the first line is "Subject:".  If so, then it'll
  180.            read until a blank line and assume all are meant
  181.            to be headers.
  182.         So the gory solution here is to move the Subject: line
  183.         up to the top.  I assume it won't break anyone elses program
  184.         or anything anyway (besides, RFC-822 specifies that the *order*
  185.         of headers is irrelevant).  Gahhhhh....
  186.     **/
  187.     fprintf(tempfile, "Subject: %s\n", subject);
  188.  
  189.     if (strlen(from_string) > 0)
  190.       if (strlen(from_addr) > 0)
  191.           fprintf(tempfile, "From: %s (%s)\n", from_addr, from_string);
  192.       else
  193.           fprintf(tempfile, "From: %s@%s (%s)\n", username, hostname,
  194.               from_string);
  195.     else
  196.       if (strlen(from_addr) > 0)
  197.         fprintf(tempfile, "From: %s\n", from_addr);
  198.       else
  199.         fprintf(tempfile, "From: %s@%s\n", username, hostname);
  200.  
  201.     fprintf(tempfile, "Date: %s\n", get_arpa_date());
  202.  
  203.     if (strlen(replyto) > 0)
  204.       fprintf(tempfile, "Reply-To: %s\n", replyto);
  205.  
  206.     while (optind < argc)
  207.           sprintf(to_list, "%s%s%s", to_list, (strlen(to_list) > 0? " ":""),
  208.           argv[optind++]);
  209.  
  210.     fprintf(tempfile, "To: %s\n", to_list);
  211.  
  212.     if (strlen(cc_list) > 0)
  213.       fprintf(tempfile, "Cc: %s\n", cc_list);
  214.  
  215. #ifndef NO_XHEADER
  216.     fprintf(tempfile, "X-Mailer: fastmail [version %s PL%d]\n",
  217.       VERSION, PATCHLEVEL);
  218. #endif /* !NO_XHEADER */
  219.     fprintf(tempfile, "\n");
  220.  
  221.     fclose(tempfile);
  222.  
  223.     /** now we'll cat both files to /bin/rmail or sendmail... **/
  224.  
  225.     sendmail_available = (access(sendmail, EXECUTE_ACCESS) != -1);
  226.  
  227.     if (debug)
  228.         printf("Mailing to %s%s%s%s%s [via %s]\n", to_list,
  229.             (strlen(cc_list) > 0 ? " ":""), cc_list,
  230.             (strlen(bcc_list) > 0 ? " ":""), bcc_list,
  231.             sendmail_available? "sendmail" : "rmail");
  232.  
  233. #ifdef OS2
  234.     sprintf(command_buffer, "%s -t", mailer);
  235. #else
  236.     sprintf(command_buffer, "cat %s %s | %s %s %s %s",
  237.         tempfilename, filename,
  238.             sendmail_available? sendmail : mailer,
  239.         to_list, cc_list, bcc_list);
  240. #endif
  241.  
  242.     if (debug)
  243.       printf("%s\n", command_buffer);
  244.  
  245. #ifdef OS2
  246.         mailpipe = popen(command_buffer, "w");
  247.     tempfile = fopen(tempfilename, "r");
  248.         while ( fgets(buffer, sizeof(buffer), tempfile) != NULL )
  249.           fputs(buffer, mailpipe);
  250.         fclose(tempfile);
  251.     tempfile = fopen(filename, "r");
  252.         while ( fgets(buffer, sizeof(buffer), tempfile) != NULL )
  253.           fputs(buffer, mailpipe);
  254.         fclose(tempfile);
  255.         pclose(mailpipe);
  256. #else
  257.     c = system(command_buffer);
  258. #endif
  259.  
  260.     unlink(tempfilename);
  261.  
  262.     exit(c != 0);
  263. }
  264.  
  265.  
  266. usage()
  267. {
  268.   printf("\nUsage: fastmail {args} filename address(es)\n");
  269.   printf( "\nwhere {args} can be:\n\n");
  270.   printf("\t-b bcc-list       addresses to send blind-carbon copies to\n");
  271.   printf("\t-c cc-list        addresses to send carbon copies to\n");
  272.   printf("\t-d                debug\n");
  273.   printf("\t-f from-name      sender's full name\n");
  274.   printf("\t-F from-addr      sender's mail address\n");
  275.   printf("\t-r reply-to       reply-to mail address\n");
  276.   printf("\t-s subject        subject of the message\n");
  277.   exit(1);
  278. }
  279.  
  280.  
  281. char *get_arpa_date()
  282. {
  283.     /** returns an ARPA standard date.  The format for the date
  284.         according to DARPA document RFC-822 is exemplified by;
  285.  
  286.                      Mon, 12 Aug 85 6:29:08 MST
  287.  
  288.     **/
  289.  
  290.     static char buffer[SLEN];    /* static character buffer       */
  291.     struct tm *the_time;        /* Time structure, see CTIME(3C) */
  292.     long       junk;        /* time in seconds....         */
  293. #ifndef    _POSIX_SOURCE
  294.     struct tm *localtime();
  295. #endif
  296. #ifdef BSD
  297. #  ifndef TZ_MINUTESWEST
  298.     struct timeb loc_time;    /* of course this is different! */
  299. #    ifndef _POSIX_SOURCE
  300.     long time();
  301. #    endif
  302. #  else
  303.     struct  timeval  time_val;
  304.     struct  timezone time_zone;
  305. #  endif
  306. #else
  307.     time_t time();
  308. #endif
  309.  
  310. #ifdef BSD
  311. #  ifndef TZ_MINUTESWEST
  312.     junk = (long) time((long *) 0);
  313.     ftime(&loc_time);
  314. #  else
  315.     gettimeofday(&time_val, &time_zone);
  316.     junk = time_val.tv_sec;
  317. #  endif
  318. #else
  319.     junk = time(0);    /* this must be here for it to work! */
  320. #endif
  321.     the_time = localtime(&junk);
  322.  
  323.     sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
  324.       arpa_dayname[the_time->tm_wday],
  325.       the_time->tm_mday % 32,
  326.       arpa_monname[the_time->tm_mon],
  327.       the_time->tm_year % 100,
  328.       the_time->tm_hour % 24,
  329.       the_time->tm_min  % 61,
  330.       the_time->tm_sec  % 61,
  331. #if defined(BSD) && !defined(_POSIX_SOURCE)
  332. #  ifndef TZ_MINUTESWEST
  333.       timezone(loc_time.time_zone, the_time->tz_isdst));
  334. #  else
  335. #   ifdef GOULD_NP1
  336.       the_time->tm_zone);
  337. #   else
  338.       timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
  339. #   endif
  340. #  endif
  341. #else
  342.       tzname[the_time->tm_isdst]);
  343. #endif
  344.  
  345.     return( (char *) buffer);
  346. }
  347.