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

  1. /*****************************************************************************
  2.  
  3.                 WWIV Version 4
  4.                     Copyright (C) 1988-1995 by Wayne Bell
  5.  
  6. Distribution of the source code for WWIV, in any form, modified or unmodified,
  7. without PRIOR, WRITTEN APPROVAL by the author, is expressly prohibited.
  8. Distribution of compiled versions of WWIV is limited to copies compiled BY
  9. THE AUTHOR.  Distribution of any copies of WWIV not compiled by the author
  10. is expressly prohibited.
  11.  
  12.  
  13. *****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "vars.h"
  18.  
  19. #pragma hdrstop
  20.  
  21. #include <dir.h>
  22. #include <math.h>
  23. #include <ctype.h>
  24.  
  25. #if defined(__OS2__) && !defined(KBDSTF_SCROLLLOCK_ON)
  26. #define KBDSTF_SCROLLLOCK_ON 0x0010
  27. #endif
  28.  
  29.  
  30. /* functions for external programs to call */
  31.  
  32. #ifndef __OS2__
  33. #pragma warn -par
  34.  
  35. void far interrupt inlii(unsigned bp, unsigned di, unsigned si,
  36.                            unsigned ds, unsigned es, unsigned dx,
  37.                            unsigned cx, unsigned bx, unsigned ax,
  38.                            unsigned ip, unsigned cs, unsigned flags,
  39.                            char *s1, char *s2, int i1, int i2)
  40. {
  41.   inli(s1,s2,i1,i2);
  42. }
  43.  
  44. void far interrupt checkai(unsigned bp, unsigned di, unsigned si,
  45.                            unsigned ds, unsigned es, unsigned dx,
  46.                            unsigned cx, unsigned bx, unsigned ax,
  47.                            unsigned ip, unsigned cs, unsigned flags,
  48.                            int *i1, int *i2)
  49. {
  50.   checka(i1,i2);
  51. }
  52.  
  53.  
  54. void far interrupt plai(unsigned bp, unsigned di, unsigned si,
  55.                            unsigned ds, unsigned es, unsigned dx,
  56.                            unsigned cx, unsigned bx, unsigned ax,
  57.                            unsigned ip, unsigned cs, unsigned flags,
  58.                            char *s1, int *i1)
  59. {
  60.   pla(s1,i1);
  61. }
  62.  
  63.  
  64. void far interrupt outchri(unsigned bp, unsigned di, unsigned si,
  65.                            unsigned ds, unsigned es, unsigned dx,
  66.                            unsigned cx, unsigned bx, unsigned ax,
  67.                            unsigned ip, unsigned cs, unsigned flags,
  68.                            char ch)
  69. {
  70.   outchr(ch);
  71. }
  72.  
  73.  
  74. void far interrupt outstri(unsigned bp, unsigned di, unsigned si,
  75.                            unsigned ds, unsigned es, unsigned dx,
  76.                            unsigned cx, unsigned bx, unsigned ax,
  77.                            unsigned ip, unsigned cs, unsigned flags,
  78.                            char *s1)
  79. {
  80.   outstr(s1);
  81. }
  82.  
  83.  
  84. void far interrupt nli(unsigned bp, unsigned di, unsigned si,
  85.                            unsigned ds, unsigned es, unsigned dx,
  86.                            unsigned cx, unsigned bx, unsigned ax,
  87.                            unsigned ip, unsigned cs, unsigned flags)
  88. {
  89.   nl();
  90. }
  91.  
  92.  
  93. void far interrupt pli(unsigned bp, unsigned di, unsigned si,
  94.                            unsigned ds, unsigned es, unsigned dx,
  95.                            unsigned cx, unsigned bx, unsigned ax,
  96.                            unsigned ip, unsigned cs, unsigned flags,
  97.                            char *s1)
  98. {
  99.   pl(s1);
  100. }
  101.  
  102.  
  103. void far interrupt emptyi(unsigned bp, unsigned di, unsigned si,
  104.                            unsigned ds, unsigned es, unsigned dx,
  105.                            unsigned cx, unsigned bx, unsigned ax,
  106.                            unsigned ip, unsigned cs, unsigned flags)
  107. {
  108.   ax=empty();
  109. }
  110.  
  111.  
  112. void far interrupt inkeyi(unsigned bp, unsigned di, unsigned si,
  113.                            unsigned ds, unsigned es, unsigned dx,
  114.                            unsigned cx, unsigned bx, unsigned ax,
  115.                            unsigned ip, unsigned cs, unsigned flags)
  116. {
  117.   ax=(unsigned) empty();
  118. }
  119.  
  120.  
  121. void far interrupt getkeyi(unsigned bp, unsigned di, unsigned si,
  122.                            unsigned ds, unsigned es, unsigned dx,
  123.                            unsigned cx, unsigned bx, unsigned ax,
  124.                            unsigned ip, unsigned cs, unsigned flags)
  125. {
  126.   ax=(unsigned) getkey();
  127. }
  128.  
  129.  
  130. void far interrupt inputi(unsigned bp, unsigned di, unsigned si,
  131.                            unsigned ds, unsigned es, unsigned dx,
  132.                            unsigned cx, unsigned bx, unsigned ax,
  133.                            unsigned ip, unsigned cs, unsigned flags,
  134.                            char *s1, int i)
  135. {
  136.   input(s1,i);
  137. }
  138.  
  139.  
  140. void far interrupt inputli(unsigned bp, unsigned di, unsigned si,
  141.                            unsigned ds, unsigned es, unsigned dx,
  142.                            unsigned cx, unsigned bx, unsigned ax,
  143.                            unsigned ip, unsigned cs, unsigned flags,
  144.                            char *s1, int i)
  145. {
  146.   inputl(s1,i);
  147. }
  148.  
  149.  
  150. void far interrupt yni(unsigned bp, unsigned di, unsigned si,
  151.                            unsigned ds, unsigned es, unsigned dx,
  152.                            unsigned cx, unsigned bx, unsigned ax,
  153.                            unsigned ip, unsigned cs, unsigned flags)
  154. {
  155.   ax=yn();
  156. }
  157.  
  158.  
  159.  
  160. void far interrupt nyi(unsigned bp, unsigned di, unsigned si,
  161.                            unsigned ds, unsigned es, unsigned dx,
  162.                            unsigned cx, unsigned bx, unsigned ax,
  163.                            unsigned ip, unsigned cs, unsigned flags)
  164. {
  165.   ax=ny();
  166. }
  167.  
  168.  
  169. void far interrupt ansici(unsigned bp, unsigned di, unsigned si,
  170.                            unsigned ds, unsigned es, unsigned dx,
  171.                            unsigned cx, unsigned bx, unsigned ax,
  172.                            unsigned ip, unsigned cs, unsigned flags,
  173.                            int i1)
  174. {
  175.   ansic(i1);
  176. }
  177.  
  178.  
  179. void far interrupt oneki(unsigned bp, unsigned di, unsigned si,
  180.                            unsigned ds, unsigned es, unsigned dx,
  181.                            unsigned cx, unsigned bx, unsigned ax,
  182.                            unsigned ip, unsigned cs, unsigned flags,
  183.                            char *s1)
  184. {
  185.   ax=(unsigned) onek(s1);
  186. }
  187.  
  188.  
  189. void far interrupt prti(unsigned bp, unsigned di, unsigned si,
  190.                            unsigned ds, unsigned es, unsigned dx,
  191.                            unsigned cx, unsigned bx, unsigned ax,
  192.                            unsigned ip, unsigned cs, unsigned flags,
  193.                            int i1, char *s1)
  194. {
  195.   prt(i1,s1);
  196. }
  197.  
  198.  
  199.  
  200. void far interrupt mpli(unsigned bp, unsigned di, unsigned si,
  201.                            unsigned ds, unsigned es, unsigned dx,
  202.                            unsigned cx, unsigned bx, unsigned ax,
  203.                            unsigned ip, unsigned cs, unsigned flags,
  204.                            int i1)
  205. {
  206.   mpl(i1);
  207. }
  208.  
  209.  
  210. #pragma warn +par
  211. #endif
  212.  
  213. /* end of functions for external programs to call */
  214.  
  215.  
  216. void reset_act_sl(void)
  217. {
  218.   actsl = thisuser.sl;
  219. }
  220.  
  221. void show_files(char *fn, char *dir)
  222. /* Displays list of files matching filespec fn in directory dir. */
  223. {
  224.   int f1,i;
  225.   char s[120],s1[120],c;
  226.   struct ffblk ff;
  227.   unsigned char drive[MAXDRIVE], direc[MAXDIR], file[MAXFILE], ext[MAXEXT];
  228.  
  229.   c=(okansi())?205:'=';
  230.   nl();
  231.  
  232.   fnsplit(dir,drive,direc,file,ext);
  233.   sprintf(s,"%s%s",get_string(971),strupr(stripfn(fn)));
  234.   strcat(s,get_string(975));
  235.   strcat(s,drive); strcat(s,direc);
  236.   strcat(s,get_string(976));
  237.   i=(thisuser.screenchars-1)/2 - strlen(stripcolors(s))/2;
  238.   npr("7%s",charstr(i,c));
  239.   outstr(s);
  240.   i=thisuser.screenchars-1-i-strlen(stripcolors(s));
  241.   npr("7%s",charstr(i,c));
  242.  
  243.   sprintf(s1,"%s%s",dir,strupr(stripfn(fn)));
  244.   f1=findfirst(s1,&ff,0);
  245.   while (f1==0) {
  246.     strcpy(s,ff.ff_name);
  247.     align(s);
  248.     sprintf(s1,"7[2%s7]1 ",s);
  249.     if (WhereX()>(thisuser.screenchars-15))
  250.       nl();
  251.     outstr(s1);
  252.     f1=findnext(&ff);
  253.   }
  254.  
  255.   nl();
  256.   ansic(7);
  257.   pl(charstr(thisuser.screenchars-1,c));
  258.   nl();
  259. }
  260.  
  261. void remove_from_temp(char *fn, char *dir, int po)
  262. {
  263.   int f1,ok;
  264.   char s[81],s1[81];
  265.   struct ffblk ff;
  266.  
  267.   sprintf(s1,"%s%s",dir,stripfn(fn));
  268.   f1=findfirst(s1,&ff,0);
  269.   ok=1;
  270.   nl();
  271.   while ((f1==0) && (ok)) {
  272.     sprintf(s,"%s%s",dir,ff.ff_name);
  273.     if (po) {
  274.       outstr(get_string(919));
  275.       pl(ff.ff_name);
  276.     }
  277.     _chmod(s,1,0);
  278.     unlink(s);
  279.     f1=findnext(&ff);
  280.   }
  281. }
  282.  
  283. void check_event(void)
  284. {
  285.   double tl;
  286.  
  287.   if ((syscfg.executetime) && (instance==1)) {
  288.     tl=time_event-timer();
  289.     if (tl<0.0)
  290.       tl += 24.0*3600.0;
  291.     if ((tl-last_time)>30.0)
  292.       do_event=1;
  293.     last_time=tl;
  294.   }
  295. }
  296.  
  297.  
  298. void run_event(void)
  299. {
  300.   if ((do_event) && (syscfg.executetime)) {
  301.     do_event=0;
  302.     nl();
  303.     pl(get_string(920));
  304.     nl();
  305.     if (syscfg.executestr[0]) {
  306.       if (instance==1) {
  307.         holdphone(1);
  308.         extern_prog(syscfg.executestr, sysinfo.spawn_opts[0]);
  309.         holdphone(0);
  310.       }
  311.       read_status();
  312.     } else
  313.       end_bbs(oklevel);
  314.   }
  315.   clrscrb();
  316. }
  317.  
  318.  
  319. double freek(int dr)
  320. {
  321.   float d;
  322.   struct dfree df;
  323.  
  324.   getdfree(dr,&df);
  325.   d=(float) df.df_avail;
  326.   d*=((float) df.df_bsec);
  327.   d*=((float) df.df_sclus);
  328.   d/=1024.0;
  329.   if (df.df_sclus==0xffff)
  330.     d=-1.0;
  331.   return(d);
  332. }
  333.  
  334. /* This should not be a problem 'till 2005 or so.                          */
  335.  
  336. unsigned char years_old(unsigned char m, unsigned char d, unsigned char y)
  337. {
  338.   struct date today;
  339.   int a;
  340.  
  341.   getdate(&today);
  342.  
  343.   if (today.da_year-1900<y)
  344.     return(0);
  345.   if (today.da_year-1900==y) {
  346.     if (today.da_mon<m)
  347.       return(0);
  348.     if (today.da_mon==m) {
  349.       if (today.da_day<d)
  350.         return(0);
  351.     }
  352.   }
  353.  
  354.   a=(int) (today.da_year-1900-y);
  355.   if (today.da_mon<m)
  356.     --a;
  357.   else
  358.     if ((today.da_mon==m) && (today.da_day<d))
  359.       --a;
  360.   return((unsigned char)a);
  361. }
  362.  
  363.  
  364.  
  365. void itimer(void)
  366. /* This function initializes the high-resolution timer */
  367. {
  368. #ifndef __OS2__
  369.   outportb(0x43,0x34);
  370.   outportb(0x40,0x00);
  371.   outportb(0x40,0x00);
  372. #endif
  373.  
  374. }
  375.  
  376. double timer(void)
  377. /* This function returns the time, in seconds since midnight. */
  378. {
  379.   double cputim;
  380. #ifdef __OS2__
  381. #define SECSINMINUTE 60
  382. #define SECSINHOUR (60 * SECSINMINUTE)
  383.  
  384.   DATETIME dt;
  385.   long l;
  386.  
  387.   DosGetDateTime(&dt);
  388.   l = (dt.hours * SECSINHOUR) + (dt.minutes * SECSINMINUTE) + dt.seconds;
  389.   cputim = (double)l + (((double) dt.hundredths) / 100);
  390. #else
  391.   unsigned short int h,m,l1,l2;
  392.  
  393.   disable();
  394.   outportb(0x43,0x00);
  395.   m=peek(0x0040,0x006c);
  396.   h=peek(0x0040,0x006e);
  397.   l1=inportb(0x40);
  398.   l2=inportb(0x40);
  399.   enable();
  400.   l1=((l2*256)+l1) ^ 65535;
  401.   cputim=((h*65536. + m)*65536. + l1)*8.380955e-7;
  402. #endif
  403.   return (cputim);
  404. }
  405.  
  406.  
  407. long timer1(void)
  408. /* This function returns the time, in ticks since midnight. */
  409. {
  410. #ifdef __OS2__
  411.   #define TICKS_PER_SECOND 18.2
  412.  
  413.   return (long) (timer() * TICKS_PER_SECOND);
  414. #else
  415.   unsigned short h,m;
  416.   long l;
  417.  
  418.   m=peek(0x0040,0x006c);
  419.   h=peek(0x0040,0x006e);
  420.   l=((long)h)*65536 + ((long)m);
  421.   return(l);
  422. #endif
  423. }
  424.  
  425.  
  426. int sysop1(void)
  427. /* This function returns the status of scoll lock.  If scroll lock is active
  428.  * (ie, the user has hit scroll lock + the light is lit if there is a
  429.  * scoll lock LED), the sysop is assumed to be available.
  430.  */
  431. {
  432. #ifdef __OS2__
  433.   KBDINFO ki;
  434.  
  435.   KbdGetStatus(&ki, 0);
  436.   return (ki.fsState & KBDSTF_SCROLLLOCK_ON);
  437. #else
  438.   if ((peekb(0,1047) & 0x10)==0)
  439.     return(0);
  440.   else
  441.     return(1);
  442. #endif
  443. }
  444.  
  445.  
  446.  
  447. int okansi(void)
  448. /* This function checks the status of the current user's record to see if
  449.  * the user has specified that he wants ANSI graphics displayed.
  450.  */
  451. {
  452.   if (x_only)
  453.     return(0);
  454.   if (thisuser.sysstatus & sysstatus_ansi)
  455.     return(1);
  456.  
  457.   return(0);
  458. }
  459.  
  460. void tmp_disable_conf(int disable)
  461. {
  462.   static int ocs, oss, ocd, osd, cnt;
  463.  
  464.   if (disable && (disable!=-1)) {
  465.     cnt++;
  466.     if (okconf(&thisuser)) {
  467.       g_flags |= g_flag_disable_conf;
  468.       ocs=curconfsub;
  469.       oss=usub[cursub].subnum;
  470.       ocd=curconfdir;
  471.       osd=udir[curdir].subnum;
  472.       setuconf(CONF_SUBS, -1, oss);
  473.       setuconf(CONF_DIRS, -1, osd);
  474.     }
  475.   } else {
  476.     if (cnt) {
  477.       cnt--;
  478.       if (disable==-1)
  479.         cnt=0;
  480.       if (cnt==0) {
  481.         if (g_flags & g_flag_disable_conf) {
  482.           g_flags &= ~g_flag_disable_conf;
  483.           setuconf(CONF_SUBS, ocs, oss);
  484.           setuconf(CONF_DIRS, ocd, osd);
  485.         }
  486.       }
  487.     }
  488.   }
  489. }
  490.  
  491. void tmp_disable_pause(int disable)
  492. {
  493.   if (disable) {
  494.     if (thisuser.sysstatus & sysstatus_pause_on_page) {
  495.       g_flags |= g_flag_disable_pause;
  496.       thisuser.sysstatus &= ~sysstatus_pause_on_page;
  497.     }
  498.   } else {
  499.     if (g_flags & g_flag_disable_pause) {
  500.       g_flags &= ~g_flag_disable_pause;
  501.       thisuser.sysstatus |= sysstatus_pause_on_page;
  502.     }
  503.   }
  504. }
  505.  
  506. int okconf(userrec *u)
  507. /* Checks status of given userrec to see if conferencing is turned on.
  508.  */
  509. {
  510.   if (g_flags & g_flag_disable_conf)
  511.     return(0);
  512.  
  513.   if (u->sysstatus & sysstatus_conference)
  514.     return(1);
  515.   else
  516.     return(0);
  517. }
  518.  
  519. void frequent_init(void)
  520. /* This should be called after a user is logged off, and will initialize
  521.  * screen-access variables.
  522.  */
  523. {
  524.   setiia(90);
  525.   g_flags=0;
  526.   in_fsed=0;
  527.   tagging=0;
  528.   curlsub=-1;
  529.   curldir=-1;
  530.   curconfsub=0;
  531.   curconfdir=0;
  532.   ansiptr=0;
  533.   curatr=0x07;
  534.   outcom=0;
  535.   incom=0;
  536.   charbufferpointer=0;
  537.   andwith=0xff;
  538.   checkit=0;
  539.   topline=0;
  540.   screenlinest=defscreenbottom+1;
  541.   if (!restoring_shrink)
  542.     clrscrb();
  543.   endofline[0]=0;
  544.   hangup=0;
  545.   hungup=0;
  546.   chatcall=0;
  547.   chatreason[0]=0;
  548.   useron=0;
  549.   change_color=0;
  550.   chatting=0;
  551.   echo=1;
  552.   irt[0]=0;
  553.   irt_name[0]=0;
  554.   okskey=0;
  555.   lines_listed=0;
  556.   read_user(1,&thisuser);
  557.   read_qscn(1,qsc,0);
  558.   if (thisuser.inact & inact_deleted)
  559.     fwaiting=0;
  560.   else
  561.     fwaiting=thisuser.waiting;
  562.   okmacro=1;
  563.   okskey=1;
  564.   helpl=0;
  565.   ihelp=0;
  566.   mailcheck=0;
  567.   smwcheck=0;
  568.   in_extern=0;
  569.   gatfn[0]=0;
  570.   use_workspace=0;
  571.   extratimecall=0.0;
  572.   two_color=0;
  573.   using_modem=0;
  574.   set_global_handle(0);
  575.   live_user=1;
  576.   _chmod(dszlog,1,0);
  577.   unlink(dszlog);
  578.   ltime=0;
  579.   set_x_only(0, NULL, 0);
  580.   set_net_num(0);
  581.   set_language(thisuser.language);
  582.   tmp_disable_conf(-1);
  583. }
  584.  
  585.  
  586. void fix_user_rec(userrec *u)
  587. {
  588.   u->name[sizeof(u->name)-1]=0;
  589.   u->realname[sizeof(u->realname)-1]=0;
  590.   u->callsign[sizeof(u->callsign)-1]=0;
  591.   u->phone[sizeof(u->phone)-1]=0;
  592.   u->pw[sizeof(u->pw)-1]=0;
  593.   u->laston[sizeof(u->laston)-1]=0;
  594.   u->note[sizeof(u->note)-1]=0;
  595.   u->macros[0][sizeof(u->macros[0])-1]=0;
  596.   u->macros[1][sizeof(u->macros[1])-1]=0;
  597.   u->macros[2][sizeof(u->macros[2])-1]=0;
  598. }
  599.  
  600.  
  601. int number_userrecs(void)
  602. {
  603.   char s[81];
  604.   int f,i;
  605.  
  606.   sprintf(s,"%sUSER.LST",syscfg.datadir);
  607.   f=sh_open1(s,O_RDONLY | O_BINARY);
  608.   if (f>0) {
  609.     i=((int) (filelength(f)/syscfg.userreclen)-1);
  610.     f=sh_close(f);
  611.   } else
  612.     i=0;
  613.   return(i);
  614. }
  615.  
  616.  
  617. void read_user(unsigned int un, userrec *u)
  618. {
  619.   char s[81];
  620.   long pos;
  621.   int f, nu;
  622.  
  623.   if (((useron) && (un==usernum)) || ((wfc) && (un==1))) {
  624.     *u=thisuser;
  625.     fix_user_rec(u);
  626.     return;
  627.   }
  628.  
  629.   sprintf(s,"%sUSER.LST",syscfg.datadir);
  630.  
  631.   f=sh_open1(s,O_RDONLY | O_BINARY);
  632.   if (f<0) {
  633.     u->inact=inact_deleted;
  634.     fix_user_rec(u);
  635.     return;
  636.   }
  637.  
  638.   nu=((int) (filelength(f)/syscfg.userreclen)-1);
  639.  
  640.   if (un>nu) {
  641.     sh_close(f);
  642.     u->inact=inact_deleted;
  643.     fix_user_rec(u);
  644.     return;
  645.   }
  646.   pos=((long) syscfg.userreclen) * ((long) un);
  647.   sh_lseek(f,pos,SEEK_SET);
  648.   sh_read(f, (void *)u, syscfg.userreclen);
  649.   sh_close(f);
  650.   fix_user_rec(u);
  651. }
  652.  
  653.  
  654. void write_user(unsigned int un, userrec *u)
  655. {
  656.   char s[81];
  657.   long pos;
  658.   int f;
  659.  
  660.   if ((un<1) || (un>syscfg.maxusers))
  661.     return;
  662.  
  663.   if (((useron) && (un==usernum)) || ((wfc) && (un==1))) {
  664.     if (u != &thisuser)
  665.       thisuser=*u;
  666.   }
  667.  
  668.   sprintf(s,"%sUSER.LST",syscfg.datadir);
  669.   f=sh_open(s,O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  670.   if (f>=0) {
  671.     pos=((long) syscfg.userreclen) * ((long) un);
  672.     sh_lseek(f,pos,SEEK_SET);
  673.     sh_write(f, (void *)u, syscfg.userreclen);
  674.     sh_close(f);
  675.   }
  676. }
  677.  
  678. /****************************************************************************/
  679.  
  680. int qscn_file=-1;
  681.  
  682. int open_qscn(void)
  683. {
  684.   char s[81];
  685.  
  686.   if (qscn_file==-1) {
  687.     sprintf(s,"%sUSER.QSC",syscfg.datadir);
  688.     qscn_file=sh_open(s,O_RDWR|O_BINARY|O_CREAT, S_IREAD|S_IWRITE);
  689.     if (qscn_file<0) {
  690.       qscn_file=-1;
  691.       return(0);
  692.     }
  693.   }
  694.   return(1);
  695. }
  696.  
  697. void close_qscn(void)
  698. {
  699.   if (qscn_file!=-1) {
  700.     sh_close(qscn_file);
  701.     qscn_file=-1;
  702.   }
  703. }
  704.  
  705. void read_qscn(unsigned int un, unsigned long *qscn, int stayopen)
  706. {
  707.   long pos;
  708.   int i;
  709.  
  710.   if (((useron) && (un==usernum)) || ((wfc) && (un==1))) {
  711.     if (qscn != qsc) {
  712.       for (i=(syscfg.qscn_len/4)-1; i>=0; i--)
  713.         qscn[i]=qsc[i];
  714.     }
  715.     return;
  716.   }
  717.  
  718.   if (open_qscn()) {
  719.     pos=((long)syscfg.qscn_len)*((long)un);
  720.     if (pos + (long)syscfg.qscn_len <= filelength(qscn_file)) {
  721.       sh_lseek(qscn_file,pos,SEEK_SET);
  722.       sh_read(qscn_file,qscn,syscfg.qscn_len);
  723.       if (!stayopen)
  724.         close_qscn();
  725.       return;
  726.     }
  727.   }
  728.  
  729.   if (!stayopen)
  730.     close_qscn();
  731.  
  732.   memset(qsc, 0, syscfg.qscn_len);
  733.   *qsc=999;
  734.   memset(qsc+1,0xff,((syscfg.max_dirs+31)/32)*4);
  735.   memset(qsc+1+(syscfg.max_dirs+31)/32,0xff,((syscfg.max_subs+31)/32)*4);
  736. }
  737.  
  738. void write_qscn(unsigned int un, unsigned long *qscn, int stayopen)
  739. {
  740.   long pos;
  741.   int i;
  742.  
  743.   if ((un<1) || (un>syscfg.maxusers))
  744.     return;
  745.  
  746.   if (((useron) && (un==usernum)) || ((wfc) && (un==1))) {
  747.     if (qsc != qscn) {
  748.       for (i=(syscfg.qscn_len/4)-1; i>=0; i--)
  749.         qsc[i]=qscn[i];
  750.     }
  751.   }
  752.  
  753.   if (open_qscn()) {
  754.     pos=((long)syscfg.qscn_len)*((long)un);
  755.     sh_lseek(qscn_file,pos,SEEK_SET);
  756.     sh_write(qscn_file,qscn,syscfg.qscn_len);
  757.     if (!stayopen)
  758.       close_qscn();
  759.   }
  760. }
  761.  
  762. /****************************************************************************/
  763.  
  764.  
  765. double ratio(void)
  766. {
  767.   double r;
  768.  
  769.   if (thisuser.dk==0)
  770.     return(99.999);
  771.   r=((float) thisuser.uk) / ((float) thisuser.dk);
  772.   if (r>99.998)
  773.     r=99.998;
  774.   return(r);
  775. }
  776.  
  777.  
  778. double post_ratio(void)
  779. {
  780.   double r;
  781.  
  782.   if (thisuser.logons==0)
  783.     return(99.999);
  784.   r=((float) thisuser.msgpost) / ((float) thisuser.logons);
  785.   if (r>99.998)
  786.     r=99.998;
  787.   return(r);
  788. }
  789.  
  790.  
  791. unsigned char *nam(userrec *u1, unsigned int un)
  792. {
  793.   unsigned char *ss;
  794.   static unsigned char o[81];
  795.   int f,p;
  796.   userrec u;
  797.  
  798.   u=*u1;
  799.   f=1;
  800.   for (p=0; p<strlen(u.name); p++) {
  801.     if (f) {
  802.       ss=strchr(translate_letters[1],u.name[p]);
  803.       if (ss)
  804.         f=0;
  805.       o[p]=u.name[p];
  806.     } else {
  807.       ss=strchr(translate_letters[1],u.name[p]);
  808.       if (ss)
  809.         o[p]=locase(u.name[p]);
  810.       else {
  811.         if (((u.name[p]>=' ') && (u.name[p]<='/')) && (u.name[p]!=39))
  812.           f=1;
  813.         o[p]=u.name[p];
  814.       }
  815.     }
  816.   }
  817.   o[p++]=32;
  818.   o[p++]='#';
  819.   itoa(un,&o[p],10);
  820.   return(o);
  821. }
  822.  
  823.  
  824. unsigned char *nam1(userrec *u1, unsigned int un, unsigned int sy)
  825. {
  826.   unsigned static char o[81];
  827.   char s[10];
  828.  
  829.   strcpy(o,nam(u1,un));
  830.   if (sy) {
  831.     sprintf(s," @%u",sy);
  832.     strcat(o,s);
  833.   }
  834.   return(o);
  835. }
  836.  
  837. double nsl(void)
  838. {
  839.   double tlt,tlc,tot,tpl,tpd,dd,rtn;
  840.   slrec xx;
  841.  
  842.   dd=timer();
  843.   if (useron) {
  844.     if (timeon>(dd+60.0))
  845.       timeon -= 24.0*3600.0;
  846.     tot=(dd-timeon);
  847.     xx=syscfg.sl[actsl];
  848.     tpl=((double) xx.time_per_logon) * 60.0;
  849.     tpd=((double) xx.time_per_day) * 60.0;
  850.     tlc = tpl - tot + (thisuser.extratime) + extratimecall;
  851.     tlt = tpd - tot - ((double) thisuser.timeontoday) + (thisuser.extratime);
  852.  
  853.     tlt=(((tlc)<(tlt)) ? (tlc) : (tlt));
  854.     if (tlt<0.0)
  855.       tlt=0.0;
  856.     if (tlt>32767.0)
  857.       tlt=32767.0;
  858.     rtn=tlt;
  859.   } else {
  860.     rtn=1.00;
  861.   }
  862.   ltime=0;
  863.   if (syscfg.executetime) {
  864.     tlt=time_event-dd;
  865.     if (tlt<0.0)
  866.       tlt += 24.0*3600.0;
  867.     if (rtn>tlt) {
  868.       rtn=tlt;
  869.       ltime=1;
  870.     }
  871.     check_event();
  872.     if (do_event)
  873.       rtn=0.0;
  874.   }
  875.   if (rtn<0.0)
  876.     rtn=0.0;
  877.   if (rtn>32767.0)
  878.     rtn=32767.0;
  879.   return(rtn);
  880. }
  881.  
  882.  
  883. char *date(void)
  884. {
  885.   static char ds[9];
  886.   struct date today;
  887.  
  888.   getdate(&today);
  889.   sprintf(ds,"%02d/%02d/%02d",today.da_mon,today.da_day,today.da_year%100);
  890.   return(ds);
  891. }
  892.  
  893. char *times(void)
  894. {
  895.   static char ti[9];
  896.   int h,m,s;
  897.   double t;
  898.  
  899.   t=timer();
  900.   h=(int) (t/3600.0);
  901.   t-=((double) (h)) * 3600.0;
  902.   m=(int) (t/60.0);
  903.   t-=((double) (m)) * 60.0;
  904.   s=(int) (t);
  905.   sprintf(ti,"%02d:%02d:%02d",h,m,s);
  906.   return(ti);
  907. }
  908.  
  909.  
  910. unsigned int finduser(unsigned char *s)
  911. {
  912.   int un;
  913.   smalrec *sr;
  914.   userrec u;
  915.   unsigned char *ss;
  916.  
  917.   if (strcmp(s,"NEW")==0)
  918.     return(-1);
  919.   if (strcmp(s,"!-@NETWORK@-!")==0)
  920.     return(-2);
  921.   if (strcmp(s,"!-@REMOTE@-!")==0)
  922.     return(-3);
  923.   if (strncmp(s,"!=@",3)==0) {
  924.     ss=s+strlen(s)-3;
  925.     if (strcmp(ss,"@=!")==0) {
  926.       strcpy(s,s+3);
  927.       s[strlen(s)-3]=0;
  928.       return(-4);
  929.     }
  930.   }
  931.  
  932.   if ((un=atoi(s))>0) {
  933.     read_user(un,&u);
  934.     if (u.inact & inact_deleted)
  935.       return(0);
  936.     return(un);
  937.   }
  938.  
  939.   read_status();
  940.   sr=(smalrec *) bsearch((void *)s,
  941.              (void *)smallist,
  942.              (size_t)status.users,
  943.              (size_t)sizeof(smalrec),
  944.              (int _Cdecl (*) (const void *, const void *))strcmp);
  945.   if (sr==0L)
  946.     return(0);
  947.   else {
  948.     read_user(sr->number,&u);
  949.     if (u.inact & inact_deleted)
  950.       return(0);
  951.     else
  952.       return(sr -> number);
  953.   }
  954. }
  955.  
  956.  
  957. int access_conf(userrec *u, int sl, confrec *c)
  958. {
  959.   int ok=1;
  960.  
  961.   if (c->num<1)
  962.     return(0);
  963.   switch (c->sex) {
  964.     case 0: if (u->sex!='M')
  965.               return(0);
  966.             break;
  967.     case 1: if (u->sex!='F')
  968.               return(0);
  969.             break;
  970.   }
  971.   if ((sl<c->minsl) || (sl>c->maxsl))
  972.     return(0);
  973.   if ((u->dsl<c->mindsl) || (u->dsl>c->maxdsl))
  974.     return(0);
  975.   if ((u->age<c->minage) || (u->age>c->maxage))
  976.     return(0);
  977.   if (incom && (modem_speed<c->minbps))
  978.     return(0);
  979.   if ((u->ar & c->ar) != c->ar)
  980.     return(0);
  981.   if ((u->dar & c->dar) != c->dar)
  982.     return(0);
  983.   if ((c->status & conf_status_ansi) &&
  984.       (!(u->sysstatus & sysstatus_ansi)))
  985.     return(0);
  986.   if ((c->status & conf_status_wwivreg) &&
  987.       (u->wwiv_regnum<1))
  988.     return(0);
  989.   if ((c->status & conf_status_offline) &&
  990.       (sl < 100))
  991.     return(0);
  992.  
  993.   return(ok);
  994. }
  995.  
  996.  
  997. int access_sub(userrec *u, int sl, subboardrec *s)
  998. {
  999.   int ok=1;
  1000.  
  1001.   if (sl<s->readsl)
  1002.     ok=0;
  1003.   else if (u->age<(s->age&0x7f))
  1004.     ok=0;
  1005.   else if ((s->ar!=0) && (((u->ar) & (s->ar))==0))
  1006.     ok=0;
  1007.   else if ((s->anony & anony_ansi_only) && (!(u->sysstatus & sysstatus_ansi)))
  1008.     ok=0;
  1009.  
  1010.   return(ok);
  1011. }
  1012.  
  1013. int access_dir(userrec *u, int sl, directoryrec *d)
  1014. {
  1015.   int ok;
  1016.  
  1017.   ok=sl;
  1018.   ok=1;
  1019.  
  1020.   if (u->dsl<d->dsl)
  1021.     ok=0;
  1022.   else if (u->age<d->age)
  1023.     ok=0;
  1024.   else if ((d->dar) && ((d->dar & u->dar)==0))
  1025.     ok=0;
  1026.   else if ((d->mask & mask_offline) && (u->dsl < 100))
  1027.     ok=0;
  1028.  
  1029.   return(ok);
  1030. }
  1031.  
  1032. void addusub(usersubrec *ss1, int ns, int sub, char key)
  1033. {
  1034.   int last_num, last, i;
  1035.  
  1036.   last_num=0;
  1037.   for (last=0; last<ns; last++) {
  1038.     if (ss1[last].subnum==-1)
  1039.       break;
  1040.     if (ss1[last].subnum==sub)
  1041.       return;
  1042.     if (ss1[last].keys[0]==0)
  1043.       last_num=last+1;
  1044.   }
  1045.  
  1046.   if (last==ns)
  1047.     return;
  1048.  
  1049.   if (key) {
  1050.     ss1[last].subnum=sub;
  1051.     ss1[last].keys[0]=key;
  1052.   } else {
  1053.     for (i=last; i>last_num; i--)
  1054.       ss1[i]=ss1[i-1];
  1055.     ss1[last_num].subnum=sub;
  1056.     ss1[last_num].keys[0]=0;
  1057.   }
  1058. }
  1059.  
  1060. int setconf(unsigned int conftype, int which, int oldsub)
  1061. {
  1062.   int i,i1, ns, osub, dp, tp;
  1063.   confrec *c;
  1064.   usersubrec *ss1, s1;
  1065.   char *xdc, *xtc;
  1066.  
  1067.   dp=1;
  1068.   tp=0;
  1069.  
  1070.   switch(conftype) {
  1071.     case CONF_SUBS:
  1072.       ss1=usub;
  1073.       ns=num_subs;
  1074.       if (oldsub==-1)
  1075.         osub=usub[cursub].subnum;
  1076.       else
  1077.         osub=oldsub;
  1078.       xdc=dc;
  1079.       xtc=tc;
  1080.       xdc[0]='/';
  1081.       if (which==-1) {
  1082.         c=NULL;
  1083.       } else {
  1084.         if ((which<0) || (which>=subconfnum))
  1085.           return(1);
  1086.         c=&(subconfs[which]);
  1087.         if (!access_conf(&thisuser, actsl, c))
  1088.           return(1);
  1089.       }
  1090.       break;
  1091.     case CONF_DIRS:
  1092.       ss1=udir;
  1093.       ns=num_dirs;
  1094.       if (oldsub==-1)
  1095.         osub=udir[curdir].subnum;
  1096.       else
  1097.         osub=oldsub;
  1098.       xdc=dcd;
  1099.       xtc=dtc;
  1100.       xdc[0]='/';
  1101.       if (which==-1) {
  1102.         c=NULL;
  1103.       } else {
  1104.         if ((which<0) || (which>=dirconfnum))
  1105.           return(1);
  1106.         c=&(dirconfs[which]);
  1107.         if (!access_conf(&thisuser, actsl, c))
  1108.           return(1);
  1109.       }
  1110.       break;
  1111.     default:
  1112.       return(1);
  1113.   }
  1114.  
  1115.   memset(&s1, 0, sizeof(s1));
  1116.   s1.subnum=-1;
  1117.  
  1118.   for (i=0; i<ns; i++)
  1119.     ss1[i]=s1;
  1120.  
  1121.   if (c) {
  1122.     for (i=0; i<c->num; i++) {
  1123.       switch(conftype) {
  1124.         case CONF_SUBS:
  1125.           if (access_sub(&thisuser, actsl, (subboardrec *)&subboards[c->subs[i]])) {
  1126.             addusub(ss1, ns, c->subs[i], subboards[c->subs[i]].key);
  1127.           }
  1128.           break;
  1129.         case CONF_DIRS:
  1130.           if (access_dir(&thisuser, actsl, (directoryrec *)&directories[c->subs[i]])) {
  1131.             addusub(ss1, ns, c->subs[i], 0);
  1132.           }
  1133.           break;
  1134.       }
  1135.     }
  1136.   } else {
  1137.     switch(conftype) {
  1138.       case CONF_SUBS:
  1139.         for (i=0; i<subconfnum; i++) {
  1140.           if (access_conf(&thisuser, actsl, &(subconfs[i]))) {
  1141.             for (i1=0; i1<subconfs[i].num; i1++) {
  1142.               if (access_sub(&thisuser, actsl,
  1143.                              (subboardrec *)&subboards[subconfs[i].subs[i1]])) {
  1144.                 addusub(ss1, ns, subconfs[i].subs[i1],
  1145.                         subboards[subconfs[i].subs[i1]].key);
  1146.               }
  1147.             }
  1148.           }
  1149.         }
  1150.         break;
  1151.       case CONF_DIRS:
  1152.         for (i=0; i<dirconfnum; i++) {
  1153.           if (access_conf(&thisuser, actsl, &(dirconfs[i]))) {
  1154.             for (i1=0; i1<dirconfs[i].num; i1++) {
  1155.               if (access_dir(&thisuser, actsl,
  1156.                              (directoryrec *)&directories[dirconfs[i].subs[i1]])) {
  1157.                 addusub(ss1, ns, dirconfs[i].subs[i1], 0);
  1158.               }
  1159.             }
  1160.           }
  1161.         }
  1162.         break;
  1163.     }
  1164.   }
  1165.  
  1166.   if ((conftype==CONF_DIRS) && (ss1[0].subnum==0))
  1167.     i1=0;
  1168.   else
  1169.     i1=1;
  1170.  
  1171.   for (i=0; (i<ns) && (ss1[i].keys[0]==0) && (ss1[i].subnum!=-1); i++) {
  1172.     if (i1<100) {
  1173.       if (((i1 % 10)==0) && i1)
  1174.         xdc[dp++]=('0'+(i1/10));
  1175.     } else {
  1176.       if ((i1 % 100)==0)
  1177.         xtc[tp++]=('0'+(i1/100));
  1178.     }
  1179.     itoa(i1++,ss1[i].keys,10);
  1180.   }
  1181.  
  1182.  
  1183.   xdc[dp]=0;
  1184.   xtc[tp]=0;
  1185.  
  1186.   for (i1=0; (i1<ns) && (ss1[i1].subnum!=-1); i1++) {
  1187.     if (ss1[i1].subnum==osub)
  1188.       break;
  1189.   }
  1190.   if ((i1>=ns) || (ss1[i1].subnum==-1))
  1191.     i1=0;
  1192.  
  1193.   switch(conftype) {
  1194.     case CONF_SUBS: cursub=i1; break;
  1195.     case CONF_DIRS: curdir=i1; break;
  1196.   }
  1197.  
  1198.   return(0);
  1199. }
  1200.  
  1201. void setuconf(int conftype, int num, int oldsub)
  1202. {
  1203.   switch(conftype) {
  1204.     case CONF_SUBS:
  1205.       if ((num>=0) && (num<MAX_CONFERENCES) && (uconfsub[num].confnum!=-1)) {
  1206.         curconfsub=num;
  1207.         setconf(conftype, uconfsub[curconfsub].confnum, oldsub);
  1208.         return;
  1209.       }
  1210.       break;
  1211.     case CONF_DIRS:
  1212.       if ((num>=0) && (num<MAX_CONFERENCES) && (uconfdir[num].confnum!=-1)) {
  1213.         curconfdir=num;
  1214.         setconf(conftype, uconfdir[curconfdir].confnum, oldsub);
  1215.         return;
  1216.       }
  1217.       break;
  1218.   }
  1219.   setconf(conftype, -1, oldsub);
  1220. }
  1221.  
  1222. void changedsl(void)
  1223. {
  1224.   int i,i2;
  1225.   int ocurconfsub, ocurconfdir;
  1226.   userconfrec c1;
  1227.  
  1228.   ocurconfsub=uconfsub[curconfsub].confnum;
  1229.   ocurconfdir=uconfdir[curconfdir].confnum;
  1230.   topscreen();
  1231.  
  1232.   c1.confnum=-1;
  1233.  
  1234.   for (i=0; i<MAX_CONFERENCES; i++) {
  1235.     uconfsub[i]=c1;
  1236.     uconfdir[i]=c1;
  1237.   }
  1238.  
  1239.   i2=0;
  1240.   for (i=0; i<subconfnum; i++) {
  1241.     if (access_conf(&thisuser, actsl, &(subconfs[i]))) {
  1242.       c1.confnum=i;
  1243.       uconfsub[i2++]=c1;
  1244.     }
  1245.   }
  1246.  
  1247.   i2=0;
  1248.   for (i=0; i<dirconfnum; i++) {
  1249.     if (access_conf(&thisuser, actsl, &(dirconfs[i]))) {
  1250.       c1.confnum=i;
  1251.       uconfdir[i2++]=c1;
  1252.     }
  1253.   }
  1254.  
  1255.   for (curconfsub=0; (curconfsub<MAX_CONFERENCES) && (uconfsub[curconfsub].confnum!=-1); curconfsub++)
  1256.     if (uconfsub[curconfsub].confnum==ocurconfsub)
  1257.       break;
  1258.   if ((curconfsub>=MAX_CONFERENCES) || (uconfsub[curconfsub].confnum==-1))
  1259.     curconfsub=0;
  1260.  
  1261.   for (curconfdir=0; (curconfdir<MAX_CONFERENCES) && (uconfdir[curconfdir].confnum!=-1); curconfdir++)
  1262.     if (uconfdir[curconfdir].confnum==ocurconfdir)
  1263.       break;
  1264.   if ((curconfdir>=MAX_CONFERENCES) || (uconfdir[curconfdir].confnum==-1))
  1265.     curconfdir=0;
  1266.  
  1267.   if (okconf(&thisuser)) {
  1268.     setuconf(CONF_SUBS, curconfsub, -1);
  1269.     setuconf(CONF_DIRS, curconfdir, -1);
  1270.   } else {
  1271.     setconf(CONF_SUBS, -1, -1);
  1272.     setconf(CONF_DIRS, -1, -1);
  1273.   }
  1274.  
  1275. }
  1276.  
  1277.  
  1278. void isr(int un, unsigned char *name)
  1279. {
  1280.   int cp,i;
  1281.   unsigned char s[81];
  1282.   smalrec sr;
  1283.  
  1284.   cp=0;
  1285.   lock_status();
  1286.   while ((cp<status.users) && (strcmp(name,(smallist[cp].name))>0))
  1287.     ++cp;
  1288.   for (i=status.users; i>cp; i--)
  1289.     smallist[i]=smallist[i-1];
  1290.   strcpy(sr.name,name);
  1291.   sr.number=un;
  1292.   smallist[cp]=sr;
  1293.   sprintf(s,"%sNAMES.LST",syscfg.datadir);
  1294.   i=sh_open1(s,O_RDWR | O_BINARY | O_TRUNC);
  1295.   if (i<0) {
  1296.     printf(get_stringx(1,132),s);
  1297.     end_bbs(noklevel);
  1298.   }
  1299.   ++status.users;
  1300.   ++status.filechange[filechange_names];
  1301.   huge_xfer(i, smallist, sizeof(smalrec), status.users, 1);
  1302.   sh_close(i);
  1303.   save_status();
  1304. }
  1305.  
  1306.  
  1307. void dsr(unsigned char *name)
  1308. {
  1309.   int cp,i;
  1310.   unsigned char s[81];
  1311.  
  1312.   cp=0;
  1313.   lock_status();
  1314.   while ((cp<status.users) && (strcmp(name,(smallist[cp].name))!=0))
  1315.     ++cp;
  1316.   if (strcmp(name,(smallist[cp].name))) {
  1317.     save_status();
  1318.     sprintf(s,get_stringx(1,74),name);
  1319.     sl1(0,s);
  1320.     sl1(0,get_stringx(1,75));
  1321.     return;
  1322.   }
  1323.   for (i=cp; i<status.users-1; i++)
  1324.     smallist[i]=smallist[i+1];
  1325.   sprintf(s,"%sNAMES.LST",syscfg.datadir);
  1326.   i=sh_open(s,O_RDWR | O_BINARY | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
  1327.   if (i<0) {
  1328.     printf(get_stringx(1,133),s);
  1329.     end_bbs(noklevel);
  1330.   }
  1331.   --status.users;
  1332.   ++status.filechange[filechange_names];
  1333.   huge_xfer(i, smallist, sizeof(smalrec), status.users, 1);
  1334.   sh_close(i);
  1335.   save_status();
  1336. }
  1337.  
  1338.  
  1339. void wait1(long l)
  1340. {
  1341.   long l1;
  1342.  
  1343.   l1 = timer1();
  1344.  
  1345. #ifndef __OS2__
  1346.   enable();
  1347. #endif
  1348.   while (labs(timer1()-l1)<l)
  1349.     giveup_timeslice();
  1350. }
  1351.  
  1352.  
  1353. void Wait(double d)
  1354. {
  1355.   wait1((long) (18.2*d));
  1356. }
  1357.  
  1358. double freek1(char *s)
  1359. {
  1360.   int d;
  1361.  
  1362.   d=cdir[0];
  1363.   if (s[1]==':')
  1364.     d=s[0];
  1365.   d=toupper(d)-'A'+1;
  1366.   return(freek(d));
  1367. }
  1368.  
  1369.  
  1370. int exist(char *s)
  1371. {
  1372.   int i;
  1373.   struct ffblk ff;
  1374.  
  1375.   i=findfirst(s,&ff,FA_HIDDEN);
  1376.   if (i)
  1377.     return(0);
  1378.   else
  1379.     return(1);
  1380. }
  1381.  
  1382.  
  1383. void add_ass(int i, char *ss)
  1384. {
  1385.   char s[81],s1[10];
  1386.  
  1387.   strcpy(s,"*** ");
  1388.   sysoplog(s);
  1389.   strcat(s,ss);
  1390.   sysoplog(s);
  1391.   itoa(i,s1,10);
  1392.   strcpy(s,get_stringx(1,76));
  1393.   strcat(s,s1);
  1394.   sysoplog(s);
  1395.   thisuser.ass_pts += i;
  1396. }
  1397.  
  1398.  
  1399. int find_interrupt(void)
  1400. {
  1401. #ifndef __OS2__
  1402.   long far *l;
  1403.   int i;
  1404.  
  1405.   for (i=0x60; i<0xf0; i++) {
  1406.     if ((i<0x70) || (i>0x77)) {
  1407.       l=MK_FP(0,(i*4));
  1408.       if (*l==0)
  1409.         return i;
  1410.     }
  1411.   }
  1412. #endif
  1413.   return(0);
  1414. }
  1415.  
  1416.  
  1417.  
  1418. /****************************************************************************/
  1419.  
  1420. void send_net(net_header_rec *nh, unsigned int *list, char *text, char *byname)
  1421. {
  1422.   int f;
  1423.   char s[100];
  1424.   long l1;
  1425.  
  1426.   sprintf(s,"%sP1%s",net_data,nete);
  1427.   f=sh_open(s,O_RDWR | O_BINARY | O_CREAT, S_IREAD | S_IWRITE);
  1428.   sh_lseek(f,0L,SEEK_END);
  1429.   if (!list)
  1430.     nh->list_len=0;
  1431.   if (!text)
  1432.     nh->length=0;
  1433.   if (nh->list_len)
  1434.     nh->tosys=0;
  1435.   l1=nh->length;
  1436.   if (byname && *byname)
  1437.     nh->length += strlen(byname)+1;
  1438.   sh_write(f,(void *)nh,sizeof(net_header_rec));
  1439.   if (nh->list_len)
  1440.     sh_write(f,(void *)list,2*(nh->list_len));
  1441.   if (byname && *byname)
  1442.     sh_write(f,byname, strlen(byname)+1);
  1443.   if (nh->length)
  1444.     sh_write(f,(void *)text,l1);
  1445.   sh_close(f);
  1446. }
  1447.  
  1448. /****************************************************************************/
  1449.  
  1450. unsigned char dow(void)
  1451. /* returns day of week, 0=Sun, 6=Sat */
  1452. {
  1453. #ifdef __OS2__
  1454.   DATETIME dt;
  1455.  
  1456.   DosGetDateTime(&dt);
  1457.   return dt.weekday;
  1458. #else
  1459.   unsigned char ch;
  1460.  
  1461.   _AH=0x2a;
  1462.   geninterrupt(0x21);
  1463.   ch=_AL;
  1464.  
  1465.   return(ch);
  1466. #endif
  1467. }
  1468.  
  1469. /****************************************************************************/
  1470.  
  1471. #define MT_DESQVIEW 0x01
  1472. #define MT_WINDOWS  0x02
  1473. #define MT_OS2      0x04
  1474.  
  1475.  
  1476. void detect_multitask(void)
  1477. {
  1478. #ifdef __OS2__
  1479.   multitasker |= MT_OS2;
  1480. #else
  1481.   get_dos_version();
  1482.   get_win_version();
  1483.   get_dv_version();
  1484. #endif
  1485. }
  1486.  
  1487.  
  1488. int get_dos_version(void)
  1489. {
  1490. #ifdef __OS2__
  1491.   return(0);
  1492. #else
  1493.   _AX=0x3000;
  1494.   geninterrupt(0x21);
  1495.   if(_AX%256 >=10) {
  1496.     multitasker |= MT_OS2;
  1497.   }
  1498.   return(_AX);
  1499. #endif
  1500. }
  1501.  
  1502.  
  1503. int get_dv_version(void)
  1504. {
  1505. #ifdef __OS2__
  1506.   return 0;
  1507. #else
  1508.   int v;
  1509.  
  1510.   _AX=0x2b01;
  1511.   _CX=0x4445;
  1512.   _DX=0x5351;
  1513.   geninterrupt(0x21);
  1514.   if (_AL == 0xff) {
  1515.     return 0;
  1516.   } else {
  1517.     v=_BX;
  1518.     multitasker |= MT_DESQVIEW;
  1519.     return v;
  1520.   }
  1521. #endif
  1522. }
  1523.  
  1524.  
  1525. int get_win_version(void)
  1526. {
  1527. #ifdef __OS2__
  1528.   return 0;
  1529. #else
  1530.   int v=0;
  1531.  
  1532. /*
  1533.  *  push  bp
  1534.  *  push  es
  1535.  *  push  bx
  1536.  */
  1537.   __emit__(0x55, 0x06, 0x53);
  1538.  
  1539.   _AX=0x352f;
  1540.   geninterrupt(0x21);
  1541.   _AX=_ES;
  1542.  
  1543.   if (_AX | _BX) {
  1544.  
  1545.     _AX=0x1600;
  1546.     geninterrupt(0x2f);
  1547.  
  1548.     v=_AX;
  1549.     if (v%256<=1)
  1550.       v=0;
  1551.   }
  1552.  
  1553. /*
  1554.  * pop bx
  1555.  * pop es
  1556.  * pop bp
  1557.  */
  1558.   __emit__(0x5b, 0x07, 0x5d);
  1559.  
  1560.   if (v!=0)
  1561.     multitasker |= MT_WINDOWS;
  1562.   return(v);
  1563. #endif
  1564. }
  1565.  
  1566. void begin_crit(void)
  1567. {
  1568. #ifndef __OS2__
  1569.   if (multitasker & MT_DESQVIEW) {
  1570.     _AX=0x101a;
  1571.     geninterrupt(0x15);
  1572.     _AX=0x101b;
  1573.     geninterrupt(0x15);
  1574.     _AX=0x1025;
  1575.     geninterrupt(0x15);
  1576.   }
  1577. #endif
  1578. }
  1579.  
  1580.  
  1581. void end_crit(void)
  1582. {
  1583. #ifndef __OS2__
  1584.   if (multitasker & MT_DESQVIEW) {
  1585.     _AX=0x101a;
  1586.     geninterrupt(0x15);
  1587.     _AX=0x101c;
  1588.     geninterrupt(0x15);
  1589.     _AX=0x1025;
  1590.     geninterrupt(0x15);
  1591.   }
  1592. #endif
  1593. }
  1594.  
  1595.  
  1596. void giveup_timeslice(void)
  1597. {
  1598. #ifdef __OS2__
  1599.   DosSleep(0);
  1600. #else
  1601.   if (multitasker) {
  1602.     switch (multitasker) {
  1603.       case 1 :/* outs("DESQView pause"); */
  1604.         dv_pause();
  1605.       break;
  1606.       case 2 :/* outs("Windows pause"); */
  1607.         win_pause();
  1608.       break;
  1609.       case 3 :/* outs("Win or DV pause"); */
  1610.       /* dv_pause();
  1611.          win_pause(); */
  1612.       /* Enable one of the above.  I believe the logical choice
  1613.          would be the pause for the multitasker loaded last.
  1614.          At this point neither is enabled when both Windows and
  1615.          DESQView are found.  I believe that pausing both would
  1616.          be a bad idea.  Let me know if you run using both
  1617.          multitaskers. */
  1618.       break;
  1619.       case 4:  /* outs("OS/2"); */
  1620.         _AX=0x1680;
  1621.         geninterrupt(0x2f);
  1622.         break;
  1623.       case 5:
  1624.       case 6:
  1625.       case 7:
  1626.         /* delay(17); */
  1627.         win_pause();
  1628.       break;
  1629.      default: /* pl("Unrecognized multitasker"); */
  1630.        break;
  1631.     }
  1632.   } else {
  1633.     /* delay(17); */
  1634.   }
  1635. #endif
  1636.   if (inst_msg_waiting())
  1637.     process_inst_msgs();
  1638. }
  1639.  
  1640.  
  1641. void dv_pause(void)
  1642. {
  1643. #ifndef __OS2__
  1644.   _AX=0x101a;
  1645.   geninterrupt(0x15);
  1646.   _AX=0x1000;
  1647.   geninterrupt(0x15);
  1648.   _AX=0x1025;
  1649.   geninterrupt(0x15);
  1650. #endif
  1651. }
  1652.  
  1653.  
  1654. void win_pause(void)
  1655. {
  1656. #ifndef __OS2__
  1657.   __emit__(0x55, 0xb8, 0x80, 0x16, 0xcd, 0x2f, 0x5d);
  1658. /*
  1659.  * push bp
  1660.  * mov ax,0x1680
  1661.  * int 0x2f
  1662.  * pop bp
  1663.  */
  1664. #endif
  1665. }
  1666.  
  1667.  
  1668. /****************************************************************************/
  1669.  
  1670.  
  1671. static int statusfile=-1;
  1672.  
  1673. void get_status(int mode, int lock)
  1674. {
  1675.   char s[81];
  1676.   char fc[7];
  1677.   int i,i1,f, onn;
  1678.   long l;
  1679.  
  1680.   if (statusfile<0) {
  1681.     sprintf(s,"%sSTATUS.DAT",syscfg.datadir);
  1682.     if (lock)
  1683.       statusfile=sh_open1(s,O_RDWR | O_BINARY);
  1684.     else
  1685.       statusfile=sh_open1(s,O_RDONLY | O_BINARY);
  1686.   } else {
  1687.     lseek(statusfile, 0L, SEEK_SET);
  1688.   }
  1689.   if (statusfile<0) {
  1690.     if(!mode) {
  1691.       printf(get_stringx(1,132),s);
  1692.       end_bbs(noklevel);
  1693.     } else {
  1694.       sysoplog(get_stringx(1,134));
  1695.     }
  1696.   } else {
  1697.     l=status.qscanptr;
  1698.     for (i=0; i<7; i++)
  1699.       fc[i]=status.filechange[i];
  1700.  
  1701.     read(statusfile,(void *)(&status), sizeof(statusrec));
  1702.     if (!lock)
  1703.       statusfile=sh_close(statusfile);
  1704.  
  1705.     if (l != status.qscanptr) {
  1706.       if (sub_dates) {
  1707.         /* kill subs cache */
  1708.         for (i1=0; i1<num_subs; i1++) {
  1709.           sub_dates[i1]=0L;
  1710.         }
  1711.       }
  1712.       c_sub=0;
  1713.       subchg=1;
  1714.       gatfn[0]=0;
  1715.     }
  1716.     for (i=0; i<7; i++) {
  1717.       if (fc[i]!=status.filechange[i]) {
  1718.         switch(i) {
  1719.           case filechange_names: /* re-read names.lst */
  1720.             if (smallist) {
  1721.               sprintf(s,"%sNAMES.LST",syscfg.datadir);
  1722.               f=sh_open1(s,O_RDONLY | O_BINARY);
  1723.               if (f>=0) {
  1724.                 huge_xfer(f, smallist, sizeof(smalrec), status.users, 0);
  1725.                 sh_close(f);
  1726.               }
  1727.             }
  1728.             break;
  1729.           case filechange_upload: /* kill dirs cache */
  1730.             if (dir_dates) {
  1731.               for (i1=0; i1<num_dirs; i1++) {
  1732.                 dir_dates[i1]=0L;
  1733.               }
  1734.             }
  1735.             c_dir=0;
  1736.             break;
  1737.           case filechange_posts:
  1738.             subchg=1;
  1739.             gatfn[0]=0;
  1740.             break;
  1741.           case filechange_email:
  1742.             emchg=1;
  1743.             mailcheck=0;
  1744.             break;
  1745.           case filechange_net:
  1746.             onn=net_num;
  1747.             zap_bbs_list();
  1748.             for (i1=0; i1<net_num_max; i1++) {
  1749.               set_net_num(i1);
  1750.               zap_call_out_list();
  1751.               zap_contacts();
  1752.             }
  1753.             set_net_num(onn);
  1754.             break;
  1755.         }
  1756.       }
  1757.     }
  1758.   }
  1759. }
  1760.  
  1761. void lock_status(void)
  1762. {
  1763.   get_status(1, 1);
  1764. }
  1765.  
  1766. void read_status(void)
  1767. {
  1768.   get_status(1, 0);
  1769. }
  1770.  
  1771. void save_status(void)
  1772. {
  1773.   char s[81];
  1774.  
  1775.   if (statusfile<0) {
  1776.     sprintf(s,"%sSTATUS.DAT",syscfg.datadir);
  1777.     statusfile=sh_open1(s,O_RDWR | O_BINARY);
  1778.   } else {
  1779.     lseek(statusfile, 0L, SEEK_SET);
  1780.   }
  1781.  
  1782.   if (statusfile<0) {
  1783.     sysoplog(get_stringx(1,135));
  1784.   } else {
  1785.     sh_write(statusfile, (void *)(&status), sizeof(statusrec));
  1786.     statusfile=sh_close(statusfile);
  1787.   }
  1788. }
  1789.  
  1790.  
  1791. /****************************************************************************/
  1792.  
  1793. /*
  1794.  * Returns 1 if a message waiting for this instance, 0 otherwise.
  1795.  */
  1796.  
  1797. int inst_msg_waiting(void)
  1798. {
  1799.   unsigned char s[81];
  1800.   int i;
  1801.   long l;
  1802.  
  1803.   if (in_extern || in_fsed || !iia || !echo)
  1804.     return(0);
  1805.  
  1806.   l=timer1();
  1807.   if (labs(l-last_iia)<iia)
  1808.     return(0);
  1809.  
  1810.   sprintf(s,"%sMSG*.%3.3d",syscfg.datadir,instance);
  1811.   i=exist(s);
  1812.   if (!i)
  1813.     last_iia=l;
  1814.  
  1815.   return(i);
  1816. }
  1817.  
  1818. /****************************************************************************/
  1819.  
  1820. /*
  1821.  * Sets inter-instance availability on/off, for inter-instance messaging.
  1822.  */
  1823.  
  1824. void setiia(int poll_ticks)
  1825. {
  1826.   iia=poll_ticks;
  1827. }
  1828.  
  1829. /****************************************************************************/
  1830.  
  1831. /* Don't ask me WHY this needs to be significantly less than 65534, but it
  1832.  * does.  65530 didn't work correctly.  I suspect it has something to do
  1833.  * with the alignment of huge pointers within the 64k segment.
  1834.  */
  1835. #define MAX_XFER 61440 /* 60 * 1024 */
  1836.  
  1837. long huge_xfer(int fd, void huge *buf, unsigned sz, unsigned nel, int wr)
  1838. {
  1839.   long nxfr=0, len=((long)sz) * ((long)nel);
  1840.   char huge *xbuf = (char huge *)buf;
  1841.   unsigned cur,cur1;
  1842.  
  1843.   while (len>0) {
  1844.  
  1845.     if (len>MAX_XFER)
  1846.       cur=MAX_XFER;
  1847.     else
  1848.       cur=len;
  1849.  
  1850.     if (wr)
  1851.       cur1=sh_write(fd,(char *)xbuf,cur);
  1852.     else
  1853.       cur1=sh_read(fd,(char *)xbuf,cur);
  1854.  
  1855.     if (cur1!=65535) {
  1856.       len  -= cur1;
  1857.       nxfr += cur1;
  1858.       xbuf  = ((char huge *)buf) + nxfr;
  1859.       /* not xbuf += cur1 due to bug in certain version of compiler */
  1860.     }
  1861.  
  1862.     if (cur1!=cur)
  1863.       break;
  1864.   }
  1865.  
  1866.   return(nxfr);
  1867. }
  1868. /****************************************************************************/
  1869.  
  1870.  
  1871. char *stripfn(char *fn)
  1872. {
  1873.   static char ofn[15];
  1874.   int i,i1;
  1875.   char s[81];
  1876.  
  1877.   i1=-1;
  1878.   for (i=0; i<strlen(fn); i++)
  1879.     if ((fn[i]=='\\') || (fn[i]==':') || (fn[i]=='/'))
  1880.       i1=i;
  1881.   if (i1!=-1)
  1882.     strcpy(s,&(fn[i1+1]));
  1883.   else
  1884.     strcpy(s,fn);
  1885.   for (i=0; i<strlen(s); i++)
  1886.     if ((s[i]>='A') && (s[i]<='Z'))
  1887.       s[i]=s[i]-'A'+'a';
  1888.   i=0;
  1889.   while (s[i]!=0) {
  1890.     if (s[i]==32)
  1891.       strcpy(&s[i],&s[i+1]);
  1892.     else
  1893.       ++i;
  1894.   }
  1895.   strcpy(ofn,s);
  1896.   return(ofn);
  1897. }
  1898.  
  1899.  
  1900. void stripfn1(char *fn)
  1901. {
  1902.   int i,i1;
  1903.   char s[81],s1[81];
  1904.  
  1905.   i1=0;
  1906.   for (i=0; i<strlen(fn); i++)
  1907.     if ((fn[i]=='\\') || (fn[i]==':') || (fn[i]=='/'))
  1908.       i1=i;
  1909.   strcpy(s1,fn);
  1910.   if (i1) {
  1911.     strcpy(s,&(fn[i1+1]));
  1912.     s1[i1+1]=0;
  1913.   } else {
  1914.     strcpy(s,fn);
  1915.     s1[0]=0;
  1916.   }
  1917.  
  1918.   for (i=0; i<strlen(s); i++)
  1919.     if ((s[i]>='A') && (s[i]<='Z'))
  1920.       s[i]=s[i]-'A'+'a';
  1921.   i=0;
  1922.   while (s[i]!=0) {
  1923.     if (s[i]==32)
  1924.       strcpy(&s[i],&s[i+1]);
  1925.     else
  1926.       ++i;
  1927.   }
  1928.   strcat(s1,s);
  1929.   strcpy(fn,s1);
  1930. }
  1931.  
  1932.  
  1933.