home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2032 / anne.jones.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  8.8 KB  |  322 lines

  1. /*
  2.  * anne.jones - anne.jones.c - 11/03/90 - Brendan Kehoe
  3.  * An implementation of Cnews' anne.jones program to parse down articles
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <pwd.h>
  9. #include <time.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <sys/utsname.h>
  13. #include "anne.h"
  14. #include <signal.h>
  15.  
  16. struct passwd *getpwuid(); /* Not included in pwd.h -- a3@rivm.nl */
  17.  
  18. #ifdef    DEBUG
  19. FILE *debug = stderr;
  20. #endif
  21.  
  22. char *get_a_line(), *safemalloc(), *saferealloc();
  23.  
  24. int
  25. main(argc, argv)
  26.      int argc;
  27.      char **argv;
  28. /*ARGSUSED*/
  29. {
  30.   char *user, *name, *home, *newsctl, *mailname, *colon, *org, *line,
  31.   **header, from[100], head[MAXHEAD], path[200], fullname[50];
  32.   static char *dayname[8] = {  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
  33.                    "Sat", "Sun",
  34.                  }, *mon[12] = {
  35.                    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  36.                    "Aug", "Sep", "Oct", "Nov", "Dec",
  37.                  };
  38.   int tmp, i, headcnt = 0, *found, *pme;
  39.   FILE *fp;
  40.   time_t t;
  41.   struct stat statbuf;
  42.   struct tm *tm;
  43.   struct utsname ut;
  44.   struct passwd *pent;
  45.   
  46.   extern char *getenv();
  47.   char *squeeze(), *getmname(), **buildbook();
  48.   FILE *trypath();
  49.   void termin(), squeeze2();
  50.   
  51.   signal(SIGSEGV, termin);
  52.   signal(SIGINT, termin);
  53.   signal(SIGQUIT, termin);
  54.   signal(SIGHUP, termin);
  55.   signal(SIGBUS, termin);
  56.  
  57.   if ((newsctl = getenv("NEWSCTL")) == (char *) NULL) {
  58.     perror("NEWSCTL");
  59.     exit(1);
  60.   }
  61.   found = (int *) calloc(NUMKNOWN + KNOWSTART, sizeof(int));
  62.   for (i = KNOWSTART; i < NUMKNOWN + KNOWSTART; i++)
  63.     found[i] = NOTFOUND;
  64.   header = (char **) buildbook(NUMHEADERS);
  65.   
  66.   /* mailname & host set */
  67.   mailname = safemalloc(301);
  68.   if ((fp = trypath(newsctl, "mailname")) != (FILE *) NULL) {
  69.     mailname = squeeze(getmname(fp));
  70.   } else if ((fp = trypath(newsctl, "whoami")) != (FILE *) NULL) {
  71.     mailname = getmname(fp);
  72. #ifdef HAVEGETHOSTNAME
  73.   } else if ((gethostname(mailname, 100)) < 0) {
  74.     perror("ghostname");
  75.     exit(1);
  76. #endif /* HAVEGETHOSTNAME */
  77.   } else if ((fp = fopen("/etc/whoami", "r")) != (FILE *) NULL) {
  78.     mailname = getmname(fp);
  79.     /* skipped the uuname -l one, since it does gethostname(2) */
  80.   } else if (uname(&ut) >= 0) {
  81.     strcpy(mailname, ut.sysname);
  82.   } else {
  83.     strcpy(mailname, "the_unknown_host");
  84.   }
  85.   
  86.   /* if it doesn't have a ., it's probably a uucp host */
  87.   if (strchr(mailname, '.') == (char *) NULL)
  88.     strcat(mailname, ".uucp");
  89.   
  90.   /* user's name set */
  91.   pent = getpwuid(geteuid());    /* make it so su'ing someone works */
  92.   if ((user = getenv("LOGNAME")) == NULL)
  93.     user = pent->pw_name;
  94.   
  95.   /* name set & cleaned up */
  96.   if (((name = getenv("NAME")) == NULL) &&
  97.       ((home = getenv("HOME")) != (char *) NULL)) {
  98.     strcpy(path, home);
  99.     strcat(path, "/.name");
  100.     stat(path, &statbuf);
  101.     if (statbuf.st_size > 0) {
  102.       if ((fp = fopen(path, "r")) != (FILE *) NULL) {
  103.     name = safemalloc(101);
  104.     if ((get_a_line(name, 100, fp)) == (char *) NULL) {
  105.       perror("get_a_line .name");
  106.       exit(1);
  107.     }
  108.     if (*(colon = (name + strlen(name) - 1)) == '\n')
  109.       *colon = '\0';
  110.     fclose(fp);
  111.       }
  112.     } else {
  113.       
  114.       /*
  115.     if gecos has '&', use capitalized login name
  116.     */
  117.       if ((strchr(pent->pw_gecos, '&') != (char *) NULL)) {
  118.     name = safemalloc(strlen(pent->pw_name) + 1);
  119.     strcpy(name, pent->pw_name);
  120.     *name = toupper(*name);
  121.       } else {
  122.     name = pent->pw_gecos;
  123.       }
  124.     }
  125.   }
  126.  
  127.   /* fullname test */
  128.   if (name != NULL) {    /* if no real name, leave it off */
  129.     strtok(name, ",");  /* preserve only the name field -- ns@iddth.id.dk */
  130.     sprintf(fullname, " (%s)", name);
  131.   }
  132.  
  133.   /* setup the from field */
  134.   sprintf(from, "%s@%s", user, mailname);
  135.   if (name != NULL)
  136.     strcat(from, fullname);
  137.   
  138.   /* set up the date */
  139.   time(&t);
  140.   tm = gmtime(&t);
  141.   
  142.   /* set up the org */
  143.   if ((org = getenv("ORGANIZATION")) == (char *) NULL) {
  144.     if (((fp = trypath(newsctl, "organization")) == (FILE *) NULL) &&
  145.     ((fp = trypath(newsctl, "organisation")) == (FILE *) NULL)) {
  146.       org = "Total lack of organization.";
  147.     } else {
  148.       org = safemalloc(ORGLEN + 1);
  149.       get_a_line(org, ORGLEN, fp);
  150.       if (*(colon = (org + strlen(org) - 1)) == '\n')
  151.     *(org + strlen(org) - 1) = '\0';
  152.       fclose(fp);
  153.     }
  154.   }
  155.  
  156.   /* now pump out a nice clean header */
  157.   line = safemalloc(MAXLINE + 1);
  158.   
  159.   while (get_a_line(line, MAXLINE, stdin) != (char *) NULL) {
  160.     /* squeeze out (tr) the bad chars */
  161. #ifdef    DEBUG
  162.     fprintf(debug, "getline got ->%s<-\n", line);
  163. #endif
  164.     if (*line != '\n') {
  165.       if (*(colon = (line + strlen(line) - 1)) == '\n')
  166.     *colon = '\0';
  167.       /* clean out the garbage */
  168.       squeeze2(line);
  169.       /* replace :tab with :spc */
  170.       if (colon = strchr(line, ':'))
  171.     if (*(colon + 1) == '\t')
  172.       *(colon + 1) = ' ';
  173.     }
  174.     header[headcnt] = safemalloc(strlen(line) + 1);
  175.     strcpy(header[headcnt++], line);
  176. #ifdef    DEBUG
  177.     fprintf(debug, "getline put ->%s<-\n", line);
  178. #endif
  179.   }
  180.   
  181.   /* thus begins the defheaders.awk hack */
  182.   
  183.   /* nullify all headers with empty contents */
  184.   for (i = 0; i < headcnt; i++) {
  185.     if ((header[i][0]) && (colon = strchr(header[i], ':'))) {
  186.       colon++;    /* move to the chr past the colon */
  187.       
  188.       /*
  189.     strspn -> the last position (the NULL) if there was
  190.     nothing but tabs & spaces .. in that case, it's an
  191.     empty header and discard it
  192.     */
  193.       if (strspn(colon, " \011") == strlen(colon)) {
  194.     header[i][0] = '\0';
  195.     continue;
  196.       }
  197.       strncpy(head, header[i], colon - header[i]);
  198.       *(head + (colon - header[i])) = '\0';
  199.       
  200.       /* fix Message-Id to read Message-ID */
  201.       if (strcmp(head, TYPONAME) == 0)
  202.     header[i][9] = 'D';
  203.       
  204.       /* mark off the ones we're expecting */
  205.       if ((tmp = know_head(head)) != NOTKNOWN)
  206.     found[tmp] = i;
  207.     }
  208.   }
  209.   
  210.   for (i = KNOWSTART; i < (NUMKNOWN + KNOWSTART); i++) {
  211.     
  212.     /*
  213.       If no header was given for something, then fill it in with
  214.       what we've come up with above
  215.       */
  216.     if (found[i] == NOTFOUND) {
  217.       switch (i) {
  218.       case PATHNAMEPOS:
  219.     header[headcnt] = safemalloc(strlen(user) + 8);
  220.     sprintf(header[headcnt], "Path: %s", user);
  221.     found[i] = headcnt++;
  222.     break;
  223.       case MSGIDPOS:
  224.     header[headcnt] = safemalloc(MSGIDLEN + 13);
  225.     sprintf(header[headcnt],
  226.         "Message-ID: <19%02d%s%02d.%02d%02d%02d.%i@%s>",
  227.         tm->tm_year, *(mon + tm->tm_mon),
  228.         tm->tm_mday, tm->tm_hour,
  229.         tm->tm_min, tm->tm_sec, getpid(),
  230.         mailname);
  231.     found[i] = headcnt++;
  232.     break;
  233.       case DATEPOS:
  234.     
  235.     /*
  236.      * put it in the form Day, DD Mon Yr hh:mm:ss GMT
  237.      */
  238.     header[headcnt] = safemalloc(DATELEN + 5);
  239.     sprintf(header[headcnt],
  240.         "Date: %s, %02d %s %02d %02d:%02d:%02d GMT",
  241.         *(dayname + tm->tm_wday), tm->tm_mday,
  242.         *(mon + tm->tm_mon), tm->tm_year,
  243.         tm->tm_hour, tm->tm_min, tm->tm_sec);
  244.     found[i] = headcnt++;
  245.     break;
  246.       case ORGPOS:
  247.     header[headcnt] = safemalloc(strlen(org) + 16);
  248.     sprintf(header[headcnt], "Organization: %s",
  249.         org);
  250.     found[i] = headcnt++;
  251.     break;
  252.       case FROMPOS:
  253.     header[headcnt] = safemalloc(strlen(from) + 8);
  254.     sprintf(header[headcnt], "From: %s", from);
  255.     found[i] = headcnt++;
  256.     break;
  257.       }
  258.     }
  259.   }
  260.   
  261.   /* kill the dist header if it's to 'world' */
  262.   if (found[DISTPOS] != NOTFOUND)
  263.     if (strcmp("Distribution: world", header[found[DISTPOS]]) == 0) {
  264.       header[found[DISTPOS]][0] = '\0';
  265.       found[DISTPOS] = NOTFOUND;
  266.     }
  267.   
  268.   /*
  269.    * if chars 1-14 of Subject header is 'Subject: cmesg ', then create
  270.    * the Control line to read 'Control: 15th_on'
  271.    * 
  272.    * if newsgroup line contains '.ctl', build Control: line so it reads
  273.    * 'Control: 8th_on'
  274.    */
  275.   if ((found[SUBJECTPOS] != NOTFOUND) && (found[CTLNAMEPOS] == NOTFOUND)) {
  276.     if (strncmp(header[found[SUBJECTPOS]],
  277.         "Subject: cmesg ", 15) == 0) {
  278.       
  279.       /*
  280.     get 'Control: ' (10) plus rest of Subject (-14)
  281.     */
  282.       header[headcnt] = safemalloc(strlen(header[found[SUBJECTPOS]]) - 3);
  283.       sprintf(header[headcnt], "Control: %s",
  284.           header[found[SUBJECTPOS]] + 15);
  285.       found[CTLNAMEPOS] = headcnt;
  286.       headcnt++;
  287.     } else if ((found[NGNAMEPOS] != NOTFOUND) &&
  288.            (strstr(header[found[NGNAMEPOS]], ".ctl") != (char *) NULL)) {
  289.       
  290.       /*
  291.        * get 'Control: ' (10) plus rest of Subject (-8)
  292.        */
  293.       header[headcnt] = safemalloc(strlen(header[found[SUBJECTPOS]]) + 3);
  294.       sprintf(header[headcnt],
  295.           "Control: %s", header[found[SUBJECTPOS]] + 9);
  296.       found[CTLNAMEPOS] = headcnt;
  297.       headcnt++;
  298.     }
  299.   }
  300.  
  301.   /* warn to stderr if there are no newsgroups listed */
  302.   if (found[NGNAMEPOS] == NOTFOUND)
  303.     fputs("no newsgroups header!\n", stderr);
  304.   
  305.   /* reorder & emit headers */
  306.   pme = (int *) calloc(headcnt, sizeof(int));
  307.   
  308.   for (i = KNOWSTART; i < ORDER + 1; i++) {
  309.     if ((found[i] != NOTFOUND) && (header[found[i]][0])) {
  310.       fprintf(stdout, "%s\n", header[found[i]]);
  311.       pme[found[i]] = 1;
  312.     }
  313.   }
  314.   
  315.   for (i = 0; i < headcnt; i++) {
  316.     if ((pme[i] != 1) && (header[i][0]))
  317.       fprintf(stdout, "%s\n", header[i]);
  318.   }
  319.   fflush(stdout);
  320.   return(0);    /* shut UP lint */
  321. }
  322.