home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elm.lzh / ELM / UTILS / FROM.C < prev    next >
C/C++ Source or Header  |  1993-03-18  |  11KB  |  445 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: from.c,v 4.1 90/04/28 22:44:41 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1 $   $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:    from.c,v $
  17.  * Revision 4.1  90/04/28  22:44:41  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  * 
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** print out whom each message is from in the pending folder or specified 
  24.     one, including a subject line if available.. 
  25.  
  26. **/
  27.  
  28. #include <stdio.h>
  29. #include <pwd.h>
  30. #include "defs.h"
  31.  
  32. static char ident[] = { WHAT_STRING };
  33.  
  34. #ifdef MMDF
  35. char username[SLEN] = {0};
  36. #endif /* MMDF */
  37.  
  38. #define LINEFEED    (char) 13
  39.  
  40. #define metachar(c)    (c == '=' || c == '+' || c == '%')
  41.  
  42. FILE *mailfile;
  43.  
  44. int   number = 0,    /* should we number the messages?? */
  45.       verbose = 0;    /* and should we prepend a header? */
  46.  
  47. main(argc, argv)
  48. int argc;
  49. char *argv[];
  50. {
  51.     char infile[SLEN], *cp ;
  52.     int  multiple_files = 0, output_files = 0, c;
  53.     struct passwd *pass;
  54. #ifndef    _POSIX_SOURCE
  55.     struct passwd *getpwuid();
  56. #endif
  57.     extern int optind;
  58.  
  59.     while ((c = getopt(argc, argv, "nv")) != EOF) 
  60.       switch (c) {
  61.         case (int)'n': number++;        break;
  62.         case (int)'v': verbose++;    break;
  63.         case (int)'?': printf("Usage: %s [-n] [-v] {filename | username}\n",
  64.                  argv[0]);
  65.                        exit(1);
  66.       }
  67.  
  68.     infile[0] = '\0';
  69.     if (optind == argc) {
  70.     /*
  71.      *    determine mail file from environment variable if found,
  72.      *    else use login name
  73.      */
  74.       if ((cp = getenv("MAIL")) == NULL) {
  75.         if ((cp = getenv("LOGNAME")) == NULL)
  76.           sprintf(infile, "%s%s", mailhome, getenv("USER"));
  77.         else
  78.           sprintf(infile, "%s%s", mailhome, cp);
  79.       }
  80.       else
  81.         strcpy(infile, cp);
  82.  
  83.       optind -= 1;    /* ensure one pass through loop */
  84.     }
  85.  
  86. #ifdef MMDF
  87.     if((pass = getpwuid(getuid())) == NULL) {
  88.       printf("You have no password entry!");
  89.       exit(1);
  90.     }
  91.     strcpy(username,pass->pw_name);
  92. #endif /* MMDF */
  93.  
  94.     multiple_files = (argc - optind > 1);
  95.  
  96.     while (optind < argc) {
  97.     
  98.       if (multiple_files) {
  99.         strcpy(infile, argv[optind]);
  100.         printf("%s%s: \n", output_files++ > 0 ? "\n":"", infile);
  101.       }
  102.       else if (infile[0] == '\0')
  103.         strcpy(infile, argv[optind]);
  104.  
  105.       if (metachar(infile[0])) {
  106.         if (expand(infile) == 0) {
  107.            fprintf(stderr, "%s: couldn't expand filename %s!\n", 
  108.                argv[0], infile);
  109.            exit(1);
  110.         }
  111.       }
  112.  
  113.       if ((mailfile = fopen(infile,"r")) == NULL) {
  114.         if (optind+1 == argc)
  115.           printf("No mail.\n");
  116.         else {
  117.           if (infile[0] == '/') 
  118.             printf("Couldn't open folder \"%s\".\n", infile);
  119.           else {
  120.             sprintf(infile,"%s%s", mailhome, argv[optind]);
  121.             if ((mailfile = fopen(infile,"r")) == NULL)
  122.               printf("Couldn't open folders \"%s\" or \"%s\".\n",
  123.              argv[optind], infile);
  124.             else {
  125.           if (read_headers()==0)
  126.                 printf("No messages in that folder!\n");
  127.               fclose(mailfile);
  128.         }
  129.           }
  130.         }
  131.       } else {
  132.         if (read_headers(optind+1 == argc)==0)
  133.           if (optind+1 == argc)
  134.             printf("No mail\n");
  135.           else
  136.             printf("No messages in that folder!\n");
  137.         fclose(mailfile);
  138.       }
  139.  
  140.       optind++;
  141.     }
  142.     exit(0);
  143. }
  144.  
  145. int
  146. read_headers(user_mailbox)
  147. int user_mailbox;
  148. {
  149.     /** Read the headers, output as found.  User-Mailbox is to guarantee
  150.         that we get a reasonably sensible message from the '-v' option
  151.      **/
  152.  
  153.     char buffer[SLEN], from_whom[SLEN], subject[SLEN];
  154.     register int in_header = 0, count = 0;
  155. #ifdef MMDF
  156.     int newheader = 0;
  157. #endif /* MMDF */
  158.  
  159.     while (fgets(buffer, SLEN, mailfile) != NULL) {
  160.       if (index(buffer, '\n') == NULL && !feof(mailfile)) {
  161.         int c;
  162.         while ((c = getc(mailfile)) != EOF && c != '\n')
  163.           ; /* keep reading */
  164.       }
  165.  
  166. #ifdef MMDF
  167.           if (strcmp(buffer, MSG_SEPERATOR) == 0) {
  168.         newheader = !newheader;
  169.         if (newheader) {
  170.           subject[0] = '\0';
  171.           in_header = 1;
  172.         }
  173.       }
  174. #else
  175.       if (first_word(buffer,"From ")
  176.        && real_from(buffer, from_whom)) {
  177.         subject[0] = '\0';
  178.         in_header = 1;
  179.       }
  180. #endif /* MMDF */
  181.       else if (in_header) {
  182. #ifdef MMDF
  183.         if (first_word(buffer,"From "))
  184.           real_from(buffer, from_whom);
  185. #endif /* MMDF */
  186.         if (first_word(buffer,">From ")) 
  187.           forwarded(buffer, from_whom); /* return address */
  188.         else if (first_word(buffer,"Subject:") ||
  189.              first_word(buffer,"Re:")) {
  190.           if (subject[0] == '\0') {
  191.             remove_first_word(buffer);
  192.         strcpy(subject, buffer);
  193.           }
  194.         }
  195.         else if (first_word(buffer,"From:") ||
  196.             first_word(buffer, ">From:"))
  197.           parse_arpa_from(buffer, from_whom);
  198.         else if (buffer[0] == LINEFEED) {
  199.           if (verbose && count == 0)
  200.             printf("%s contains the following messages:\n\n",
  201.             user_mailbox?"Your mailbox" : "Folder");
  202. #ifdef MMDF
  203.           if (*from_whom == '\0')
  204.                 strcpy(from_whom,username);
  205. #endif /* MMDF */
  206.           ++count;
  207.           show_header(count, from_whom, subject);
  208.           in_header = 0;
  209.         }
  210.       }
  211.     }
  212.     return(count);
  213. }
  214.  
  215. int
  216. real_from(buffer, who)
  217. char *buffer, *who;
  218. {
  219.     /***** returns true iff 's' has the seven 'from' fields,
  220.            initializing the who to the sender *****/
  221.  
  222.     char junk[SLEN];
  223.  
  224.     junk[0] = '\0';
  225.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  226.                 who, junk);
  227.     return(junk[0] != '\0');
  228. }
  229.  
  230. forwarded(buffer, who)
  231. char *buffer, *who;
  232. {
  233.     /** change 'from' and date fields to reflect the ORIGINATOR of 
  234.         the message by iteratively parsing the >From fields... **/
  235.  
  236.     char machine[SLEN], buff[SLEN], holding_from[SLEN];
  237.  
  238.     machine[0] = '\0';
  239.     holding_from[0] = '\0';
  240.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %*s %s",
  241.                 holding_from, machine);
  242.  
  243.     if(machine[0] == '\0')    /* try for address with timezone in date */
  244.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  245.                 holding_from, machine);
  246.  
  247.     if (machine[0] == '\0') /* try for srm address */
  248.       sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  249.                 holding_from, machine);
  250.  
  251.     if (machine[0] == '\0')
  252.       sprintf(buff, holding_from[0] ? holding_from : "anonymous");
  253.     else
  254.       sprintf(buff,"%s!%s", machine, holding_from);
  255.  
  256.     strncpy(who, buff, SLEN);
  257. }
  258.  
  259. remove_first_word(string)
  260. char *string;
  261. {    /** removes first word of string, ie up to first non-white space
  262.         following a white space! **/
  263.  
  264.     register int loc;
  265.  
  266.     for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  267.         ;
  268.  
  269.     while (string[loc] == ' ' || string[loc] == '\t')
  270.       loc++;
  271.     
  272.     move_left(string, loc);
  273. }
  274.  
  275. move_left(string, chars)
  276. char string[];
  277. int  chars;
  278. {
  279.     /** moves string chars characters to the left DESTRUCTIVELY **/
  280.  
  281.     register int i;
  282.  
  283.     chars--; /* index starting at zero! */
  284.  
  285.     for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  286.       string[i-chars] = string[i];
  287.  
  288.     string[i-chars] = '\0';
  289. }
  290.  
  291. show_header(count, from, subject)
  292. int  count;
  293. char *from, *subject;
  294. {
  295.     /** output header in clean format, including abbreviation
  296.         of return address if more than one machine name is
  297.         contained within it! **/
  298.  
  299.     char buffer[SLEN];
  300.     int  loc, i=0, exc=0, len;
  301.  
  302. #ifndef INTERNET
  303.     char *p;
  304.     
  305.     if (chloc(from,'!') != -1 && chloc(from,'@') > 0) {
  306.       for (p=from;*p != '@'; p++) ;
  307.       *p = '\0';
  308.     }
  309. #endif
  310.  
  311.     loc = strlen(from);
  312.  
  313.     while (exc < 2 && loc > 0)
  314.       if (from[--loc] == '!')
  315.         exc++;
  316.  
  317.     if (exc == 2) { /* lots of machine names!  Get last one */
  318.       loc++;
  319.       len = strlen(from);
  320.       while (loc < len && loc < SLEN)
  321.         buffer[i++] = from[loc++];
  322.       buffer[i] = '\0';
  323.       if (number)
  324.         printf("%3d: %-20s  %s\n", count, buffer, subject);
  325.       else
  326.         printf("%-20s  %s\n", buffer, subject);
  327.     }
  328.     else
  329.       if (number)
  330.         printf("%3d: %-20s  %s\n", count, from, subject);
  331.       else
  332.         printf("%-20s  %s\n", from, subject);
  333. }    
  334.  
  335. parse_arpa_from(buffer, newfrom)
  336. char *buffer, *newfrom;
  337. {
  338.     /** try to parse the 'From:' line given... It can be in one of
  339.         two formats:
  340.         From: Dave Taylor <hpcnou!dat>
  341.         or  From: hpcnou!dat (Dave Taylor)
  342.         Change 'newfrom' ONLY if sucessfully parsed this entry and
  343.         the resulting name is non-null! 
  344.     **/
  345.  
  346.     char temp_buffer[SLEN], *temp;
  347.     register int i, j = 0, in_parens;
  348.  
  349.     temp = (char *) temp_buffer;
  350.     temp[0] = '\0';
  351.  
  352.     no_ret(buffer);        /* blow away '\n' char! */
  353.  
  354.     if (lastch(buffer) == '>') {
  355.       for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  356.            buffer[i] != '('; i++)
  357.         temp[j++] = buffer[i];
  358.       temp[j] = '\0';
  359.     }
  360.     else if (lastch(buffer) == ')') {
  361.       in_parens = 1;
  362.       for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '<'; i--) {
  363.         switch(buffer[i]) {
  364.         case ')':    in_parens++;
  365.             break;
  366.         case '(':    in_parens--;
  367.             break;
  368.         }
  369.         if(!in_parens) break;
  370.         temp[j++] = buffer[i];
  371.       }
  372.       temp[j] = '\0';
  373.       reverse(temp);
  374.     }
  375.  
  376. /* this stuff copied from src/addr_util.c */
  377. #ifdef USE_EMBEDDED_ADDRESSES
  378.  
  379.     /** if we have a null string at this point, we must just have a 
  380.         From: line that contains an address only.  At this point we
  381.         can have one of a few possibilities...
  382.  
  383.         From: address
  384.         From: <address>
  385.         From: address ()
  386.     **/
  387.       
  388.     if (strlen(temp) == 0) {
  389.       if (lastch(buffer) != '>') {       
  390.         for (i=strlen("From:");buffer[i] != '\0' && buffer[i] != '('; i++)
  391.           temp[j++] = buffer[i];
  392.         temp[j] = '\0';
  393.       }
  394.       else {    /* get outta '<>' pair, please! */
  395.         for (i=strlen(buffer)-2;buffer[i] != '<' && buffer[i] != ':';i--)
  396.           temp[j++] = buffer[i];
  397.         temp[j] = '\0';
  398.         reverse(temp);
  399.       }
  400.     }
  401. #endif
  402.  
  403.     if (strlen(temp) > 0) {        /* mess with buffer... */
  404.  
  405.       /* remove leading spaces... */
  406.  
  407.       while (whitespace(temp[0]))
  408.         temp = (char *) (temp + 1);        /* increment address! */
  409.  
  410.       /* remove trailing spaces... */
  411.  
  412.       i = strlen(temp) - 1;
  413.  
  414.       while (whitespace(temp[i]))
  415.        temp[i--] = '\0';
  416.  
  417.       /* remove surrounding paired quotation marks */
  418.       if((temp[i] == '"') & (*temp == '"')) {
  419.         temp[i] = '\0';
  420.         temp++;
  421.       }
  422.  
  423.       /* if anything is left, let's change 'from' value! */
  424.  
  425.       if (strlen(temp) > 0)
  426.         strcpy(newfrom, temp);
  427.     }
  428. }
  429.  
  430. reverse(string)
  431. char *string;
  432. {
  433.     /** reverse string... pretty trivial routine, actually! **/
  434.  
  435.     char buffer[SLEN];
  436.     register int i, j = 0;
  437.  
  438.     for (i = strlen(string)-1; i >= 0; i--)
  439.       buffer[j++] = string[i];
  440.  
  441.     buffer[j] = '\0';
  442.  
  443.     strcpy(string, buffer);
  444. }
  445.