home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / cnews.src.lzh / libcnews / string.c < prev    next >
C/C++ Source or Header  |  1989-07-13  |  6KB  |  253 lines

  1. /*
  2.  * string operations
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #include "libc.h"
  9. #include "news.h"
  10.  
  11. /* forwards */
  12. char *findhost();
  13.  
  14. /*
  15.  * Return strsave() of the first word in "tokens".
  16.  * Words are delimited by spaces.
  17.  */
  18.  
  19. char *first(tokens)
  20. char *tokens;
  21. {
  22.     return strsvto(tokens, ' ');
  23. }
  24.  
  25. /*
  26.  * Turn a newsgroup name into a file name, in place.
  27.  */
  28.  
  29. void mkfilenm(ng)
  30. register char *ng;
  31. {
  32.     for (; *ng != '\0'; ng++)
  33.         if (*ng == NGDELIM)
  34.             *ng = FNDELIM;
  35. }
  36.  
  37. void trim(s)                    /* trim trailing newline */
  38. char *s;
  39. {
  40.     register char *nl;
  41.  
  42.     INDEX(s, '\n', nl);
  43.     if (nl != NULL)
  44.         *nl = '\0';
  45. }
  46.  
  47. char *skipsp(s)                /* skip any whitespace at *s */
  48. register char *s;
  49. {
  50.     while (iswhite(*s))
  51.         s++;
  52.     return s;
  53. }
  54.  
  55. char *strsvto(s, c)                /* save s up to (but excluding) c */
  56. char *s;
  57. int c;
  58. {
  59.     register char *endp, *copy;
  60.  
  61.     endp = index(s, c);        /* find interesting part's end of s */
  62.     if (endp != NULL)
  63.         *endp = '\0';        /* restored below */
  64.     copy = strsave(s);        /* copy interesting substring of s */
  65.         if (endp != NULL)
  66.             *endp = c;
  67.     return copy;
  68. }
  69.  
  70. int charcount(s, c)            /* how many c's in s? */
  71. register char *s;
  72. register int c;
  73. {
  74.     register int count = 0;
  75.  
  76. #ifdef CLASSY
  77.     for (; (s = index(s, c)) != NULL; s = (s == NULL? NULL: s+1))
  78.         ++count;
  79. #else
  80.     while (*s != '\0')
  81.         if (*s++ == c)
  82.             ++count;
  83. #endif                /* CLASSY */
  84.     return count;
  85. }
  86.  
  87. char *nullify(s)                /* return s or "" if NULL */
  88. register char *s;
  89. {
  90.     if (s == NULL)
  91.         return "";
  92.     else
  93.         return s;
  94. }
  95.  
  96. /*
  97.  *    If c is NUL, hostchar will be false, so don't test (optimisation: ==).
  98.  */
  99.  
  100. #define nothostchar(c, ch) (!hostchar(c, ch) /* || (c) == '\0' */ )
  101.  
  102. /*
  103.  *    True if c can be part of a hostname.  RFC 850 allows letters, digits,
  104.  *    periods, and hyphens and specifically disallows blanks.  False may
  105.  *    mean c is NUL.
  106.  */
  107.  
  108. #define hostchar(c, ch) ((ch) = (c), \
  109.     (isascii(ch) && isalnum(ch) || (ch) == '.' || (ch) == '-'))
  110.  
  111. /*
  112.  * Return true iff any host in hosts appears in s, as per hostin().
  113.  * hosts are separated by non-hostname characters.
  114.  */
  115.  
  116. boolean anyhostin(hosts, s)
  117. char *hosts, *s;
  118. {
  119.     register char *host = hosts;
  120.  
  121.     while (*host != '\0') {
  122.         register char *delimp;
  123.         register int ch;
  124.         register int delim;
  125.         register boolean hostisin;
  126.  
  127.         while (nothostchar(*host, ch) && *host != '\0')
  128.             ++host;            /* skip leading delims */
  129.         if (*host == '\0')        /* no more hosts */
  130.             break;
  131.         for (delimp = host; hostchar(*delimp, ch); delimp++)
  132.             ;            /* skip to next delim */
  133.         delim = *delimp;        /* may be NUL */
  134.         *delimp = '\0';            /* terminate host */
  135.         hostisin = hostin(host, s);
  136.         *delimp = delim;        /* restore hosts delimiter */
  137.         if (hostisin)
  138.             return YES;
  139.         host = delimp;            /* advance to next host */
  140.     }
  141.     return NO;
  142. }
  143.  
  144. /*
  145.  * Return true iff host appears in s, with no characters from the alphabet
  146.  * of legal hostname characters immediately adjacent.
  147.  */
  148.  
  149. boolean hostin(host, s)
  150. register char *host, *s;
  151. {
  152.     return findhost(host, s) != NULL;
  153. }
  154.  
  155. /*
  156.  * Return the number of machines appearing in path,
  157.  * by counting transitions from delimiters.
  158.  * See hostin() for the rules, and the macros.
  159.  */
  160.  
  161. int hopcount(path)
  162. register char *path;
  163. {
  164.     register int count = 0;
  165.     register int ch;
  166.  
  167.     for (; *path != '\0'; path++)
  168.         if (nothostchar(path[0], ch) && hostchar(path[1], ch))
  169.             ++count;    /* trailing edge of delimiters */
  170.     return count;
  171. }
  172.  
  173. char *sendersite(path)
  174. register char *path;
  175. {
  176.     register char *p;
  177.     register int ch;
  178.     static char *sender = NULL;
  179.  
  180.     nnfree(&sender);        /* free the last answer */
  181.     for (p = path; hostchar(*p, ch); p++)
  182.         ;
  183.     if (*p == '\0')            /* only a user name */
  184.         return hostname();    /* a local posting */
  185.     else {
  186.         register int delim = *p;
  187.  
  188.         *p = '\0';
  189.         sender = strsave(path);    /* copy the first machine name */
  190.         *p = delim;
  191.         return sender;
  192.     }
  193. }
  194.  
  195. /*
  196.  *    Canonicalise rawpath: NULL -> "", chop last site (actually user name)
  197.  *    but not its leading delimiter, and if Approved:, chop everything after
  198.  *    the site, and its trailing delimiter, from Approved: (or Sender:)
  199.  *    (user@host).  Result is malloced memory.
  200.  */
  201.  
  202. char *canonpath(rawpath, approved, sender)
  203. char *rawpath, *approved, *sender;
  204. {
  205.     register char *newpath = strsave(nullify(rawpath));
  206.     register char *p, *lastdelim = newpath, *site = NULL;    /* p-csu v3 */
  207.     register int ch;
  208.  
  209.     for (p = newpath; *p != '\0'; ++p)
  210.         if (nothostchar(*p, ch))
  211.             lastdelim = p + 1;    /* just past delim; p-csu v3 */
  212.     if (lastdelim != NULL)
  213.         *lastdelim = '\0';        /* omit user's name */
  214.  
  215.     if (approved != NULL) {            /* moderated article */
  216.         site = index(approved, '@');
  217.         if (site == NULL)
  218.             site = index(nullify(sender), '@');
  219.     }
  220.     if (site != NULL) {
  221.         p = findhost(site+1, newpath);
  222.         if (p != NULL && *p++ != '\0')    /* delim after site? p-csu v3 */
  223.             *p = '\0';        /* terminate newpath after site */
  224.     }
  225.     return newpath;
  226. }
  227.  
  228. /*
  229.  * Return pointer to the first byte after host in path, if any,
  230.  * with no characters from the alphabet of legal hostname characters
  231.  * immediately adjacent.
  232.  * This function is a profiling hot spot, so it has been optimised.
  233.  */
  234.  
  235. char *findhost(host, path)
  236. register char *host, *path;
  237. {
  238.     register int hostlen = strlen(host), ch;
  239.  
  240.     /* Special case: match host!path or host. */
  241.     if (STREQN(path, host, hostlen) && nothostchar(path[hostlen], ch))
  242.         return &path[hostlen];
  243.  
  244.     /* Match path2!host!path or path2!host. */
  245.     while (*path != '\0')
  246.         if (hostchar(path[0], ch))    /* can't start after here */
  247.             ++path;
  248.         else if ((++path, STREQN(path, host, hostlen)) &&
  249.                nothostchar(path[hostlen], ch))
  250.             return &path[hostlen];
  251.     return NULL;
  252. }
  253.