home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 400-499 / ff473.lzh / CNewsSrc / cnews_src.lzh / libcnews / string.c < prev    next >
C/C++ Source or Header  |  1991-01-07  |  6KB  |  289 lines

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