home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / nn.tar / nn-6.5.1 / contrib / recmail.c < prev    next >
C/C++ Source or Header  |  1995-04-29  |  8KB  |  305 lines

  1. /*
  2.  *    Copyright (c) 1990 Tom Dawes-Gamble.
  3.  *      For Copyright restrictions see the README file distributed with nn. 
  4.  *          
  5.  *    Mail sender for nn with C news and smail.
  6.  *    
  7.  *      Written by Tom Dawes-Gamble Texas Instruments Ltd, Bedford England.
  8.  *
  9.  *    e-mail tmdg@texins.uucp
  10.  *      uucp   ..!ukc.co.uk!pyrltd!miclon!texins!tmdg
  11.  *
  12.  *      When I installed nn with Cnews I could not find an equivalent
  13.  *    to the Bnews recmail so I wrote this to do the job.
  14.  *    It seems to work for me.
  15.  *    I have no idea how this will work for mailers other than smail
  16.  *
  17.  *    YOU WILL need to look at the way get_host_name works for you system
  18.  *    
  19.  *    If you use this program please let me know so that I can mail you
  20.  *    any enhancements.
  21.  *
  22.  */
  23.  
  24. /*  you can use the smail defs if required */
  25. #ifdef SMAIL_DEFS_H
  26. #include  SMAIL_DEFS_H
  27. #else
  28. #define MYDOM ".uucp"
  29. #endif /* SMAIL_DEFS_H */
  30.  
  31. #define MAILER "/bin/smail"   /* The pathname of your mailer */
  32.  
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <string.h>
  36. #include <pwd.h>
  37. #include <sys/utsname.h>
  38. #include <sys/types.h>
  39. #include <time.h>
  40.  
  41. /* where is the local time zone name ? */
  42.  
  43.     /* xenix 2.3.2 has this in the tm structure */
  44. /*#define TIMEZONE_NAME(tm) ((tm)->tm_name) /* */
  45.     /* some systems have it here */
  46. #define TIMEZONE_NAME(tm) (asctime(tm)?tzname[(tm)->tm_isdst?1:0]:"") /* */
  47.  
  48. extern char *getlogin();
  49. extern char *getenv();
  50. extern char *malloc();
  51. extern char *mktemp();
  52. extern struct passwd *getpwnam();
  53. void get_host_name();
  54.  
  55. char *day_name[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  56.  
  57. char *month[] = {    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  58.             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  59.  
  60. char *mail_template = "/tmp/rmXXXXXX";
  61. char *mail_spool = "/tmp/rmXXXXXX";
  62.  
  63. #undef BUFSIZ
  64. #define BUFSIZ 1024          /* a 1024 byte buffer should be enough */
  65.  
  66. #define ERROR_MSG_0 "%s: Unable to read stdin ** Error = %d\n"
  67. #define ERROR_MSG_1 "%s: Unable to create spool file ** Error = %d\n"
  68.  
  69. FILE *sfd, *fopen();
  70.  
  71. void send_the_message();
  72. void build_the_header();
  73.  
  74. int main(argc, argv)
  75. int argc;
  76. char **argv;
  77. {
  78.     char inbuff[BUFSIZ];    /*  Buffer for stdin  */
  79.     char pbuff[BUFSIZ];    /*  Buffer to hold the name of recipients */
  80.         char **tolist, *tonames[100];  /* I think that should cope for now */ 
  81.  
  82.     if (argc != 1) {
  83.         (void) fprintf(stderr,
  84.             "%s does not allow any arguments yet!\n", argv[0]);
  85.         exit(1);
  86.     }
  87.     tolist = tonames;
  88.  
  89. /*  FIX  this could be much better */
  90.     *tolist++ = MAILER;
  91.     *tolist++ = "-f";
  92.     *tolist++ = mktemp(strcpy(mail_spool, mail_template));
  93.     *tolist = pbuff;
  94.  
  95.     if ((sfd = fopen(mail_spool, "w")) == NULL){
  96.         (void) fprintf(stderr, ERROR_MSG_1, argv[0], MAILER, errno);
  97.         exit(1);
  98.     }
  99.     build_the_header();
  100.  
  101.     /* Now send the mail down the tube */
  102.  
  103.     while((fgets(inbuff, BUFSIZ, stdin)) == inbuff){
  104.             /* strip blind copies */
  105.         if (strncmp(inbuff, "Bc: ", 4)){ /* true if not Bc: */
  106.             (void) fprintf(sfd, "%s", inbuff);
  107.         }
  108.          if (!strncmp(inbuff, "To: ", 4)){
  109.             tolist += get_names(inbuff, tolist);
  110.         } else if (!strncmp(inbuff, "Cc: ", 4)){
  111.             tolist += get_names(inbuff, tolist);
  112.         } else if (!strncmp(inbuff, "Bc: ", 4)){
  113.             tolist += get_names(inbuff, tolist);
  114.         } else if (!strcmp(inbuff, "\n")){
  115.             break;
  116.         }
  117.     }
  118.     while((fgets(inbuff, BUFSIZ, stdin)) == inbuff){
  119.         (void) fprintf(sfd, "%s", inbuff);
  120.     }
  121.     (void) fflush(sfd);
  122.     (void) fclose(sfd);
  123.     *tolist = NULL;
  124.     send_the_message(tonames);
  125.     exit(0);
  126. }
  127.  
  128. get_names(line_buffer, to_names)
  129. char *line_buffer;
  130. char **to_names;
  131. {
  132.     char *curr_name;
  133.     char *next_name;
  134.     int name_count;
  135.  
  136.     name_count = 0;
  137.     (void) strip_comments(line_buffer);
  138.         (void) check_for_bracket(line_buffer);
  139.     while (next_name = strchr(line_buffer, ' ')){
  140.         *next_name++ = '\0';
  141.         while (*next_name == ' ')
  142.             next_name++;
  143.         curr_name = *to_names;
  144.         curr_name += strlen(curr_name) + 1;
  145.         (void) strcpy(*to_names++, line_buffer);
  146.         *to_names = curr_name;
  147.         (void) strcpy(line_buffer, next_name);
  148.         name_count++;
  149.     }
  150.     if (strlen(line_buffer)){
  151.         curr_name = *to_names;
  152.         curr_name += strlen(curr_name) + 1;
  153.         (void) strcpy(*to_names++, line_buffer);
  154.         *to_names = curr_name;
  155.         name_count++;
  156.     }
  157.     return name_count;
  158. }
  159.     
  160. /*    FIX    Correct the order of the head lines */
  161. void
  162. build_the_header()
  163. {
  164.     struct passwd *login, *getpwnam(), *getpwuid();
  165.     struct passwd *effective;
  166.     struct tm *gmt;
  167.     struct tm *loc;
  168.     long tics;
  169.     char hostname[9];
  170.  
  171.     if(!(login = getpwnam(getlogin())))
  172.         login = getpwuid(getuid());
  173.     get_host_name(hostname);
  174.     gmt = (struct tm *) malloc(sizeof (struct tm));
  175.     tics = time((long *) 0);
  176.     loc = gmtime(&tics );
  177.     *gmt = *loc;
  178.     loc = localtime(&tics );
  179.     (void) fprintf(sfd, "%s\n", login->pw_name);
  180. /* the Reply to: line doesn't look nice on xenix */
  181.     (void) fprintf(sfd, "Reply-To:   %s@%s%s (%s)\n", login->pw_name,
  182.         hostname, MYDOM, login->pw_comment);
  183. /* I'm not sure about this so if it's wrong please tell me */
  184.     if (getuid() != login->pw_uid){
  185.         effective = getpwuid(getuid());
  186.         (void) fprintf(sfd, "Sender:     %s@%s%s (%s)\n", 
  187.             effective->pw_name, hostname, MYDOM,
  188.             effective->pw_comment);
  189.     }
  190.     (void) fprintf(sfd, "Message-Id: <%d%02d%02d%02d%02d.%s%05d@%s%s>\n", 
  191.         gmt->tm_year, (gmt->tm_mon + 1), gmt->tm_mday,
  192.         gmt->tm_hour, gmt->tm_min,
  193.         "AA", getpid(), hostname, MYDOM);
  194.     (void) fprintf(sfd, "Date: %s, %d %s %d %02d:%02d:%02d GMT\n", 
  195.         day_name[gmt->tm_wday], gmt->tm_mday, month[gmt->tm_mon],
  196.         gmt->tm_year, gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
  197.     (void) fprintf(sfd, "From: %s@%s%s \(%s\)\n",
  198.          login->pw_name, hostname, MYDOM, login->pw_comment);
  199. /*  To help local people know when you sent the mail */
  200.     if (loc->tm_isdst || strncmp(TIMEZONE_NAME(loc),  "GMT", 3))
  201.         (void) fprintf(sfd,
  202.             "X-Local-time: %s, %d %s %d %02d:%02d:%02d %s\n", 
  203.             day_name[loc->tm_wday], loc->tm_mday,
  204.             month[loc->tm_mon], loc->tm_year, loc->tm_hour,
  205.             loc->tm_min, loc->tm_sec, TIMEZONE_NAME(loc));
  206. }
  207.  
  208. void
  209. send_the_message(arg_list)
  210. char *arg_list[];
  211. {
  212.     int  cid, rid;
  213.     int  child_stat;
  214.  
  215.     /*fprintf(stderr, "%s\n", *arg_list);*/
  216.  
  217.     if (cid = fork()){
  218.         if ( (rid = wait((int *)&child_stat)) == -1){
  219.             (void) fprintf(stderr, "%d %d %d %x\n",
  220.                     cid, rid, errno, child_stat);
  221.         } else  {
  222.             cid = 0;
  223. /* FIX I would like to unlink but can't since it causes smail to fail */
  224.         /*(void) unlink(mail_spool);*/
  225.         }
  226.     } else {
  227.         (void) execvp(*arg_list, arg_list);
  228.     }
  229.     return;
  230.     
  231. }
  232.  
  233. /* FIX  This is for xenix  System V can use unames */
  234. void
  235. get_host_name(hostname)
  236. char *hostname;
  237. {
  238.     FILE *hfd;
  239.     char *h;
  240.     
  241.     hfd = fopen("/etc/systemid", "r");
  242.     if (hfd == NULL) {
  243. #ifdef HOSTNAME
  244.         strcpy(hostname, HOSTNAME);    /* maybe from smail defs.h */
  245. #else
  246.         strcpy(hostname, "UNKNOWN");
  247. #endif
  248.         return;
  249.     }
  250.     h = fgets(hostname, 9, hfd);
  251.     (void) fclose(hfd);
  252.     while (*h != '\0')
  253.         if (*h == '\n')
  254.             *h = '\0';
  255.         else
  256.             h++;
  257.     return;
  258. }
  259.  
  260. /*    remove first word and any comments  */
  261. /*    Note comment is totaly removed and replaced by space  */
  262. /*    this may need changeing  */
  263. /*    all space will be compressed to a single space  */
  264. /*      FIX required to handle tabs at the moment \tword starting
  265.     a line will be lost but thats not what I want */
  266.  
  267. strip_comments(buff)
  268. char *buff;
  269. {
  270.     char *begin, *end;
  271.  
  272.     if (end = strchr(buff, ' ')){
  273.         while (*end == ' ') end++;
  274.         (void) strcpy(buff, end);
  275.     }
  276.     while(begin = strchr(buff, '(')){
  277.         end = strchr(begin, ')');
  278.         end++;
  279.         (void) strcpy(begin, end);
  280.     }
  281.     end = strchr(buff, '\n');
  282.     *end = '\0';
  283.     return;
  284. }
  285.  
  286.  
  287. /*    This routine test the line for <machine readable field>
  288.         if found then only those fields are left   */
  289.  
  290. check_for_bracket(buff)
  291. char *buff;
  292. {
  293.     char *begin, *end;
  294.  
  295.     while(begin = strchr(buff, '<')){
  296.         begin++;
  297.         (void) strcpy(buff, begin);
  298.         end = strchr(begin, '>');
  299.         *end = ' ';
  300.         buff = end + 1;
  301.     }
  302.     return;
  303. }
  304.  
  305.