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.orig.lzh / rna / funcs.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  10KB  |  590 lines

  1. #include "defs.h"
  2.  
  3. /*
  4.  * string handling functions
  5.  */
  6. char *
  7. myalloc(size)
  8. int size;
  9. {
  10.     register char *cp;
  11.  
  12.     extern char *malloc();
  13.  
  14.     if ((cp = malloc((unsigned) size)) == NIL(char))
  15.         error("No more memory.");
  16.     return cp;
  17. }
  18.  
  19.  
  20. char *
  21. myrealloc(ptr, size)
  22. char *ptr;
  23. int size;
  24. {
  25.     register char *cp;
  26.  
  27.     extern char *realloc();
  28.  
  29.     if ((cp = realloc(ptr, (unsigned) size)) == NIL(char))
  30.         error("No more memory.");
  31.     return cp;
  32. }
  33.  
  34.  
  35. char *
  36. newstr(s)
  37. char *s;
  38. {
  39.     return strcpy(myalloc(strlen(s) + 1), s);
  40. }
  41.  
  42.  
  43. char *
  44. newstr2(s1, s2)
  45. char *s1, *s2;
  46. {
  47.     return strcat(strcpy(myalloc(strlen(s1) + strlen(s2) + 1), s1), s2);
  48. }
  49.  
  50.  
  51. char *
  52. newstr3(s1, s2, s3)
  53. char *s1, *s2, *s3;
  54. {
  55.     return strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) + strlen(s3) +
  56.         1), s1), s2), s3);
  57. }
  58.  
  59.  
  60. char *
  61. newstr4(s1, s2, s3, s4)
  62. char *s1, *s2, *s3, *s4;
  63. {
  64.     return strcat(strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) +
  65.         strlen(s3) + strlen(s4) + 1), s1), s2), s3), s4);
  66. }
  67.  
  68.  
  69. char *
  70. newstr5(s1, s2, s3, s4, s5)
  71. char *s1, *s2, *s3, *s4, *s5;
  72. {
  73.     return strcat(strcat(strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) +
  74.         strlen(s3) + strlen(s4) + strlen(s5) + 1), s1), s2), s3), s4), s5);
  75. }
  76.  
  77.  
  78. char *
  79. newstr6(s1, s2, s3, s4, s5, s6)
  80. char *s1, *s2, *s3, *s4, *s5, *s6;
  81. {
  82.     return strcat(strcat(strcat(strcat(strcat(strcpy(myalloc(strlen(s1) +
  83.         strlen(s2) + strlen(s3) + strlen(s4) + strlen(s5) + strlen(s6) + 1),
  84.          s1), s2), s3), s4), s5), s6);
  85. }
  86.  
  87.  
  88. char *
  89. catstr(old, s)
  90. char *old, *s;
  91. {
  92.     return strcat(myrealloc(old, strlen(old) + strlen(s) + 1), s);
  93. }
  94.  
  95.  
  96. char *
  97. catstr2(old, s1, s2)
  98. char *old, *s1, *s2;
  99. {
  100.     return strcat(strcat(myrealloc(old, strlen(old) + strlen(s1) + strlen(s2) +
  101.         1), s1), s2);
  102. }
  103.  
  104.  
  105. /*
  106.  * News group matching.
  107.  *
  108.  * nglist is a list of newsgroups.
  109.  * sublist is a list of subscriptions.
  110.  * sublist may have "meta newsgroups" in it.
  111.  * All fields are NGSEPCHAR separated.
  112.  *
  113.  * sublist uses "all" like shell uses "*", and "." like shell uses "/"
  114.  * if subscription X matches Y, it also matches Y.anything
  115.  */
  116. ngmatch(nglist, sublist)
  117. char *nglist, *sublist;
  118. {
  119.     register char *n, *s, *nd, *sd;
  120.     register int rc;
  121.  
  122.     rc = 0;
  123.     n = nglist;
  124.     while (*n && rc == 0) {
  125.         if (nd = strchr(n, NGSEPCHAR))
  126.             *nd = '\0';
  127.         s = sublist;
  128.         while (*s) {
  129.             if (sd = strchr(s, NGSEPCHAR))
  130.                 *sd = '\0';
  131.             if (*s != NEGCHAR)
  132.                 rc |= ptrncmp(s, n);
  133.             else
  134.                 rc &= ~ptrncmp(s + 1, n);
  135.             if (sd)
  136.                 *sd = NGSEPCHAR, s = sd + 1;
  137.             else
  138.                 break;
  139.         }
  140.         if (nd)
  141.             *nd = NGSEPCHAR, n = nd + 1;
  142.         else
  143.             break;
  144.     }
  145.     return rc;
  146. }
  147.  
  148.  
  149. /*
  150.  * Compare two newsgroups for equality.
  151.  * The first one may be a "meta" newsgroup.
  152.  */
  153. static
  154. ptrncmp(ng1, ng2)
  155. register char *ng1, *ng2;
  156. {
  157.  
  158.     while (1) {
  159.         if (ng1[0] == 'a' && ng1[1] == 'l' && ng1[2] == 'l' && (ng1[3] ==
  160.             '\0' || ng1[3] == '.')) {
  161.             if (ng1[3] == '\0')    /* "all" matches anything */
  162.                 return 1;
  163.             while (*ng2 && *ng2 != '.')
  164.                 ng2++;
  165.             if (*ng2 != '.')        /* "all." doesn't match "xx" */
  166.                 return 0;
  167.             ng1 += 4, ng2++;
  168.             continue;
  169.         }
  170.         while (*ng1 && *ng1 != '.' && *ng1 == *ng2)
  171.             ng1++, ng2++;
  172.         if (*ng1 == '.') {
  173.             if (*ng2 != '.' && *ng2 != '\0')
  174.                 return 0;    /* "."'s don't line up */
  175.             if (*ng2)
  176.                 ng2++;
  177.             ng1++;            /* "."'s line up - keep going */
  178.         } else if (*ng1 == '\0')
  179.             return (*ng2 == '\0' || *ng2 == '.');
  180.             /* full match or X matching X.thing */
  181.         else
  182.             return 0;
  183.     }
  184.     /* NOTREACHED */
  185. }
  186.  
  187.  
  188. /*
  189.  * return new newsgroup composed of only those from 'nglist'
  190.  * subscribed to by 'sublist'
  191.  * return NULL for empty list
  192.  */
  193. char *
  194. ngsquash(nglist, sublist)
  195. register char *nglist, *sublist;
  196. {
  197.     register char *delim;
  198.     register char *newg;
  199.  
  200.     newg = NIL(char);
  201.     while (*nglist) {
  202.         if (delim = strchr(nglist, NGSEPCHAR))
  203.             *delim = '\0';
  204.         if (ngmatch(nglist, sublist))
  205.             newg = (newg ? catstr2(newg, NGSEPS, nglist) : newstr(nglist));
  206.         if (delim)
  207.             *delim = NGSEPCHAR, nglist = delim + 1;
  208.         else
  209.             break;
  210.     }
  211.     return newg;
  212. }
  213.  
  214.  
  215. /*
  216.  * get unique sequence number from SEQ
  217.  */
  218. char *
  219. getunique()
  220. {
  221.     register long number;
  222.     register FILE    *f;
  223.     static char buf[12];
  224.  
  225.     f = fopenl(SEQ);
  226.     if (fread(buf, 1, sizeof(buf), f) > 0)
  227.         number = atol(buf);
  228.     else
  229.         number = 1;
  230.  
  231.     rewind(f);
  232.     (void) fprintf(f, "%ld\n", number + 1);
  233.     fclose(f);
  234. #if !AUSAM
  235.     unlock(SEQ);
  236. #endif
  237.  
  238.     sprintf(buf, "%ld", number);
  239.     return buf;
  240. }
  241.  
  242.  
  243. /*
  244.  * open a locked file (or create) for reading and writing
  245.  */
  246. FILE *
  247. fopenl(fname)
  248. char *fname;
  249. {
  250.     register FILE    *f;
  251. #ifdef AUSAM
  252.     struct stat sbuf;
  253. #endif
  254.  
  255.     extern uid_t    newsuid;
  256.  
  257.     if ((f = fopen(fname, "r+")) == NIL(FILE) && (f = fopen(fname, "w+")) ==
  258.         NIL(FILE))
  259.         error("Can't open %s", fname);
  260.  
  261. #if AUSAM
  262.     if (fstat(fileno(f), &sbuf) != 0)
  263.         error("Can't stat %s", fname);
  264.     if ((sbuf.st_mode & S_IFMT) != S_IFALK && (chmod(fname, (int) (sbuf.st_mode
  265.         &~S_IFMT) | S_IFALK) != 0 || chown(fname, (int) newsuid, (int) newsuid) !=
  266.         0 || fclose(f) == EOF || (f = fopen(fname, "r+")) == NIL(FILE)))
  267.         error("Can't create %s", fname);
  268. #else
  269.     chown(fname, (int) newsuid, (int) newsuid);
  270.     lock(fname);
  271. #endif
  272.  
  273.     return f;
  274. }
  275.  
  276.  
  277. #if !AUSAM
  278.  
  279. #define LSUFFIX    ".lock"        /* suffix for lock files */
  280.  
  281. lock(fname)
  282. char *fname;
  283. {
  284.     register char *lname;
  285.     register int i, f;
  286.  
  287.     lname = newstr2(fname, LSUFFIX);
  288.     for (i = 0; i < 10; i++) {
  289.         if ((f = creat(lname, 0)) != -1) {
  290.             close(f);
  291.             free(lname);
  292.             return;
  293.         }
  294.         sleep(2);
  295.     }
  296.     error("Can't creat %s after %d tries", lname, i);
  297. }
  298.  
  299.  
  300. unlock(fname)
  301. char *fname;
  302. {
  303.     register char *lname;
  304.  
  305.     lname = newstr2(fname, LSUFFIX);
  306.     unlink(lname);
  307.     free(lname);
  308. }
  309.  
  310.  
  311. #endif
  312.  
  313. /*
  314.  * open a file
  315.  */
  316. FILE *
  317. fopenf(name, mode)
  318. char *name, *mode;
  319. {
  320.     register FILE    *f;
  321.  
  322.     if ((f = fopen(name, mode)) == NIL(FILE))
  323.         error("Can't %s %s", *mode == 'r' ? "open" : "create", name);
  324.     return f;
  325. }
  326.  
  327.  
  328. /*
  329.  * replace all '.''s with '/'
  330.  */
  331. char *
  332. convg(s)
  333. register char *s;
  334. {
  335.     register char *sav;
  336.  
  337.     sav = s;
  338.     while (s = strchr(s, '.'))
  339.         *s = '/';
  340.     return sav;
  341. }
  342.  
  343.  
  344. /*
  345.  * replace all '/''s with '.'
  346.  */
  347. char *
  348. rconvg(s)
  349. register char *s;
  350. {
  351.     register char *sav;
  352.  
  353.     sav = s;
  354.     while (s = strchr(s, '/'))
  355.         *s = '.';
  356.     return sav;
  357. }
  358.  
  359.  
  360. /*
  361.  * get a line from stdin
  362.  * trim leading and trailing blanks
  363.  */
  364. char *
  365. mgets()
  366. {
  367.     register char *s;
  368.     static char buf[BUFSIZ];
  369.  
  370.     fflush(stdout);
  371.     if (fgets(buf, sizeof(buf), stdin) == NIL(char)) {
  372.         (void) printf("\n");
  373.         return NIL(char);
  374.     }
  375.     if (s = strchr(buf, '\n'))
  376.         while (isspace(*s) && s > buf)
  377.             *s-- = '\0';
  378.     else
  379.      {
  380.         (void) printf("Input line too long.\n");
  381.         return NIL(char);
  382.     }
  383.     s = buf;
  384.     while (isspace(*s))
  385.         s++;
  386.     return s;
  387. }
  388.  
  389.  
  390. readln(f)
  391. FILE *f;
  392. {
  393.     register int c;
  394.  
  395.     if (feof(f) || ferror(f))
  396.         return;
  397.     while ((c = getc(f)) != '\n' && c != EOF)
  398.         ;
  399. }
  400.  
  401.  
  402. /*
  403.  * compare string pointers
  404.  */
  405. strpcmp(a, b)
  406. char **a, **b;
  407. {
  408.     return CMP(*a, *b);
  409. }
  410.  
  411.  
  412. /*
  413.  * apply the given function to each member in the newsgroup
  414.  */
  415. /* VARARGS2 */
  416. applyng(ng, func, arg1)
  417. register char *ng;
  418. register int (*func)();
  419. char *arg1;
  420. {
  421.     register char *delim;
  422.     register int err;
  423.  
  424.     err = 0;
  425.     while (*ng) {
  426.         if (delim = strchr(ng, NGSEPCHAR))
  427.             *delim = '\0';
  428.         err += (*func)(ng, arg1);
  429.         if (delim)
  430.             *delim = NGSEPCHAR, ng = delim + 1;
  431.         else
  432.             break;
  433.     }
  434.     return err;
  435. }
  436.  
  437.  
  438. /*
  439.  * generate a return address
  440.  */
  441. char *
  442. getretaddr(hp)
  443. header *hp;
  444. {
  445.     register char *ra;
  446.  
  447.     extern char *getpath(), *exaddress();
  448. #ifdef NETPATH
  449.     extern char *getnetpath();
  450. #endif
  451.  
  452.     if (hp->h_replyto)
  453.         ra = exaddress(hp->h_replyto);
  454.     else if (hp->h_from)
  455.         ra = exaddress(hp->h_from);
  456.     else
  457.         ra = NIL(char);
  458.     if (hp->h_path && !ra)
  459.         ra = getpath(hp->h_path);
  460. #ifdef NETPATH
  461.     if (CMPN(ra, PATHPREF, sizeof(PATHPREF) - 1) == 0)
  462.         ra = getnetpath(ra);
  463. #endif
  464.     return ra;
  465. }
  466.  
  467.  
  468. /*
  469.  * try and make a proper address
  470.  */
  471. char *
  472. exaddress(addr)
  473. char *addr;
  474. {
  475.     register char *space, *dot, *at;
  476.     register char *raddr;
  477.  
  478.     raddr = NIL(char);
  479.     if (space = strchr(addr, ' '))
  480.         *space = '\0';
  481.     if (at = strchr(addr, '@')) {
  482.         *at = '\0';
  483.         if (dot = strchr(at + 1, '.')) {
  484.             *dot = '\0';
  485. #if OZ
  486.             if (CMP(dot + 1, MYDOMAIN) == 0)
  487.                 raddr = newstr3(addr, ":", at + 1);
  488.             else
  489. #endif
  490.                 raddr = newstr4(PATHPREF, at + 1, PSEPS, addr);
  491.             *dot = '.';
  492.         }
  493.         *at = '@';
  494.     }
  495.     if (space)
  496.         *space = ' ';
  497.     return raddr;
  498.  
  499. }
  500.  
  501.  
  502. /*
  503.  * return the last two components of the path
  504.  */
  505. char *
  506. getpath(path)
  507. char *path;
  508. {
  509.     register char *exlast, *ex;
  510.     register char *raddr;
  511.  
  512.     if (exlast = strrchr(path, PSEPCHAR)) {
  513.         *exlast = '\0';
  514.         if (ex = strrchr(path, PSEPCHAR))
  515.             raddr = newstr4(PATHPREF, ex + 1, PSEPS, exlast + 1);
  516.         else
  517.             raddr = newstr3(path, PSEPS, exlast + 1);
  518.         *exlast = PSEPCHAR;
  519.     } else
  520.         raddr = NIL(char);
  521.     return raddr;
  522. }
  523.  
  524.  
  525. #ifdef NETPATH
  526. /*
  527.  * try and work out a path from our "netpath" database
  528.  */
  529. char *
  530. getnetpath(path)
  531. char *path;
  532. {
  533.     FILE         * f;
  534.     register char *ex1, *ex2, *com, *new;
  535.     char buf[BUFSIZ];
  536.  
  537.     if ((ex1 = strchr(path, PSEPCHAR)) && (ex2 = strchr(ex1 + 1, PSEPCHAR))) {
  538.         *ex2 = '\0';
  539.         com = newstr4("exec ", NETPATH, " mulga ", ex1 + 1);
  540.         if ((f = popen(com, "r")) == NIL(FILE))
  541.             (void) printf("Couldn't run \"%s\"\n", com);
  542.         else
  543.          {
  544.             fread(buf, sizeof(buf), 1, f);
  545.             if (pclose(f) != 0) {
  546.                 (void) printf("Error in running \"%s\"\n", com);
  547.                 fflush(stdout);
  548.             } else if (CMPN(buf, "mulga!", 6) == 0) {
  549.                 if (ex1 = strchr(buf, '\n'))
  550.                     *ex1 = '\0';
  551.                 new = newstr4(buf + 6, PSEPS, ex2 + 1, ":mulga");
  552.                 free(path);
  553.                 path = new;
  554.             }
  555.         }
  556.         free(com);
  557.         *ex2 = PSEPCHAR;
  558.     }
  559.     return path;
  560.  
  561. }
  562.  
  563.  
  564. #endif
  565.  
  566. /*
  567.  * remove extra spaces, and insert separators if necessary in
  568.  * newsgroups specification
  569.  */
  570. convgrps(sp)
  571. register char *sp;
  572. {
  573.     register char *sep;
  574.  
  575.     sep = NIL(char);
  576.     while (*sp) {
  577.         if (sep)
  578.             sp++;
  579.         while (*sp && (isspace(*sp) || *sp == NGSEPCHAR))
  580.             strcpy(sp, sp + 1);
  581.         if (sep)
  582.             *sep = (*sp ? NGSEPCHAR : '\0');
  583.         while (*sp && !isspace(*sp) && *sp != NGSEPCHAR)
  584.             sp++;
  585.         sep = sp;
  586.     }
  587. }
  588.  
  589.  
  590.