home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / XTRN_OVL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-24  |  47.1 KB  |  1,454 lines

  1. #line 1 "XTRN_OVL.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include "sbbs.h"
  6.  
  7. char *hungupstr="\1n\1h%s\1n hung up on \1h%s\1n %s\r\n";
  8.  
  9. #ifndef __FLAT__
  10. extern uint riobp;
  11. #endif
  12.  
  13. extern mswtyp;
  14. extern uint fakeriobp;
  15.  
  16. /****************************************************************************/
  17. /* Convert C string to pascal string                                        */
  18. /****************************************************************************/
  19. void str2pas(char *instr, char *outstr)
  20. {
  21.     int i;
  22.  
  23. outstr[0]=strlen(instr);
  24. for(i=0;i<outstr[0];i++)
  25.     outstr[i+1]=instr[i];
  26. }
  27.  
  28. /****************************************************************************/
  29. /* Convert from unix time (seconds since 1/70) to julian (days since 1900)    */
  30. /****************************************************************************/
  31. int unixtojulian(time_t unix)
  32. {
  33.     int days[12]={0,31,59,90,120,151,181,212,243,273,304,334};
  34.     long j;
  35.     struct date d;
  36.     struct time t;
  37.  
  38. unixtodos(unix,&d,&t);
  39. j=36525L*d.da_year;
  40. if(!(j%100) && d.da_mon<3)
  41.     j--;
  42. j=(j-(1900*36525))/100;
  43. j+=d.da_day+days[d.da_mon-1];
  44. return(j);
  45. }
  46.  
  47. /****************************************************************************/
  48. /* Convert julian date into unix format                                     */
  49. /****************************************************************************/
  50. time_t juliantounix(ulong j)
  51. {
  52.     int days[2][12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
  53.                        0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
  54.     long temp;
  55.     int leap,counter;
  56.  
  57.     if(!j) return(0L);
  58.  
  59.     date.da_year=(100L*j)/36525L;
  60.     temp=(long)date.da_year*36525L;
  61.     date.da_year+=1900;
  62.     j-=temp/100L;
  63.  
  64.     if (!(temp%100)) {
  65.         j++;
  66.         leap=1; }
  67.     else leap=0;
  68.  
  69.     for(date.da_mon=counter=0;counter<12;counter++)
  70.         if(days[leap][counter]<j)
  71.             date.da_mon=counter;
  72.  
  73.     date.da_day=j-days[leap][date.da_mon];
  74.     date.da_mon++;    /* go from 0 to 1 based */
  75.  
  76.     curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
  77.     return(dostounix(&date,&curtime));
  78. }
  79.  
  80. /****************************************************************************/
  81. /* Creates various types of xtrn (Doors, Chains, etc.) data files.         */
  82. /****************************************************************************/
  83. void xtrndat(char *name, char *dropdir, uchar type, ulong tleft)
  84. {
  85.     char str[1024],tmp2[128],c,*p;
  86.     int i,file;
  87.     long l;
  88.     FILE *stream;
  89.     struct time lastcall;
  90.     stats_t stats;
  91.  
  92. if(type==XTRN_SBBS) {    /* SBBS XTRN.DAT file */
  93.     sprintf(str,"%sXTRN.DAT",dropdir);
  94.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  95.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  96.         return; }
  97.  
  98.     sprintf(str,"%s\r\n%s\r\n%s\r\n%s\r\n"
  99.         ,name                                /* User name */
  100.         ,sys_name                            /* System name */
  101.         ,sys_op                             /* Sysop name */
  102.         ,sys_guru);                         /* Guru name */
  103.     write(file,str,strlen(str));
  104.  
  105.     sprintf(str,"%s\r\n%s\r\n%u\r\n%u\r\n%lu\r\n%s\r\n%lu\r\n%lu\r\n"
  106.         ,ctrl_dir                            /* Ctrl dir */
  107.         ,data_dir                            /* Data dir */
  108.         ,sys_nodes                            /* Total system nodes */
  109.         ,node_num                            /* Current node */
  110.         ,tleft                                /* User Timeleft in seconds */
  111.         ,useron.misc&ANSI                    /* User ANSI ? (Yes/Mono/No) */
  112.             ? useron.misc&COLOR
  113.             ? "Yes":"Mono":"No"
  114.         ,rows                                /* User Screen lines */
  115.         ,useron.cdt+useron.freecdt);        /* User Credits */
  116.     write(file,str,strlen(str));
  117.  
  118.     sprintf(str,"%u\r\n%u\r\n%s\r\n%c\r\n%u\r\n%s\r\n"
  119.         ,useron.level                        /* User main level */
  120.         ,useron.level                        /* User transfer level */
  121.         ,useron.birth                        /* User birthday */
  122.         ,useron.sex                         /* User sex (M/F) */
  123.         ,useron.number                        /* User number */
  124.         ,useron.phone);                     /* User phone number */
  125.     write(file,str,strlen(str));
  126.  
  127.     sprintf(str,"%u\r\n%u\r\n%x\r\n%lu\r\n%s\r\n%s\r\n"
  128.         "%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%lu\r\n"
  129.         ,online==ON_LOCAL ? 0:com_port        /* Com port or 0 if local */
  130.         ,com_irq                            /* Com IRQ */
  131.         ,com_base                            /* Com base in hex */
  132.         ,dte_rate                            /* Com rate */
  133.         ,mdm_misc&MDM_CTS       ? "Yes":"No" /* Hardware flow ctrl Y/N */
  134.         ,mdm_misc&MDM_STAYHIGH ? "Yes":"No" /* Locked DTE rate Y/N */
  135.         ,mdm_init                            /* Modem initialization string */
  136.         ,mdm_spec                            /* Modem special init string */
  137.         ,mdm_term                            /* Modem terminal mode init str */
  138.         ,mdm_dial                            /* Modem dial string */
  139.         ,mdm_offh                            /* Modem off-hook string */
  140.         ,mdm_answ                            /* Modem answer string */
  141. #ifndef __FLAT__
  142.         ,sys_status&SS_DCDHIGH ? &fakeriobp : &riobp-1                             /* Modem status register */
  143. #else
  144.         ,0
  145. #endif
  146.         );
  147.     write(file,str,strlen(str));
  148.  
  149.     sprintf(str,"%u\r\n",total_xtrns);
  150.     write(file,str,strlen(str));            /* Total external programs */
  151.  
  152.     for(i=0;i<total_xtrns;i++) {            /* Each program's name */
  153.         if(SYSOP || chk_ar(xtrn[i]->ar,useron))
  154.             strcpy(str,xtrn[i]->name);
  155.         else
  156.             str[0]=0;                        /* Blank if no access */
  157.         strcat(str,crlf);
  158.         write(file,str,strlen(str)); }
  159.  
  160.     sprintf(str,"%s\r\n%s\r\n"
  161.         ,ltoaf(useron.flags1,tmp)             /* Main flags */
  162.         ,ltoaf(useron.flags2,tmp2)             /* Transfer flags */
  163.         );
  164.     write(file,str,strlen(str));
  165.  
  166.     sprintf(str,"%s\r\n%s\r\n%lx\r\n%s\r\n%s\r\n%s\r\n"
  167.         ,ltoaf(useron.exempt,tmp)            /* Exemptions */
  168.         ,ltoaf(useron.rest,tmp2)            /* Restrictions */
  169.         ,useron.expire                        /* Expiration date in unix form */
  170.         ,useron.address                     /* Address */
  171.         ,useron.location                    /* City/State */
  172.         ,useron.zipcode                     /* Zip/Postal code */
  173.         );
  174.     write(file,str,strlen(str));
  175.  
  176.     sprintf(str,"%s\r\n%s\r\n%d\r\n%s\r\n%lu\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
  177.         "%lx\r\n%d\r\n"
  178.         ,ltoaf(useron.flags3,tmp)            /* Flag set #3 */
  179.         ,ltoaf(useron.flags4,tmp2)            /* Flag set #4 */
  180.         ,mswtyp                             /* Time-slice type */
  181.         ,useron.name                        /* Real name/company */
  182.         ,cur_rate                            /* DCE rate */
  183.         ,exec_dir
  184.         ,text_dir
  185.         ,temp_dir
  186.         ,sys_id
  187.         ,node_misc
  188. #ifdef __FLAT__
  189.         ,rio_handle
  190. #else
  191.         ,-1
  192. #endif
  193.         );
  194.     write(file,str,strlen(str));
  195.  
  196.     close(file); }
  197.  
  198. else if(type==XTRN_WWIV) {    /*    WWIV CHAIN.TXT File */
  199.     sprintf(str,"%sCHAIN.TXT",dropdir);
  200.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  201.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  202.         return; }
  203.  
  204.     sprintf(str,"%u\r\n%s\r\n%s\r\n%s\r\n%u\r\n%c\r\n"
  205.         ,useron.number                        /* User number */
  206.         ,name                                /* User name */
  207.         ,useron.name                        /* User real name */
  208.         ,nulstr                             /* User call sign */
  209.         ,getage(useron.birth)                /* User age */
  210.         ,useron.sex);                        /* User sex (M/F) */
  211.     strupr(str);
  212.     write(file,str,strlen(str));
  213.  
  214.     sprintf(str,"%lu\r\n%s\r\n%u\r\n%lu\r\n%u\r\n%u\r\n%u\r\n%u\r\n%u\r\n"
  215.         ,useron.cdt+useron.freecdt            /* Gold */
  216.         ,unixtodstr(useron.laston,tmp)        /* User last on date */
  217.         ,80                                 /* User screen width */
  218.         ,rows                                /* User screen length */
  219.         ,useron.level                        /* User SL */
  220.         ,0                                    /* Cosysop? */
  221.         ,SYSOP                                /* Sysop? (1/0) */
  222.         ,(useron.misc&ANSI) ? 1:0            /* ANSI ? (1/0) */
  223.         ,online==ON_REMOTE);                /* Remote (1/0) */
  224.     write(file,str,strlen(str));
  225.  
  226.     sprintf(str,"%lu\r\n%s\r\n%s\r\n%s\r\n%lu\r\n%d\r\n%s\r\n%s\r\n"
  227.         "%u\r\n%u\r\n%lu\r\n%u\r\n%lu\r\n%u\r\n%s\r\n"
  228.         ,tleft                                /* Time left in seconds */
  229.         ,node_dir                            /* Gfiles dir (log dir) */
  230.         ,data_dir                            /* Data dir */
  231.         ,"NODE.LOG"                         /* Name of log file */
  232.         ,dte_rate                            /* DTE rate */
  233.         ,com_port                            /* COM port number */
  234.         ,sys_name                            /* System name */
  235.         ,sys_op                             /* Sysop name */
  236.         ,0                                    /* Logon time (sec past 12am) */
  237.         ,0                                    /* Current time (sec past 12am) */
  238.         ,useron.ulb/1024UL                    /* User uploaded kbytes */
  239.         ,useron.uls                         /* User uploaded files */
  240.         ,useron.dlb/1024UL                    /* User downloaded kbytes */
  241.         ,useron.dls                         /* User downloaded files */
  242.         ,"8N1");                            /* Data, parity, stop bits */
  243.     write(file,str,strlen(str));
  244.  
  245.     close(file); }
  246.  
  247. else if(type==XTRN_GAP) {    /* Gap DOOR.SYS File */
  248.     sprintf(str,"%sDOOR.SYS",dropdir);
  249.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  250.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  251.         return; }
  252.  
  253.     sprintf(str,"COM%d:\r\n%lu\r\n%u\r\n%u\r\n%lu\r\n%c\r\n%c\r\n%c\r\n%c\r\n"
  254.         ,online==ON_REMOTE ? com_port:0     /* 01: COM port - 0 if Local */
  255.         ,cur_rate                            /* 02: DCE rate */
  256.         ,8                                    /* 03: Data bits */
  257.         ,node_num                            /* 04: Node number */
  258.         ,dte_rate                            /* 05: DTE rate */
  259.         ,console&CON_L_ECHO ? 'Y':'N'       /* 06: Screen display */
  260.         ,'Y'                                /* 07: Printer toggle */
  261.         ,'Y'                                /* 08: Page bell */
  262.         ,'Y');                              /* 09: Caller alarm */
  263.     write(file,str,strlen(str));
  264.  
  265.     sprintf(str,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
  266.         ,name                                /* 10: User name */
  267.         ,useron.location                    /* 11: User location */
  268.         ,useron.phone                        /* 12: User home phone */
  269.         ,useron.phone                        /* 13: User work/data phone */
  270.         ,useron.pass);                        /* 14: User password */
  271.     write(file,str,strlen(str));
  272.  
  273.     sprintf(str,"%u\r\n%u\r\n%s\r\n%lu\r\n%lu\r\n%s\r\n"
  274.         ,useron.level                        /* 15: User security level */
  275.         ,useron.logons                        /* 16: User total logons */
  276.         ,unixtodstr(useron.laston,tmp)        /* 17: User last on date */
  277.         ,tleft                                /* 18: User time left in sec */
  278.         ,tleft/60                            /* 19: User time left in min */
  279.         ,useron.misc&NO_EXASCII             /* 20: GR if COLOR ANSI */
  280.             ? "7E" : (useron.misc&(ANSI|COLOR))==(ANSI|COLOR) ? "GR" : "NG");
  281.     write(file,str,strlen(str));
  282.  
  283.     sprintf(str,"%lu\r\n%c\r\n%s\r\n%u\r\n%s\r\n%u\r\n%c\r\n%u\r\n%u\r\n"
  284.         ,rows                                /* 21: User screen length */
  285.         ,useron.misc&EXPERT ? 'Y':'N'       /* 22: Expert? (Y/N) */
  286.         ,ltoaf(useron.flags1,tmp2)            /* 23: Registered conferences */
  287.         ,0                                    /* 24: Conference came from */
  288.         ,unixtodstr(useron.expire,tmp)        /* 25: User expiration date */
  289.         ,useron.number                        /* 26: User number */
  290.         ,'Y'                                /* 27: Default protocol */
  291.         ,useron.uls                         /* 28: User total uploads */
  292.         ,useron.dls);                        /* 29: User total downloads */
  293.     write(file,str,strlen(str));
  294.  
  295.     sprintf(str,"%u\r\n%lu\r\n%s\r\n%s\r\n%s\r\n%s"
  296.         "\r\n%s\r\n%02d:%02d\r\n%c\r\n"
  297.         ,0                                    /* 30: Kbytes downloaded today */
  298.         ,(useron.cdt+useron.freecdt)/1024UL /* 31: Max Kbytes to download today */
  299.         ,useron.birth                        /* 32: User birthday */
  300.         ,node_dir                            /* 33: Path to MAIN directory */
  301.         ,data_dir                            /* 34: Path to GEN directory */
  302.         ,sys_op                             /* 35: Sysop name */
  303.         ,nulstr                             /* 36: Alias name */
  304.         ,0 // sys_eventtime/60                /* 37: Event time HH:MM */
  305.         ,0 // sys_eventtime%60
  306.         ,'Y');                              /* 38: Error correcting connection */
  307.     write(file,str,strlen(str));
  308.  
  309.     unixtodos(ns_time,&date,&curtime);
  310.     sprintf(str,"%c\r\n%c\r\n%u\r\n%lu\r\n%02d/%02d/%02d\r\n"
  311.         ,(useron.misc&(NO_EXASCII|ANSI|COLOR))==ANSI
  312.             ? 'Y':'N'                       /* 39: ANSI supported but NG mode */
  313.         ,'Y'                                /* 40: Use record locking */
  314.         ,14                                 /* 41: BBS default color */
  315.         ,useron.min                         /* 42: Time credits in minutes */
  316.         ,date.da_mon                        /* 43: File new-scan date */
  317.         ,date.da_day
  318.         ,date.da_year-1900);
  319.     write(file,str,strlen(str));
  320.  
  321.     unixtodos(logontime,&date,&curtime);
  322.     unixtodos(useron.laston,&date,&lastcall);
  323.     sprintf(str,"%02d:%02d\r\n%02d:%02d\r\n%u\r\n%u\r\n%lu\r\n"
  324.         "%lu\r\n%s\r\n%u\r\n%u\r\n"
  325.         ,curtime.ti_hour                    /* 44: Time of this call */
  326.         ,curtime.ti_min
  327.         ,lastcall.ti_hour                    /* 45: Time of last call */
  328.         ,lastcall.ti_min
  329.         ,999                                /* 46: Max daily files available */
  330.         ,0                                    /* 47: Files downloaded so far today */
  331.         ,useron.ulb/1024UL                    /* 48: Total Kbytes uploaded */
  332.         ,useron.dlb/1024UL                    /* 49: Total Kbytes downloaded */
  333.         ,useron.comment                     /* 50: User comment */
  334.         ,0                                    /* 51: Total doors opened */
  335.         ,useron.posts);                     /* 52: User message left */
  336.     write(file,str,strlen(str));
  337.  
  338.     close(file); }
  339.  
  340. else if(type==XTRN_RBBS || type==XTRN_RBBS1) {
  341.     if(type==XTRN_RBBS)
  342.         sprintf(str,"%sDORINFO%X.DEF",dropdir,node_num);   /* support 1-F */
  343.     else
  344.         sprintf(str,"%sDORINFO1.DEF",dropdir);
  345.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  346.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  347.         return; }
  348.  
  349.     strcpy(tmp,sys_op);
  350.     p=strchr(tmp,SP);
  351.     if(p)
  352.         *(p++)=0;
  353.     else
  354.         p=nulstr;
  355.  
  356.     sprintf(str,"%s\r\n%s\r\n%s\r\nCOM%d\r\n%lu BAUD,N,8,1\r\n%u\r\n"
  357.         ,sys_name                            /* Name of BBS */
  358.         ,tmp                                /* Sysop's firstname */
  359.         ,p                                    /* Sysop's lastname */
  360.         ,online==ON_REMOTE ? com_port:0     /* COM port number, 0 if local */
  361.         ,dte_rate                            /* DTE rate */
  362.         ,0);                                /* Network type */
  363.     strupr(str);
  364.     write(file,str,strlen(str));
  365.  
  366.     strcpy(tmp,name);
  367.     p=strchr(tmp,SP);
  368.     if(p)
  369.         *(p++)=0;
  370.     else
  371.         p=nulstr;
  372.     sprintf(str,"%s\r\n%s\r\n%s\r\n%u\r\n%u\r\n%lu\r\n"
  373.         ,tmp                                /* User's firstname */
  374.         ,p                                    /* User's lastname */
  375.         ,useron.location                    /* User's city */
  376.         ,(useron.misc&ANSI)==ANSI            /* 1=ANSI 0=ASCII */
  377.         ,useron.level                        /* Security level */
  378.         ,tleft/60);                         /* Time left in minutes */
  379.     strupr(str);
  380.     write(file,str,strlen(str));
  381.  
  382.     close(file);
  383.  
  384.     sprintf(str,"%sEXITINFO.BBS",dropdir);
  385.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  386.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  387.         return; }
  388.     write(file,&(uint)dte_rate,sizeof(int));      /* BaudRate */
  389.     /* SysInfo */
  390.     getstats(0,&stats);
  391.     write(file,&stats.logons,sizeof(long)); /* CallCount */
  392.     write(file,nulstr,36);                    /* LastCallerName */
  393.     write(file,nulstr,36);                    /* LastCallerAlias */
  394.     write(file,nulstr,92);                    /* ExtraSpace */
  395.     /* TimeLogInfo */
  396.     write(file,nulstr,9);                    /* StartDate */
  397.     write(file,nulstr,24*sizeof(int));        /* BusyPerHour */
  398.     write(file,nulstr,7*sizeof(int));        /* BusyPerDay */
  399.     /* UserInfo */
  400.     str2pas(name,str);                /* Name */
  401.     write(file,str,36);
  402.     str2pas(useron.location,str);
  403.     write(file,str,26);                     /* City */
  404.     str2pas(useron.pass,str);
  405.     write(file,str,16);                     /* Pwd */
  406.     str2pas(useron.phone,str);
  407.     write(file,str,13);                     /* DataPhone */
  408.     write(file,str,13);                     /* HomePhone */
  409.     unixtodos(useron.laston,&date,&lastcall);
  410.     sprintf(tmp,"%02d:%02d",lastcall.ti_hour,lastcall.ti_min);
  411.     str2pas(tmp,str);
  412.     write(file,str,6);                        /* LastTime */
  413.     unixtodstr(useron.laston,tmp);
  414.     str2pas(tmp,str);
  415.     write(file,str,9);                        /* LastDate */
  416.     c=0;
  417.     if(useron.misc&DELETED) c|=(1<<0);
  418.     if(useron.misc&CLRSCRN) c|=(1<<1);
  419.     if(useron.misc&UPAUSE)     c|=(1<<2);
  420.     if(useron.misc&ANSI)    c|=(1<<3);
  421.     if(useron.sex=='F')     c|=(1<<7);
  422.     write(file,&c,1);                        /* Attrib */
  423.     write(file,&useron.flags1,4);            /* Flags */
  424.     i=0;
  425.     write(file,&i,sizeof(int));             /* Credit */
  426.     write(file,&i,sizeof(int));             /* Pending */
  427.     write(file,&useron.posts,sizeof(int));    /* TimesPosted */
  428.     write(file,&i,sizeof(int));             /* HighMsgRead */
  429.     i=useron.level;
  430.     write(file,&i,sizeof(int));             /* SecLvl */
  431.     i=0;
  432.     write(file,&i,sizeof(int));             /* Times */
  433.     write(file,&useron.uls,sizeof(int));    /* Ups */
  434.     write(file,&useron.dls,sizeof(int));    /* Downs */
  435.     i=useron.ulb/1024UL;
  436.     write(file,&i,sizeof(int));             /* UpK */
  437.     i=useron.dlb/1024UL;
  438.     write(file,&i,sizeof(int));             /* DownK */
  439.     i=logon_dlb/1024UL;
  440.     write(file,&i,sizeof(int));             /* TodayK */
  441.     i=0;
  442.     write(file,&i,sizeof(int));             /* Elapsed */
  443.     write(file,&i,sizeof(int));             /* Len */
  444.     write(file,&i,sizeof(int));             /* CombinedPtr */
  445.     write(file,&i,sizeof(int));             /* AliasPtr */
  446.     l=0;
  447.     write(file,&l,sizeof(long));            /* Birthday (as a long?) */
  448.     /* EventInfo */
  449.     c=0;
  450.     write(file,&c,sizeof(char));            /* Status */
  451.     write(file,&l /* sys_eventtime */,sizeof(long));    /* RunTime */
  452.     write(file,&c,sizeof(char));            /* ErrorLevel */
  453.     c=0xff;
  454.     write(file,&c,sizeof(char));            /* Days */
  455.     // c=sys_eventnode==node_num || sys_misc&SM_TIMED_EX ? 1 : 0;
  456.     c=0;
  457.     write(file,&c,sizeof(char));            /* Forced */
  458.     if(!total_events)
  459.         l=0;
  460.     else
  461.         l=event[0]->last;
  462.     write(file,&l,sizeof(long));            /* LastTimeRun */
  463.     memset(str,0,40);
  464.     write(file,str,7);                        /* Spare */
  465.  
  466.     c=0;
  467.     write(file,&c,1);                        /* NetMailEntered */
  468.     write(file,&c,1);                        /* EchoMailEntered */
  469.  
  470.     unixtodos(logontime,&date,&curtime);
  471.     sprintf(tmp,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
  472.     str2pas(tmp,str);
  473.     write(file,str,6);                        /* LoginTime */
  474.     unixtodstr(logontime,tmp);
  475.     str2pas(tmp,str);
  476.     write(file,str,9);                        /* LoginDate */
  477.     write(file,&level_timepercall[useron.level],sizeof(int));  /* TmLimit */
  478.     write(file,&logontime,sizeof(long));    /* LoginSec */
  479.     write(file,&useron.cdt,sizeof(long));    /* Credit */
  480.     write(file,&useron.number,sizeof(int)); /* UserRecNum */
  481.     write(file,&i,2);                        /* ReadThru */
  482.     write(file,&i,2);                        /* PageTimes */
  483.     write(file,&i,2);                        /* DownLimit */
  484.     c=sys_status&SS_SYSPAGE ? 1:0;
  485.     write(file,&c,1);                        /* WantChat */
  486.     c=0;
  487.     write(file,&c,1);                        /* GosubLevel */
  488.  
  489.     memset(str,0,255);
  490.     for(i=1;i<20;i++)
  491.         write(file,str,9);                    /* GosubData */
  492.     write(file,str,9);                        /* Menu */
  493.     c=useron.misc&CLRSCRN ? 1:0;
  494.     write(file,&c,1);                        /* ScreenClear */
  495.     c=useron.misc&UPAUSE ? 1:0;
  496.     write(file,&c,1);                        /* MorePrompts */
  497.     c=useron.misc&NO_EXASCII ? 0:1;
  498.     write(file,&c,1);                        /* GraphicsMode */
  499.     c=useron.xedit ? 1:0;
  500.     write(file,&c,1);                        /* ExternEdit */
  501.     i=rows;
  502.     write(file,&i,2);                        /* ScreenLength */
  503.     c=1;
  504.     write(file,&c,1);                        /* MNP_Connect */
  505.     write(file,str,49);                     /* ChatReason */
  506.     c=0;
  507.     write(file,&c,1);                        /* ExternLogoff */
  508.     c=useron.misc&ANSI ? 1:0;
  509.     write(file,&c,1);                        /* ANSI_Capable */
  510.     close(file);
  511.     }
  512.  
  513. else if(type==XTRN_WILDCAT) { /* WildCat CALLINFO.BBS File */
  514.     sprintf(str,"%sCALLINFO.BBS",dropdir);
  515.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  516.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  517.         return; }
  518.  
  519.     if(online==ON_LOCAL) i=5;
  520.     else
  521.         switch(dte_rate) {
  522.             case 300:
  523.                 i=1;
  524.                 break;
  525.             case 1200:
  526.                 i=2;
  527.                 break;
  528.             case 2400:
  529.                 i=0;
  530.                 break;
  531.             case 9600:
  532.                 i=3;
  533.                 break;
  534.             case 19200:
  535.                 i=4;
  536.                 break;
  537.             case 38400:
  538.                 i=6;
  539.                 break;
  540.             default:
  541.                 i=7;
  542.                 break; }
  543.     sprintf(str,"%s\r\n%u\r\n%s\r\n%u\r\n%lu\r\n%s\r\n%s\r\n%u\r\n"
  544.         ,name                                /* User name */
  545.         ,i                                    /* DTE rate */
  546.         ,useron.location                    /* User location */
  547.         ,useron.level                        /* Security level */
  548.         ,tleft/60                            /* Time left in min */
  549.         ,useron.misc&ANSI ? "COLOR":"MONO"  /* ANSI ??? */
  550.         ,useron.pass                        /* Password */
  551.         ,useron.number);                    /* User number */
  552.     write(file,str,strlen(str));
  553.  
  554.     unixtodos(now,&date,&curtime);
  555.     sprintf(str,"%lu\r\n%02d:%02d\r\n%02d:%02d %02d/%02d/%02d\r\n%s\r\n"
  556.         ,tleft                                /* Time left in seconds */
  557.         ,curtime.ti_hour,curtime.ti_min     /* Current time HH:MM */
  558.         ,curtime.ti_hour,curtime.ti_min     /* Current time and date HH:MM */
  559.         ,date.da_mon,date.da_day            /* MM/DD/YY */
  560.         ,date.da_year-1900
  561.         ,nulstr);                            /* Conferences with access */
  562.     write(file,str,strlen(str));
  563.  
  564.     unixtodos(useron.laston,&date,&lastcall);
  565.     sprintf(str,"%u\r\n%u\r\n%u\r\n%u\r\n%s\r\n%s %02u:%02u\r\n"
  566.         ,0                                    /* Daily download total */
  567.         ,0                                    /* Max download files */
  568.         ,0                                    /* Daily download k total */
  569.         ,0                                    /* Max download k total */
  570.         ,useron.phone                        /* User phone number */
  571.         ,unixtodstr(useron.laston,tmp)        /* Last on date and time */
  572.         ,lastcall.ti_hour                    /* MM/DD/YY  HH:MM */
  573.         ,lastcall.ti_min);
  574.     write(file,str,strlen(str));
  575.  
  576.     unixtodos(ns_time,&date,&curtime);
  577.     sprintf(str,"%s\r\n%s\r\n%02d/%02d/%02d\r\n%u\r\n%lu\r\n%u"
  578.         "\r\n%u\r\n%u\r\n"
  579.         ,useron.misc&EXPERT                 /* Expert or Novice mode */
  580.             ? "EXPERT":"NOVICE"
  581.         ,"All"                              /* Transfer Protocol */
  582.         ,date.da_mon,date.da_day            /* File new-scan date */
  583.         ,date.da_year-1900                    /* in MM/DD/YY */
  584.         ,useron.logons                        /* Total logons */
  585.         ,rows                                /* Screen length */
  586.         ,0                                    /* Highest message read */
  587.         ,useron.uls                         /* Total files uploaded */
  588.         ,useron.dls);                        /* Total files downloaded */
  589.     write(file,str,strlen(str));
  590.  
  591.     sprintf(str,"%u\r\n%s\r\nCOM%u\r\n%s\r\n%lu\r\n%s\r\n%s\r\n"
  592.         ,8                                    /* Data bits */
  593.         ,online==ON_LOCAL?"LOCAL":"REMOTE"  /* Online local or remote */
  594.         ,com_port                            /* COMx port */
  595.         ,useron.birth                        /* User birthday */
  596.         ,dte_rate                            /* DTE rate */
  597.         ,"FALSE"                            /* Already connected? */
  598.         ,"Normal Connection");              /* Normal or ARQ connect */
  599.     write(file,str,strlen(str));
  600.  
  601.     sprintf(str,"%02d/%02d/%02d %02d:%02d\r\n%u\r\n%u\r\n"
  602.         ,date.da_mon,date.da_day            /* Current date MM/DD/YY */
  603.         ,date.da_year-1900
  604.         ,curtime.ti_hour,curtime.ti_min     /* Current time HH:MM */
  605.         ,node_num                            /* Node number */
  606.         ,0);                                /* Door number */
  607.     write(file,str,strlen(str));
  608.  
  609.     close(file); }
  610.  
  611. else if(type==XTRN_PCBOARD) { /* PCBoard Files */
  612.     sprintf(str,"%sPCBOARD.SYS",dropdir);
  613.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  614.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  615.         return; }
  616.  
  617.     sprintf(str,"%2d%2d%2d%2d%c%2d%c%c%5u%-5.5s"
  618.         ,-1                                 /* Display on/off */
  619.         ,0                                    /* Printer on/off */
  620.         ,sys_status&SS_SYSPAGE ? -1:0        /* Page Bell on/off */
  621.         ,node_misc&NM_ANSALARM ? -1:0        /* Caller Alarm on/off */
  622.         ,SP                                 /* Sysop next flag */
  623.         ,0                                    /* Error corrected */
  624.         ,useron.misc&NO_EXASCII ? '7'       /* Graphics mode */
  625.             : (useron.misc&(COLOR|ANSI))==(COLOR|ANSI) ? 'Y':'N'
  626.         ,'A'                                /* Node chat status */
  627.         ,(uint)dte_rate                     /* DTE Port Speed */
  628.         ,connection                         /* Connection description */
  629.         );
  630.     write(file,str,23);
  631.  
  632.     write(file,&useron.number,2);            /* User record number */
  633.  
  634.     strcpy(tmp,name);
  635.     p=strchr(tmp,SP);
  636.     if(p) *p=0;
  637.     sprintf(str,"%-15.15s%-12s"
  638.         ,tmp                                /* User's first name */
  639.         ,useron.pass);                        /* User's password */
  640.     write(file,str,27);
  641.  
  642.     unixtodos(logontime,&date,&curtime);
  643.     i=(curtime.ti_hour*60)+curtime.ti_min;
  644.     write(file,&i,2);                        /* Logon time in min since mid */
  645.  
  646.     now=time(NULL);
  647.     i=-(((now-starttime)/60)+useron.ttoday); /* Negative minutes used */
  648.     write(file,&i,2);
  649.  
  650.     sprintf(str,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
  651.     write(file,str,5);
  652.  
  653.     i=level_timepercall[useron.level];        /* Time allowed on */
  654.     write(file,&i,2);
  655.  
  656.     i=0;                                    /* Allowed K-bytes for D/L */
  657.     write(file,&i,2);
  658.     write(file,&i,1);                        /* Conference user was in */
  659.     write(file,&i,2);                        /* Conferences joined */
  660.     write(file,&i,2);                        /* "" */
  661.     write(file,&i,2);                        /* "" */
  662.     write(file,&i,2);                        /* Conferences scanned */
  663.     write(file,&i,2);                        /* "" */
  664.     write(file,&i,2);                        /* Conference add time */
  665.     write(file,&i,2);                        /* Upload/Sysop Chat time min */
  666.  
  667.     strcpy(str,"    ");
  668.     write(file,str,4);                        /* Language extension */
  669.  
  670.     sprintf(str,"%-25.25s",name);           /* User's full name */
  671.     write(file,str,25);
  672.  
  673.     i=(tleft/60);
  674.     write(file,&i,2);                        /* Minutes remaining */
  675.  
  676.     write(file,&node_num,1);                /* Node number */
  677.  
  678.     sprintf(str,"%02d:%02d%2d%2d"           /* Scheduled Event time */
  679.         ,0 // sys_eventtime/60
  680.         ,0 // sys_eventtime%60
  681.         ,0 // sys_timed[0] ? -1:0                 /* Event active ? */
  682.         ,0                                    /* Slide event ? */
  683.         );
  684.     write(file,str,9);
  685.  
  686.     l=0L;
  687.     write(file,&l,4);                        /* Memorized message number */
  688.  
  689.     sprintf(str,"%d%c%c%d%s%c%c%d%d%d%c%c"
  690.         ,com_port                            /* COM Port number */
  691.         ,SP                                 /* Reserved */
  692.         ,SP                                 /* "" */
  693.         ,(useron.misc&ANSI)==ANSI            /* 1=ANSI 0=NO ANSI */
  694.         ,"01-01-80"                         /* last event date */
  695.         ,0,0                                /* last event minute */
  696.         ,0                                    /* caller exited to dos */
  697.         ,sys_status&SS_EVENT ? 1:0            /* event up coming */
  698.         ,0                                    /* stop uploads */
  699.         ,0,0                                /* conference user was in */
  700.         );
  701.     write(file,str,19);
  702.  
  703.     close(file);            /* End of PCBOARD.SYS creation */
  704.  
  705.     sprintf(str,"%sUSERS.SYS",dropdir);
  706.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  707.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  708.         return; }
  709.  
  710.     /* Write goof-ball header */
  711.  
  712.     i=145;
  713.     write(file,&i,2);        /* PCBoard version number (i.e. 145) */
  714.     l=useron.number;
  715.     write(file,&l,4);        /* Record number for USER's file */
  716.     i=218;
  717.     write(file,&i,2);        /* Size of "fixed" user record */
  718.     i=1;
  719.     write(file,&i,2);        /* Number of conference areas */
  720.     i=7;
  721.     write(file,&i,2);        /* Number of bit map fields for conferences */
  722.     i=5;
  723.     write(file,&i,2);        /* Size of each bit map field */
  724.     memset(str,0,15);
  725.     write(file,str,15);     /* Name of Third Party Application (if any) */
  726.     i=0;
  727.     write(file,&i,2);        /* Version number for application (if any) */
  728.     write(file,&i,2);        /* Size of a "fixed length" record (if any) */
  729.     write(file,&i,2);        /* Size of conference record (if any) */
  730.     l=0;
  731.     write(file,&l,4);        /* Offset of AppRec into USERS.INF (if any) */
  732.     i=0;
  733.     write(file,&i,1);        /* 1, if USERS.SYS file has been updated */
  734.  
  735.     /* Write fixed record portion */
  736.  
  737.     write(file,name,26);            /* Name */
  738.     sprintf(str,"%.24s",useron.location);
  739.     write(file,str,25);             /* Location */
  740.     write(file,useron.pass,13);     /* Password */
  741.     write(file,useron.phone,14);    /* Business or Data Phone */
  742.     write(file,useron.phone,14);    /* Home or Voice Phone */
  743.     i=unixtojulian(useron.laston);
  744.     write(file,&i,2);                /* Date last on */
  745.     unixtodos(useron.laston,&date,&curtime);
  746.     sprintf(str,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
  747.     write(file,str,6);                /* Last time on */
  748.     if(useron.misc&EXPERT)
  749.         i=1;
  750.     else
  751.         i=0;
  752.     write(file,&i,1);                /* Expert mode */
  753.     i='Z';
  754.     write(file,&i,1);                /* Protocol (A-Z) */
  755.     if(useron.misc&CLRSCRN)
  756.         i=2;
  757.     else
  758.         i=0;
  759.     write(file,&i,1);                /* bit packed flags */
  760.     i=0;
  761.     write(file,&i,2);                /* DOS date for last DIR Scan */
  762.     i=useron.level;
  763.     write(file,&i,2);                /* Security level */
  764.     write(file,&useron.logons,2);    /* Number of times caller has connected */
  765.     c=rows;
  766.     write(file,&c,1);                /* Page length */
  767.     write(file,&useron.uls,2);        /* Number of uploads */
  768.     write(file,&useron.dls,2);        /* Number of downloads */
  769.     l=0;
  770.     write(file,&l,4);                /* Number of download bytes today */
  771.     write(file,&useron.note,31);    /* Comment #1 */
  772.     write(file,&useron.comp,31);    /* Comment #2 */
  773.     i=(now-starttime)/60;
  774.     write(file,&i,2);                /* Minutes online (this logon?) */
  775.     i=unixtojulian(useron.expire);
  776.     write(file,&i,2);                /* Expiration date */
  777.     i=expired_level;
  778.     write(file,&i,2);                /* Expired security level */
  779.     i=1;
  780.     write(file,&i,2);                /* Current conference */
  781.     write(file,&useron.dlb,4);        /* Bytes downloaded */
  782.     write(file,&useron.ulb,4);        /* Bytes uploaded */
  783.     if(useron.misc&DELETED)
  784.         i=1;
  785.     else
  786.         i=0;
  787.     write(file,&i,1);                /* Deleted? */
  788.     l=useron.number;
  789.     write(file,&l,4);                /* Record number in USERS.INF file */
  790.     l=0;
  791.     memset(str,0,9);
  792.     write(file,str,9);                /* Reserved */
  793.     write(file,&l,4);                /* Number of messages read */
  794.     l=useron.posts+useron.emails+useron.fbacks;
  795.     write(file,&l,4);                /* Number of messages left */
  796.     close(file);
  797.  
  798.     /* End of USERS.SYS creation */
  799.  
  800.     }
  801.  
  802. else if(type==XTRN_SPITFIRE) {     /* SpitFire SFDOORS.DAT File */
  803.     sprintf(str,"%sSFDOORS.DAT",dropdir);
  804.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  805.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  806.         return; }
  807.  
  808.     now=time(NULL);
  809.     unixtodos(now,&date,&curtime);
  810.     l=((((long)curtime.ti_hour*60L)+(long)curtime.ti_min)*60L)
  811.         +(long)curtime.ti_sec;
  812.  
  813.     strcpy(tmp,name);
  814.     if((p=strchr(tmp,SP))!=NULL)
  815.         *p=0;
  816.  
  817.     sprintf(str,"%u\r\n%s\r\n%s\r\n%s\r\n%lu\r\n%u\r\n%lu\r\n%lu\r\n"
  818.         ,useron.number                        /* User number */
  819.         ,name                                /* User name */
  820.         ,useron.pass                        /* Password */
  821.         ,tmp                                /* User's first name */
  822.         ,dte_rate                            /* DTE Rate */
  823.         ,com_port                            /* COM Port */
  824.         ,tleft/60                            /* Time left in minutes */
  825.         ,l                                    /* Seconds since midnight (now) */
  826.         );
  827.     write(file,str,strlen(str));
  828.  
  829.     unixtodos(logontime,&date,&curtime);
  830.     l=((((long)curtime.ti_hour*60L)+(long)curtime.ti_min)*60L)
  831.         +(long)curtime.ti_sec;
  832.  
  833.     sprintf(str,"%s\r\n%s\r\n%u\r\n%u\r\n%u\r\n%u\r\n%lu\r\n%lu\r\n%s\r\n"
  834.         "%s\r\n%s\r\n%lu\r\n%s\r\n%u\r\n%u\r\n%u\r\n%u\r\n%u\r\n%lu\r\n%u\r\n"
  835.         "%lu\r\n%lu\r\n%s\r\n%s\r\n"
  836.         ,dropdir
  837.         ,useron.misc&ANSI ? "TRUE":"FALSE"  /* ANSI ? True or False */
  838.         ,useron.level                        /* Security level */
  839.         ,useron.uls                         /* Total uploads */
  840.         ,useron.dls                         /* Total downloads */
  841.         ,level_timepercall[useron.level]    /* Minutes allowed this call */
  842.         ,l                                    /* Secs since midnight (logon) */
  843.         ,starttime-logontime                /* Extra time in seconds */
  844.         ,"FALSE"                            /* Sysop next? */
  845.         ,"FALSE"                            /* From Front-end? */
  846.         ,"FALSE"                            /* Software Flow Control? */
  847.         ,dte_rate                            /* DTE Rate */
  848.         ,"FALSE"                            /* Error correcting connection? */
  849.         ,0                                    /* Current conference */
  850.         ,0                                    /* Current file dir */
  851.         ,node_num                            /* Node number */
  852.         ,15                                 /* Downloads allowed per day */
  853.         ,0                                    /* Downloads already this day */
  854.         ,100000                             /* Download bytes allowed/day */
  855.         ,0                                    /* Downloaded bytes already today */
  856.         ,useron.ulb/1024L                    /* Kbytes uploaded */
  857.         ,useron.dlb/1024L                    /* Kbytes downloaded */
  858.         ,useron.phone                        /* Phone Number */
  859.         ,useron.location                    /* City, State */
  860.         );
  861.     write(file,str,strlen(str));
  862.  
  863.     close(file); }
  864.  
  865. else if(type==XTRN_UTI) { /* UTI v2.1 - UTIDOOR.TXT */
  866.     sprintf(str,"%sUTIDOOR.TXT",dropdir);
  867.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  868.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  869.         return; }
  870.  
  871.     strcpy(tmp,name);
  872.     strupr(tmp);
  873.     sprintf(str,"%s\r\n%lu\r\n%u\r\n%lu\r\n%lu\r\n"
  874.         ,tmp                                /* User name */
  875.         ,cur_rate                            /* Actual BPS rate */
  876.         ,online==ON_LOCAL ? 0: com_port     /* COM Port */
  877.         ,dte_rate                            /* DTE rate */
  878.         ,tleft);                            /* Time left in sec */
  879.     write(file,str,strlen(str));
  880.  
  881.     close(file); }
  882.  
  883. else if(type==XTRN_SR) { /* Solar Realms DOORFILE.SR */
  884.     sprintf(str,"%sDOORFILE.SR",dropdir);
  885.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  886.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  887.         return; }
  888.  
  889.     sprintf(str,"%s\r\n%d\r\n%d\r\n%lu\r\n%lu\r\n%u\r\n%lu\r\n"
  890.         ,name                                /* Complete name of user */
  891.         ,useron.misc&ANSI ? 1:0             /* ANSI ? */
  892.         ,useron.misc&NO_EXASCII ? 0:1        /* IBM characters ? */
  893.         ,rows                                /* Page length */
  894.         ,dte_rate                            /* Baud rate */
  895.         ,online==ON_LOCAL ? 0:com_port        /* COM port */
  896.         ,tleft/60                            /* Time left (in minutes) */
  897.         );
  898.     write(file,str,strlen(str));
  899.     close(file); }
  900.  
  901. else if(type==XTRN_TRIBBS) { /* TRIBBS.SYS */
  902.     sprintf(str,"%sTRIBBS.SYS",dropdir);
  903.     if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  904.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  905.         return; }
  906.  
  907.     sprintf(str,"%u\r\n%s\r\n%s\r\n%u\r\n%c\r\n%c\r\n%lu\r\n%s\r\n%s\r\n%s\r\n"
  908.         ,useron.number                        /* User's record number */
  909.         ,name                                /* User's name */
  910.         ,useron.pass                        /* User's password */
  911.         ,useron.level                        /* User's level */
  912.         ,useron.misc&EXPERT ? 'Y':'N'       /* Expert? */
  913.         ,useron.misc&ANSI ? 'Y':'N'         /* ANSI? */
  914.         ,tleft/60                            /* Minutes left */
  915.         ,useron.phone                        /* User's phone number */
  916.         ,useron.location                    /* User's city and state */
  917.         ,useron.birth                        /* User's birth date */
  918.         );
  919.     write(file,str,strlen(str));
  920.  
  921.     sprintf(str,"%u\r\n%u\r\n%lu\r\n%lu\r\n%c\r\n%c\r\n%s\r\n%s\r\n%s\r\n"
  922.         ,node_num                            /* Node number */
  923.         ,com_port                            /* Serial port */
  924.         ,online==ON_LOCAL ? 0L:cur_rate     /* Baud rate */
  925.         ,dte_rate                            /* Locked rate */
  926.         ,mdm_misc&(MDM_RTS|MDM_CTS) ? 'Y':'N'
  927.         ,'Y'                                /* Error correcting connection */
  928.         ,sys_name                            /* Board's name */
  929.         ,sys_op                             /* Sysop's name */
  930.         ,useron.handle                        /* User's alias */
  931.         );
  932.     write(file,str,strlen(str));
  933.     close(file); }
  934.  
  935. else if(type)
  936.     errormsg(WHERE,ERR_CHK,"Drop file type",type);
  937.  
  938. }
  939.  
  940. /****************************************************************************/
  941. /* Reads in MODUSER.DAT, EXITINFO.BBS, or DOOR.SYS and modify the current    */
  942. /* user's values.                                                           */
  943. /****************************************************************************/
  944. void moduserdat(uint xtrnnum)
  945. {
  946.     char str[256],path[256],c,startup[128];
  947.     uint i;
  948.     long mod;
  949.     int file;
  950.     FILE *stream;
  951.  
  952. sprintf(startup,"%s\\",xtrn[xtrnnum]->path);
  953. if(xtrn[xtrnnum]->type==XTRN_RBBS) {
  954.     sprintf(path,"%sEXITINFO.BBS"
  955.         ,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
  956.     if((file=nopen(path,O_RDONLY))!=-1) {
  957.         lseek(file,361,SEEK_SET);
  958.         read(file,&useron.flags1,4); /* Flags */
  959.         putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16));
  960.         lseek(file,373,SEEK_SET);
  961.         read(file,&i,2);            /* SecLvl */
  962.         if(i<90) {
  963.             useron.level=i;
  964.             putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); }
  965.         close(file);
  966.         remove(path); }
  967.     return; }
  968. else if(xtrn[xtrnnum]->type==XTRN_GAP) {
  969.     sprintf(path,"%sDOOR.SYS"
  970.         ,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
  971.     if((stream=fopen(path,"rb"))!=NULL) {
  972.         for(i=0;i<15;i++)            /* skip first 14 lines */
  973.             if(!fgets(str,128,stream))
  974.                 break;
  975.         if(i==15 && isdigit(str[0])) {
  976.             mod=atoi(str);
  977.             if(mod<90) {
  978.                 useron.level=mod;
  979.                 putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); } }
  980.  
  981.         for(;i<23;i++)
  982.             if(!fgets(str,128,stream))
  983.                 break;
  984.         if(i==23) {                     /* set main flags */
  985.             useron.flags1=aftol(str);
  986.             putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
  987.  
  988.         for(;i<25;i++)
  989.             if(!fgets(str,128,stream))
  990.                 break;
  991.         if(i==25 && isdigit(str[0]) && isdigit(str[1])
  992.             && (str[2]=='/' || str[2]=='-') /* xx/xx/xx or xx-xx-xx */
  993.             && isdigit(str[3]) && isdigit(str[4])
  994.             && (str[5]=='/' || str[5]=='-')
  995.             && isdigit(str[6]) && isdigit(str[7])) { /* valid expire date */
  996.             useron.expire=dstrtounix(str);
  997.             putuserrec(useron.number,U_EXPIRE,8,ultoa(useron.expire,tmp,16)); }
  998.  
  999.         for(;i<29;i++)                    /* line 29, total downloaded files */
  1000.             if(!fgets(str,128,stream))
  1001.                 break;
  1002.         if(i==29) {
  1003.             truncsp(str);
  1004.             useron.dls=atoi(str);
  1005.             putuserrec(useron.number,U_DLS,5,str); }
  1006.  
  1007.         if(fgets(str,128,stream)) {     /* line 30, Kbytes downloaded today */
  1008.             i++;
  1009.             truncsp(str);
  1010.             mod=atol(str)*1024L;
  1011.             if(mod) {
  1012.                 useron.dlb=adjustuserrec(useron.number,U_DLB,10,mod);
  1013.                 subtract_cdt(mod); } }
  1014.  
  1015.         for(;i<42;i++)
  1016.             if(!fgets(str,128,stream))
  1017.                 break;
  1018.         if(i==42 && isdigit(str[0])) {    /* Time Credits in Minutes */
  1019.             useron.min=atol(str);
  1020.             putuserrec(useron.number,U_MIN,10,ultoa(useron.min,tmp,10)); }
  1021.  
  1022.         fclose(stream); }
  1023.     return; }
  1024.  
  1025. else if(xtrn[xtrnnum]->type==XTRN_PCBOARD) {
  1026.     sprintf(path,"%sUSERS.SYS"
  1027.         ,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
  1028.     if((file=nopen(path,O_RDONLY))!=-1) {
  1029.         lseek(file,39,SEEK_SET);
  1030.         read(file,&c,1);
  1031.         if(c==1) {     /* file has been updated */
  1032.             lseek(file,105,SEEK_CUR);    /* read security level */
  1033.             read(file,&i,2);
  1034.             if(i<90) {
  1035.                 useron.level=i;
  1036.                 putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); }
  1037.             lseek(file,75,SEEK_CUR);    /* read in expiration date */
  1038.             read(file,&i,2);    /* convert from julian to unix */
  1039.             useron.expire=juliantounix(i);
  1040.             putuserrec(useron.number,U_EXPIRE,8,ltoa(useron.expire,tmp,16)); }
  1041.         close(file); }
  1042.     return; }
  1043.  
  1044. sprintf(path,"%sMODUSER.DAT"
  1045.         ,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
  1046. if((stream=fopen(path,"rb"))!=NULL) {        /* File exists */
  1047.     if(fgets(str,81,stream) && (mod=atol(str))!=0) {
  1048.         ultoac(mod>0L ? mod : -mod,tmp);        /* put commas in the # */
  1049.         strcpy(str,"Credit Adjustment: ");
  1050.         if(mod<0L)
  1051.             strcat(str,"-");                    /* negative, put '-' */
  1052.         strcat(str,tmp);
  1053.         if(mod>0L)
  1054.             strcpy(tmp,"$+");
  1055.         else
  1056.             strcpy(tmp,"$-");
  1057.         logline(tmp,str);
  1058.         if(mod>0L)            /* always add to real cdt */
  1059.             useron.cdt=adjustuserrec(useron.number,U_CDT,10,mod);
  1060.         else
  1061.             subtract_cdt(-mod); }    /* subtract from free cdt first */
  1062.     if(fgets(str,81,stream)) {        /* main level */
  1063.         mod=atoi(str);
  1064.         if(isdigit(str[0]) && mod<90) {
  1065.             useron.level=mod;
  1066.             putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); } }
  1067.     fgets(str,81,stream);         /* was transfer level, now ignored */
  1068.     if(fgets(str,81,stream)) {        /* flags #1 */
  1069.         if(strchr(str,'-'))         /* remove flags */
  1070.             useron.flags1&=~aftol(str);
  1071.         else                        /* add flags */
  1072.             useron.flags1|=aftol(str);
  1073.         putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
  1074.  
  1075.     if(fgets(str,81,stream)) {        /* flags #2 */
  1076.         if(strchr(str,'-'))         /* remove flags */
  1077.             useron.flags2&=~aftol(str);
  1078.         else                        /* add flags */
  1079.             useron.flags2|=aftol(str);
  1080.         putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,tmp,16)); }
  1081.  
  1082.     if(fgets(str,81,stream)) {        /* exemptions */
  1083.         if(strchr(str,'-'))
  1084.             useron.exempt&=~aftol(str);
  1085.         else
  1086.             useron.exempt|=aftol(str);
  1087.         putuserrec(useron.number,U_EXEMPT,8,ultoa(useron.exempt,tmp,16)); }
  1088.     if(fgets(str,81,stream)) {        /* restrictions */
  1089.         if(strchr(str,'-'))
  1090.             useron.rest&=~aftol(str);
  1091.         else
  1092.             useron.rest|=aftol(str);
  1093.         putuserrec(useron.number,U_REST,8,ultoa(useron.rest,tmp,16)); }
  1094.     if(fgets(str,81,stream)) {        /* Expiration date */
  1095.         if(isxdigit(str[0]))
  1096.             putuserrec(useron.number,U_EXPIRE,8,str); }
  1097.     if(fgets(str,81,stream)) {        /* additional minutes */
  1098.         mod=atol(str);
  1099.         if(mod) {
  1100.             sprintf(str,"Minute Adjustment: %s",ultoac(mod,tmp));
  1101.             logline("*+",str);
  1102.             useron.min=adjustuserrec(useron.number,U_MIN,10,mod); } }
  1103.  
  1104.     if(fgets(str,81,stream)) {        /* flags #3 */
  1105.         if(strchr(str,'-'))         /* remove flags */
  1106.             useron.flags3&=~aftol(str);
  1107.         else                        /* add flags */
  1108.             useron.flags3|=aftol(str);
  1109.         putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,tmp,16)); }
  1110.  
  1111.     if(fgets(str,81,stream)) {        /* flags #4 */
  1112.         if(strchr(str,'-'))         /* remove flags */
  1113.             useron.flags4&=~aftol(str);
  1114.         else                        /* add flags */
  1115.             useron.flags4|=aftol(str);
  1116.         putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,tmp,16)); }
  1117.  
  1118.     if(fgets(str,81,stream)) {        /* flags #1 to REMOVE only */
  1119.         useron.flags1&=~aftol(str);
  1120.         putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
  1121.     if(fgets(str,81,stream)) {        /* flags #2 to REMOVE only */
  1122.         useron.flags2&=~aftol(str);
  1123.         putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,tmp,16)); }
  1124.     if(fgets(str,81,stream)) {        /* flags #3 to REMOVE only */
  1125.         useron.flags3&=~aftol(str);
  1126.         putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,tmp,16)); }
  1127.     if(fgets(str,81,stream)) {        /* flags #4 to REMOVE only */
  1128.         useron.flags4&=~aftol(str);
  1129.         putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,tmp,16)); }
  1130.     if(fgets(str,81,stream)) {        /* exemptions to remove */
  1131.         useron.exempt&=~aftol(str);
  1132.         putuserrec(useron.number,U_EXEMPT,8,ultoa(useron.exempt,tmp,16)); }
  1133.     if(fgets(str,81,stream)) {        /* restrictions to remove */
  1134.         useron.rest&=~aftol(str);
  1135.         putuserrec(useron.number,U_REST,8,ultoa(useron.rest,tmp,16)); }
  1136.  
  1137.     fclose(stream);
  1138.     remove(path); }
  1139. }
  1140.  
  1141. /****************************************************************************/
  1142. /* This is the external programs (doors) section of the bbs                 */
  1143. /* Return 1 if no externals available, 0 otherwise.                         */
  1144. /****************************************************************************/
  1145. char xtrn_sec()
  1146. {
  1147.     char str[256];
  1148.     int file,j,k,xsec,*usrxtrn,usrxtrns,*usrxsec,usrxsecs;
  1149.     uint i;
  1150.  
  1151. if(!total_xtrns || !total_xtrnsecs) {
  1152.     bputs(text[NoXtrnPrograms]);
  1153.     return(1); }
  1154.  
  1155. if((usrxtrn=(int *)MALLOC(total_xtrns*sizeof(int)))==NULL) {
  1156.     errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrns);
  1157.     return(1); }
  1158. if((usrxsec=(int *)MALLOC(total_xtrnsecs*sizeof(int)))==NULL) {
  1159.     errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrnsecs);
  1160.     FREE(usrxtrn);
  1161.     return(1); }
  1162.  
  1163. while(online) {
  1164.     for(i=0,usrxsecs=0;i<total_xtrnsecs;i++)
  1165.         if(chk_ar(xtrnsec[i]->ar,useron))
  1166.             usrxsec[usrxsecs++]=i;
  1167.     if(!usrxsecs) {
  1168.         bputs(text[NoXtrnPrograms]);
  1169.         FREE(usrxtrn);
  1170.         FREE(usrxsec);
  1171.         return(1); }
  1172.     if(usrxsecs>1) {
  1173.         sprintf(str,"%sMENU\\XTRN_SEC.*",text_dir);
  1174.         if(fexist(str)) {
  1175.             menu("XTRN_SEC");
  1176.             xsec=getnum(usrxsecs);
  1177.             if(xsec<=0)
  1178.                 break;
  1179.             xsec--;
  1180.             xsec=usrxsec[xsec]; }
  1181.         else {
  1182.             for(i=0;i<total_xtrnsecs;i++)
  1183.                 uselect(1,i,"External Program Section"
  1184.                     ,xtrnsec[i]->name,xtrnsec[i]->ar);
  1185.             xsec=uselect(0,0,0,0,0); }
  1186.         if(xsec==-1)
  1187.             break; }
  1188.     else
  1189.         xsec=0;
  1190.  
  1191.     while(!chk_ar(xtrnsec[xsec]->ar,useron))
  1192.         xsec++;
  1193.  
  1194.     if(xsec>=total_xtrnsecs) {
  1195.         bputs(text[NoXtrnPrograms]);
  1196.         FREE(usrxtrn);
  1197.         FREE(usrxsec);
  1198.         return(1); }
  1199.  
  1200.     while(online) {
  1201.         for(i=0,usrxtrns=0;i<total_xtrns; i++) {
  1202.             if(xtrn[i]->sec!=xsec)
  1203.                 continue;
  1204.             if(xtrn[i]->misc&EVENTONLY)
  1205.                 continue;
  1206.             if(!chk_ar(xtrn[i]->ar,useron))
  1207.                 continue;
  1208.             usrxtrn[usrxtrns++]=i; }
  1209.         if(!usrxtrns) {
  1210.             bputs(text[NoXtrnPrograms]);
  1211.             pause();
  1212.             break; }
  1213.         sprintf(str,"%sMENU\\XTRN%u.*",text_dir,xsec+1);
  1214.         if(fexist(str)) {
  1215.             sprintf(str,"XTRN%u",xsec+1);
  1216.             menu(str); }
  1217.         else {
  1218.             bprintf(text[XtrnProgLstHdr],xtrnsec[xsec]->name);
  1219.             bputs(text[XtrnProgLstTitles]);
  1220.             if(usrxtrns>=10) {
  1221.                 bputs("     ");
  1222.                 bputs(text[XtrnProgLstTitles]); }
  1223.             CRLF;
  1224.             bputs(text[XtrnProgLstUnderline]);
  1225.             if(usrxtrns>=10) {
  1226.                 bputs("     ");
  1227.                 bputs(text[XtrnProgLstUnderline]); }
  1228.             CRLF;
  1229.             if(usrxtrns>=10)
  1230.                 j=(usrxtrns/2)+(usrxtrns&1);
  1231.             else
  1232.                 j=usrxtrns;
  1233.             for(i=0;i<j && !msgabort();i++) {
  1234.                 bprintf(text[XtrnProgLstFmt],i+1
  1235.                     ,xtrn[usrxtrn[i]]->name,xtrn[usrxtrn[i]]->cost);
  1236.                 if(usrxtrns>=10) {
  1237.                     k=(usrxtrns/2)+i+(usrxtrns&1);
  1238.                     if(k<usrxtrns) {
  1239.                         bputs("     ");
  1240.                         bprintf(text[XtrnProgLstFmt],k+1
  1241.                             ,xtrn[usrxtrn[k]]->name
  1242.                             ,xtrn[usrxtrn[k]]->cost); } }
  1243.                 CRLF; }
  1244.             ASYNC;
  1245.             mnemonics(text[WhichXtrnProg]); }
  1246.         getnodedat(node_num,&thisnode,1);
  1247.         thisnode.aux=0; /* aux is 0, only if at menu */
  1248.         putnodedat(node_num,thisnode);
  1249.         action=NODE_XTRN;
  1250.         SYNC;
  1251.         if((j=getnum(usrxtrns))<1)
  1252.             break;
  1253.         exec_xtrn(usrxtrn[j-1]); }
  1254.     if(usrxsecs<2)
  1255.         break; }
  1256. FREE(usrxtrn);
  1257. FREE(usrxsec);
  1258. return(0);
  1259. }
  1260.  
  1261. /****************************************************************************/
  1262. /* This function handles configured external program execution.             */
  1263. /****************************************************************************/
  1264. void exec_xtrn(uint xtrnnum)
  1265. {
  1266.     char str[256],str2[256],path[256],dropdir[128],name[32],c,e,mode;
  1267.     int file;
  1268.     uint i;
  1269.     long mod;
  1270.     ulong tleft;
  1271.     FILE *stream;
  1272.     node_t node;
  1273.     time_t start,end;
  1274.  
  1275.  
  1276. if(!chk_ar(xtrn[xtrnnum]->run_ar,useron)
  1277.     || !chk_ar(xtrnsec[xtrn[xtrnnum]->sec]->ar,useron)) {
  1278.     bputs(text[CantRunThatProgram]);
  1279.     return; }
  1280.  
  1281. if(xtrn[xtrnnum]->cost && !(useron.exempt&FLAG('X'))) {    /* costs */
  1282.     if(xtrn[xtrnnum]->cost>useron.cdt+useron.freecdt) {
  1283.         bputs(text[NotEnoughCredits]);
  1284.         pause();
  1285.         return; }
  1286.     subtract_cdt(xtrn[xtrnnum]->cost); }
  1287.  
  1288. if(!(xtrn[xtrnnum]->misc&MULTIUSER)) {
  1289.     for(i=1;i<=sys_nodes;i++) {
  1290.         getnodedat(i,&node,0);
  1291.         c=i;
  1292.         if((node.status==NODE_INUSE || node.status==NODE_QUIET)
  1293.             && node.action==NODE_XTRN && node.aux==(xtrnnum+1)) {
  1294.             if(node.status==NODE_QUIET) {
  1295.                 strcpy(str,sys_guru);
  1296.                 c=sys_nodes+1; }
  1297.             else if(node.misc&NODE_ANON)
  1298.                 strcpy(str,"UNKNOWN USER");
  1299.             else
  1300.                 username(node.useron,str);
  1301.             bprintf(text[UserRunningXtrn],str
  1302.                 ,xtrn[xtrnnum]->name,c);
  1303.             pause();
  1304.             break; } }
  1305.     if(i<=sys_nodes)
  1306.         return; }
  1307.  
  1308. sprintf(str,"%s\\",xtrn[xtrnnum]->path);
  1309. strcpy(path,xtrn[xtrnnum]->misc&STARTUPDIR ? str : node_dir);
  1310. strcpy(dropdir,xtrn[xtrnnum]->misc&STARTUPDIR ? str : node_dir);
  1311.  
  1312. switch(xtrn[xtrnnum]->type) {
  1313.     case XTRN_WWIV:
  1314.         strcat(path,"CHAIN.TXT");
  1315.         break;
  1316.     case XTRN_GAP:
  1317.         strcat(path,"DOOR.SYS");
  1318.         break;
  1319.     case XTRN_RBBS:
  1320.         sprintf(str,"DORINFO%X.DEF",node_num);
  1321.         strcat(path,str);
  1322.         break;
  1323.     case XTRN_RBBS1:
  1324.         strcat(path,"DORINFO1.DEF");
  1325.         break;
  1326.     case XTRN_WILDCAT:
  1327.         strcat(path,"CALLINFO.BBS");
  1328.         break;
  1329.     case XTRN_PCBOARD:
  1330.         strcat(path,"PCBOARD.SYS");
  1331.         break;
  1332.     case XTRN_UTI:
  1333.         strcat(path,"UTIDOOR.TXT");
  1334.         break;
  1335.     case XTRN_SR:
  1336.         strcat(path,"DOORFILE.SR");
  1337.         break;
  1338.     default:
  1339.         strcat(path,"XTRN.DAT");
  1340.         break; }
  1341. getnodedat(node_num,&thisnode,1);
  1342. thisnode.aux=xtrnnum+1;
  1343. thisnode.action=NODE_XTRN;
  1344. putnodedat(node_num,thisnode);
  1345.  
  1346. if(xtrn[xtrnnum]->misc&REALNAME)
  1347.     strcpy(name,useron.name);
  1348. else
  1349.     strcpy(name,useron.alias);
  1350.  
  1351. gettimeleft();
  1352. tleft=timeleft+(xtrn[xtrnnum]->textra*60);
  1353. if(xtrn[xtrnnum]->maxtime && tleft>xtrn[xtrnnum]->maxtime)
  1354.     tleft=(xtrn[xtrnnum]->maxtime*60);
  1355. xtrndat(name,dropdir,xtrn[xtrnnum]->type,tleft);
  1356. if(!online)
  1357.     return;
  1358. sprintf(str,"Ran external: %s",xtrn[xtrnnum]->name);
  1359. logline("X-",str);
  1360. if(xtrn[xtrnnum]->cmd[0]!='*' && sys_status&SS_LOGOPEN) {
  1361.     close(logfile);
  1362.     sys_status&=~SS_LOGOPEN; }
  1363.  
  1364. sprintf(str,"%sINTRSBBS.DAT"
  1365.         ,xtrn[xtrnnum]->path[0] ? xtrn[xtrnnum]->path : node_dir);
  1366. remove(str);
  1367. sprintf(str,"%sHANGUP.NOW",node_dir);
  1368. remove(str);
  1369. sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
  1370. remove(str);
  1371.  
  1372. mode=0;     /* EX_CC */
  1373. if(xtrn[xtrnnum]->misc&IO_INTS)
  1374.     mode|=(EX_OUTR|EX_INR|EX_OUTL);
  1375. if(xtrn[xtrnnum]->misc&WWIVCOLOR)
  1376.     mode|=EX_WWIV;
  1377. if(xtrn[xtrnnum]->misc&SWAP)
  1378.     mode|=EX_SWAP;
  1379. if(xtrn[xtrnnum]->misc&MODUSERDAT) {     /* Delete MODUSER.DAT */
  1380.     sprintf(str,"%sMODUSER.DAT",dropdir);       /* if for some weird  */
  1381.     remove(str); }                                /* reason it's there  */
  1382.  
  1383. if(xtrn[xtrnnum]->path[0]) {
  1384.     if(xtrn[xtrnnum]->path[1]==':')                /* drive letter specified */
  1385.         setdisk(toupper(xtrn[xtrnnum]->path[0])-'A');
  1386.     if(chdir(xtrn[xtrnnum]->path))
  1387.         errormsg(WHERE,ERR_CHDIR,xtrn[xtrnnum]->path,0); }
  1388.  
  1389. start=time(NULL);
  1390. external(cmdstr(xtrn[xtrnnum]->cmd,path,dropdir,NULL),mode);
  1391. end=time(NULL);
  1392. if(xtrn[xtrnnum]->misc&FREETIME)
  1393.     starttime+=end-start;
  1394. if(xtrn[xtrnnum]->clean[0]) {
  1395.     if(xtrn[xtrnnum]->path[0]) {
  1396.         if(xtrn[xtrnnum]->path[1]==':')             /* drive letter specified */
  1397.             setdisk(toupper(xtrn[xtrnnum]->path[0])-'A');
  1398.         if(chdir(xtrn[xtrnnum]->path))
  1399.             errormsg(WHERE,ERR_CHDIR,xtrn[xtrnnum]->path,0); }
  1400.     external(cmdstr(xtrn[xtrnnum]->clean,path,nulstr,NULL)
  1401.         ,mode&~EX_INR); }
  1402. /* Re-open the logfile */
  1403. if(!(sys_status&SS_LOGOPEN)) {
  1404.     sprintf(str,"%sNODE.LOG",node_dir);
  1405.     if((logfile=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1)
  1406.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
  1407.     else
  1408.         sys_status|=SS_LOGOPEN; }
  1409.  
  1410. sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
  1411. batch_add_list(str);
  1412.  
  1413. sprintf(str,"%sHANGUP.NOW",node_dir);
  1414. if(fexist(str)) {
  1415.     remove(str);
  1416.     hangup(); }
  1417. if(online==ON_REMOTE) {
  1418.     checkline();
  1419.     if(!online) {
  1420.         sprintf(str,"%sHUNGUP.LOG",data_dir);
  1421.         if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
  1422.             errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
  1423.             return; }
  1424.         getnodedat(node_num,&thisnode,0);
  1425.         now=time(NULL);
  1426.         sprintf(str,hungupstr,useron.alias,xtrn[thisnode.aux-1]->name
  1427.             ,timestr(&now));
  1428.         write(file,str,strlen(str));
  1429.         close(file); } }
  1430. if(xtrn[xtrnnum]->misc&MODUSERDAT) {    /* Modify user data */
  1431.     moduserdat(xtrnnum);
  1432.     statusline(); }
  1433.  
  1434. }
  1435.  
  1436. /****************************************************************************/
  1437. /* This function will execute an external program if it is configured to    */
  1438. /* run during the event specified.                                          */
  1439. /****************************************************************************/
  1440. void user_event(char event)
  1441. {
  1442.     uint i;
  1443.  
  1444. for(i=0;i<total_xtrns;i++) {
  1445.     if(xtrn[i]->event!=event)
  1446.         continue;
  1447.     if(!chk_ar(xtrn[i]->ar,useron)
  1448.         || !chk_ar(xtrnsec[xtrn[i]->sec]->ar,useron))
  1449.         continue;
  1450.     exec_xtrn(i); }
  1451. }
  1452.  
  1453.  
  1454.