home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / readnews / header.c < prev    next >
C/C++ Source or Header  |  1994-08-25  |  9KB  |  408 lines

  1. /*
  2.  * extract/output headers
  3.  */
  4.  
  5. #include "defs.h"
  6. #include <sys/timeb.h>
  7.  
  8. extern char systemid[];
  9. extern long now;
  10.  
  11. char hform[]         = "%s: %s\n";
  12.  
  13. /* Mandatory Headers */
  14. char t_relayversion[]     = "Relay-Version";
  15. char t_postversion[]     = "Posting-Version";
  16. char t_from[]         = "From";
  17. char t_date[]         = "Date";
  18. char t_newsgroups[]     = "Newsgroups";
  19. char t_subject[]     = "Subject";
  20. char t_messageid[]     = "Message-ID";
  21. char t_path[]         = "Path";
  22.  
  23. /* Optional Headers */
  24. char t_replyto[]     = "Reply-To";
  25. char t_sender[]         = "Sender";
  26. char t_followupto[]     = "Followup-To";
  27. char t_datereceived[]     = "Date-Received";
  28. char t_expires[]     = "Expires";
  29. char t_references[]     = "References";
  30. char t_control[]     = "Control";
  31. char t_distribution[]     = "Distribution";
  32. char t_organization[]     = "Organization";
  33. char t_lines[]         = "Lines";
  34.  
  35. typedef enum ft
  36. {
  37.     f_control, f_date, f_datereceived, f_distribution,
  38.     f_expires, f_followupto, f_from, f_lines, f_messageid,
  39.     f_newsgroups, f_organization, f_path, f_postversion,
  40.     f_references, f_relayversion, f_replyto, f_sender,
  41.     f_subject
  42. }
  43.  
  44.  
  45. ftype;
  46.  
  47. typedef struct field {
  48.     char *f_name;
  49.     ftype    f_type;
  50. } field;
  51.  
  52. static field fields[] = 
  53. {
  54.     { t_control,     f_control     },
  55.     { t_date,         f_date         },
  56.     { t_datereceived,     f_datereceived     },
  57.     { t_distribution,     f_distribution     },
  58.     { t_expires,     f_expires     },
  59.     { t_followupto,     f_followupto     },
  60.     { t_from,         f_from         },
  61.     { t_lines,     f_lines         },
  62.     { t_messageid,     f_messageid     },
  63.     { t_newsgroups,     f_newsgroups     },
  64.     { t_organization,     f_organization     },
  65.     { t_path,         f_path         },
  66.     { t_postversion,     f_postversion     },
  67.     { t_references,     f_references     },
  68.     { t_relayversion,     f_relayversion     },
  69.     { t_replyto,     f_replyto     },
  70.     { t_sender,     f_sender     },
  71.     { t_subject,     f_subject     }
  72. };
  73.  
  74.  
  75. char *weekdays[7] = 
  76. {
  77.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  78. };
  79.  
  80.  
  81. char *months[12] = 
  82. {
  83.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  84.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  85. };
  86.  
  87.  
  88. static
  89. fieldcmp(a, b)
  90. field *a, *b;
  91. {
  92.     return CMP(a->f_name, b->f_name);
  93. }
  94.  
  95.  
  96. /*
  97.  * Binary search algorithm, generalized from Knuth (6.2.1) Algorithm B.
  98.  *
  99.  * Written by J. S. Rugaber; rewritten by L. Rosler, Dept. 45175, August, 1981.
  100.  */
  101. char *
  102. search(key, base, nel, width, compar)
  103. char *key;            /* Key to be located */
  104. char *base;            /* Beginning of table */
  105. unsigned nel;            /* Number of elements in the table */
  106. unsigned width;            /* Width of an element (bytes) */
  107. int    (*compar)();        /* Comparison function */
  108. {
  109.     int two_width = width + width;
  110.     char *last = base + width * (nel - 1); /* Last element in table */
  111.  
  112.     while (last >= base) {
  113.  
  114.         register char *p = base + width * ((last - base)/two_width);
  115.         register int res = (*compar)(key, p);
  116.  
  117.         if (res == 0)
  118.             return (p);    /* Key found */
  119.         if (res < 0)
  120.             last = p - width;
  121.         else
  122.             base = p + width;
  123.     }
  124.     return ((char *) 0);        /* Key not found */
  125. }
  126.  
  127.  
  128. /*
  129.  * extract headers from file,
  130.  * position file to start of body
  131.  */
  132. gethead(f, hp)
  133. FILE *f;
  134. header *hp;
  135. {
  136.     register char *colon, *space, *s;
  137.     register field    *fp;
  138.     field        af;
  139.     char buf[BUFLEN*2];
  140.     char *hfgets();
  141.  
  142.     memset((char *) hp, 0, sizeof(header));
  143.     while (hfgets(buf, sizeof(buf), f)) {
  144.         if (buf[0] == '\n')
  145.             return;
  146.         if (isupper(buf[0]) && (colon = strchr(buf, ':')) &&
  147.             (space = strchr(buf, ' ')) && (colon + 1 == space)) {
  148.             *colon = '\0';
  149.             af.f_name = buf;
  150.             fp = (field * )search((char *)&af, (char *)fields,
  151.                 sizeof fields/sizeof fields[0], sizeof fields[0],
  152.                 fieldcmp);
  153.             *colon = ':';
  154.         } else
  155.             fp = NULL;
  156.         if (!fp)
  157.             if (hp->h_others)
  158.                 hp->h_others = catstr(hp->h_others, buf);
  159.             else
  160.                 hp->h_others = newstr(buf);
  161.         else {
  162.             if (colon = strchr(space + 1, '\n'))
  163.                 *colon = '\0';
  164.             s = newstr(space + 1);
  165.             switch (fp->f_type) {
  166.             case f_control:        
  167.                 hp->h_control = s;    
  168.                 break;
  169.             case f_date:        
  170.                 hp->h_date = s;        
  171.                 break;
  172.             case f_datereceived:    
  173.                 hp->h_datereceived = s;    
  174.                 break;
  175.             case f_distribution:    
  176.                 hp->h_distribution = s;    
  177.                 break;
  178.             case f_expires:        
  179.                 hp->h_expires = s;    
  180.                 break;
  181.             case f_followupto:    
  182.                 hp->h_followupto = s;    
  183.                 break;
  184.             case f_from:        
  185.                 hp->h_from = s;        
  186.                 break;
  187.             case f_lines:        
  188.                 hp->h_lines = s;    
  189.                 break;
  190.             case f_messageid:    
  191.                 hp->h_messageid = s;    
  192.                 break;
  193.             case f_newsgroups:    
  194.                 hp->h_newsgroups = s;    
  195.                 break;
  196.             case f_organization:    
  197.                 hp->h_organisation = s;    
  198.                 break;
  199.             case f_path:        
  200.                 hp->h_path = s;        
  201.                 break;
  202.             case f_postversion:    
  203.                 hp->h_postversion = s;    
  204.                 break;
  205.             case f_references:    
  206.                 hp->h_references = s;    
  207.                 break;
  208.             case f_relayversion:    
  209.                 hp->h_relayversion = s;    
  210.                 break;
  211.             case f_replyto:        
  212.                 hp->h_replyto = s;    
  213.                 break;
  214.             case f_sender:        
  215.                 hp->h_sender = s;    
  216.                 break;
  217.             case f_subject:        
  218.                 hp->h_subject = s;    
  219.                 break;
  220.             }
  221.         }
  222.     }
  223. }
  224.  
  225.  
  226. /*
  227.  * put headers to file
  228.  */
  229. puthead(hp, f, com)
  230. header *hp;
  231. FILE *f;
  232. pheadcom com;            /* actually ignored now */
  233. {
  234.     register char *s;
  235.     char *getunique();
  236.     extern char *getenv();
  237.  
  238.     if (hp->h_relayversion)
  239.         (void) fprintf(f, hform, t_relayversion, hp->h_relayversion);
  240.  
  241.     if (hp->h_postversion)
  242.         (void) fprintf(f, hform, t_postversion, hp->h_postversion);
  243.  
  244.     if (hp->h_from)
  245.         (void) fprintf(f, hform, t_from, hp->h_from);
  246.  
  247.     if (hp->h_date)
  248.         (void) fprintf(f, hform, t_date, hp->h_date);
  249.  
  250.     if (hp->h_newsgroups)
  251.         (void) fprintf(f, hform, t_newsgroups, hp->h_newsgroups);
  252.  
  253.     if (hp->h_subject)
  254.         (void) fprintf(f, hform, t_subject, hp->h_subject);
  255.  
  256.     if (hp->h_messageid)
  257.         (void) fprintf(f, hform, t_messageid, hp->h_messageid);
  258.  
  259.     if (hp->h_path)
  260.         (void) fprintf(f, hform, t_path, hp->h_path);
  261.  
  262.     /* optional */
  263.  
  264.     if (hp->h_replyto)
  265.         (void) fprintf(f, hform, t_replyto, hp->h_replyto);
  266.  
  267.     if (hp->h_sender)
  268.         (void) fprintf(f, hform, t_sender, hp->h_sender);
  269.  
  270.     if (hp->h_followupto)
  271.         (void) fprintf(f, hform, t_followupto, hp->h_followupto);
  272.  
  273.     if (hp->h_datereceived)
  274.         (void) fprintf(f, hform, t_datereceived, hp->h_datereceived);
  275.  
  276.     if (hp->h_expires)
  277.         (void) fprintf(f, hform, t_expires, hp->h_expires);
  278.  
  279.     if (hp->h_references)
  280.         (void) fprintf(f, hform, t_references, hp->h_references);
  281.  
  282.     if (hp->h_control)
  283.         (void) fprintf(f, hform, t_control, hp->h_control);
  284.  
  285.     if (hp->h_distribution)
  286.         (void) fprintf(f, hform, t_distribution, hp->h_distribution);
  287.  
  288.     if (hp->h_organisation)
  289.         (void) fprintf(f, hform, t_organization, hp->h_organisation);
  290.  
  291.     if (hp->h_lines)
  292.         (void) fprintf(f, hform, t_lines, hp->h_lines);
  293.  
  294.     if (hp->h_others)
  295.         fputs(hp->h_others, f);
  296. }
  297.  
  298.  
  299. /*
  300.  * free all strings allocated to header
  301.  */
  302. freehead(hp)
  303. register header *hp;
  304. {
  305.     if (hp->h_relayversion)    
  306.         free(hp->h_relayversion);
  307.     if (hp->h_postversion)    
  308.         free(hp->h_postversion);
  309.     if (hp->h_from)        
  310.         free(hp->h_from);
  311.     if (hp->h_date)        
  312.         free(hp->h_date);
  313.     if (hp->h_newsgroups)    
  314.         free(hp->h_newsgroups);
  315.     if (hp->h_subject)    
  316.         free(hp->h_subject);
  317.     if (hp->h_messageid)    
  318.         free(hp->h_messageid);
  319.     if (hp->h_path)        
  320.         free(hp->h_path);
  321.     if (hp->h_replyto)    
  322.         free(hp->h_replyto);
  323.     if (hp->h_sender)    
  324.         free(hp->h_sender);
  325.     if (hp->h_followupto)    
  326.         free(hp->h_followupto);
  327.     if (hp->h_datereceived)    
  328.         free(hp->h_datereceived);
  329.     if (hp->h_expires)    
  330.         free(hp->h_expires);
  331.     if (hp->h_references)    
  332.         free(hp->h_references);
  333.     if (hp->h_control)    
  334.         free(hp->h_control);
  335.     if (hp->h_distribution)    
  336.         free(hp->h_distribution);
  337.     if (hp->h_organisation)    
  338.         free(hp->h_organisation);
  339.     if (hp->h_lines)        
  340.         free(hp->h_lines);
  341.     if (hp->h_others)    
  342.         free(hp->h_others);
  343. }
  344.  
  345.  
  346. /*
  347.  * hfgets is like fgets, but deals with continuation lines.
  348.  * It also ensures that even if a line that is too long is
  349.  * received, the remainder of the line is thrown away
  350.  * instead of treated like a second line.
  351.  */
  352. char *
  353. hfgets(buf, len, fp)
  354. char *buf;
  355. int len;
  356. FILE *fp;
  357. {
  358.     register int c;
  359.     register char *cp, *tp;
  360.  
  361.     if ((cp = fgets(buf, len, fp)) == NULL)
  362.         return NULL;
  363.  
  364.     if (*cp == '\n')
  365.         return cp;
  366.  
  367.     tp = cp + strlen(cp);
  368.     if (tp[-1] != '\n') {
  369.         /* Line too long - part read didn't fit into a newline */
  370.         while ((c = getc(fp)) != '\n' && c != EOF)
  371.             ;
  372.     } else
  373.         *--tp = '\0';    /* clobber newline */
  374.  
  375.     while ((c = getc(fp)) == ' ' || c == '\t') {
  376.         /* Continuation line. */
  377.         while ((c = getc(fp)) == ' ' || c == '\t')
  378.             ;
  379.         if (tp - cp < len) {
  380.             *tp++ = ' ';
  381.             *tp++ = c;
  382.         }
  383.         while ((c = getc(fp)) != '\n' && c != EOF)
  384.             if (tp - cp < len)
  385.                 *tp++ = c;
  386.     }
  387.     *tp++ = '\n';
  388.     *tp++ = '\0';
  389.     if (c != EOF)
  390.         ungetc(c, fp);    /* push back first char of next header */
  391.     return cp;
  392. }
  393.  
  394.  
  395.  
  396. /*
  397.  * ascii to time
  398.  * return 0L on error
  399.  */
  400. long
  401. atot(s)
  402. char *s;
  403. {
  404.     extern long getindate();
  405.  
  406.     return getindate(s, (struct timeb *)NULL);
  407. }
  408.