home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / QWK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-13  |  25.6 KB  |  943 lines

  1. #line 1 "QWK.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /****************************************************/
  6. /* Functions that pertain solely to the QWK packets */
  7. /****************************************************/
  8.  
  9. #include "sbbs.h"
  10. #include "etext.h"
  11. #include "post.h"
  12. #include "qwk.h"
  13.  
  14. time_t qwkmail_time;
  15.  
  16. /****************************************************************************/
  17. /* Removes ctrl-a codes from the string 'instr'                             */
  18. /****************************************************************************/
  19. void remove_ctrl_a(char *instr)
  20. {
  21.     char str[512];
  22.     uint i,j,k;
  23.  
  24. j=strlen(instr);
  25. for(k=i=0;i<j;i++) {
  26.     if(instr[i]==1)
  27.         i++;
  28.     else str[k++]=instr[i]; }
  29. str[k]=0;
  30. strcpy(instr,str);
  31. }
  32.  
  33.  
  34. /****************************************************************************/
  35. /* Converts a long to an msbin real number. required for QWK NDX file        */
  36. /****************************************************************************/
  37. float ltomsbin(long val)
  38. {
  39.     converter t;
  40.     int   sign, exp;    /* sign and exponent */
  41.  
  42. t.f[0]=(float)val;
  43. sign=t.uc[3]/0x80;
  44. exp=((t.ui[1]>>7)-0x7f+0x81)&0xff;
  45. t.ui[1]=(t.ui[1]&0x7f)|(sign<<7)|(exp<<8);
  46. return(t.f[0]);
  47. }
  48.  
  49. int route_circ(char *via, char *id)
  50. {
  51.     char str[256],*p,*sp;
  52.  
  53. strcpy(str,via);
  54. p=str;
  55. while(*p && *p<=SP)
  56.     p++;
  57. while(*p) {
  58.     sp=strchr(p,'/');
  59.     if(sp) *sp=0;
  60.     if(!stricmp(p,id))
  61.         return(1);
  62.     if(!sp)
  63.         break;
  64.     p=sp+1; }
  65. return(0);
  66. }
  67.  
  68. int qwk_route(char *inaddr, char *fulladdr)
  69. {
  70.     char node[10],str[256],*p;
  71.     int file,i;
  72.     FILE *stream;
  73.  
  74. fulladdr[0]=0;
  75. sprintf(str,"%.255s",inaddr);
  76. p=strrchr(str,'/');
  77. if(p) p++;
  78. else p=str;
  79. sprintf(node,"%.8s",p);                 /* node = destination node */
  80. truncsp(node);
  81.  
  82. for(i=0;i<total_qhubs;i++)                /* Check if destination is our hub */
  83.     if(!stricmp(qhub[i]->id,node))
  84.         break;
  85. if(i<total_qhubs) {
  86.     strcpy(fulladdr,node);
  87.     return(0); }
  88.  
  89. i=matchuser(node);                        /* Check if destination is a node */
  90. if(i) {
  91.     getuserrec(i,U_REST,8,str);
  92.     if(ahtoul(str)&FLAG('Q')) {
  93.         strcpy(fulladdr,node);
  94.         return(i); } }
  95.  
  96. sprintf(node,"%.8s",inaddr);            /* node = next hop */
  97. p=strchr(node,'/');
  98. if(p) *p=0;
  99. truncsp(node);                            
  100.  
  101. if(strchr(inaddr,'/')) {                /* Multiple hops */
  102.  
  103.     for(i=0;i<total_qhubs;i++)            /* Check if next hop is our hub */
  104.         if(!stricmp(qhub[i]->id,node))
  105.             break;
  106.     if(i<total_qhubs) {
  107.         strcpy(fulladdr,inaddr);
  108.         return(0); }
  109.  
  110.     i=matchuser(node);                    /* Check if next hop is a node */
  111.     if(i) {
  112.         getuserrec(i,U_REST,8,str);
  113.         if(ahtoul(str)&FLAG('Q')) {
  114.             strcpy(fulladdr,inaddr);
  115.             return(i); } } }
  116.  
  117. p=strchr(node,SP);
  118. if(p) *p=0;
  119.  
  120. sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
  121. if((stream=fnopen(&file,str,O_RDONLY))==NULL)
  122.     return(0);
  123.  
  124. strcat(node,":");
  125. fulladdr[0]=0;
  126. while(!feof(stream)) {
  127.     if(!fgets(str,256,stream))
  128.         break;
  129.     if(!strnicmp(str+9,node,strlen(node))) {
  130.         fclose(stream);
  131.         truncsp(str);
  132.         sprintf(fulladdr,"%s/%s",str+9+strlen(node),inaddr);
  133.         break; } }
  134.  
  135. fclose(stream);
  136. if(!fulladdr[0])            /* First hop not found in ROUTE.DAT */
  137.     return(0);
  138.  
  139. sprintf(node,"%.8s",fulladdr);
  140. p=strchr(node,'/');
  141. if(p) *p=0;
  142. truncsp(node);
  143.  
  144. for(i=0;i<total_qhubs;i++)                /* Check if first hop is our hub */
  145.     if(!stricmp(qhub[i]->id,node))
  146.         break;
  147. if(i<total_qhubs)
  148.     return(0);
  149.  
  150. i=matchuser(node);                        /* Check if first hop is a node */
  151. if(i) {
  152.     getuserrec(i,U_REST,8,str);
  153.     if(ahtoul(str)&FLAG('Q'))
  154.         return(i); }
  155. fulladdr[0]=0;
  156. return(0);
  157. }
  158.  
  159.  
  160. /* Via is in format: NODE/NODE/... */
  161. void update_qwkroute(char *via)
  162. {
  163.     static uint total_nodes;
  164.     static char **qwk_node;
  165.     static char **qwk_path;
  166.     static time_t *qwk_time;
  167.     char str[256],*p,*tp,node[9];
  168.     int i,file;
  169.     time_t t;
  170.     FILE *stream;
  171.  
  172. if(via==NULL) {
  173.     if(!total_nodes)
  174.         return;
  175.     sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
  176.     if((stream=fnopen(&file,str,O_WRONLY|O_CREAT|O_TRUNC))!=NULL) {
  177.         t=time(NULL);
  178.         t-=(90L*24L*60L*60L);
  179.         for(i=0;i<total_nodes;i++)
  180.             if(qwk_time[i]>t)
  181.                 fprintf(stream,"%s %s:%s\r\n"
  182.                     ,unixtodstr(qwk_time[i],str),qwk_node[i],qwk_path[i]);
  183.         fclose(stream); }
  184.     else
  185.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  186.     for(i=0;i<total_nodes;i++) {
  187.         FREE(qwk_node[i]);
  188.         FREE(qwk_path[i]); }
  189.     if(qwk_node) {
  190.         FREE(qwk_node);
  191.         qwk_node=NULL; }
  192.     if(qwk_path) {
  193.         FREE(qwk_path);
  194.         qwk_path=NULL; }
  195.     if(qwk_time) {
  196.         FREE(qwk_time);
  197.         qwk_time=NULL; }
  198.     total_nodes=0;
  199.     return; }
  200.  
  201. if(!total_nodes) {
  202.     sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
  203.     if((stream=fnopen(&file,str,O_RDONLY))!=NULL) {
  204.         while(!feof(stream)) {
  205.             if(!fgets(str,255,stream))
  206.                 break;
  207.             truncsp(str);
  208.             t=dstrtounix(str);
  209.             p=strchr(str,':');
  210.             if(!p) continue;
  211.             *p=0;
  212.             sprintf(node,"%.8s",str+9);
  213.             tp=strchr(node,SP);         /* change "node bbs:" to "node:" */
  214.             if(tp) *tp=0;
  215.             for(i=0;i<total_nodes;i++)
  216.                 if(!stricmp(qwk_node[i],node))
  217.                     break;
  218.             if(i<total_nodes && qwk_time[i]>t)
  219.                 continue;
  220.             if(i==total_nodes) {
  221.                 if((qwk_node=REALLOC(qwk_node,sizeof(char *)*(i+1)))==NULL) {
  222.                     errormsg(WHERE,ERR_ALLOC,str,9*(i+1));
  223.                     break; }
  224.                 if((qwk_path=REALLOC(qwk_path,sizeof(char *)*(i+1)))==NULL) {
  225.                     errormsg(WHERE,ERR_ALLOC,str,128*(i+1));
  226.                     break; }
  227.                 if((qwk_time=REALLOC(qwk_time,sizeof(time_t)*(i+1)))==NULL) {
  228.                     errormsg(WHERE,ERR_ALLOC,str,sizeof(time_t)*(i+1));
  229.                     break; }
  230.                 if((qwk_node[i]=MALLOC(9))==NULL) {
  231.                     errormsg(WHERE,ERR_ALLOC,str,9);
  232.                     break; }
  233.                 if((qwk_path[i]=MALLOC(128))==NULL) {
  234.                     errormsg(WHERE,ERR_ALLOC,str,128);
  235.                     break; }
  236.                 total_nodes++; }
  237.             strcpy(qwk_node[i],node);
  238.             p++;
  239.             while(*p && *p<=SP) p++;
  240.             sprintf(qwk_path[i],"%.127s",p);
  241.             qwk_time[i]=t; }
  242.         fclose(stream); } }
  243.  
  244. strupr(via);
  245. p=strchr(via,'/');   /* Skip uplink */
  246.  
  247. while(p && *p) {
  248.     p++;
  249.     sprintf(node,"%.8s",p);
  250.     tp=strchr(node,'/');
  251.     if(tp) *tp=0;
  252.     tp=strchr(node,SP);         /* no spaces allowed */
  253.     if(tp) *tp=0;
  254.     truncsp(node);
  255.     for(i=0;i<total_nodes;i++)
  256.         if(!stricmp(qwk_node[i],node))
  257.             break;
  258.     if(i==total_nodes) {        /* Not in list */
  259.         if((qwk_node=REALLOC(qwk_node,sizeof(char *)*(total_nodes+1)))==NULL) {
  260.             errormsg(WHERE,ERR_ALLOC,str,9*(total_nodes+1));
  261.             break; }
  262.         if((qwk_path=REALLOC(qwk_path,sizeof(char *)*(total_nodes+1)))==NULL) {
  263.             errormsg(WHERE,ERR_ALLOC,str,128*(total_nodes+1));
  264.             break; }
  265.         if((qwk_time=REALLOC(qwk_time,sizeof(time_t)*(total_nodes+1)))
  266.             ==NULL) {
  267.             errormsg(WHERE,ERR_ALLOC,str,sizeof(time_t)*(total_nodes+1));
  268.             break; }
  269.         if((qwk_node[total_nodes]=MALLOC(9))==NULL) {
  270.             errormsg(WHERE,ERR_ALLOC,str,9);
  271.             break; }
  272.         if((qwk_path[total_nodes]=MALLOC(128))==NULL) {
  273.             errormsg(WHERE,ERR_ALLOC,str,128);
  274.             break; }
  275.         total_nodes++; }
  276.     sprintf(qwk_node[i],"%.8s",node);
  277.     sprintf(qwk_path[i],"%.*s",(uint)((p-1)-via),via);
  278.     qwk_time[i]=time(NULL);
  279.     p=strchr(p,'/'); }
  280. }
  281.  
  282. /****************************************************************************/
  283. /* Successful download of QWK packet                                        */
  284. /****************************************************************************/
  285. void qwk_success(ulong msgcnt, char bi, char prepack)
  286. {
  287.     char    str[128];
  288.     int     i;
  289.     ulong    l,msgs,deleted=0;
  290.     mail_t    *mail;
  291.     smbmsg_t msg;
  292.  
  293. if(!prepack) {
  294.     logline("D-","Downloaded QWK packet");
  295.     posts_read+=msgcnt;
  296.  
  297.     if(useron.rest&FLAG('Q')) {
  298.         sprintf(str,"%sQNET\\%.8s.OUT\\",data_dir,useron.alias);
  299.         delfiles(str,"*.*"); }
  300.  
  301.     sprintf(str,"%sFILE\\%04u.QWK",data_dir,useron.number);
  302.     remove(str);
  303.  
  304.     if(!bi) {
  305.         batch_download(-1);
  306.         delfiles(temp_dir,"*.*"); } }
  307.  
  308. if(useron.rest&FLAG('Q'))
  309.     useron.qwk|=(QWK_EMAIL|QWK_ALLMAIL|QWK_DELMAIL);
  310. if(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL)) {
  311.     sprintf(smb.file,"%sMAIL",data_dir);
  312.     smb.retry_time=smb_retry_time;
  313.     if((i=smb_open(&smb))!=0) {
  314.         errormsg(WHERE,ERR_OPEN,smb.file,i);
  315.         return; }
  316.  
  317.     msgs=loadmail(&mail,useron.number,0
  318.         ,useron.qwk&QWK_ALLMAIL ? LM_QWK : LM_UNREAD|LM_QWK);
  319.  
  320.     if((i=smb_locksmbhdr(&smb))!=0) {              /* Lock the base, so nobody */
  321.         if(msgs)
  322.             FREE(mail);
  323.         smb_close(&smb);
  324.         errormsg(WHERE,ERR_LOCK,smb.file,i);    /* messes with the index */
  325.         return; }
  326.  
  327.     if((i=smb_getstatus(&smb))!=0) {
  328.         if(msgs)
  329.             FREE(mail);
  330.         smb_close(&smb);
  331.         errormsg(WHERE,ERR_READ,smb.file,i);
  332.         return; }
  333.  
  334.     /* Mark as READ and DELETE */
  335.     for(l=0;l<msgs;l++) {
  336.         if(mail[l].time>qwkmail_time)
  337.             continue;
  338.         msg.idx.offset=0;
  339.         if(!loadmsg(&msg,mail[l].number))
  340.             continue;
  341.         if(!(msg.hdr.attr&MSG_READ)) {
  342.             if(thisnode.status==NODE_INUSE)
  343.                 telluser(msg);
  344.             msg.hdr.attr|=MSG_READ;
  345.             msg.idx.attr=msg.hdr.attr;
  346.             smb_putmsg(&smb,&msg); }
  347.         if(!(msg.hdr.attr&MSG_PERMANENT)
  348.             && ((msg.hdr.attr&MSG_KILLREAD && msg.hdr.attr&MSG_READ)
  349.             || (useron.qwk&QWK_DELMAIL))) {
  350.             msg.hdr.attr|=MSG_DELETE;
  351.             msg.idx.attr=msg.hdr.attr;
  352.             if((i=smb_putmsg(&smb,&msg))!=0)
  353.                 errormsg(WHERE,ERR_WRITE,smb.file,i);
  354.             else
  355.                 deleted++; }
  356.         smb_freemsgmem(&msg);
  357.         smb_unlockmsghdr(&smb,&msg); }
  358.  
  359.     if(deleted && sys_misc&SM_DELEMAIL)
  360.         delmail(useron.number,MAIL_YOUR);
  361.     smb_close(&smb);
  362.     if(msgs)
  363.         FREE(mail); }
  364.  
  365. }
  366.  
  367. /****************************************************************************/
  368. /* QWK mail packet section                                                    */
  369. /****************************************************************************/
  370. void qwk_sec()
  371. {
  372.     uchar    str[256],tmp2[256],ch,bi=0
  373.             ,*AttemptedToDownloadQWKpacket="Attempted to download QWK packet";
  374.     int     s;
  375.     uint    i,j,k;
  376.     ulong    msgcnt,l;
  377.     time_t    *sav_ptr;
  378.     file_t    fd;
  379.  
  380. getusrdirs();
  381. fd.dir=total_dirs;
  382. if((sav_ptr=(time_t *)MALLOC(sizeof(time_t)*total_subs))==NULL) {
  383.     errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(time_t)*total_subs);
  384.     return; }
  385. for(i=0;i<total_subs;i++)
  386.     sav_ptr[i]=sub[i]->ptr;
  387. for(i=0;i<total_prots;i++)
  388.     if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron))
  389.         bi++;                /* number of bidirectional protocols configured */
  390. if(useron.rest&FLAG('Q'))
  391.     getusrsubs();
  392. delfiles(temp_dir,"*.*");
  393. while(online) {
  394.     if((useron.misc&(WIP|RIP) || !(useron.misc&EXPERT))
  395.         && !(useron.rest&FLAG('Q')))
  396.         menu("QWK");
  397.     action=NODE_TQWK;
  398.     ASYNC;
  399.     bputs(text[QWKPrompt]);
  400.     strcpy(str,"?UDCSPQ\r");
  401.     if(bi)
  402.         strcat(str,"B");
  403.     ch=getkeys(str,0);
  404.     if(ch>SP)
  405.         logch(ch,0);
  406.     if(sys_status&SS_ABORT || ch=='Q' || ch==CR)
  407.         break;
  408.     if(ch=='?') {
  409.         if((useron.misc&(WIP|RIP) || !(useron.misc&EXPERT))
  410.             && !(useron.rest&FLAG('Q')))
  411.             continue;
  412.         menu("QWK");
  413.         continue; }
  414.     if(ch=='S') {
  415.         new_scan_cfg(SUB_NSCAN);
  416.         delfiles(temp_dir,"*.*");
  417.         continue; }
  418.     if(ch=='P') {
  419.         new_scan_ptr_cfg();
  420.         for(i=0;i<total_subs;i++)
  421.             sav_ptr[i]=sub[i]->ptr;
  422.         delfiles(temp_dir,"*.*");
  423.         continue; }
  424.     if(ch=='C') {
  425.         while(online) {
  426.             CLS;
  427.             bputs("\1n\1gQWK Settings:\1n\r\n\r\n");
  428.             bprintf("A) %-30s: %s\r\n"
  429.                 ,"Ctrl-A Color Codes"
  430.                 ,useron.qwk&QWK_EXPCTLA
  431.                 ? "Expand to ANSI" : useron.qwk&QWK_RETCTLA ? "Leave in"
  432.                 : "Strip");
  433.             bprintf("T) %-30s: %s\r\n"
  434.                 ,"Archive Type"
  435.                 ,useron.tmpext);
  436.             bprintf("E) %-30s: %s\r\n"
  437.                 ,"Include E-mail Messages"
  438.                 ,useron.qwk&QWK_EMAIL ? "Un-read Only"
  439.                 : useron.qwk&QWK_ALLMAIL ? text[Yes] : text[No]);
  440.             bprintf("I) %-30s: %s\r\n"
  441.                 ,"Include File Attachments"
  442.                 ,useron.qwk&QWK_ATTACH ? text[Yes] : text[No]);
  443.             bprintf("D) %-30s: %s\r\n"
  444.                 ,"Delete E-mail Automatically"
  445.                 ,useron.qwk&QWK_DELMAIL ? text[Yes]:text[No]);
  446.             bprintf("F) %-30s: %s\r\n"
  447.                 ,"Include New Files List"
  448.                 ,useron.qwk&QWK_FILES ? text[Yes]:text[No]);
  449.             bprintf("N) %-30s: %s\r\n"
  450.                 ,"Include Index Files"
  451.                 ,useron.qwk&QWK_NOINDEX ? text[No]:text[Yes]);
  452.             bprintf("C) %-30s: %s\r\n"
  453.                 ,"Include Control Files"
  454.                 ,useron.qwk&QWK_NOCTRL ? text[No]:text[Yes]);
  455.             bprintf("Y) %-30s: %s\r\n"
  456.                 ,"Include Messages from You"
  457.                 ,useron.qwk&QWK_BYSELF ? text[Yes]:text[No]);
  458.             bprintf("Z) %-30s: %s\r\n"
  459.                 ,"Include Time Zone (TZ)"
  460.                 ,useron.qwk&QWK_TZ ? text[Yes]:text[No]);
  461.             bprintf("V) %-30s: %s\r\n"
  462.                 ,"Include Message Path (VIA)"
  463.                 ,useron.qwk&QWK_VIA ? text[Yes]:text[No]);
  464.             //bprintf("Q) Quit\r\n\r\n");
  465.             bputs(text[UserDefaultsWhich]);
  466.             ch=getkeys("AQEDFIOQTYNCZV",0);
  467.             if(sys_status&SS_ABORT || !ch || ch=='Q')
  468.                 break;
  469.             switch(ch) {
  470.                 case 'A':
  471.                     if(!(useron.qwk&(QWK_EXPCTLA|QWK_RETCTLA)))
  472.                         useron.qwk|=QWK_EXPCTLA;
  473.                     else if(useron.qwk&QWK_EXPCTLA) {
  474.                         useron.qwk&=~QWK_EXPCTLA;
  475.                         useron.qwk|=QWK_RETCTLA; }
  476.                     else
  477.                         useron.qwk&=~(QWK_EXPCTLA|QWK_RETCTLA);
  478.                     break;
  479.                 case 'T':
  480.                     for(i=0;i<total_fcomps;i++)
  481.                         uselect(1,i,"Archive Types",fcomp[i]->ext,fcomp[i]->ar);
  482.                     s=uselect(0,0,0,0,0);
  483.                     if(s>=0) {
  484.                         strcpy(useron.tmpext,fcomp[s]->ext);
  485.                         putuserrec(useron.number,U_TMPEXT,3,useron.tmpext); }
  486.                     break;
  487.                 case 'E':
  488.                     if(!(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL)))
  489.                         useron.qwk|=QWK_EMAIL;
  490.                     else if(useron.qwk&QWK_EMAIL) {
  491.                         useron.qwk&=~QWK_EMAIL;
  492.                         useron.qwk|=QWK_ALLMAIL; }
  493.                     else
  494.                         useron.qwk&=~(QWK_EMAIL|QWK_ALLMAIL);
  495.                     break;
  496.                 case 'I':
  497.                     useron.qwk^=QWK_ATTACH;
  498.                     break;
  499.                 case 'D':
  500.                     useron.qwk^=QWK_DELMAIL;
  501.                     break;
  502.                 case 'F':
  503.                     useron.qwk^=QWK_FILES;
  504.                     break;
  505.                 case 'N':   /* NO IDX files */
  506.                     useron.qwk^=QWK_NOINDEX;
  507.                     break;
  508.                 case 'C':
  509.                     useron.qwk^=QWK_NOCTRL;
  510.                     break;
  511.                 case 'Z':
  512.                     useron.qwk^=QWK_TZ;
  513.                     break;
  514.                 case 'V':
  515.                     useron.qwk^=QWK_VIA;
  516.                     break;
  517.                 case 'Y':   /* Yourself */
  518.                     useron.qwk^=QWK_BYSELF;
  519.                     break; }
  520.             putuserrec(useron.number,U_QWK,8,ultoa(useron.qwk,str,16)); }
  521.         delfiles(temp_dir,"*.*");
  522.         continue; }
  523.  
  524.  
  525.     if(ch=='B') {   /* Bidirectional QWK and REP packet transfer */
  526.         sprintf(str,"%s%s.QWK",temp_dir,sys_id);
  527.         if(!fexist(str) && !pack_qwk(str,&msgcnt,0)) {
  528.             for(i=0;i<total_subs;i++)
  529.                 sub[i]->ptr=sav_ptr[i];
  530.             remove(str);
  531.             last_ns_time=ns_time;
  532.             continue; }
  533.         bprintf(text[UploadingREP],sys_id);
  534.         menu("BIPROT");
  535.         mnemonics(text[ProtocolOrQuit]);
  536.         strcpy(tmp2,"Q");
  537.         for(i=0;i<total_prots;i++)
  538.             if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron)) {
  539.                 sprintf(tmp,"%c",prot[i]->mnemonic);
  540.                 strcat(tmp2,tmp); }
  541.         ch=getkeys(tmp2,0);
  542.         if(ch=='Q' || sys_status&SS_ABORT) {
  543.             for(i=0;i<total_subs;i++)
  544.                 sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
  545.             last_ns_time=ns_time;
  546.             continue; }
  547.         for(i=0;i<total_prots;i++)
  548.             if(prot[i]->bicmd[0] && prot[i]->mnemonic==ch
  549.                 && chk_ar(prot[i]->ar,useron))
  550.                 break;
  551.         if(i<total_prots) {
  552.             batup_total=1;
  553.             batup_dir[0]=total_dirs;
  554.             sprintf(batup_name[0],"%s.REP",sys_id);
  555.             batdn_total=1;
  556.             batdn_dir[0]=total_dirs;
  557.             sprintf(batdn_name[0],"%s.QWK",sys_id);
  558.             if(!create_batchdn_lst() || !create_batchup_lst()
  559.                 || !create_bimodem_pth()) {
  560.                 batup_total=batdn_total=0;
  561.                 continue; }
  562.             sprintf(str,"%s%s.QWK",temp_dir,sys_id);
  563.             sprintf(tmp2,"%s.QWK",sys_id);
  564.             padfname(tmp2,fd.name);
  565.             sprintf(str,"%sBATCHDN.LST",node_dir);
  566.             sprintf(tmp2,"%sBATCHUP.LST",node_dir);
  567.             j=protocol(cmdstr(prot[i]->bicmd,str,tmp2,NULL),0);
  568.             batdn_total=batup_total=0;
  569.             if(prot[i]->misc&PROT_DSZLOG) {
  570.                 if(!checkprotlog(fd)) {
  571.                     logline("D!",AttemptedToDownloadQWKpacket);
  572.                     last_ns_time=ns_time;
  573.                     for(i=0;i<total_subs;i++)
  574.                         sub[i]->ptr=sav_ptr[i]; } /* re-load saved pointers */
  575.                 else {
  576.                     qwk_success(msgcnt,1,0);
  577.                     for(i=0;i<total_subs;i++)
  578.                         sav_ptr[i]=sub[i]->ptr; } }
  579.             else if(j) {
  580.                 logline("D!",AttemptedToDownloadQWKpacket);
  581.                 last_ns_time=ns_time;
  582.                 for(i=0;i<total_subs;i++)
  583.                     sub[i]->ptr=sav_ptr[i]; }
  584.             else {
  585.                 qwk_success(msgcnt,1,0);
  586.                 for(i=0;i<total_subs;i++)
  587.                     sav_ptr[i]=sub[i]->ptr; }
  588.             sprintf(str,"%s%s.QWK",temp_dir,sys_id);
  589.             remove(str);
  590.             unpack_rep();
  591.             delfiles(temp_dir,"*.*");
  592.             //autohangup();
  593.             }
  594.         else {
  595.             last_ns_time=ns_time;
  596.             for(i=0;i<total_subs;i++)
  597.                 sub[i]->ptr=sav_ptr[i]; } }
  598.  
  599.     else if(ch=='D') {   /* Download QWK Packet of new messages */
  600.         sprintf(str,"%s%s.QWK",temp_dir,sys_id);
  601.         if(!fexist(str) && !pack_qwk(str,&msgcnt,0)) {
  602.             for(i=0;i<total_subs;i++)
  603.                 sub[i]->ptr=sav_ptr[i];
  604.             last_ns_time=ns_time;
  605.             remove(str);
  606.             continue; }
  607.         if(online==ON_LOCAL) {            /* Local QWK packet creation */
  608.             bputs(text[EnterPath]);
  609.             if(!getstr(str,60,K_LINE|K_UPPER)) {
  610.                 for(i=0;i<total_subs;i++)
  611.                     sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
  612.                 last_ns_time=ns_time;
  613.                 continue; }
  614.             backslashcolon(str);
  615.             sprintf(tmp2,"%s%s.QWK",str,sys_id);
  616.             if(fexist(tmp2)) {
  617.                 for(i=0;i<10;i++) {
  618.                     sprintf(tmp2,"%s%s.QW%d",str,sys_id,i);
  619.                     if(!fexist(tmp2))
  620.                         break; }
  621.                 if(i==10) {
  622.                     bputs(text[FileAlreadyThere]);
  623.                     last_ns_time=ns_time;
  624.                     for(i=0;i<total_subs;i++)
  625.                         sub[i]->ptr=sav_ptr[i];
  626.                     continue; } }
  627.             sprintf(tmp,"%s%s.QWK",temp_dir,sys_id);
  628.             if(mv(tmp,tmp2,0)) { /* unsuccessful */
  629.                 for(i=0;i<total_subs;i++)
  630.                     sub[i]->ptr=sav_ptr[i];
  631.                 last_ns_time=ns_time; }
  632.             else {
  633.                 bprintf(text[FileNBytesSent],tmp2,ultoac(flength(tmp2),tmp));
  634.                 qwk_success(msgcnt,0,0);
  635.                 for(i=0;i<total_subs;i++)
  636.                     sav_ptr[i]=sub[i]->ptr; }
  637.             continue; }
  638.  
  639.         /***************/
  640.         /* Send Packet */
  641.         /***************/
  642.         menu("DLPROT");
  643.         mnemonics(text[ProtocolOrQuit]);
  644.         strcpy(tmp2,"Q");
  645.         for(i=0;i<total_prots;i++)
  646.             if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
  647.                 sprintf(tmp,"%c",prot[i]->mnemonic);
  648.                 strcat(tmp2,tmp); }
  649.         ungetkey(useron.prot);
  650.         ch=getkeys(tmp2,0);
  651.         if(ch=='Q' || sys_status&SS_ABORT) {
  652.             for(i=0;i<total_subs;i++)
  653.                 sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
  654.             last_ns_time=ns_time;
  655.             continue; }
  656.         for(i=0;i<total_prots;i++)
  657.             if(prot[i]->dlcmd[0] && prot[i]->mnemonic==ch
  658.                 && chk_ar(prot[i]->ar,useron))
  659.                 break;
  660.         if(i<total_prots) {
  661.             sprintf(str,"%s%s.QWK",temp_dir,sys_id);
  662.             sprintf(tmp2,"%s.QWK",sys_id);
  663.             padfname(tmp2,fd.name);
  664.             j=protocol(cmdstr(prot[i]->dlcmd,str,nulstr,NULL),0);
  665.             if(prot[i]->misc&PROT_DSZLOG) {
  666.                 if(!checkprotlog(fd)) {
  667.                     last_ns_time=ns_time;
  668.                     for(i=0;i<total_subs;i++)
  669.                         sub[i]->ptr=sav_ptr[i]; } /* re-load saved pointers */
  670.                 else {
  671.                     qwk_success(msgcnt,0,0);
  672.                     for(i=0;i<total_subs;i++)
  673.                         sav_ptr[i]=sub[i]->ptr; } }
  674.             else if(j) {
  675.                 logline("D!",AttemptedToDownloadQWKpacket);
  676.                 last_ns_time=ns_time;
  677.                 for(i=0;i<total_subs;i++)
  678.                     sub[i]->ptr=sav_ptr[i]; }
  679.             else {
  680.                 qwk_success(msgcnt,0,0);
  681.                 for(i=0;i<total_subs;i++)
  682.                     sav_ptr[i]=sub[i]->ptr; }
  683.             autohangup(); }
  684.         else {     /* if not valid protocol (hungup?) */
  685.             for(i=0;i<total_subs;i++)
  686.                 sub[i]->ptr=sav_ptr[i];
  687.             last_ns_time=ns_time; } }
  688.  
  689.     else if(ch=='U') { /* Upload REP Packet */
  690. /*
  691.         if(useron.rest&FLAG('Q') && useron.rest&FLAG('P')) {
  692.             bputs(text[R_Post]);
  693.             continue; }
  694. */
  695.  
  696.         delfiles(temp_dir,"*.*");
  697.         bprintf(text[UploadingREP],sys_id);
  698.         for(k=0;k<total_fextrs;k++)
  699.             if(!stricmp(fextr[k]->ext,useron.tmpext)
  700.                 && chk_ar(fextr[k]->ar,useron))
  701.                 break;
  702.         if(k>=total_fextrs) {
  703.             bputs(text[QWKExtractionFailed]);
  704.             errorlog("Couldn't extract REP packet - configuration error");
  705.             continue; }
  706.  
  707.         if(online==ON_LOCAL) {        /* Local upload of rep packet */
  708.             bputs(text[EnterPath]);
  709.             if(!getstr(str,60,K_LINE|K_UPPER))
  710.                 continue;
  711.             backslashcolon(str);
  712.             sprintf(tmp,"%s.REP",sys_id);
  713.             strcat(str,tmp);
  714.             sprintf(tmp,"%s%s.REP",temp_dir,sys_id);
  715.             if(!mv(str,tmp,0))
  716.                 unpack_rep();
  717.             delfiles(temp_dir,"*.*");
  718.             continue; }
  719.  
  720.         /******************/
  721.         /* Receive Packet */
  722.         /******************/
  723.         menu("ULPROT");
  724.         mnemonics(text[ProtocolOrQuit]);
  725.         strcpy(tmp2,"Q");
  726.         for(i=0;i<total_prots;i++)
  727.             if(prot[i]->ulcmd[0] && chk_ar(prot[i]->ar,useron)) {
  728.                 sprintf(tmp,"%c",prot[i]->mnemonic);
  729.                 strcat(tmp2,tmp); }
  730.         ch=getkeys(tmp2,0);
  731.         if(ch=='Q' || sys_status&SS_ABORT)
  732.             continue;
  733.         for(i=0;i<total_prots;i++)
  734.             if(prot[i]->ulcmd[0] && prot[i]->mnemonic==ch
  735.                 && chk_ar(prot[i]->ar,useron))
  736.                 break;
  737.         if(i>=total_prots)    /* This shouldn't happen */
  738.             continue;
  739.         sprintf(str,"%s%s.REP",temp_dir,sys_id);
  740.         protocol(cmdstr(prot[i]->ulcmd,str,nulstr,NULL),0);
  741.         unpack_rep();
  742.         delfiles(temp_dir,"*.*");
  743.         //autohangup();
  744.         } }
  745. delfiles(temp_dir,"*.*");
  746. FREE(sav_ptr);
  747. }
  748.  
  749. void qwksetptr(uint subnum, char *buf, int reset)
  750. {
  751.     long    l;
  752.     ulong    last;
  753.  
  754. if(buf[2]=='/' && buf[5]=='/') {    /* date specified */
  755.     l=dstrtounix(buf);
  756.     sub[subnum]->ptr=getmsgnum(subnum,l);
  757.     return; }
  758. l=atol(buf);
  759. if(l>=0)                              /* ptr specified */
  760.     sub[subnum]->ptr=l;
  761. else if(l) {                          /* relative ptr specified */
  762.     getlastmsg(subnum,&last,0);
  763.     if(-l>last)
  764.         sub[subnum]->ptr=0;
  765.     else
  766.         sub[subnum]->ptr=last+l; }
  767. else if(reset)
  768.     getlastmsg(subnum,&sub[subnum]->ptr,0);
  769. }
  770.  
  771.  
  772. /****************************************************************************/
  773. /* Process a QWK Config line                                                */
  774. /****************************************************************************/
  775. void qwkcfgline(char *buf,uint subnum)
  776. {
  777.     char    str[128];
  778.     int     x,y;
  779.     long    l;
  780.     ulong    qwk=useron.qwk,last;
  781.     file_t    f;
  782.  
  783. sprintf(str,"%.25s",buf);
  784. strupr(str);
  785. bprintf("\1n\r\n\1b\1hQWK Control [\1c%s\1b]: \1g%s\r\n"
  786.     ,subnum==INVALID_SUB ? "Mail":sub[subnum]->qwkname,str);
  787.  
  788. if(subnum!=INVALID_SUB) {                    /* Only valid in sub-boards */
  789.  
  790.     if(!strncmp(str,"DROP ",5)) {              /* Drop from new-scan */
  791.         l=atol(str+5);
  792.         if(!l)
  793.             sub[subnum]->misc&=~SUB_NSCAN;
  794.         else {
  795.             x=l/1000;
  796.             y=l-(x*1000);
  797.             if(x>=usrgrps || y>=usrsubs[x]) {
  798.                 bprintf(text[QWKInvalidConferenceN],l);
  799.                 sprintf(str,"Invalid conference number %lu",l);
  800.                 logline("Q!",str); }
  801.             else
  802.                 sub[usrsub[x][y]]->misc&=~SUB_NSCAN; }
  803.         return; }
  804.  
  805.     if(!strncmp(str,"ADD YOURS ",10)) {               /* Add to new-scan */
  806.         sub[subnum]->misc|=(SUB_NSCAN|SUB_YSCAN);
  807.         qwksetptr(subnum,str+10,0);
  808.         return; }
  809.  
  810.     else if(!strncmp(str,"YOURS ",6)) {
  811.         sub[subnum]->misc|=(SUB_NSCAN|SUB_YSCAN);
  812.         qwksetptr(subnum,str+6,0);
  813.         return; }
  814.  
  815.     else if(!strncmp(str,"ADD ",4)) {               /* Add to new-scan */
  816.         sub[subnum]->misc|=SUB_NSCAN;
  817.         sub[subnum]->misc&=~SUB_YSCAN;
  818.         qwksetptr(subnum,str+4,0);
  819.         return; }
  820.  
  821.     if(!strncmp(str,"RESET ",6)) {             /* set msgptr */
  822.         qwksetptr(subnum,str+6,1);
  823.         return; }
  824.  
  825.     if(!strncmp(str,"SUBPTR ",7)) {
  826.         qwksetptr(subnum,str+7,1);
  827.         return; }
  828.     }
  829.  
  830. if(!strncmp(str,"RESETALL ",9)) {              /* set all ptrs */
  831.     for(x=0;x<usrgrps;x++)
  832.         for(y=0;y<usrsubs[x];y++)
  833.             if(sub[usrsub[x][y]]->misc&SUB_NSCAN)
  834.                 qwksetptr(usrsub[x][y],str+9,1); }
  835.  
  836. else if(!strncmp(str,"ALLPTR ",7)) {              /* set all ptrs */
  837.     for(x=0;x<usrgrps;x++)
  838.         for(y=0;y<usrsubs[x];y++)
  839.             if(sub[usrsub[x][y]]->misc&SUB_NSCAN)
  840.                 qwksetptr(usrsub[x][y],str+7,1); }
  841.  
  842. else if(!strncmp(str,"FILES ",6)) {                 /* files list */
  843.     if(!strncmp(str+6,"ON ",3))
  844.         useron.qwk|=QWK_FILES;
  845.     else if(str[8]=='/' && str[11]=='/') {      /* set scan date */
  846.         useron.qwk|=QWK_FILES;
  847.         ns_time=dstrtounix(str+6); }
  848.     else
  849.         useron.qwk&=~QWK_FILES; }
  850.  
  851. else if(!strncmp(str,"OWN ",4)) {                   /* message from you */
  852.     if(!strncmp(str+4,"ON ",3))
  853.         useron.qwk|=QWK_BYSELF;
  854.     else
  855.         useron.qwk&=~QWK_BYSELF;
  856.     return; }
  857.  
  858. else if(!strncmp(str,"NDX ",4)) {                   /* include indexes */
  859.     if(!strncmp(str+4,"OFF ",4))
  860.         useron.qwk|=QWK_NOINDEX;
  861.     else
  862.         useron.qwk&=~QWK_NOINDEX; }
  863.  
  864. else if(!strncmp(str,"CONTROL ",8)) {               /* exclude ctrl files */
  865.     if(!strncmp(str+8,"OFF ",4))
  866.         useron.qwk|=QWK_NOCTRL;
  867.     else
  868.         useron.qwk&=~QWK_NOCTRL; }
  869.  
  870. else if(!strncmp(str,"VIA ",4)) {                   /* include @VIA: */
  871.     if(!strncmp(str+4,"ON  ",3))
  872.         useron.qwk|=QWK_VIA;
  873.     else
  874.         useron.qwk&=~QWK_VIA; }
  875.  
  876. else if(!strncmp(str,"TZ ",3)) {                    /* include @TZ: */
  877.     if(!strncmp(str+3,"ON ",3))
  878.         useron.qwk|=QWK_TZ;
  879.     else
  880.         useron.qwk&=~QWK_TZ; }
  881.  
  882. else if(!strncmp(str,"ATTACH ",7)) {                /* file attachments */
  883.     if(!strncmp(str+7,"ON ",3))
  884.         useron.qwk|=QWK_ATTACH;
  885.     else
  886.         useron.qwk&=~QWK_ATTACH; }
  887.  
  888. else if(!strncmp(str,"DELMAIL ",8)) {               /* delete mail */
  889.     if(!strncmp(str+8,"ON ",3))
  890.         useron.qwk|=QWK_DELMAIL;
  891.     else
  892.         useron.qwk&=~QWK_DELMAIL; }
  893.  
  894. else if(!strncmp(str,"CTRL-A ",7)) {                /* Ctrl-a codes  */
  895.     if(!strncmp(str+7,"KEEP ",5)) {
  896.         useron.qwk|=QWK_RETCTLA;
  897.         useron.qwk&=~QWK_EXPCTLA; }
  898.     else if(!strncmp(str+7,"EXPAND ",7)) {
  899.         useron.qwk|=QWK_EXPCTLA;
  900.         useron.qwk&=~QWK_RETCTLA; }
  901.     else
  902.         useron.qwk&=~(QWK_EXPCTLA|QWK_RETCTLA); }
  903.  
  904. else if(!strncmp(str,"MAIL ",5)) {                  /* include e-mail */
  905.     if(!strncmp(str+5,"ALL ",4)) {
  906.         useron.qwk|=QWK_ALLMAIL;
  907.         useron.qwk&=~QWK_EMAIL; }
  908.     else if(!strncmp(str+5,"ON ",3)) {
  909.         useron.qwk|=QWK_EMAIL;
  910.         useron.qwk&=~QWK_ALLMAIL; }
  911.     else
  912.         useron.qwk&=~(QWK_ALLMAIL|QWK_EMAIL); }
  913.  
  914. else if(!strncmp(str,"FREQ ",5)) {                  /* file request */
  915.     padfname(str+5,f.name);
  916.     strupr(f.name);
  917.     for(x=0;x<usrlibs;x++) {
  918.         for(y=0;y<usrdirs[x];y++)
  919.             if(findfile(usrdir[x][y],f.name))
  920.                 break;
  921.         if(y<usrdirs[x])
  922.             break; }
  923.     if(x>=usrlibs) {
  924.         bprintf("\r\n%s",f.name);
  925.         bputs(text[FileNotFound]); }
  926.     else {
  927.         f.dir=usrdir[x][y];
  928.         getfileixb(&f);
  929.         f.size=0;
  930.         getfiledat(&f);
  931.         if(f.size==-1L)
  932.             bprintf(text[FileIsNotOnline],f.name);
  933.         else
  934.             addtobatdl(f); } }
  935.  
  936. else bputs("\1r\1h\1iUnrecognized Control Command!\1n\r\n");
  937.  
  938. if(qwk!=useron.qwk)
  939.     putuserrec(useron.number,U_QWK,8,ultoa(useron.qwk,tmp,16));
  940. }
  941.  
  942.  
  943.