home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3138 / anne.jones.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-27  |  9.9 KB  |  370 lines

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