home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / MAIN_WFC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-08  |  44.8 KB  |  1,544 lines

  1. #line 1 "MAIN_WFC.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include "sbbs.h"
  6. #include "etext.h"
  7. #include "cmdshell.h"
  8. #include "qwk.h"
  9.  
  10. extern char onquiet,nmi,llo,qwklogon;
  11. extern char term_ret;
  12. extern ulong connect_rate;     /* already connected at xbps */
  13. extern char *wday[],*mon[];
  14. extern char *hungupstr;
  15. extern char cidarg[];
  16.  
  17. void reset_logon_vars(void)
  18. {
  19.     int i;
  20.  
  21. sys_status&=~(SS_USERON|SS_TMPSYSOP|SS_LCHAT|SS_ABORT
  22.     |SS_PAUSEON|SS_PAUSEOFF|SS_EVENT|SS_NEWUSER|SS_NEWDAY);
  23. keybufbot=keybuftop=lbuflen=slcnt=altul=timeleft_warn=0;
  24. logon_uls=logon_ulb=logon_dls=logon_dlb=0;
  25. logon_posts=logon_emails=logon_fbacks=0;
  26. batdn_total=batup_total=0;
  27. usrgrps=usrlibs=0;
  28. curgrp=curlib=0;
  29. for(i=0;i<total_libs;i++)
  30.     curdir[i]=0;
  31. for(i=0;i<total_grps;i++)
  32.     cursub[i]=0;
  33. }
  34.  
  35. void mail_maint(void)
  36. {
  37.     int i;
  38.  
  39. lprintf("\r\n\r\nPurging deleted/expired e-mail...");
  40. sprintf(smb.file,"%sMAIL",data_dir);
  41. smb.retry_time=smb_retry_time;
  42. if((i=smb_open(&smb))!=0)
  43.     errormsg(WHERE,ERR_OPEN,smb.file,i);
  44. else {
  45.     if((i=smb_locksmbhdr(&smb))!=0)
  46.         errormsg(WHERE,ERR_LOCK,smb.file,i);
  47.     else
  48.         delmail(0,MAIL_ALL);
  49.     smb_close(&smb); }
  50. }
  51.  
  52. /*************************************************************/
  53. /* Returns 0 to reinitialize modem and start WFC cycle again */
  54. /* Returns 1 to continue checking things peacefully          */
  55. /*************************************************************/
  56. char wfc_events(time_t lastnodechk)
  57. {
  58.     char    str[256],str2[256],*buf;
  59.     int     i,j,k,file,ret=1,chunk;
  60.     ulong    l,m;
  61.     user_t    user;
  62.     node_t    node;
  63.     struct    ffblk ff;
  64.     struct    tm *gm;
  65.     struct    date lastdate;
  66.  
  67. for(i=0;i<total_qhubs;i++) {
  68.     gm=localtime(&now);       /* Qnet call out based on time */
  69.     unixtodos(qhub[i]->last,&date,&curtime);
  70.     if(node_num==qhub[i]->node                /* or frequency */
  71.         && (qhub[i]->last==-1L
  72.         || ((qhub[i]->freq
  73.             && (now-qhub[i]->last)/60>qhub[i]->freq)
  74.         || (qhub[i]->time
  75.             && (gm->tm_hour*60)+gm->tm_min>=qhub[i]->time
  76.         && (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)))
  77.         && qhub[i]->days&(1<<gm->tm_wday))) {
  78.         offhook();
  79.         lputc(FF);
  80.         sprintf(str,"%sQNET\\%s.NOW"
  81.             ,data_dir,qhub[i]->id);
  82.         remove(str);                    /* Remove semaphore file */
  83.         sprintf(str,"%sQNET\\%s.PTR"
  84.             ,data_dir,qhub[i]->id);
  85.         file=nopen(str,O_RDONLY);
  86.         for(j=0;j<qhub[i]->subs;j++) {
  87.             sub[qhub[i]->sub[j]]->ptr=0;
  88.             lseek(file,sub[qhub[i]->sub[j]]->ptridx*4L,SEEK_SET);
  89.             read(file,&sub[qhub[i]->sub[j]]->ptr,4); }
  90.         if(file!=-1)
  91.             close(file);
  92.         if(pack_rep(i)) {
  93.             if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
  94.                 errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
  95.             else {
  96.                 for(j=l=0;j<qhub[i]->subs;j++) {
  97.                     while(filelength(file)<sub[qhub[i]->sub[j]]->ptridx*4L)
  98.                         write(file,&l,4);        /* initialize ptrs to null */
  99.                     lseek(file,sub[qhub[i]->sub[j]]->ptridx*4L,SEEK_SET);
  100.                     write(file,&sub[qhub[i]->sub[j]]->ptr,4); }
  101.                 close(file); } }
  102.         delfiles(temp_dir,"*.*");
  103.  
  104.         qhub[i]->last=time(NULL);
  105.         sprintf(str,"%sQNET.DAB",ctrl_dir);
  106.         if((file=nopen(str,O_WRONLY))==-1) {
  107.             errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
  108.             bail(1); }
  109.         lseek(file,sizeof(time_t)*i,SEEK_SET);
  110.         write(file,&qhub[i]->last,sizeof(time_t));
  111.         close(file);
  112.  
  113.         if(qhub[i]->call[0]) {
  114.             getnodedat(node_num,&thisnode,1);
  115.             thisnode.status=NODE_NETTING;
  116.             putnodedat(node_num,thisnode);
  117.             lputc(FF);
  118.             external(cmdstr(qhub[i]->call,nulstr,nulstr,NULL),EX_SWAP);
  119.             ret=0; }
  120.         for(j=0;j<10;j++) {
  121.             sprintf(str,"%s%s.QW%c",data_dir,qhub[i]->id,j ? (j-1)+'0' : 'K');
  122.             if(fexist(str)) {
  123.                 lclini(node_scrnlen-1);
  124.                 delfiles(temp_dir,"*.*");
  125.                 unpack_qwk(str,i); } }
  126.         lputc(FF); } }
  127.  
  128. for(i=0;i<total_phubs;i++) {
  129.     gm=localtime(&now);       /* PostLink call out based on time */
  130.     unixtodos(phub[i]->last,&date,&curtime);
  131.     if(node_num==phub[i]->node                /* or frequency */
  132.         && ((phub[i]->freq
  133.             && (now-phub[i]->last)/60>phub[i]->freq)
  134.         || (phub[i]->time
  135.             && (gm->tm_hour*60)+gm->tm_min>=phub[i]->time
  136.         && (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)))
  137.         && phub[i]->days&(1<<gm->tm_wday)) {
  138.         offhook();
  139.         lputc(FF);
  140.  
  141.         phub[i]->last=time(NULL);
  142.         sprintf(str,"%sPNET.DAB",ctrl_dir);
  143.         if((file=nopen(str,O_WRONLY))==-1) {
  144.             errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
  145.             bail(1); }
  146.         lseek(file,sizeof(time_t)*i,SEEK_SET);
  147.         write(file,&phub[i]->last,sizeof(time_t));
  148.         close(file);
  149.  
  150.         if(phub[i]->call[0]) {
  151.             getnodedat(node_num,&thisnode,1);
  152.             thisnode.status=NODE_NETTING;
  153.             putnodedat(node_num,thisnode);
  154.             lputc(FF);
  155.             external(cmdstr(phub[i]->call,nulstr,nulstr,NULL),EX_SWAP);
  156.             ret=0; } } }
  157.  
  158. for(i=0;i<total_events;i++) {
  159.     if(!event[i]->node || event[i]->node>sys_nodes)
  160.         continue;
  161.     gm=localtime(&now);
  162.     unixtodos(event[i]->last,&date,&curtime);
  163.     if(event[i]->last==-1
  164.         || ((gm->tm_hour*60)+gm->tm_min>=event[i]->time
  165.         && (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)
  166.         && event[i]->days&(1<<gm->tm_wday))) {
  167.  
  168.         if(event[i]->misc&EVENT_EXCL) { /* exclusive event */
  169.             offhook();
  170.             lputc(FF);
  171.             if(event[i]->node!=node_num) {
  172.                 lprintf("Waiting for node %d to run timed event.\r\n\r\n"
  173.                     ,event[i]->node);
  174.                 lputs("Hit any key to abort wait...");
  175.                 getnodedat(node_num,&thisnode,1);
  176.                 thisnode.status=NODE_EVENT_LIMBO;
  177.                 thisnode.aux=event[i]->node;
  178.                 putnodedat(node_num,thisnode);
  179.                 lastnodechk=0;     /* really last event time check */
  180.                 while(!lkbrd(0)) {
  181.                     mswait(1);
  182.                     now=time(NULL);
  183.                     if(now-lastnodechk<10)
  184.                         continue;
  185.                     getnodedat(node_num,&thisnode,0);
  186.                     if(thisnode.misc&NODE_DOWN)
  187.                         return(0);
  188.                     lastnodechk=now;
  189.                     sprintf(str,"%sTIME.DAB",ctrl_dir);
  190.                     if((file=nopen(str,O_RDONLY))==-1) {
  191.                         errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
  192.                         event[i]->last=now;
  193.                         return(0); }
  194.                     lseek(file,(long)i*4L,SEEK_SET);
  195.                     read(file,&event[i]->last,sizeof(time_t));
  196.                     close(file);
  197.                     if(now-event[i]->last<(60*60))    /* event is done */
  198.                         break; }
  199.                 sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
  200.                 remove(str);
  201.                 event[i]->last=now;
  202.                 ret=0; }
  203.             else {
  204.                 lputs("Waiting for all nodes to become inactive before "
  205.                     "running timed event.\r\n\r\n");
  206.                 lputs("Hit any key to abort wait and run event now...\r\n\r\n");
  207.                 getnodedat(node_num,&thisnode,1);
  208.                 thisnode.status=NODE_EVENT_WAITING;
  209.                 putnodedat(node_num,thisnode);
  210.                 lastnodechk=0;
  211.                 while(!lkbrd(0)) {
  212.                     mswait(1);
  213.                     now=time(NULL);
  214.                     if(now-lastnodechk<10)
  215.                         continue;
  216.                     lastnodechk=now;
  217.                     getnodedat(node_num,&thisnode,0);
  218.                     if(thisnode.misc&NODE_DOWN)
  219.                         return(0);
  220.                     for(j=1;j<=sys_nodes;j++) {
  221.                         if(j==node_num)
  222.                             continue;
  223.                         getnodedat(j,&node,0);
  224.                         if(node.status==NODE_EVENT_WAITING)  /* two nodes */
  225.                             break;                             /* waiting ?!?! */
  226.                         if(node.status!=NODE_OFFLINE
  227.                             && node.status!=NODE_EVENT_LIMBO)
  228.                             break; }
  229.                     if(j>sys_nodes) /* all nodes either offline or in limbo */
  230.                         break;
  231.                     lprintf("\rWaiting for node %d (status=%d)"
  232.                         ,j,node.status);
  233.                     lputc(CLREOL); } } }
  234.         if(event[i]->node!=node_num)
  235.             event[i]->last=now;
  236.         else {
  237.             sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
  238.             remove(str);
  239.             offhook();
  240.             lputc(FF);
  241.             getnodedat(node_num,&thisnode,1);
  242.             thisnode.status=NODE_EVENT_RUNNING;
  243.             putnodedat(node_num,thisnode);
  244.             if(event[i]->dir[0]) {
  245.                 if(event[i]->dir[1]==':')           /* drive letter specified */
  246.                     setdisk(toupper(event[i]->dir[0])-'A');
  247.                 if(chdir(event[i]->dir))
  248.                     errormsg(WHERE,ERR_CHDIR,event[i]->dir,0); }
  249.  
  250.             external(cmdstr(event[i]->cmd,nulstr,nulstr,NULL),0);  /* EX_CC */
  251.             event[i]->last=time(NULL);
  252.             sprintf(str,"%sTIME.DAB",ctrl_dir);
  253.             if((file=nopen(str,O_WRONLY))==-1) {
  254.                 errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
  255.                 return(ret); }
  256.             lseek(file,(long)i*4L,SEEK_SET);
  257.             write(file,&event[i]->last,sizeof(time_t));
  258.             close(file);
  259.             ret=0; } } }
  260.  
  261.  
  262. if(sys_status&SS_DAILY || thisnode.misc&NODE_EVENT) {  /* daily events */
  263.  
  264.     offhook();
  265.     lputc(FF);
  266.  
  267.     if(sys_status&SS_DAILY) {
  268.  
  269.         getnodedat(node_num,&thisnode,1);
  270.         now=time(NULL);
  271.         j=lastuser();
  272.         thisnode.status=NODE_EVENT_RUNNING;
  273.         putnodedat(node_num,thisnode);
  274.  
  275.         lprintf("Running system daily maintenance...\r\n\r\n");
  276.         logentry("!:","Ran system daily maintenance");
  277.         for(i=1;i<=j;i++) {
  278.  
  279.             lprintf("\rChecking user %5u of %-5u",i,j);
  280.             user.number=i;
  281.             getuserdat(&user);
  282.  
  283.             /***********************************************/
  284.             /* Fix name (NAME.DAT and USER.DAT) mismatches */
  285.             /***********************************************/
  286.             if(user.misc&DELETED) {
  287.                 if(strcmp(username(i,str2),"DELETED USER"))
  288.                     putusername(i,nulstr);
  289.                 continue; }
  290.  
  291.             if(strcmp(user.alias,username(i,str2)))
  292.                 putusername(i,user.alias);
  293.  
  294.             if(!(user.misc&(DELETED|INACTIVE))
  295.                 && user.expire && (ulong)user.expire<=(ulong)now) {
  296.                 putsmsg(i,text[AccountHasExpired]);
  297.                 sprintf(str,"%s #%u Expired",user.alias,user.number);
  298.                 logentry("!%",str);
  299.                 if(level_misc[user.level]&LEVEL_EXPTOVAL
  300.                     && level_expireto[user.level]<10) {
  301.                     user.flags1=val_flags1[level_expireto[user.level]];
  302.                     user.flags2=val_flags2[level_expireto[user.level]];
  303.                     user.flags3=val_flags3[level_expireto[user.level]];
  304.                     user.flags4=val_flags4[level_expireto[user.level]];
  305.                     user.exempt=val_exempt[level_expireto[user.level]];
  306.                     user.rest=val_rest[level_expireto[user.level]];
  307.                     if(val_expire[level_expireto[user.level]])
  308.                         user.expire=now
  309.                             +(val_expire[level_expireto[user.level]]*24*60*60);
  310.                     else
  311.                         user.expire=0;
  312.                     user.level=val_level[level_expireto[user.level]]; }
  313.                 else {
  314.                     if(level_misc[user.level]&LEVEL_EXPTOLVL)
  315.                         user.level=level_expireto[user.level];
  316.                     else
  317.                         user.level=expired_level;
  318.                     user.flags1&=~expired_flags1; /* expired status */
  319.                     user.flags2&=~expired_flags2; /* expired status */
  320.                     user.flags3&=~expired_flags3; /* expired status */
  321.                     user.flags4&=~expired_flags4; /* expired status */
  322.                     user.exempt&=~expired_exempt;
  323.                     user.rest|=expired_rest;
  324.                     user.expire=0; }
  325.                 putuserrec(i,U_LEVEL,2,itoa(user.level,str,10));
  326.                 putuserrec(i,U_FLAGS1,8,ultoa(user.flags1,str,16));
  327.                 putuserrec(i,U_FLAGS2,8,ultoa(user.flags2,str,16));
  328.                 putuserrec(i,U_FLAGS3,8,ultoa(user.flags3,str,16));
  329.                 putuserrec(i,U_FLAGS4,8,ultoa(user.flags4,str,16));
  330.                 putuserrec(i,U_EXPIRE,8,ultoa(user.expire,str,16));
  331.                 putuserrec(i,U_EXEMPT,8,ultoa(user.exempt,str,16));
  332.                 putuserrec(i,U_REST,8,ultoa(user.rest,str,16));
  333.                 if(expire_mod[0]) {
  334.                     useron=user;
  335.                     online=ON_LOCAL;
  336.                     exec_bin(expire_mod,&main_csi);
  337.                     online=0; }
  338.                 }
  339.  
  340.             /***********************************************************/
  341.             /* Auto deletion based on expiration date or days inactive */
  342.             /***********************************************************/
  343.             if(!(user.exempt&FLAG('P'))     /* Not a permanent account */
  344.                 && !(user.misc&(DELETED|INACTIVE))     /* alive */
  345.                 && (sys_autodel && (now-user.laston)/(long)(24L*60L*60L)
  346.                 > sys_autodel)) {            /* Inactive too long */
  347.                 sprintf(str,"Auto-Deleted %s #%u",user.alias,user.number);
  348.                 logentry("!*",str);
  349.                 delallmail(i);
  350.                 putusername(i,nulstr);
  351.                 putuserrec(i,U_MISC,8,ultoa(user.misc|DELETED,str,16)); }
  352.  
  353.             if(!(user.misc&(DELETED|INACTIVE))
  354.                 && preqwk_ar[0] && chk_ar(preqwk_ar,user)) {  /* Pre-QWK */
  355.                 for(k=1;k<=sys_nodes;k++) {
  356.                     getnodedat(k,&node,0);
  357.                     if((node.status==NODE_INUSE || node.status==NODE_QUIET
  358.                         || node.status==NODE_LOGON) && node.useron==i)
  359.                         break; }
  360.                 if(k<=sys_nodes)    /* Don't pre-pack with user online */
  361.                     continue;
  362.                 lclini(node_scrnlen-1);
  363.                 lclatr(LIGHTGRAY);
  364.                 lputc(FF);
  365.                 console|=CON_L_ECHO;
  366.                 lprintf("Pre-packing QWK for %s...\r\n"
  367.                     ,user.alias);
  368.                 useron=user;
  369.                 online=ON_LOCAL;
  370.                 statline=sys_def_stat;
  371.                 statusline();
  372.                 useron.qwk&=~QWK_FILES; /* turn off for pre-packing */
  373.                 useron.misc|=(ANSI|COLOR);
  374.                 delfiles(temp_dir,"*.*");
  375.                 getmsgptrs();
  376.                 getusrsubs();
  377.                 batdn_total=0;
  378.                 sprintf(str,"%sFILE\\%04u.QWK"
  379.                     ,data_dir,useron.number);
  380.                 if(pack_qwk(str,&l,1)) {
  381.                     qwk_success(l,0,1);
  382.                     putmsgptrs(); }
  383.                 delfiles(temp_dir,"*.*");
  384.                 lclatr(LIGHTGRAY);
  385.                 lclini(node_scrnlen);
  386.                 online=0;
  387.                 lputc(FF); } }
  388.  
  389.         mail_maint();
  390.  
  391.         lprintf("\r\n\r\nRunning system daily event...\r\n");
  392.         logentry("!:","Ran system daily event");
  393.         sys_status&=~SS_DAILY;
  394.         if(sys_daily[0])
  395.             external(cmdstr(sys_daily,nulstr,nulstr,NULL),0); }    /* EX_CC */
  396.  
  397.     if(thisnode.misc&NODE_EVENT) {
  398.         getnodedat(node_num,&thisnode,1);
  399.         thisnode.status=NODE_EVENT_RUNNING;
  400.         putnodedat(node_num,thisnode);
  401.         if(node_daily[0])
  402.             external(cmdstr(node_daily,nulstr,nulstr,NULL),0); /* EX_CC */
  403.         getnodedat(node_num,&thisnode,1);
  404.         thisnode.misc&=~NODE_EVENT;
  405.         putnodedat(node_num,thisnode); }
  406.     ret=0; }
  407. return(ret);
  408. }
  409.  
  410. /****************************************************************************/
  411. /* This function waits for either a caller or a local logon. It returns 0   */
  412. /* if the user failed the logon procedure, a 1 if the user succeeded        */
  413. /* Called from function main                                                */
  414. /****************************************************************************/
  415. char waitforcall()
  416. {
  417.     static uint calls;
  418.     uchar str[256],str2[256],cname[LEN_CID+1],c,gotcaller=0,x,y,dcd,*p
  419.         ,ans=0,hbeat=0,menuon=0,blank=0
  420.         ,*ok=mdm_misc&MDM_VERBAL ? "OK":"0"
  421.  
  422.     /* IP logging vars added by enigma */
  423.         , ipstr[256], *ips;
  424.  
  425.     uint i,j,k,nodes,lastnodes=0;
  426.     long l,m;
  427.     int file,result_code=0;
  428.     time_t start,lastnodechk=0,laststatchk=0,laststatfdate=0;
  429.     node_t node;
  430.     struct tm *gm;
  431.     struct dfree d;
  432.     stats_t stats,node_stats;
  433.  
  434. reset_logon_vars();
  435. ipstr[0]=cid[0]=cname[0]=0;
  436. online=console=0;
  437. start=time(NULL);
  438.  
  439. getnodedat(node_num,&thisnode,1);
  440. thisnode.status=NODE_WFC;
  441. thisnode.misc&=~(NODE_INTR|NODE_MSGW|NODE_NMSG|NODE_UDAT|NODE_POFF|NODE_AOFF);
  442. putnodedat(node_num,thisnode);
  443. catsyslog(0);
  444. if(term_ret)
  445.     return(terminal());
  446. /***
  447. if(com_port)
  448.     rioctl(0x10f);  /* for blanking debug line */
  449. ***/
  450.  
  451. if(qoc && calls) {
  452.     if(qoc==1)
  453.         offhook();
  454.     lclini(node_scrnlen);
  455.     lputc(FF);
  456.     bail(0); }
  457. useron.misc=0;
  458. rows=24;
  459. lputc(FF);
  460. if(node_misc&NM_RESETVID) {
  461.     textmode(C40);
  462.     textmode(C80);
  463.     _setcursortype(_NORMALCURSOR); }
  464.  
  465. lclatr(curatr=LIGHTGRAY);
  466. lclini(node_scrnlen);
  467.  
  468.  
  469. lputc(FF);
  470. if(com_port && !connect_rate) {  /* Initialize the modem */
  471.     lprintf("\rSetting DTE rate: %lu baud",com_rate);
  472.     lputc(CLREOL);
  473. #ifdef __OS2__
  474.     if((i=setbaud(com_rate))!=0) {
  475. #else
  476.     if((i=setbaud((uint)(com_rate&0xffffL)))!=0) {
  477. #endif
  478.         lprintf(" - Failed! (%d)\r\n",i);
  479.         bail(1); }
  480.     c=0;
  481.     if(!nmi && !(mdm_misc&MDM_DUMB))    /* if not dumb */
  482.     while(c<4) {
  483.         rioctl(IOFB);
  484.         rioctl(IOCM|PAUSE|ABORT);
  485.         rioctl(IOCS|PAUSE|ABORT);
  486.  
  487.         if(mdm_misc&MDM_CTS)
  488.             if(!(rioctl(IOSTATE)&CTS)) {
  489.                 lputs("\rWaiting up to 30 seconds for CTS to raise (  )\b\b\b");
  490.                 for(i=0;i<30 && !lkbrd(0);i++) {   /* wait upto 15 seconds */
  491.                     lprintf("%2d\b\b",i+1);
  492.                     mswait(1000);
  493.                     if(rioctl(IOSTATE)&CTS)
  494.                         break; }
  495.                 if(i==30) {
  496.                     lputs("\r\n\r\nModem configured for hardware flow "
  497.                         "control and CTS is stuck low.\r\n");
  498.                     logline("@!","CTS stuck low. Can't initialize.");
  499.                     bail(1); } }
  500.  
  501.         lputs("\rInitializing modem...");
  502.         lputc(CLREOL);
  503.  
  504.         dtr(5);         /* in case we're still connected to somebody */
  505.         dtr(1);
  506.         mswait(750);    /* DTR is sometimes slow */
  507.         rioctl(IOFB);   /* crap comes in when dtr is raised ? */
  508.         if(rioctl(IOSTATE)&DCD && mdm_hang[0]) {
  509.             mdmcmd(mdm_hang);
  510.             if(strcmp(str,"0") && strcmp(str,"OK"))
  511.                 getmdmstr(str,SEC_OK); }
  512.  
  513.         /******************************************/
  514.         /* Take phone off-hook while initializing */
  515.         /******************************************/
  516.         offhook();        
  517.         getmdmstr(str,SEC_OK);
  518.         if(strcmp(str,"0") && strcmp(str,"OK"))
  519.             getmdmstr(str,SEC_OK);
  520.  
  521.         /*********************************************************/
  522.         /* Send User Configured (broken?) initialization strings */
  523.         /*********************************************************/
  524.         mdmcmd(mdm_init);
  525.         if(mdm_spec[0]) {
  526.             getmdmstr(str,SEC_OK);
  527.             if(strcmp(str,"0") && strcmp(str,"OK"))
  528.                 getmdmstr(str,SEC_OK);
  529.             mdmcmd(mdm_spec); }
  530.         getmdmstr(str,SEC_OK);
  531.         if(strcmp(str,"0") && strcmp(str,"OK"))
  532.             getmdmstr(str,SEC_OK);
  533.  
  534.         /*****************************/
  535.         /* Send AT&C1 if DCD is high */
  536.         /*****************************/
  537.         if(rioctl(IOSTATE)&DCD) {
  538.             lputs("\r\nDCD is high. Sending AT&C1 to modem...");
  539.             mdmcmd("AT&C1");
  540.             getmdmstr(str,SEC_OK);
  541.             if(strcmp(str,ok))
  542.                 getmdmstr(str,SEC_OK); }
  543.  
  544.         /**********************************************/
  545.         /* DCD still high? Pause and try dropping DTR */
  546.         /**********************************************/
  547.         if(rioctl(IOSTATE)&DCD) {
  548.             lputs("\r\nDCD is high. Pausing...");
  549.             dtr(0);
  550.             mswait(2000);
  551.             rioctl(MSR);
  552.             if(rioctl(IOSTATE)&DCD) {
  553.                 lputs("\rDCD was high after modem init.\r\n");
  554.                 logentry("@!","DCD was high after modem init");
  555.                 if(mdm_misc&MDM_NODTR)
  556.                     mdmcmd(mdm_hang);
  557.                 else
  558.                     dtr(15);
  559.                 if(rioctl(IOSTATE)&DCD) {
  560.                     lputs("Hanging up failed to lower DCD.\r\n");
  561.                     logentry("@!","Hanging up failed to lower DCD");
  562.                     if(++c==4)
  563.                         break;
  564.                     continue; } }
  565.             dtr(1); }
  566.  
  567.         /************************************************************/
  568.         /* Let's repair any damage the user configured init strings */
  569.         /* may have caused                                            */
  570.         /************************************************************/
  571.         for(i=0;i<4;i++) {
  572.             rioctl(IOFB);
  573.             mdmcmd("AT");
  574.             if(!getmdmstr(str,SEC_OK) || !strcmp(str,ok))
  575.                 break;
  576.             if(!strcmp(str,"AT")) {     /* Echoing commands? */
  577.                 getmdmstr(str,SEC_OK);    /* Get OK */
  578.                 lputs("\r\nCommand echoed. Sending ATE0 to modem...");
  579.                 mdmcmd("ATE0"); }
  580.             else if(mdm_misc&MDM_VERBAL && !strcmp(str,"0")) { /* numeric? */
  581.                 lputs("\r\nNumeric response. Sending ATV1 to modem...");
  582.                 mdmcmd("ATV1"); }
  583.             else if(!(mdm_misc&MDM_VERBAL) && !strcmp(str,"OK")) {
  584.                 lputs("\r\nVerbal response. Sending ATV0 to modem...");
  585.                 mdmcmd("ATV0"); }
  586.             else {
  587.                 lprintf("\r\nUnrecognized response '%s'. Sending AT to modem..."
  588.                     ,str);
  589.                 mdmcmd("AT"); }
  590.             if(getmdmstr(str,SEC_OK) && !strcmp(str,ok))
  591.                 break; }
  592.  
  593.         /************************************************/
  594.         /* Put phone back on-hook and check result code */
  595.         /************************************************/
  596.         if(!mdm_hang[0])
  597.             mdmcmd("ATH");
  598.         else
  599.             mdmcmd(mdm_hang); 
  600.         if(!getmdmstr(str,SEC_OK)) {
  601.             lputs("\r\nNo response.\r\n");
  602.             logentry("@!","No response"); }
  603.         else {
  604.             if(!strcmp(str,ok))
  605.                 break;
  606.             lprintf("\r\nInvalid result code: '%s' "
  607.                 "instead of '%s'.\r\n",str,ok);
  608.             sprintf(tmp,"Invalid result code: '%s' instead of '%s'.",str,ok);
  609.             logentry("@!",tmp); }
  610.         if(++c==4)
  611.             break;
  612.         rioini(0,0);                /* remove com routines */
  613.         sys_status&=~SS_COMISR;
  614.         comini();
  615.         setrate(); }
  616.     if(c==4) {
  617.         lputs("\r\nModem failed initialization.\r\n");
  618.         errorlog("Modem failed initialization.");
  619.         offhook();
  620.         bail(1); }
  621.     lputc(FF); }
  622.  
  623. else if(com_port && connect_rate) {
  624.     gotcaller=1;
  625.     console=CON_R_ECHO|CON_L_ECHO|CON_R_INPUT|CON_L_INPUT;
  626.     online=ON_REMOTE;
  627.     sprintf(connection,"%lu",connect_rate);
  628.     cur_rate=connect_rate;
  629.     cur_cps=connect_rate/10;
  630.     connect_rate=0;
  631.     if(cidarg[0]) {                     /* Caller-id passed as argument */
  632.         mdm_misc|=MDM_CALLERID;
  633.         p=strstr(cidarg,"NUMBER:");
  634.         if(p) p+=8;
  635.         else {
  636.             p=strstr(cidarg,"NMBR");
  637.             if(p) p+=7; }
  638.         if(p) {                            /* 3 message format */
  639.             sprintf(cid,"%.*s",LEN_CID,p);
  640.             for(i=strlen(cid);!isdigit(cid[i]) && i;i--)
  641.                 ;
  642.             cid[i+1]=0;                     /* chop off non-numbers */
  643.             p=strstr(cidarg,"NAME:");
  644.             if(p) p+=6;
  645.             else {
  646.                 p=strstr(cidarg,"NAME");
  647.                 if(p) p+=7; }
  648.             if(p)
  649.                 sprintf(cname,"%.*s",LEN_CID,p); }
  650.         else if(strlen(cidarg)>12)           /* Single message format */
  651.             sprintf(cid,"%.*s",LEN_CID,cidarg+12);
  652.         else
  653.             sprintf(cid,"ERROR: '%s'",cidarg); } }
  654.  
  655.  
  656. if(!online) {
  657.     /*******************************************************/
  658.     /* To make sure that BBS print routines work correctly */
  659.     /*******************************************************/
  660.     useron.number=1;
  661.     getuserdat(&useron);
  662.     if(!useron.number)
  663.         useron.misc=ANSI|COLOR; }
  664.  
  665. useron.misc&=~UPAUSE;    /* make sure pause is off */
  666.  
  667. if(llo) {
  668.     quicklogonstuff();
  669.     sys_status&=~SS_USERON;
  670.     gotcaller=1; }
  671.  
  672. if(!(useron.misc&EXPERT) && !gotcaller) {    /* Novice sysop */
  673.     console=CON_L_ECHO;
  674.     online=ON_LOCAL;
  675.     lputc(FF);
  676.     tos=1;
  677.     lncntr=0;
  678.     menu("WFC");
  679.     menuon=1;
  680.     online=0; }
  681.  
  682. while(!gotcaller) {
  683.     mswait(0);           /* give up rest of time slice */
  684.  
  685.     console=CON_L_ECHO;
  686.     now=time(NULL);
  687.  
  688.     if(node_scrnblank && (now-start)/60>node_scrnblank
  689.         && !blank) { /* blank screen */
  690.         lputc(FF);
  691.         menuon=0;
  692.         blank=1; }
  693.     if(mdm_reinit && (now-start)/60>mdm_reinit) /* reinitialize modem */
  694.         return(0);
  695.     if(now-lastnodechk>node_sem_check) {  /* check node.dab every x seconds */
  696.  
  697. #if 1
  698.         if((i=heapcheck())!=_HEAPOK) {
  699.             lputc(FF);
  700.             offhook();
  701.             errormsg(WHERE,ERR_CHK,"heap",i);
  702.             bail(1); }
  703. #endif
  704.  
  705.         for(i=0;i<total_qhubs;i++)
  706.             if(node_num==qhub[i]->node) {
  707.                 sprintf(str,"%sQNET\\%s.NOW",data_dir,qhub[i]->id);
  708.                 if(fexist(str))
  709.                     qhub[i]->last=-1; }
  710.  
  711.         for(i=0;i<total_events;i++)
  712.             if(node_num==event[i]->node || event[i]->misc&EVENT_EXCL) {
  713.                 sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
  714.                 if(fexist(str))
  715.                     event[i]->last=-1; }
  716.  
  717.         lastnodechk=now;
  718.         getnodedat(node_num,&thisnode,0);
  719.         if(thisnode.misc&NODE_DOWN) {
  720.             lputc(FF);
  721.             offhook();
  722.             bail(0); }
  723.         if(thisnode.status!=NODE_WFC) {
  724.             getnodedat(node_num,&thisnode,1);
  725.             thisnode.status=NODE_WFC;
  726.             putnodedat(node_num,thisnode); }
  727.         if(thisnode.misc&NODE_RRUN) {   /* Re-run the node */
  728.             offhook();
  729.             lputc(FF);
  730.             getnodedat(node_num,&thisnode,1);
  731.             thisnode.status=NODE_OFFLINE;
  732.             thisnode.misc=0;
  733.             putnodedat(node_num,thisnode);
  734.             close(nodefile);
  735.             close(node_ext);
  736.             sys_status&=~SS_NODEDAB;
  737.             if(sys_status&SS_LOGOPEN)
  738.                 close(logfile);
  739.             if(sys_status&SS_COMISR)
  740.                 rioini(0,0);
  741.             sys_status&=~(SS_COMISR|SS_INITIAL|SS_LOGOPEN);
  742.             p=strchr(orgcmd,' ');
  743.             if(p)
  744.                 p++;
  745.             close(5);
  746.             if(execle(orgcmd,orgcmd,p,NULL,envp)) {
  747.                 lprintf("\r\nCouldn't execute %s!\r\n",orgcmd);
  748.                 bail(1); } } }
  749.  
  750.     if(!wfc_events(lastnodechk))
  751.         return(0);
  752.  
  753.     if(!menuon) {
  754.         /******************/
  755.         /* Roaming cursor */
  756.         /******************/
  757.         x=lclwx();
  758.         y=lclwy();
  759.         switch(random(5)) {
  760.             case 0:
  761.                 if(x>1)
  762.                     x--;
  763.                 break;
  764.             case 1:
  765.                 if(x<79)
  766.                     x++;
  767.                 break;
  768.             case 2:
  769.                 if(y>1)
  770.                     y--;
  771.                 break;
  772.             case 4:
  773.                 if(y<node_scrnlen-2)
  774.                     y++;
  775.                 break; } }
  776.     else {                        /* across the bottom */
  777.         y=25;
  778.         x=lclwx();
  779.         if(x%2) x+=2;
  780.         else x-=2;
  781.         if(x<1)
  782.             x=1;
  783.         else if(x>80)
  784.             x=80;
  785. /*
  786.         lclxy(x,y);
  787.         gettext(x,y,x,y,&i);
  788.         lclatr(random(0xf)+1);
  789.         lputc(i);
  790.         lclatr(LIGHTGRAY);
  791. */
  792. /**
  793.         mswait(100);
  794.         puttext(x,y,x,y,&i);
  795. **/        }
  796.  
  797. #ifndef __FLAT__        // Heart beat always for 32-bit OSs
  798.     if(inDV) {
  799. #endif
  800.         lclxy(80,1);
  801.         if(hbeat) {
  802.             lclatr(RED|HIGH);
  803.             lputc(3); }
  804.         else
  805.             lputc(0);
  806.         hbeat=!hbeat;
  807.         lclatr(LIGHTGRAY);
  808. #ifndef __FLAT__
  809.         }
  810. #endif
  811.  
  812.     lclxy(x,y);
  813.     mswait(100);
  814.  
  815.                                 /* Wait for call screen */
  816.                                 /* check every 10 seconds */
  817.  
  818.     if(node_misc&NM_WFCSCRN && now-laststatchk>node_stat_check
  819.         && !menuon && !blank) {
  820.         laststatchk=now;
  821.         sprintf(str,"%sDSTS.DAB",ctrl_dir);
  822.         if(fdate(str)!=laststatfdate) {   /* system statistics */
  823.             lclxy(1,1);
  824.             lclatr(LIGHTGRAY);
  825.             lputs("Retrieving Statistics.");
  826.             lputc(CLREOL);
  827.             if(!laststatfdate)    /* First time this WFC */
  828.                 getstats(node_num,&node_stats);
  829.             lputc('.');
  830.             laststatfdate=fdate(str);
  831.             getstats(0,&stats);
  832.             lputc('.');
  833.             l=m=0;
  834.             if(node_misc&NM_WFCMSGS) {
  835.                 for(i=0;i<total_subs;i++)
  836.                     l+=getposts(i);             /* l=total posts */
  837.                 lputc('.');
  838.                 for(i=0;i<total_dirs;i++)
  839.                     m+=getfiles(i);             /* m=total files */
  840.                 lputc('.'); }
  841.             i=getmail(0,0);                 /* i=total email */
  842.             lputc('.');
  843.             j=getmail(1,0);                 /* j=total fback */
  844.             lclxy(1,1);
  845.             lclatr(GREEN);
  846.             lprintf("Node #: ");
  847.             lclatr(GREEN|HIGH);
  848.             gm=localtime(&now);
  849.             lprintf("%-3u ",node_num);
  850.             lclatr(GREEN);
  851.             lprintf("%-3.3s %-2u  Space: ",mon[gm->tm_mon],gm->tm_mday);
  852.             if(temp_dir[1]==':')
  853.                 k=temp_dir[0]-'A'+1;
  854.             else k=0;
  855.             getdfree(k,&d);
  856.             if((ulong)d.df_bsec*(ulong)d.df_sclus
  857.                 *(ulong)d.df_avail<((ulong)min_dspace*1024L)*2L)
  858.                 lclatr(RED|HIGH|BLINK);
  859.             else
  860.                 lclatr(GREEN|HIGH);
  861.             sprintf(str,"%sk",ultoac(((ulong)d.df_bsec
  862.                 *(ulong)d.df_sclus*(ulong)d.df_avail)/1024UL,tmp));
  863.             lprintf("%-12.12s",str);
  864.             if(lastuseron[0]) {
  865.                 lclatr(GREEN);
  866.                 lprintf("Laston: ");
  867.                 lclatr(GREEN|HIGH);
  868.                 lprintf(lastuseron);
  869.                 lclatr(GREEN);
  870.                 if(thisnode.connection)
  871.                     lprintf(" %u",thisnode.connection);
  872.                 else
  873.                     lprintf(" Local"); }
  874.             lprintf("\r\n");
  875.             lclatr(GREEN);
  876.             lprintf("Logons: ");
  877.             lclatr(GREEN|HIGH);
  878.             sprintf(tmp,"%lu/%lu",node_stats.ltoday,stats.ltoday);
  879.             lprintf("%-12.12s",tmp);
  880.             lclatr(GREEN);
  881.             lprintf("Total: ");
  882.             lclatr(GREEN|HIGH);
  883.             lprintf("%-12.12s",ultoac(stats.logons,tmp));
  884.             lclatr(GREEN);
  885.             lprintf("Timeon: ");
  886.             lclatr(GREEN|HIGH);
  887.             sprintf(tmp,"%lu/%lu",node_stats.ttoday,stats.ttoday);
  888.             lprintf("%-12.12s",tmp);
  889.             lclatr(GREEN);
  890.             lprintf("Total: ");
  891.             lclatr(GREEN|HIGH);
  892.             lprintf("%-12.12s\r\n",ultoac(stats.timeon,tmp));
  893.             lclatr(GREEN);
  894.             lprintf("Emails: ");
  895.             lclatr(GREEN|HIGH);
  896.             sprintf(str,"%u/%u",(uint)stats.etoday,i);
  897.             lprintf("%-12.12s",str);
  898.             lclatr(GREEN);
  899.             lprintf("Posts: ");
  900.             lclatr(GREEN|HIGH);
  901.             sprintf(str,"%u",(uint)stats.ptoday);
  902.             if(node_misc&NM_WFCMSGS) {
  903.                 strcat(str,"/");
  904.                 strcat(str,ultoa(l,tmp,10)); }
  905.             lprintf("%-12.12s",str);
  906.             lclatr(GREEN);
  907.             lprintf("Fbacks: ");
  908.             lclatr(GREEN|HIGH);
  909.             sprintf(str,"%u/%u",(uint)stats.ftoday,j);
  910.             lprintf("%-12.12s",str);
  911.             lclatr(GREEN);
  912.             lprintf("Users: ");
  913.             lclatr(GREEN|HIGH);
  914.             sprintf(str,"%u/%u",stats.nusers,lastuser());
  915.             lprintf("%-12.12s\r\n",str);
  916.             lclatr(GREEN);
  917.             lprintf("Uloads: ");
  918.             lclatr(GREEN|HIGH);
  919.             ultoac(stats.ulb/1024UL,tmp);
  920.             strcat(tmp,"k");
  921.             lprintf("%-12.12s",tmp);
  922.             lclatr(GREEN);
  923.             lprintf("Files: ");
  924.             lclatr(GREEN|HIGH);
  925.             sprintf(str,"%u",(uint)stats.uls);
  926.             if(node_misc&NM_WFCMSGS) {
  927.                 strcat(str,"/");
  928.                 strcat(str,ultoa(m,tmp,10)); }
  929.             lprintf("%-12.12s",str);
  930.             lclatr(GREEN);
  931.             lprintf("Dloads: ");
  932.             lclatr(GREEN|HIGH);
  933.             ultoac(stats.dlb/1024UL,tmp);
  934.             strcat(tmp,"k");
  935.             lprintf("%-12.12s",tmp);
  936.             lclatr(GREEN);
  937.             lprintf("Files: ");
  938.             lclatr(GREEN|HIGH);
  939.             lprintf("%-12.12s\r\n",ultoac(stats.dls,tmp)); }
  940.         lclatr(curatr=LIGHTGRAY);
  941.         lclxy(1,6);
  942.         nodes=0;
  943.         for(i=1;i<=sys_nodes;i++) {
  944.             getnodedat(i,&node,0);
  945.             if((node.status!=NODE_WFC && node.status!=NODE_OFFLINE)
  946.                 || node.errors) {
  947.                 lputc(CLREOL);
  948.                 printnodedat(i,node);
  949.                 nodes++; } }
  950.         if(nodes<lastnodes) {
  951.             i=j=lclwy();
  952.             j+=(lastnodes-nodes)+1;
  953.             for(;i<=node_scrnlen && i<j;i++) {
  954.                 lclxy(1,i);
  955.                 lputc(CLREOL); } }
  956.         lastnodes=nodes;
  957.         lclatr(curatr=LIGHTGRAY); }
  958.  
  959.  
  960.     if(!(node_misc&NM_NO_LKBRD) && lkbrd(1)) {
  961.         start=time(NULL);
  962.         /* menuon=0; */
  963.         lputc(FF);
  964.         tos=1;
  965.         lncntr=0;
  966.         i=lkbrd(0);
  967.         if(!(i&0xff) && (i>=0x3b00 && i<=0x4400)
  968.             || i==0x8500 || i==0x8600) {        /* F1-F12 */
  969.             if(i>=0x3b00 && i<=0x4400)
  970.                 i=((i-0x3b00)>>8);
  971.             else if(i==0x8500)
  972.                 i=10;
  973.             else
  974.                 i=11;
  975.             offhook();
  976.             external(cmdstr(wfc_scmd[i],nulstr,nulstr,NULL),EX_SWAP);
  977.             return(0); }
  978.  
  979.         if(isdigit(i&0xff)) {
  980.             offhook();
  981.             external(cmdstr(wfc_cmd[i&0xf],nulstr,nulstr,NULL),0);
  982.             return(0); }
  983.  
  984.         switch(toupper(i)) {
  985.             case 'A':   /* forced answer */
  986.                 ans=1;
  987.                 break;
  988.             case 'C':   /* configure */
  989.                 if(node_misc&NM_SYSPW) {
  990.                     quicklogonstuff();
  991.                     if(!chksyspass(1))
  992.                         return(0); }
  993.                 offhook();
  994.                  if(sys_status&SS_LOGOPEN) {
  995.                     close(logfile);
  996.                     sys_status&=~SS_LOGOPEN; }
  997.                 if(sys_status&SS_COMISR) {
  998.                     rioini(0,0);    /* replace COM i/o vectors */
  999.                     sys_status&=~SS_COMISR; }
  1000.                 close(nodefile);
  1001.                 close(node_ext);
  1002.                 sys_status&=~SS_NODEDAB;
  1003.                 sprintf(str,"%sEXECSBBS.%s",exec_dir,
  1004. #ifdef __OS2__
  1005.                     "EXE"
  1006. #else
  1007.                     "COM"
  1008. #endif
  1009.                     );
  1010.                 sprintf(tmp,"\"%s \"",cmdstr(scfg_cmd,nulstr,nulstr,NULL));
  1011.                 if(execl(str,str,".",tmp,orgcmd,NULL,envp)) {
  1012.                     errormsg(WHERE,ERR_EXEC,str,0);
  1013.                     bail(1); }
  1014.             case 'D':   /* Dos shell */
  1015.                 offhook();
  1016.                 external(comspec,0);
  1017.                 return(0);
  1018.             case 'F':   /* Force Network Call-out */
  1019.                 quicklogonstuff();
  1020.                 lclatr(YELLOW);
  1021.                 lputs("QWK Hub ID: ");
  1022.                 lclatr(WHITE);
  1023.                 if(!getstr(str,8,K_UPPER))
  1024.                     return(0);
  1025.                 for(i=0;i<total_qhubs;i++)
  1026.                     if(!stricmp(str,qhub[i]->id)) {
  1027.                         if(qhub[i]->node==node_num)
  1028.                             qhub[i]->last=-1;
  1029.                         else {
  1030.                             sprintf(tmp,"%sQNET\\%s.NOW",data_dir,str);
  1031.                             if((file=nopen(tmp,O_CREAT|O_TRUNC|O_WRONLY))
  1032.                                 !=-1)
  1033.                                 close(file); }
  1034.                         break; }
  1035.                 return(0);
  1036.             case 'L':   /* Log */
  1037.                 if(node_misc&NM_SYSPW) {
  1038.                     quicklogonstuff();
  1039.                     if(!chksyspass(1))
  1040.                         return(0); }
  1041.                 offhook();
  1042.                 now=time(NULL);
  1043.                 unixtodos(now,&date,&curtime);
  1044.                 sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG"
  1045.                     ,data_dir,date.da_mon,date.da_day,date.da_year-1900);
  1046.                 external(cmdstr(node_viewer,str,nulstr,NULL),0);
  1047.                 return(0);
  1048.             case 'M':   /* Read all mail */
  1049.                 quicklogonstuff();
  1050.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1051.                     return(0);
  1052.                 readmail(1,MAIL_ALL);
  1053.                 online=console=0;
  1054.                 return(0);
  1055.             case 'N':   /* Node statistics */
  1056.                 quicklogonstuff();
  1057.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1058.                     return(0);
  1059.                 useron.misc|=UPAUSE;
  1060.                 printstatslog(node_num);
  1061.                 pause();
  1062.                 return(0);
  1063.             case 'Q':   /* Quit */
  1064.                 offhook();
  1065.                 bail(0);
  1066.             case 'R':   /* Read feedback */
  1067.                 quicklogonstuff();
  1068.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1069.                     return(0);
  1070.                 readmail(1,MAIL_YOUR);
  1071.                 return(0);
  1072.             case 'K':   /* Sent mail */
  1073.                 quicklogonstuff();
  1074.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1075.                     return(0);
  1076.                 readmail(1,MAIL_SENT);
  1077.                 return(0);
  1078.             case 'S':   /* System Statistics */
  1079.                 quicklogonstuff();
  1080.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1081.                     return(0);
  1082.                 useron.misc|=UPAUSE;
  1083.                 printstatslog(0);
  1084.                 pause();
  1085.                 return(0);
  1086.             case 'T':   /* Terminal mode */
  1087.                 if(!com_port) {
  1088.                     lprintf("No COM port configured.");
  1089.                     getch();
  1090.                     lputc(FF);
  1091.                     return(0); }
  1092.                 if(node_misc&NM_SYSPW) {
  1093.                     quicklogonstuff();
  1094.                     if(!chksyspass(1))
  1095.                         return(0); }
  1096.                 return(terminal());
  1097.             case 'U':   /* User edit */
  1098.                 quicklogonstuff();
  1099.                 useredit(0,1);
  1100.                 return(0);
  1101.             case 'E':
  1102.             case 'W':   /* Write e-mail */
  1103.                 quicklogonstuff();
  1104.                 if(node_misc&NM_SYSPW && !chksyspass(1))
  1105.                     return(0);
  1106.                 bputs(text[Email]);
  1107.                 if(!getstr(str,50,0))
  1108.                     return(0);
  1109.                 if(!strchr(str,'@') && (i=finduser(str))!=0)
  1110.                     email(i,nulstr,nulstr,WM_EMAIL);
  1111.                 else
  1112.                     netmail(str,nulstr,0);
  1113.                 return(0);
  1114.             case 'X':   /* Exit with phone on-hook */
  1115.                 bail(0);
  1116.             case 'Y':   /* Yesterday's log */
  1117.                 if(node_misc&NM_SYSPW) {
  1118.                     quicklogonstuff();
  1119.                     if(!chksyspass(1))
  1120.                         return(0); }
  1121.                 offhook();
  1122.                 now=time(NULL);
  1123.                 now-=(ulong)60L*24L*60L;
  1124.                 unixtodos(now,&date,&curtime);
  1125.                 sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG"
  1126.                     ,data_dir,date.da_mon,date.da_day,date.da_year-1900);
  1127.                 external(cmdstr(node_viewer,str,nulstr,NULL),0);
  1128.                 return(0);
  1129.             case 'Z':
  1130.                 mail_maint();
  1131.                 return(0);
  1132.             case '?':   /* Menu */
  1133.                 if(menuon) {
  1134.                     menuon=0;
  1135.                     lputc(FF);
  1136.                     laststatchk=0;
  1137.                     laststatfdate=0; }
  1138.                 else {
  1139.                     online=ON_LOCAL;
  1140.                     menu("WFC");
  1141.                     menuon=1;
  1142.                     blank=0;
  1143.                     online=0; }
  1144.                 continue;
  1145.             case SP:   /* Log on */
  1146.                 lclatr(WHITE|HIGH); lputc('Y'); lclatr(GREEN);
  1147.                 lputs(" Yes\r\n");
  1148.                 lclatr(WHITE|HIGH); lputc('Z'); lclatr(GREEN);
  1149.                 lputs(" Yes, Quiet\r\n");
  1150.                 lclatr(WHITE|HIGH); lputc('F'); lclatr(GREEN);
  1151.                 lputs(" Fast User #1\r\n");
  1152.                 lclatr(WHITE|HIGH); lputc('Q'); lclatr(GREEN);
  1153.                 lputs(" Fast User #1, Quiet\r\n");
  1154.                 lclatr(BROWN|HIGH);
  1155.                 lputs("\r\nLog on? [No]: ");
  1156.                 lclatr(LIGHTGRAY);
  1157.                 i=getch();
  1158.                 switch(toupper(i)) {
  1159.                     case 'Z':
  1160.                         onquiet=1;
  1161.                     case 'Y':       /* Yes, logon */
  1162.                         lputc(FF);
  1163.                         quicklogonstuff();
  1164.                         sys_status&=~SS_USERON;
  1165.                         useron.misc=(UPAUSE|ANSI|COLOR);
  1166.                         gotcaller=1;
  1167.                         continue;
  1168.                     case 'Q':
  1169.                         onquiet=1;
  1170.                     case 'F':
  1171.                         lputc(FF);
  1172.                         quicklogonstuff();
  1173.                         if(sys_misc&SM_REQ_PW || node_misc&NM_SYSPW) {
  1174.                             useron.misc=(UPAUSE|ANSI|COLOR);
  1175.                             gotcaller=1;
  1176.                             continue; }
  1177.                         if(!useron.number) {
  1178.                             lputc(7);
  1179.                             lputs("A Sysop account hasn't been created");
  1180.                             getch();
  1181.                             return(0); }
  1182.                         return(logon());
  1183.                     default:
  1184.                         return(0); }
  1185.             default:
  1186.                 lputs("Hit '?' for a menu.");
  1187.                 continue; } }
  1188.     if(com_port) {
  1189.         if(mdm_misc&MDM_VERBAL) {
  1190.             if(rioctl(RXBC)) {
  1191.                 lputc(FF);
  1192.                 getmdmstr(str,SEC_RING);
  1193.                 if(!strcmp(str,"RING"))
  1194.                     ans=1; } }
  1195.         else {    /* numeric */
  1196.             if(incom()=='2')
  1197.                 ans=1; }
  1198.         if(mdm_misc&MDM_DUMB && DCDHIGH)
  1199.             ans=1; }
  1200.     if(ans) {
  1201.         lputc(FF);
  1202.         if(mdm_misc&MDM_CALLERID) {
  1203.             lputs("Obtaining Caller-ID...");
  1204.             getmdmstr(str,SEC_CID);
  1205.             lprintf("\r\nCID: %s",str);
  1206.             if(!strncmpi(str,"TIME:",5)) {  /* 3 message format */
  1207.                 getmdmstr(str,SEC_CID);
  1208.                 lprintf("\r\nCID: %s",str);
  1209.                 p=strchr(str,':');
  1210.                 if(p)
  1211.                     strcpy(cid,p+2);        /* Phone Number */
  1212.                 getmdmstr(str,SEC_CID);
  1213.                 lprintf("\r\nCID: %s",str);
  1214.                 p=strchr(str,':');
  1215.                 if(p)
  1216.                     sprintf(cname,"%.*s",LEN_CID,p+2); }    /* Caller Name */
  1217.             else if(!strncmpi(str,"DATE =",6)) { /* Supra format */
  1218.                 getmdmstr(str,SEC_CID);
  1219.                 lprintf("\r\nCID: %s",str);     /* TIME = line */
  1220.                 getmdmstr(str,SEC_CID);
  1221.                 lprintf("\r\nCID: %s",str);     /* NMBR = line */
  1222.                 p=strchr(str,'=');
  1223.                 if(p)
  1224.                     sprintf(strstr(str,"NAME") ? cname:cid,"%.*s",LEN_CID,p+2);
  1225.                 getmdmstr(str,SEC_CID);         /* NAME = line */
  1226.                 lprintf("\r\nCID: %s",str);
  1227.                 p=strchr(str,'=');
  1228.                 if(p)
  1229.                     sprintf(strstr(str,"NAME") ? cname:cid,"%.*s",LEN_CID,p+2);
  1230.                 }
  1231.             else if(strlen(str)>12)         /* Single message format */
  1232.                 sprintf(cid,"%.*s",LEN_CID,str+12);
  1233.             else
  1234.                 sprintf(cid,"ERROR: '%s'",str);
  1235.             lputs(crlf); }
  1236.         cur_rate=cur_cps=0;
  1237.         connection[0]=0;
  1238.         result_code=0;
  1239.         if(!(mdm_misc&MDM_DUMB)) {
  1240.             if(mdm_rings>1) {
  1241.                 lputs("Ring\r\n");
  1242.                 for(i=1;i<mdm_rings;i++)
  1243.                     if(!getmdmstr(str,10))
  1244.                         break;
  1245.                     else
  1246.                         lputs("Ring\r\n");
  1247.                 if(i<mdm_rings)
  1248.                     return(0);
  1249.                 lputs(crlf); }
  1250.             lputs("Answering...");
  1251.             mdmcmd(mdm_answ);
  1252.             rioctl(IOFI);                        // flush extra ring results
  1253.             while(!cur_rate || rioctl(RXBC)) {    // no connect or more rsults
  1254.                 if(!getmdmstr(str,SEC_ANSWER)) {
  1255.                     if(cur_rate)
  1256.                         break;
  1257.                     lprintf("\r\nNO CARRIER\r\n");
  1258.                     if(!(mdm_misc&MDM_NODTR)) {
  1259.                         dtr(15);
  1260.                         dtr(1);
  1261.                         mswait(500); }
  1262.                     mdmcmd(nulstr);
  1263.                     hangup();
  1264.                     return(0); }
  1265.                 i=0;
  1266.                 while(i<2
  1267.                     && (!strcmp(str,"2")
  1268.                     || !strcmp(str,"RING"))) { /* Ring? Get next result */
  1269.                     lputs("Ring\r\n");
  1270.                     if(i) {
  1271.                         mdmcmd(mdm_answ);      /* Give a second ATA */
  1272.                         rioctl(IOFI); }
  1273.                     if(!getmdmstr(str,SEC_ANSWER)) {
  1274.                         if(!(mdm_misc&MDM_NODTR)) {
  1275.                             dtr(15);
  1276.                             dtr(1);
  1277.                             mswait(500); }
  1278.                         mdmcmd(nulstr);
  1279.                         hangup();          /* Get next result code from modem */
  1280.                         return(0); }
  1281.                     i++; }
  1282.                 if(!strcmp(str,"3") || !strcmp(str,"NO CARRIER")) {
  1283.                     lprintf("\r\nNO CARRIER\r\n");
  1284.                     hangup();
  1285.                     return(0); }
  1286.  
  1287.                 lprintf("\r\nResult Code: %s\r\n",str);
  1288.  
  1289.                 /* IP (vmodem) logging additions by enigma */
  1290.                 ips = strstr(str, "TEL FROM ");
  1291.                 if(ips) {
  1292.                   strcpy(ipstr, ips+9);
  1293.                 }
  1294.  
  1295.                 if(strstr(str,"FAX") || strstr(str,"+FCO")) {
  1296.                                     /* Just for the ZyXEL's */
  1297.                     mswait(1500);   /* 1 and a half second wait for ZyXEL */
  1298.                     sys_misc&=~SM_ERRALARM;
  1299.                     bail(100); }
  1300.  
  1301.                 if(mdm_misc&MDM_VERBAL) {
  1302.                     if(!cur_rate
  1303.                         && (!strnicmp(str,"CONNECT ",8)
  1304.                         || !strnicmp(str,"CARRIER ",8))) {
  1305.                         cur_rate=atol(str+8);
  1306.                         // build description
  1307.                         for(i=8,j=0;str[i] && j<LEN_MODEM;i++) {
  1308.                             if(j==2 && isdigit(str[i])
  1309.                                 && str[i+1]=='0' && str[i+2]=='0'
  1310.                                 && !isdigit(str[i+3]) && j+1<LEN_MODEM) {
  1311.                                 connection[j++]='.';
  1312.                                 connection[j++]=str[i];
  1313.                                 i+=2; }
  1314.                             else
  1315.                                 connection[j++]=str[i]; }
  1316.                         connection[j]=0; }
  1317.                     if(!cur_rate && !strcmp(str,"CONNECT"))
  1318.                         cur_rate=com_rate;
  1319.                     if(cur_rate
  1320.                         && (strstr(str,"ARQ") || strstr(str,"MNP")
  1321.                         || strstr(str,"V42") || strstr(str,"LAPM")
  1322.                         || strstr(str,"REL")))
  1323.                         cur_cps=cur_rate/9; }
  1324.                 else {    /* numeric */
  1325.                     j=atoi(str);
  1326.                     for(i=0;i<mdm_results;i++)
  1327.                         if(mdm_result[i].code==j) break;
  1328.                     if(!cur_rate) {
  1329.                         if(i==mdm_results) {
  1330.                             lprintf("Unknown result code: '%s'\r\n",str);
  1331.                             sprintf(tmp,"Unknown modem result code: '%s'",str);
  1332.                             errorlog(tmp);
  1333.                             if(mdm_misc&MDM_KNOWNRES || !mdm_results) {
  1334.                                 hangup();
  1335.                                 return(0); }    /* Don't allow invalid codes */
  1336.                             i--; }    /* Use last configured result code */
  1337.                         else
  1338.                             result_code=mdm_result[i].code; }
  1339.                     if(!strncmpi(mdm_result[i].str,"EXIT ",5))
  1340.                         bail(atoi(mdm_result[i].str+5));
  1341.                     if(!strcmpi(mdm_result[i].str,"FAX")) {
  1342.                         lputs("FAX Connection\r\n");
  1343.                         bail(100); }
  1344.                     if(!strcmpi(mdm_result[i].str,"IGNORE") || cur_rate)
  1345.                         lputs("Ignored\r\n");
  1346.                     else {
  1347.                         cur_rate=mdm_result[i].rate;
  1348.                         cur_cps=mdm_result[i].cps;
  1349.                         strcpy(connection,mdm_result[i].str); } } } }
  1350.         else   /* dumb modem */
  1351.             cur_rate=com_rate;
  1352.  
  1353.         if(!connection[0])
  1354.             sprintf(connection,"%lu",cur_rate);
  1355.         lprintf("Logging Caller in at %s\r\n",connection);
  1356.         if(!cur_cps)
  1357.             cur_cps=cur_rate/10L;
  1358.  
  1359.         rioctl(IOCE|((RXLOST|FERR|PERR|OVRR)<<8));  /* clear error flags */
  1360.         console=CON_R_ECHO|CON_L_ECHO|CON_R_INPUT|CON_L_INPUT;
  1361.         online=ON_REMOTE;
  1362.         gotcaller=1;
  1363.         putcom(crlf);
  1364. #if defined(__OS2__)
  1365.         putcom(decrypt(VersionNoticeOS2,0));
  1366. #elif defined(__WIN32__)
  1367.         putcom(decrypt(VersionNoticeW32,0));
  1368. #else
  1369.         putcom(decrypt(VersionNoticeDOS,0));
  1370. #endif
  1371.         putcom(crlf);
  1372.         lprintf("Pausing %u Seconds...",mdm_ansdelay);
  1373.         if(node_misc&NM_ANSALARM) {
  1374.             now=time(NULL);
  1375.             while(time(NULL)-now<mdm_ansdelay)
  1376.                 for(x=0;x<10;x++)
  1377.                     for(y=0;y<10;y++)
  1378.                         beep((x*100)+(y*5),10); }
  1379.         else
  1380.             secwait(mdm_ansdelay);
  1381.         nosound();
  1382.         rioctl(IOFI); } }    /* flush input buffer */
  1383.  
  1384. reset_logon_vars();
  1385. calls++;
  1386. useron.misc=0;
  1387. answertime=logontime=starttime=time(NULL);
  1388. if(online==ON_REMOTE) {
  1389.     setrate();
  1390.  
  1391.     now=time(NULL);
  1392.     gm=localtime(&now);
  1393.     sprintf(str,"%02d:%02d%c  %s %s %02d %u            Node %3u  %5lubps (%s)"
  1394.         ,gm->tm_hour>12 ? gm->tm_hour-12 : gm->tm_hour==0 ? 12 : gm->tm_hour
  1395.         ,gm->tm_min,gm->tm_hour>=12 ? 'p' : 'a',wday[gm->tm_wday]
  1396.         ,mon[gm->tm_mon],gm->tm_mday,gm->tm_year+1900,node_num,cur_rate
  1397.         ,connection);
  1398.     if(result_code) {
  1399.         sprintf(tmp," [%d]",result_code);
  1400.         strcat(str,tmp); }
  1401.     logline("@",str);
  1402.  
  1403.     /* IP trashcan modification by enigma */
  1404.     if(trashcan(ipstr,"IP")) {
  1405.         sprintf(tmp, "IP Trashcan: %s, hanging up!\r\n", ipstr);
  1406.         logline("@!",tmp);
  1407.         hangup();
  1408.         return(0); }
  1409.  
  1410.     if(mdm_misc&MDM_CALLERID) {
  1411.         outcom(0xC);
  1412. #if defined(__OS2__)
  1413.         putcom(decrypt(VersionNoticeOS2,0));
  1414. #elif defined(__WIN32__)
  1415.         putcom(decrypt(VersionNoticeW32,0));
  1416. #else
  1417.         putcom(decrypt(VersionNoticeDOS,0));
  1418. #endif
  1419.         putcom(crlf);
  1420.         sprintf(str,"CID: %-*s %s",LEN_CID,cid,cname);
  1421.         logline("@*",str);
  1422.         if(trashcan(cid,"CID")) {
  1423.             hangup();
  1424.             return(0); } } }
  1425. lclini(node_scrnlen-1);
  1426. if(online==ON_REMOTE) {
  1427.     if(node_dollars_per_call) { /* Billing node stuff */
  1428.         now=time(NULL);
  1429.         bprintf(text[BillingNodeMsg],sys_name,node_dollars_per_call);
  1430.         while(online && now-answertime<30) {
  1431.             if(incom()!=NOINP) {
  1432.                 if(!(mdm_misc&MDM_NODTR))
  1433.                     dtr(15);
  1434.                 else
  1435.                     mdmcmd(mdm_hang); }
  1436.             checkline();
  1437.             now=time(NULL); }
  1438.         if(!online)
  1439.             return(0); }
  1440.     rioctl(IOFI);
  1441.     putcom("\x1b[99B\x1b[6n\x1b[!_\x1b[0t_\x1b[0m_\xC");
  1442.     lputc(FF);
  1443.     i=l=lncntr=autoterm=0;
  1444.     tos=1;
  1445. #if defined(__OS2__)
  1446.     strcpy(str,decrypt(VersionNoticeOS2,0));
  1447. #elif defined(__WIN32__)
  1448.     strcpy(str,decrypt(VersionNoticeW32,0));
  1449. #else
  1450.     strcpy(str,decrypt(VersionNoticeDOS,0));
  1451. #endif
  1452.     strcat(str,decrypt(CopyrightNotice,0));
  1453.     center(str);
  1454.     while(i++<30 && l<40) {         /* wait up to 3 seconds for response */
  1455.         if((c=(incom()&0x7f))=='R') {   /* break immediately if response */
  1456.             str[l++]=c;
  1457.             mswait(110);
  1458.             break; }
  1459.         if(c) {
  1460.             str[l++]=c;
  1461.             if(l==1 && c!=ESC)
  1462.                 break; }
  1463.         else
  1464.             mswait(100); }
  1465.  
  1466.     if(rioctl(RXBC))    /* wait a bit for extra RIP reply chars */
  1467.         mswait(550);
  1468.  
  1469.     while((i=(incom()&0x7f))!=NOINP && l<40)
  1470.         str[l++]=i;
  1471.     str[l]=0;
  1472.  
  1473. #if 0
  1474.     for(i=0;str[i];i++)
  1475.         lprintf("%02X ",str[i]);
  1476.     lputs(crlf);
  1477. #endif
  1478.  
  1479.     if(l) {
  1480.         if(str[0]==ESC && str[1]=='[') {
  1481.             useron.misc|=(ANSI|COLOR);
  1482.             autoterm|=ANSI;
  1483.             rows=((str[2]&0xf)*10)+(str[3]&0xf);
  1484.             if(rows<10 || rows>99) rows=24; }
  1485.         truncsp(str);
  1486.         if(strstr(str,"RIPSCRIP")) {
  1487.             logline("@R",strstr(str,"RIPSCRIP"));
  1488.             useron.misc|=(RIP|COLOR|ANSI);
  1489.             autoterm|=(RIP|COLOR|ANSI); }
  1490.         else if(strstr(str,"DC-TERM")
  1491.             && toupper(*(strstr(str,"DC-TERM")+12))=='W') {
  1492.             logline("@W",strstr(str,"DC-TERM"));
  1493.             useron.misc|=(WIP|COLOR|ANSI);
  1494.             autoterm|=(WIP|COLOR|ANSI); } }
  1495.     rioctl(IOFI); /* flush left-over or late response chars */
  1496.     sprintf(str,"%sANSWER",text_dir);
  1497.     sprintf(tmp,"%s.%s",str,autoterm&WIP ? "WIP":"RIP");
  1498.     sprintf(str2,"%s.ANS",str);
  1499.     if(autoterm&(RIP|WIP) && fexist(tmp))
  1500.         strcat(str,autoterm&WIP ? ".WIP":".RIP");
  1501.     else if(autoterm&ANSI && fexist(str2))
  1502.         strcat(str,".ANS");
  1503.     else
  1504.         strcat(str,".ASC");
  1505.     rioctl(IOSM|PAUSE);
  1506.     sys_status|=SS_PAUSEON;
  1507.     tos=1;
  1508.     printfile(str,P_NOABORT);
  1509.     sys_status&=~SS_PAUSEON;
  1510.     CRLF; }
  1511. else
  1512.     useron.misc=(UPAUSE|ANSI|COLOR);
  1513.  
  1514. useron.number=0;
  1515.  
  1516. exec_bin(login_mod,&main_csi);
  1517.  
  1518. if(!useron.number)
  1519.     hangup();
  1520. if(!online) {
  1521.     logout();
  1522.     return(0); }
  1523.  
  1524. if(online==ON_REMOTE && mdm_misc&MDM_CALLERID) {
  1525.     strcpy(useron.note,cid);
  1526.     putuserrec(useron.number,U_NOTE,LEN_NOTE,useron.note); }
  1527.  
  1528. /* log the IP by enigma */
  1529.  
  1530. if(online==ON_REMOTE && ipstr[0]!='\0') {
  1531.     sprintf(useron.note, "Telnet: %s", ipstr);
  1532.     putuserrec(useron.number,U_NOTE,LEN_NOTE,useron.note);
  1533.     logline("@*", useron.note); }
  1534.  
  1535. if(!(sys_status&SS_USERON)) {
  1536.     errormsg(WHERE,ERR_CHK,"User not logged on",0);
  1537.     hangup();
  1538.     logout();
  1539.     return(0); }
  1540.  
  1541. return(1);
  1542. }
  1543.  
  1544.