home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / UTIL / WWIVSOR / CONF.C < prev    next >
Text File  |  1995-05-12  |  37KB  |  1,535 lines

  1. /*****************************************************************************
  2.  
  3.                                 WWIV Version 4
  4.                     Copyright (C) 1988-1995 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15. #include "vars.h"
  16.  
  17. #pragma hdrstop
  18.  
  19. #include "share.h"
  20.  
  21. /****************************************************************************/
  22.  
  23. /* Max line length in conference files */
  24. #define MAX_CONF_LINE 4096
  25.  
  26. /* To prevent heap fragmentation, allocate confrec.subs in multiples. */
  27. #define CONF_MULTIPLE ((unsigned int)(max_subs/5))
  28.  
  29. /****************************************************************************/
  30.  
  31. /*
  32.  * Returns info on conference types
  33.  */
  34.  
  35. int get_conf_info(unsigned int conftype, unsigned int *num, confrec **cpp, char *fn, unsigned int *num_s, userconfrec **uc)
  36. {
  37.   switch(conftype) {
  38.     case CONF_SUBS:
  39.       if (cpp)
  40.         *cpp=subconfs;
  41.       if (num)
  42.         *num=subconfnum;
  43.       if (fn)
  44.         sprintf(fn,"%sSUBS.CNF",syscfg.datadir);
  45.       if (num_s)
  46.         *num_s=num_subs;
  47.       if (uc)
  48.         *uc=uconfsub;
  49.       return(0);
  50.     case CONF_DIRS:
  51.       if (cpp)
  52.         *cpp=dirconfs;
  53.       if (num)
  54.         *num=dirconfnum;
  55.       if (fn)
  56.         sprintf(fn,"%sDIRS.CNF",syscfg.datadir);
  57.       if (num_s)
  58.         *num_s=num_dirs;
  59.       if (uc)
  60.         *uc=uconfdir;
  61.       return(0);
  62.   }
  63.   return(1);
  64. }
  65.  
  66. /****************************************************************************/
  67.  
  68. /*
  69.  * Presents user with selection of conferences, gets selection, and changes
  70.  * conference.
  71.  */
  72.  
  73. void jump_conf(unsigned int conftype)
  74. {
  75.   int i, abort=0;
  76.   unsigned char ch, s[81], s1[81];
  77.   confrec *cp;
  78.   userconfrec *uc;
  79.   unsigned int nc;
  80.  
  81.   get_conf_info(conftype, &nc, &cp, NULL, NULL, &uc);
  82.   abort=0;
  83.   strcpy(s," ");
  84.   nl();
  85.   ansic(1);
  86.   pl(get_string(1081));
  87.   nl();
  88.   for (i=0; (i<MAX_CONFERENCES) && (uc[i].confnum!=-1); i++) {
  89.     sprintf(s1,"2%c7)1 %s",cp[uc[i].confnum].designator,
  90.       stripcolors(cp[uc[i].confnum].name));
  91.     pla(s1,&abort);
  92.     s[i+1]=cp[uc[i].confnum].designator;
  93.     s[i+2]=0;
  94.   }
  95.  
  96.   nl();
  97.   ansic(2);
  98.   npr(get_string(1082));
  99.   npr("%s",&s[1]);
  100.   outstr(get_string(1083));
  101.   ch=onek(s);
  102.   if (ch!=' ') {
  103.     for (i=0; (i<MAX_CONFERENCES) && (uc[i].confnum!=-1); i++) {
  104.       if (ch==cp[uc[i].confnum].designator) {
  105.         setuconf(conftype, i, -1);
  106.         break;
  107.       }
  108.     }
  109.   }
  110. }
  111.  
  112. /****************************************************************************/
  113.  
  114. /*
  115.  * Removes, inserts, or swaps subs/dirs in all conferences of a specified
  116.  * type.
  117.  */
  118.  
  119. void update_conf(unsigned int conftype, SUBCONF_TYPE *sub1, SUBCONF_TYPE *sub2, unsigned int action)
  120. {
  121.   confrec *cp;
  122.   unsigned int nc, num_s;
  123.   int pos1, pos2;
  124.   int i,i1;
  125.   confrec c;
  126.  
  127.   if (get_conf_info(conftype, &nc, &cp, NULL, &num_s, NULL))
  128.     return;
  129.  
  130.   if ((!nc) || (!cp))
  131.     return;
  132.  
  133.   switch (action) {
  134.     case CONF_UPDATE_INSERT:
  135.       if (!sub1)
  136.         return;
  137.       for (i=0; i<nc; i++) {
  138.         c=cp[i];
  139.         if ((c.num) && (c.subs)) {
  140.           for (i1=0; i1<c.num; i1++) {
  141.             if (c.subs[i1]>=*sub1)
  142.               c.subs[i1]=c.subs[i1]+1;
  143.           }
  144.         }
  145.         cp[i]=c;
  146.       }
  147.       save_confs(conftype, -1, NULL);
  148.       break;
  149.     case CONF_UPDATE_DELETE:
  150.       if (!sub1)
  151.         return;
  152.       for (i=0; i<nc; i++) {
  153.         c=cp[i];
  154.         if ((c.num) && (c.subs)) {
  155.           if (in_conference(*sub1,&c)!=-1)
  156.             delsubconf(conftype, &c, sub1);
  157.         }
  158.         for (i1=0; i1<c.num; i1++) {
  159.           if (c.subs[i1]>=*sub1)
  160.             c.subs[i1]=c.subs[i1]-1;
  161.         }
  162.         cp[i]=c;
  163.       }
  164.       save_confs(conftype, -1, NULL);
  165.       break;
  166.     case CONF_UPDATE_SWAP:
  167.       if ((!sub1) || (!sub2))
  168.         return;
  169.       for (i=0; i<nc; i++) {
  170.         c=cp[i];
  171.         pos1=in_conference(*sub1,&c);
  172.         pos2=in_conference(*sub2,&c);
  173.         if (pos1!=-1)
  174.           c.subs[pos1]=*sub2;
  175.         if (pos2!=-1)
  176.           c.subs[pos2]=*sub1;
  177.         cp[i]=c;
  178.       }
  179.       save_confs(conftype, -1, NULL);
  180.       break;
  181.   }
  182. }
  183.  
  184. /****************************************************************************/
  185.  
  186. /*
  187.  * Returns bitmapped word representing an AR or DAR string.
  188.  */
  189.  
  190. unsigned int str_to_arword(unsigned char *arstr)
  191. {
  192.   int i;
  193.   unsigned int rar=0;
  194.   char s[81];
  195.  
  196.   strcpy(s,arstr);
  197.   strupr(s);
  198.  
  199.   for (i=0; i<16; i++) {
  200.     if (strchr(s,i+'A')!=NULL)
  201.       rar |= (1 << i);
  202.   }
  203.   return(rar);
  204. }
  205.  
  206. /****************************************************************************/
  207.  
  208. /*
  209.  * Converts an unsigned int to a string representing those ARs (DARs).
  210.  */
  211.  
  212. unsigned char *word_to_arstr(unsigned int ar)
  213. {
  214.   static unsigned char arstr[17];
  215.   unsigned int i, i1=0;
  216.  
  217.   if (ar) {
  218.     for (i=0; i<16; i++) {
  219.       if ((1 << i) & ar) {
  220.         arstr[i1++]='A'+i;
  221.       }
  222.     }
  223.   }
  224.   arstr[i1]=0;
  225.   if (!arstr[0])
  226.     strcpy(arstr,"-");
  227.   return(arstr);
  228. }
  229.  
  230. /****************************************************************************/
  231.  
  232. /*
  233.  * Returns first available conference designator, of a specified conference
  234.  * type.
  235.  */
  236.  
  237. unsigned char first_available_designator(unsigned int conftype)
  238. {
  239.   int i,i1;
  240.   confrec *cp;
  241.   unsigned int nc;
  242.  
  243.   if (get_conf_info(conftype, &nc, &cp, NULL, NULL, NULL))
  244.     return(0);
  245.  
  246.   if (nc==MAX_CONFERENCES)
  247.     return(0);
  248.   for (i=0; i<MAX_CONFERENCES; i++) {
  249.     for (i1=0; i1<nc; i1++) {
  250.       if (cp[i1].designator==('A'+i)) {
  251.         break;
  252.       }
  253.     }
  254.     if (i1>=nc)
  255.       return(i+'A');
  256.   }
  257.   return(0);
  258. }
  259.  
  260. /****************************************************************************/
  261.  
  262. /*
  263.  * Returns 1 if subnum is allocated to conference c, 0 otherwise.
  264.  */
  265.  
  266. int in_conference(unsigned int subnum, confrec *c)
  267. {
  268.   int init=-1;
  269.   unsigned int i;
  270.  
  271.   if ((!c) || (!c->subs) || (c->num==0))
  272.     return(-1);
  273.   for (i=0; i<c->num; i++)
  274.     if (init==-1)
  275.       if (c->subs[i]==subnum)
  276.         init=i;
  277.   return(init);
  278. }
  279.  
  280. /****************************************************************************/
  281.  
  282. /*
  283.  * Saves conferences of a specified conference-type.
  284.  */
  285.  
  286. void save_confs(unsigned int conftype, int whichnum, confrec *c)
  287. {
  288.   unsigned char cf[81];
  289.   unsigned int i,i2,num, num1;
  290.   FILE *f;
  291.   confrec *cp;
  292.  
  293.   if (get_conf_info(conftype, &num, &cp, cf, NULL, NULL))
  294.     return;
  295.  
  296.   f=fsh_open(cf,"wt");
  297.   if (!f) {
  298.     ansic(6);
  299.     nl();
  300.     outstr(get_string(1084));
  301.     pl(cf);
  302.     return;
  303.   }
  304.  
  305.   num1=num;
  306.   if (whichnum==num)
  307.     num1++;
  308.  
  309.   fprintf(f,"%s\n\n",get_string(1085));
  310.   for (i=0; i<num1; i++) {
  311.     if (whichnum==i) {
  312.       if (c) {
  313.         fprintf(f,"~%c %s\n!%d %d %d %d %d %d %d %u %d %s ",
  314.           c->designator, c->name, c->status, c->minsl, c->maxsl, c->mindsl,
  315.           c->maxdsl, c->minage, c->maxage, c->minbps, c->sex,
  316.           word_to_arstr(c->ar));
  317.         fprintf(f,"%s\n@", word_to_arstr(c->dar));
  318.         if (((c->num)>0) && (c->subs!=NULL)) {
  319.           for (i2=0; i2<c->num; i2++)
  320.             fprintf(f,"%d ",c->subs[i2]);
  321.         }
  322.         fprintf(f,"\n\n");
  323.       } else
  324.         continue;
  325.     }
  326.     if (i<num) {
  327.       fprintf(f,"~%c %s\n!%d %d %d %d %d %d %d %u %d %s ",
  328.         cp[i].designator, cp[i].name, cp[i].status,
  329.         cp[i].minsl, cp[i].maxsl, cp[i].mindsl,
  330.         cp[i].maxdsl, cp[i].minage, cp[i].maxage,
  331.         cp[i].minbps, cp[i].sex, word_to_arstr(cp[i].ar));
  332.       fprintf(f,"%s\n@",word_to_arstr(cp[i].dar));
  333.       if (cp[i].num>0) {
  334.         for (i2=0; i2<cp[i].num; i2++)
  335.           fprintf(f,"%d ",cp[i].subs[i2]);
  336.       }
  337.       fprintf(f,"\n\n");
  338.     }
  339.   }
  340.   fsh_close(f);
  341. }
  342.  
  343. /****************************************************************************/
  344.  
  345. /*
  346.  * Lists subs/dirs/whatever allocated to a specific conference.
  347.  */
  348.  
  349. void showsubconfs(unsigned int conftype, confrec *c)
  350. {
  351.   int abort,i,i1,test;
  352.   unsigned int num;
  353.   char s[120], indexstr[5], confstr[MAX_CONFERENCES+1], ts[2];
  354.   confrec *cp;
  355.   unsigned int nc;
  356.  
  357.   if (!c)
  358.     return;
  359.  
  360.   if (get_conf_info(conftype, &nc, &cp, NULL, &num, NULL))
  361.     return;
  362.  
  363.   abort=0;
  364.   pla(get_string(1086),&abort);
  365.   pla(get_string(1087),&abort);
  366.  
  367.   for (i=0; (i<num) && (!abort); i++) {
  368.     test=in_conference(i,c);
  369.     itoa(test,indexstr,10);
  370.  
  371.     /* build conf list string */
  372.     strcpy(confstr,"");
  373.     for (i1=0; i1<nc; i1++) {
  374.       if (in_conference(i, &cp[i1])!=-1) {
  375.         sprintf(ts, "%c", cp[i1].designator);
  376.         strcat(confstr,ts);
  377.       }
  378.     }
  379.     sort_conf_str(confstr);
  380.  
  381.     switch (conftype) {
  382.       case CONF_SUBS:
  383.         sprintf(s,"%3d %-39s %4.4s %s",i,stripcolors(subboards[i].name),
  384.           (test>-1)?indexstr:charstr(4,'-'),confstr);
  385.         break;
  386.       case CONF_DIRS:
  387.         sprintf(s,"%3d %-39s %4.4s %s",i,stripcolors(directories[i].name),
  388.           (test>-1)?indexstr:charstr(4,'-'),confstr);
  389.         break;
  390.     }
  391.     pla(s,&abort);
  392.   }
  393. }
  394.  
  395. /****************************************************************************/
  396.  
  397. /*
  398.  * Takes a string like "100-150,201,333" and returns pointer to list of
  399.  * numbers. Number of numbers in the list is returned in numinlist.
  400.  */
  401.  
  402. SUBCONF_TYPE *str_to_numrange(unsigned char *s, int *numinlist)
  403. {
  404.   unsigned char ls[81], rs[81], workstr[81];
  405.   int i,i1,cnt=0,lonum,hinum;
  406.   SUBCONF_TYPE intarray[1024], *intlist;
  407.   unsigned int wc1, wc2;
  408.  
  409.   /* init vars */
  410.   memset(intarray, 0, sizeof(intarray));
  411.   *numinlist=0;
  412.  
  413.   /* check for input string */
  414.   if (!s)
  415.     return(NULL);
  416.  
  417.   /* get num "words" in input string */
  418.   wc1=wordcount(s, ",");
  419.  
  420.   for (i1=1; (i1<=wc1); i1++) {
  421.     checkhangup();
  422.     if (hangup) {
  423.       *numinlist=0;
  424.       return(NULL);
  425.     }
  426.     strncpy(workstr, extractword(i1, s, ","), sizeof(workstr));
  427.     wc2=wordcount(workstr, " -\t\r\n");
  428.     switch (wc2) {
  429.       case 0:
  430.         break;
  431.       case 1:
  432.         i=atoi(extractword(1,workstr," -\t\r\n"));
  433.         if ((i<1024) && (i>=0)) {
  434.           if (intarray[i]==0) {
  435.             intarray[i]=1;
  436.             cnt++;
  437.           }
  438.         }
  439.         break;
  440.       default:
  441.         /* get left/right string */
  442.         strncpy(ls, extractword(1,workstr," -\t\r\n,"), sizeof(ls));
  443.         strncpy(rs, extractword(2,workstr," -\t\r\n,"), sizeof(rs));
  444.         /* convert to numbers */
  445.         lonum=atoi(ls);
  446.         hinum=atoi(rs);
  447.         /* Switch them around if they were reversed */
  448.         if (lonum>hinum) {
  449.           i=lonum;
  450.           lonum=hinum;
  451.           hinum=i;
  452.         }
  453.         if (lonum<0)
  454.           lonum=0;
  455.         if (hinum>1023)
  456.           hinum=1023;
  457.         for (i=lonum; i<=hinum; i++) {
  458.           if (intarray[i]==0) {
  459.             intarray[i]=1;
  460.             cnt++;
  461.           }
  462.         }
  463.         break;
  464.     } /* end switch */
  465.   }
  466.  
  467.   if (!cnt)
  468.     return(NULL);
  469.  
  470.   /* allocate memory for list */
  471.   intlist=(SUBCONF_TYPE *)malloca(cnt * sizeof(SUBCONF_TYPE));
  472.   if (intlist) {
  473.     for (i=i1=0; i<1024; i++) {
  474.       if (intarray[i]==1)
  475.         intlist[i1++]=i;
  476.     }
  477.     *numinlist=cnt;
  478.     return(intlist);
  479.   } else {
  480.     *numinlist=0;
  481.     return(NULL);
  482.   }
  483. }
  484.  
  485. /****************************************************************************/
  486.  
  487. /*
  488.  * Function to add one subconf (sub/dir/whatever) to a conference.
  489.  */
  490.  
  491. void addsubconf(unsigned int conftype, confrec *c, SUBCONF_TYPE *which)
  492. {
  493.   SUBCONF_TYPE *intlist;
  494.   int i1,lnum,hnum,numinlist;
  495.   unsigned int i, num;
  496.   SUBCONF_TYPE *tptr;
  497.   unsigned char s[81];
  498.  
  499.   if ((!c) || (!c->subs))
  500.     return;
  501.  
  502.   if (get_conf_info(conftype, NULL, NULL, NULL, &num, NULL))
  503.     return;
  504.  
  505.   if (num<1)
  506.     return;
  507.  
  508.   if (c->num>=1023) {
  509.     pl(get_string(1490));
  510.     return;
  511.   }
  512.  
  513.   if (which==NULL) {
  514.     nl();
  515.     prt(2,get_string(1088));
  516.     mpl(60);
  517.     input(s,60);
  518.     if (!s[0])
  519.       return;
  520.     intlist=str_to_numrange(s, &numinlist);
  521.     lnum=0; hnum=numinlist-1;
  522.   } else {
  523.     intlist=NULL;
  524.     lnum=hnum=*which;
  525.   }
  526.  
  527.   /* add the subconfs now */
  528.   for (i=lnum; i<=hnum; i++) {
  529.     if (which==NULL)
  530.       i1=intlist[i];
  531.     else
  532.       i1=i;
  533.     if (i1>=num)
  534.       break;
  535.     if (in_conference(i1,c)>-1)
  536.       continue;
  537.     if (c->num>=c->maxnum) {
  538.       c->maxnum += CONF_MULTIPLE;
  539.       tptr=malloca(c->maxnum * sizeof(SUBCONF_TYPE));
  540.       if (tptr) {
  541.         memmove(tptr, c->subs, (c->maxnum-CONF_MULTIPLE) * sizeof(SUBCONF_TYPE));
  542.         bbsfree(c->subs);
  543.         c->subs=tptr;
  544.       } else {
  545.         ansic(6);
  546.         pl(get_string(98));
  547.         if (intlist)
  548.           bbsfree(intlist);
  549.         return;
  550.       }
  551.     }
  552.     c->subs[c->num]=i1;
  553.     c->num++;
  554.   }
  555.   if (intlist)
  556.     bbsfree(intlist);
  557. }
  558.  
  559. /****************************************************************************/
  560.  
  561. /*
  562.  * Function to delete one subconf (sub/dir/whatever) from a conference.
  563.  */
  564.  
  565. void delsubconf(unsigned int conftype, confrec *c, SUBCONF_TYPE *which)
  566. {
  567.   int pos,lnum,hnum,numinlist;
  568.   unsigned int num;
  569.   SUBCONF_TYPE i,i1,i2,*intlist;
  570.   unsigned char s[81];
  571.  
  572.   if ((!c) || (!c->subs) || (c->num<1))
  573.     return;
  574.  
  575.   if (get_conf_info(conftype, NULL, NULL, NULL, &num, NULL))
  576.     return;
  577.  
  578.   if (which==NULL) {
  579.     nl();
  580.     prt(2,get_string(1091));
  581.     mpl(60);
  582.     input(s,60);
  583.     if (!s[0])
  584.       return;
  585.     intlist=str_to_numrange(s, &numinlist);
  586.     lnum=0; hnum=numinlist-1;
  587.   } else {
  588.     intlist=NULL;
  589.     lnum=hnum=*which;
  590.   }
  591.  
  592.   for (i=lnum; i<=hnum; i++) {
  593.     if (which==NULL)
  594.       i1=intlist[i];
  595.     else
  596.       i1=i;
  597.     if (i1>=num)
  598.       break;
  599.     pos=in_conference(i1,c);
  600.     if (pos<0)
  601.       continue;
  602.     for (i2=pos; i2<c->num; i2++)
  603.       c->subs[i2]=c->subs[i2+1];
  604.     c->num--;
  605.   }
  606.   if (intlist)
  607.     bbsfree(intlist);
  608. }
  609.  
  610. /****************************************************************************/
  611.  
  612. /*
  613.  * Function for editing the data for one conference.
  614.  */
  615.  
  616. int modify_conf(unsigned int conftype, unsigned int n)
  617. {
  618.   int done=0, ok, changed=0;
  619.   confrec c, *cp;
  620.   unsigned int num, ns;
  621.   SUBCONF_TYPE i;
  622.   unsigned char ch, ch1, s[81];
  623.  
  624.   if (get_conf_info(conftype, &num, &cp, NULL, &ns, NULL) || (n>=num))
  625.     return(0);
  626.  
  627.   c=cp[n];
  628.  
  629.   do {
  630.     outchr(12);
  631.  
  632.     outstr(get_string(1093));
  633.     npr("%c\r\n", c.designator);
  634.  
  635.     outstr(get_string(1094));
  636.     npr("%.52s\r\n", c.name);
  637.  
  638.     outstr(get_string(1095));
  639.     pln(c.minsl);
  640.  
  641.     outstr(get_string(1096));
  642.     pln(c.maxsl);
  643.  
  644.     outstr(get_string(1097));
  645.     pln(c.mindsl);
  646.  
  647.     outstr(get_string(1098));
  648.     pln(c.maxdsl);
  649.  
  650.     outstr(get_string(1099));
  651.     pln(c.minage);
  652.  
  653.     outstr(get_string(1100));
  654.     pln(c.maxage);
  655.  
  656.     outstr(get_string(1101));
  657.     pl(word_to_arstr(c.ar));
  658.  
  659.     outstr(get_string(1102));
  660.     pl(word_to_arstr(c.dar));
  661.  
  662.     outstr(get_string(1103));
  663.     pln(c.minbps);
  664.  
  665.     outstr(get_string(1104));
  666.     switch (c.sex) {
  667.       case 0:
  668.         pl(get_string(1105));
  669.         break;
  670.       case 1:
  671.         pl(get_string(1106));
  672.         break;
  673.       case 2:
  674.         pl(get_string(1107));
  675.         break;
  676.     }
  677.  
  678.     outstr(get_string(1108));
  679.     pl((c.status & conf_status_ansi)?str_yes:str_no);
  680.  
  681.     outstr(get_string(1109));
  682.     pl((c.status & conf_status_wwivreg)?str_yes:str_no);
  683.  
  684.     outstr(get_string(1491));
  685.     pl((c.status & conf_status_offline)?str_no:str_yes);
  686.  
  687.     pl(get_string(1110));
  688.     pl(get_string(1111));
  689.  
  690.     nl();
  691.  
  692.     prt(2,get_string(1113));
  693.  
  694.     ch=onek("QSABCDEFGHIJKLMNO");
  695.  
  696.     switch (ch) {
  697.       case 'A':
  698.         nl();
  699.         prt(2,get_string(1115));
  700.         ch1=onek("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  701.         ok=1;
  702.         for (i=0; i<num; i++) {
  703.           if (i==n)
  704.             i++;
  705.           if (ok)
  706.             if (cp)
  707.               if (cp[i].designator==ch1)
  708.                 ok=0;
  709.         }
  710.         if (!ok) {
  711.           nl();
  712.           prt(6,get_string(1117));
  713.           nl();
  714.           pausescr();
  715.           break;
  716.         }
  717.         c.designator=ch1;
  718.         changed=1;
  719.         break;
  720.       case 'B':
  721.         nl();
  722.         prt(2,get_string(1118));
  723.         inputl(s,60);
  724.         if (s[0]) {
  725.           strcpy(c.name,s);
  726.           changed=1;
  727.         }
  728.         break;
  729.       case 'C':
  730.         nl();
  731.         prt(2,get_string(1119));
  732.         input(s,3);
  733.         if (s[0]) {
  734.           if ((atoi(s)>=0) && (atoi(s)<=255)) {
  735.             c.minsl=atoi(s);
  736.             changed=1;
  737.           }
  738.         }
  739.         break;
  740.       case 'D':
  741.         nl();
  742.         prt(2,get_string(1120));
  743.         input(s,3);
  744.         if (s[0]) {
  745.           if ((atoi(s)>=0) && (atoi(s)<=255)) {
  746.             c.maxsl=atoi(s);
  747.             changed=1;
  748.           }
  749.         }
  750.         break;
  751.       case 'E':
  752.         nl();
  753.         prt(2,get_string(1121));
  754.         input(s,3);
  755.         if (s[0]) {
  756.           if ((atoi(s)>=0) && (atoi(s)<=255)) {
  757.             c.mindsl=atoi(s);
  758.             changed=1;
  759.           }
  760.         }
  761.         break;
  762.       case 'F':
  763.         nl();
  764.         prt(2,get_string(1122));
  765.         input(s,3);
  766.         if (s[0]) {
  767.           if ((atoi(s)>=0) && (atoi(s)<=255)) {
  768.             c.maxdsl=atoi(s);
  769.             changed=1;
  770.           }
  771.         }
  772.         break;
  773.       case 'G':
  774.         nl();
  775.         prt(2,get_string(1123));
  776.         input(s,2);
  777.         if (s[0]) {
  778.           c.minage=atoi(s);
  779.           changed=1;
  780.         }
  781.         break;
  782.       case 'H':
  783.         nl();
  784.         prt(2,get_string(1124));
  785.         input(s,3);
  786.         if (s[0]) {
  787.           if ((atoi(s)>=0) && (atoi(s)<=255)) {
  788.             c.maxage=atoi(s);
  789.             changed=1;
  790.           }
  791.         }
  792.         break;
  793.       case 'I':
  794.         nl();
  795.         prt(2,get_string(1125));
  796.         ch1=onek("\rABCDEFGHIJKLMNOP ");
  797.         switch (ch1) {
  798.           case ' ':
  799.           case '\r':
  800.             break;
  801.           default:
  802.             c.ar ^= (1 << (ch1-'A'));
  803.             changed=1;
  804.             break;
  805.         }
  806.         break;
  807.       case 'J':
  808.         nl();
  809.         prt(2,get_string(1126));
  810.         ch1=onek("\rABCDEFGHIJKLMNOP ");
  811.         switch (ch1) {
  812.           case ' ':
  813.           case '\r':
  814.             break;
  815.           default:
  816.             c.dar ^= (1 << (ch1-'A'));
  817.             changed=1;
  818.             break;
  819.         }
  820.         break;
  821.       case 'K':
  822.         nl();
  823.         prt(2,get_string(1127));
  824.         input(s,5);
  825.         if (s[0]) {
  826.           c.minbps=(SUBCONF_TYPE)(atol(s));
  827.           changed=1;
  828.         }
  829.         break;
  830.       case 'L':
  831.         nl();
  832.         changed=1;
  833.         prt(5, get_string(1128));
  834.         ch1=onek("MFA");
  835.         switch (ch1) {
  836.           case 'M':
  837.             c.sex=0;
  838.             break;
  839.           case 'F':
  840.             c.sex=1;
  841.             break;
  842.           case 'A':
  843.             c.sex=2;
  844.             break;
  845.         }
  846.         break;
  847.       case 'M':
  848.         nl();
  849.         changed=1;
  850.         c.status &= ~conf_status_ansi;
  851.         prt(5, get_string(1129));
  852.         if (yn())
  853.           c.status |= conf_status_ansi;
  854.         break;
  855.       case 'N':
  856.         nl();
  857.         changed=1;
  858.         c.status &= ~conf_status_wwivreg;
  859.         prt(5, get_string(1130));
  860.         if (yn())
  861.           c.status |= conf_status_wwivreg;
  862.         break;
  863.       case 'O':
  864.         nl();
  865.         changed=1;
  866.         c.status &= ~conf_status_offline;
  867.         prt(5, get_string(1492));
  868.         if (!ny())
  869.           c.status |= conf_status_offline;
  870.         break;
  871.       case 'S':
  872.         ok=0;
  873.         do {
  874.           nl();
  875.           prt(2,get_string(1131));
  876.           ch1=onek("QARCFS");
  877.           switch (ch1) {
  878.             case 'A':
  879.               addsubconf(conftype, &c, NULL);
  880.               changed=1;
  881.               break;
  882.             case 'R':
  883.               delsubconf(conftype, &c, NULL);
  884.               changed=1;
  885.               break;
  886.             case 'C':
  887.               for (i=0; i<ns; i++) {
  888.                 if (in_conference(i,&c)>-1) {
  889.                   delsubconf(conftype, &c, &i);
  890.                   changed=1;
  891.                 }
  892.               }
  893.               break;
  894.             case 'F':
  895.               for (i=0; i<ns; i++) {
  896.                 if (in_conference(i,&c)<0) {
  897.                   addsubconf(conftype, &c, &i);
  898.                   changed=1;
  899.                 }
  900.               }
  901.               break;
  902.             case 'Q':
  903.               ok=1;
  904.               break;
  905.             case 'S':
  906.               nl();
  907.               showsubconfs(conftype, &c);
  908.               break;
  909.           }
  910.         } while (!ok);
  911.         break;
  912.       case 'Q':
  913.         done=1;
  914.         break;
  915.     }
  916.   } while ((!done) && (!hangup));
  917.  
  918.   cp[n]=c;
  919.   return(changed);
  920. }
  921.  
  922. /****************************************************************************/
  923.  
  924. /*
  925.  * Function for inserting one conference.
  926.  */
  927.  
  928. void insert_conf(unsigned int conftype, unsigned int n)
  929. {
  930.   confrec c;
  931.   unsigned int num;
  932.  
  933.   if (get_conf_info(conftype, &num, NULL, NULL, NULL, NULL) || (n>num))
  934.     return;
  935.  
  936.   c.designator=first_available_designator(conftype);
  937.  
  938.   if (c.designator==0)
  939.     return;
  940.  
  941.   sprintf(c.name,"%s%c",get_string(1133),c.designator);
  942.   c.minsl=0; c.maxsl=255; c.mindsl=0; c.maxdsl=255; c.minage=0;
  943.   c.maxage=255; c.status=0; c.minbps=0; c.sex=2;  c.ar=0; c.dar=0; c.num=0;
  944.   c.subs=NULL;
  945.  
  946.   save_confs(conftype, n, &c);
  947.  
  948.   read_in_conferences(conftype);
  949.  
  950.   if (modify_conf(conftype, n))
  951.     save_confs(conftype, -1, NULL);
  952. }
  953.  
  954. /****************************************************************************/
  955.  
  956. /*
  957.  * Function for deleting one conference.
  958.  */
  959.  
  960. void delete_conf(unsigned int conftype, unsigned int n)
  961. {
  962.   unsigned int num;
  963.  
  964.   if (get_conf_info(conftype, &num, NULL, NULL, NULL, NULL) || (n>=num))
  965.     return;
  966.  
  967.   save_confs(conftype, n, NULL);
  968.   read_in_conferences(conftype);
  969. }
  970.  
  971. /****************************************************************************/
  972.  
  973. /*
  974.  * Function for editing conferences.
  975.  */
  976.  
  977. void conf_edit(unsigned int conftype)
  978. {
  979.   int done=0, ec;
  980.   char ch;
  981.   confrec *cp;
  982.   unsigned int num;
  983.  
  984.   if (get_conf_info(conftype, &num, &cp, NULL, NULL, NULL))
  985.     return;
  986.  
  987.   outchr(12);
  988.   list_confs(conftype,1);
  989.  
  990.   do {
  991.     nl();
  992.     outstr(get_string(1134));
  993.     ch=onek("QIDM?");
  994.     get_conf_info(conftype, &num, &cp, NULL, NULL, NULL);
  995.     switch (ch) {
  996.       case 'D':
  997.         if (num==1) {
  998.           nl();
  999.           pl(get_string(1135));
  1000.         } else {
  1001.           ec=select_conf(get_string(1136),conftype, 0);
  1002.           if (ec>=0)
  1003.             delete_conf(conftype, ec);
  1004.         }
  1005.         break;
  1006.       case 'I':
  1007.         if (num==MAX_CONFERENCES) {
  1008.           nl();
  1009.           pl(get_string(1137));
  1010.         } else {
  1011.           ec=select_conf(get_string(1138),conftype, 0);
  1012.           if (ec!=-1) {
  1013.             if (ec==-2)
  1014.               ec=num;
  1015.             insert_conf(conftype, ec);
  1016.           }
  1017.         }
  1018.         break;
  1019.       case 'M':
  1020.         ec=select_conf(get_string(1139),conftype, 0);
  1021.         if (ec>=0) {
  1022.           if (modify_conf(conftype, ec))
  1023.             save_confs(conftype,-1,NULL);
  1024.         }
  1025.         break;
  1026.       case 'Q':
  1027.         done=1;
  1028.         break;
  1029.       case '?':
  1030.         outchr(12);
  1031.         list_confs(conftype,1);
  1032.         break;
  1033.     }
  1034.   } while ((!done) && (!hangup));
  1035.   if (!wfc)
  1036.     changedsl();
  1037. }
  1038.  
  1039. /****************************************************************************/
  1040.  
  1041. /*
  1042.  * Lists conferences of a specified type. If OP_FLAGS_SHOW_HIER is set,
  1043.  * then the subs (dirs, whatever) in each conference are also shown.
  1044.  */
  1045.  
  1046. void list_confs(unsigned int conftype, int ssc)
  1047. {
  1048.   unsigned char s[121], s1[121];
  1049.   int abort=0;
  1050.   unsigned int i,i2, num, num_s;
  1051.   confrec *cp;
  1052.  
  1053.   if (get_conf_info(conftype, &num, &cp, NULL, &num_s, NULL))
  1054.     return;
  1055.  
  1056.   pla(get_string(1140),&abort);
  1057.   pla(get_string(1141),&abort);
  1058.  
  1059.   for (i=0; ((i<num) && (!abort)); i++) {
  1060.     ansic(7);
  1061.     sprintf(s,"%c═4 %c 1 %-23.23s %3d %3d %4d %4d %4d %4d %5u %-3.3s ",
  1062.         (i==(num-1))?'╚':'╠', cp[i].designator, cp[i].name, cp[i].minsl,
  1063.         cp[i].maxsl, cp[i].mindsl, cp[i].maxdsl, cp[i].minage, cp[i].maxage,
  1064.         cp[i].minbps, word_to_arstr(cp[i].ar));
  1065.     sprintf(s1,"%-3.3s %c %1.1s %1.1s",
  1066.         word_to_arstr(cp[i].dar),
  1067.         (cp[i].sex)?((cp[i].sex==2)?'A':'F'):'M',
  1068.         (cp[i].status & conf_status_ansi)?str_yes:str_no,
  1069.         (cp[i].status & conf_status_wwivreg)?str_yes:str_no);
  1070.     strcat(s,s1);
  1071.     pla(s,&abort);
  1072.     if (sysinfo.flags & OP_FLAGS_SHOW_HIER) {
  1073.       if ((cp[i].num>0) && (cp[i].subs!=NULL) && (ssc)) {
  1074.         for (i2=0; ((i2<cp[i].num) && (!abort)); i2++) {
  1075.           if (cp[i].subs[i2]<num_s) {
  1076.             ansic(7);
  1077.             sprintf(s,"%c  %c─── 9",(i!=(num-1))?'║':' ',
  1078.               (i2==(cp[i].num-1))?'└':'├');
  1079.             switch(conftype) {
  1080.               case CONF_SUBS:
  1081.                 sprintf(s1,"%s%-3d : %s",get_string(1142),subconfs[i].subs[i2],
  1082.                     stripcolors(subboards[cp[i].subs[i2]].name));
  1083.                 break;
  1084.               case CONF_DIRS:
  1085.                 sprintf(s1,"%s%-3d : %s",get_string(1143),dirconfs[i].subs[i2],
  1086.                     stripcolors(directories[cp[i].subs[i2]].name));
  1087.                 break;
  1088.             }
  1089.             strcat(s,s1);
  1090.             pla(s,&abort);
  1091.           }
  1092.         }
  1093.       }
  1094.     }
  1095.   }
  1096.   nl();
  1097. }
  1098.  
  1099. /****************************************************************************/
  1100.  
  1101. /*
  1102.  * Allows user to select a conference. Returns the conference selected
  1103.  * (0-based), or -1 if the user aborted. Error message is printed for
  1104.  * invalid conference selections.
  1105.  */
  1106.  
  1107. int select_conf(unsigned char *s, unsigned int conftype, int listconfs)
  1108. {
  1109.   int i,i1,ok=0,sl=0;
  1110.   unsigned char *mmk;
  1111.  
  1112.   do {
  1113.     if ((listconfs) || (sl)) {
  1114.       nl();
  1115.       list_confs(conftype,0);
  1116.       sl=0;
  1117.     }
  1118.     if (s && s[0]) {
  1119.       nl();
  1120.       prt(1,s);
  1121.     }
  1122.     mmk=mmkey(0);
  1123.     if (!mmk[0]) {
  1124.       i=-1;
  1125.       ok=1;
  1126.     } else {
  1127.       switch (mmk[0]) {
  1128.         case '?':
  1129.           sl=1;
  1130.           break;
  1131.         default:
  1132.           switch (conftype) {
  1133.             case CONF_SUBS:
  1134.               for (i1=0; i1<subconfnum; i1++) {
  1135.                 if (mmk[0]==subconfs[i1].designator) {
  1136.                   ok=1;
  1137.                   i=i1;
  1138.                   break;
  1139.                 }
  1140.               }
  1141.               break;
  1142.             case CONF_DIRS:
  1143.               for (i1=0; i1<dirconfnum; i1++) {
  1144.                 if (mmk[0]==dirconfs[i1].designator) {
  1145.                   ok=1;
  1146.                   i=i1;
  1147.                   break;
  1148.                 }
  1149.               }
  1150.               break;
  1151.           }
  1152.           if (mmk[0]=='$') {
  1153.             i=-2;
  1154.             ok=1;
  1155.           }
  1156.           break;
  1157.       }
  1158.       if ((!ok) && (!sl)) {
  1159.         nl();
  1160.         pl(get_string(1144));
  1161.       }
  1162.     }
  1163.   } while (!ok && !hangup);
  1164.   return(i);
  1165. }
  1166.  
  1167. /****************************************************************************/
  1168.  
  1169. /*
  1170.  * Creates a default conference file. Should only be called if no conference
  1171.  * file for that conference type already exists.
  1172.  */
  1173.  
  1174. int create_conf_file(unsigned int conftype)
  1175. {
  1176.   unsigned char cf[81];
  1177.   unsigned int i,num;
  1178.   FILE *f;
  1179.  
  1180.   if (get_conf_info(conftype, NULL, NULL, cf, &num, NULL))
  1181.     return(0);
  1182.  
  1183.   f=fsh_open(cf,"wt");
  1184.   if (!f)
  1185.     return(0);
  1186.  
  1187.   fprintf(f,"%s\n\n",get_string(1085));
  1188.   fprintf(f,"~A General\n!0 0 255 0 255 0 255 0 2 - -\n@");
  1189.   for (i=0;i<num;i++)
  1190.     fprintf(f,"%d ",i);
  1191.   fprintf(f,"\n\n");
  1192.  
  1193.   fsh_close(f);
  1194.   return(1);
  1195. }
  1196.  
  1197. /****************************************************************************/
  1198.  
  1199. /*
  1200.  * Reads in conferences and returns pointer to conference data. Out-of-memory
  1201.  * messages are shown if applicable.
  1202.  */
  1203.  
  1204. confrec *read_conferences(unsigned char *cf, unsigned int *nc, int max)
  1205. {
  1206.   unsigned char ts[128], *ls, *bs, *ss;
  1207.   unsigned long l;
  1208.   int i, i1, i2, i3, cc=0, nw, ok=1;
  1209.   confrec *conferences;
  1210.   FILE *f;
  1211.  
  1212.   *nc=get_num_conferences(cf);
  1213.   if (*nc<1)
  1214.     return(NULL);
  1215.  
  1216.   if (!exist(cf))
  1217.     return(NULL);
  1218.  
  1219.   f=fsh_open(cf,"rt");
  1220.   if (!f)
  1221.     return(NULL);
  1222.  
  1223.   l=((long)*nc)*sizeof(confrec);
  1224.   conferences=(confrec *)malloca(l);
  1225.   if (!conferences) {
  1226.     printf("%s%s.",get_string(1145),cf);
  1227.     fsh_close(f);
  1228.     return(NULL);
  1229.   }
  1230.  
  1231.   memset(conferences, 0, l);
  1232.   ls=malloca(MAX_CONF_LINE);
  1233.   if (!ls) {
  1234.     fsh_close(f);
  1235.     return(NULL);
  1236.   }
  1237.  
  1238.   while ((fgets(ls, MAX_CONF_LINE, f) != NULL) && (cc<MAX_CONFERENCES)) {
  1239.     nw=wordcount(ls, DELIMS_WHITE);
  1240.     if (nw) {
  1241.       strncpy(ts,extractword(1,ls,DELIMS_WHITE),sizeof(ts));
  1242.       if (ts[0]) {
  1243.         switch (ts[0]) {
  1244.           case '~':
  1245.             if ((nw>1) && (strlen(ts)>1) && (strlen(ls)>3)) {
  1246.               bs=strtok(&ls[3],"\r\n");
  1247.               if (bs) {
  1248.                 conferences[cc].designator=ts[1];
  1249.                 strncpy(conferences[cc].name,bs,sizeof(conferences[cc].name));
  1250.               }
  1251.             }
  1252.             break;
  1253.           case '!':
  1254.             if ((!conferences[cc].designator) || (nw!=11))
  1255.               break;
  1256.             for (i=1;i<=nw;i++) {
  1257.               strncpy(ts,extractword(i,ls,DELIMS_WHITE),sizeof(ts));
  1258.               switch (i) {
  1259.                 case 1:
  1260.                   if (strlen(ts)>=2)
  1261.                     conferences[cc].status=atoi(&ts[1]);
  1262.                   break;
  1263.                 case 2:
  1264.                   conferences[cc].minsl=atoi(ts);
  1265.                   break;
  1266.                 case 3:
  1267.                   conferences[cc].maxsl=atoi(ts);
  1268.                   break;
  1269.                 case 4:
  1270.                   conferences[cc].mindsl=atoi(ts);
  1271.                   break;
  1272.                 case 5:
  1273.                   conferences[cc].maxdsl=atoi(ts);
  1274.                   break;
  1275.                 case 6:
  1276.                   conferences[cc].minage=atoi(ts);
  1277.                   break;
  1278.                 case 7:
  1279.                   conferences[cc].maxage=atoi(ts);
  1280.                   break;
  1281.                 case 8:
  1282.                   conferences[cc].minbps=atol(ts);
  1283.                   break;
  1284.                 case 9:
  1285.                   conferences[cc].sex=atoi(ts);
  1286.                   break;
  1287.                 case 10:
  1288.                   conferences[cc].ar=str_to_arword(ts);
  1289.                   break;
  1290.                 case 11:
  1291.                   conferences[cc].dar=str_to_arword(ts);
  1292.                   break;
  1293.               }
  1294.             }
  1295.             break;
  1296.           case '@':
  1297.             if (!conferences[cc].designator)
  1298.               break;
  1299.             if (strlen(extractword(1,ls,DELIMS_WHITE))<2)
  1300.               conferences[cc].num=0;
  1301.             else
  1302.               conferences[cc].num=nw;
  1303.             conferences[cc].maxnum=conferences[cc].num;
  1304.             l=(long)(conferences[cc].num*sizeof(unsigned int)+1);
  1305.             conferences[cc].subs=(unsigned short *)malloca(l);
  1306.             ok=(conferences[cc].subs!=NULL);
  1307.             if (ok)
  1308.               memset(conferences[cc].subs,0,l);
  1309.             else {
  1310.               printf("%s%d, %s %s%s.",get_string(1146),get_string(1625),cc+1,
  1311.                 syscfg.datadir,cf);
  1312.               for (i2=0;i2<cc;i2++)
  1313.                 bbsfree(conferences[i2].subs);
  1314.               bbsfree(conferences);
  1315.               bbsfree(ls);
  1316.               fsh_close(f);
  1317.               return(NULL);
  1318.             }
  1319.             i=0;
  1320.             i1=0;
  1321.             for (ss=strtok(ls,DELIMS_WHITE); ((ss) && (i++<nw)); ss=strtok(NULL,DELIMS_WHITE)) {
  1322.               if (i==1) {
  1323.                 if (strlen(ss)>=2)
  1324.                   i3=atoi(ss+1);
  1325.                 else
  1326.                   i3=-1;
  1327.               } else {
  1328.                 i3=atoi(ss);
  1329.               }
  1330.               if ((i3>=0) && (i3<max)) {
  1331.                 conferences[cc].subs[i1++]=i3;
  1332.               }
  1333.             }
  1334.             conferences[cc].num=i1;
  1335.             cc++;
  1336.             break;
  1337.         }
  1338.       }
  1339.     }
  1340.   }
  1341.   fsh_close(f);
  1342.   bbsfree(ls);
  1343.   return(conferences);
  1344. }
  1345.  
  1346. /****************************************************************************/
  1347.  
  1348. /*
  1349.  * Reads in a conference type. Creates default conference file if it is
  1350.  * necessary. If conferences cannot be read, then BBS aborts.
  1351.  */
  1352.  
  1353. void read_in_conferences(int conftype)
  1354. {
  1355.   unsigned int i, *np, max;
  1356.   unsigned char s[81];
  1357.   confrec **cpp;
  1358.  
  1359.   if (get_conf_info(conftype, NULL, NULL, s, &max, NULL))
  1360.     return;
  1361.  
  1362.   switch(conftype) {
  1363.     case CONF_SUBS: cpp=&subconfs; np=&subconfnum; break;
  1364.     case CONF_DIRS: cpp=&dirconfs; np=&dirconfnum; break;
  1365.   }
  1366.  
  1367.   /* free up any old memory */
  1368.   if (*cpp) {
  1369.     for (i=0; i<*np; i++)
  1370.       if ((*cpp)[i].subs)
  1371.         bbsfree((*cpp)[i].subs);
  1372.     bbsfree(*cpp);
  1373.     *cpp=NULL;
  1374.   }
  1375.  
  1376.   if (!exist(s)) {
  1377.     if (!create_conf_file(conftype)) {
  1378.       printf("%s\n",get_string(1147));
  1379.       end_bbs(noklevel);
  1380.     }
  1381.   }
  1382.   *cpp=read_conferences(s, np, max);
  1383.   if (!(*cpp)) {
  1384.     printf("%s\n",get_string(1148));
  1385.     end_bbs(noklevel);
  1386.   }
  1387. }
  1388.  
  1389. /****************************************************************************/
  1390.  
  1391. /*
  1392.  * Reads all conferences into memory. Creates default conference files if
  1393.  * none exist. If called when conferences already in memory, then memory
  1394.  * for "old" conference data is deallocated first.
  1395.  */
  1396.  
  1397. void read_all_conferences(void)
  1398. {
  1399.   read_in_conferences(CONF_SUBS);
  1400.   read_in_conferences(CONF_DIRS);
  1401. }
  1402.  
  1403. /****************************************************************************/
  1404.  
  1405. /*
  1406.  * Returns number of conferences in a specified conference file.
  1407.  */
  1408.  
  1409. unsigned int get_num_conferences(unsigned char *cf)
  1410. {
  1411. #ifdef MALLOC_STR
  1412.   unsigned char *ls;
  1413. #else
  1414.   unsigned char ls[MAX_CONF_LINE];
  1415. #endif
  1416.   int i=0;
  1417.   FILE *f;
  1418.  
  1419.   if (!exist(cf))
  1420.     return(0);
  1421.   f=fsh_open(cf,"rt");
  1422.   if (!f)
  1423.     return(0);
  1424. #ifdef MALLOC_STR
  1425.   ls=malloca(MAX_CONF_LINE);
  1426.   if (!ls) {
  1427.     fsh_close(f);
  1428.     return(0);
  1429.   }
  1430. #endif
  1431.  
  1432.   while (fgets(ls, sizeof(ls), f) != NULL)
  1433.     if (ls[0]=='~')
  1434.       i++;
  1435.  
  1436.   fsh_close(f);
  1437. #ifdef MALLOC_STR
  1438.   bbsfree(ls);
  1439. #endif
  1440.   return(i);
  1441. }
  1442.  
  1443. /****************************************************************************/
  1444.  
  1445. /*
  1446.  * Returns number of "words" in a specified string, using a specified set
  1447.  * of characters as delimiters.
  1448.  */
  1449.  
  1450. unsigned int wordcount(unsigned char *instr, unsigned char *delimstr)
  1451. {
  1452.   unsigned char *s;
  1453. #ifdef MALLOC_STR
  1454.   unsigned char *ts;
  1455. #else
  1456.   unsigned char ts[MAX_CONF_LINE];
  1457. #endif
  1458.   int i=0;
  1459.  
  1460. #ifdef MALLOC_STR
  1461.   ts=malloca(MAX_CONF_LINE);
  1462.   if (!ts)
  1463.     return(0);
  1464. #endif
  1465.   strcpy(ts,instr);
  1466.   for (s=strtok(ts,delimstr); s; s=strtok(NULL,delimstr))
  1467.     i++;
  1468. #ifdef MALLOC_STR
  1469.   bbsfree(ts);
  1470. #endif
  1471.   return(i);
  1472. }
  1473.  
  1474. /****************************************************************************/
  1475.  
  1476. /*
  1477.  * Returns pointer to string representing the nth "word" of a string, using
  1478.  * a specified set of characters as delimiters.
  1479.  */
  1480.  
  1481. unsigned char *extractword(unsigned ww,unsigned char *instr,unsigned char *delimstr)
  1482. {
  1483.   unsigned char *s;
  1484. #ifdef MALLOC_STR
  1485.   unsigned char *ts;
  1486. #else
  1487.   unsigned char ts[MAX_CONF_LINE];
  1488. #endif
  1489.   static unsigned char rs[41];
  1490.   int i=0;
  1491.  
  1492.   if (!ww)
  1493.     return("");
  1494.  
  1495. #ifdef MALLOC_STR
  1496.   ts=malloca(MAX_CONF_LINE);
  1497.   if (!ts)
  1498.     return("");
  1499. #endif
  1500.   strcpy(ts,instr);
  1501.   for (s=strtok(ts,delimstr); ((s) && (i++<ww)); s=strtok(NULL,delimstr)) {
  1502.     if (i==ww) {
  1503.       strcpy(rs,s);
  1504. #ifdef MALLOC_STR
  1505.       bbsfree(ts);
  1506. #endif
  1507.       return(rs);
  1508.     }
  1509.   }
  1510. #ifdef MALLOC_STR
  1511.   bbsfree(ts);
  1512. #endif
  1513.   return("");
  1514. }
  1515.  
  1516. /****************************************************************************/
  1517.  
  1518. void sort_conf_str(unsigned char *s)
  1519. {
  1520.   unsigned char s1[81], s2[81];
  1521.   unsigned char i;
  1522.  
  1523.   strncpy(s1, s, sizeof(s1));
  1524.   strncpy(s2, charstr(MAX_CONFERENCES, 32), sizeof(s2));
  1525.  
  1526.   for (i='A'; i<='Z'; i++) {
  1527.     if (strchr(s1, i)!=NULL)
  1528.       s2[i-'A']=i;
  1529.   }
  1530.   trimstr(s2);
  1531.   strcpy(s, s2);
  1532. }
  1533.  
  1534. /****************************************************************************/
  1535.