home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / MAILBOX.C < prev    next >
C/C++ Source or Header  |  1994-10-06  |  42KB  |  1,521 lines

  1. /* NOTE: because of size, the previous 'mailbox.c' and 'mailbox2.c'
  2.  * have been split in 5 parts:
  3.  * mboxcmd.c, containing the 'mbox' subcommands,
  4.  * mailbox.c, containing general mailbox user commands,
  5.  * mboxfile.c, containing file mailbox user commands,
  6.  * mboxmail.c, containing mail mailbox user commands, and
  7.  * mboxgate.c, containing gateway mailbox user commands.
  8.  * 940215 - WG7J
  9.  */
  10.   
  11. /* There are only two functions in this mailbox code that depend on the
  12.  * underlying protocol, namely mbx_getname() and dochat(). All the other
  13.  * functions can hopefully be used without modification on other stream
  14.  * oriented protocols than AX.25 or NET/ROM.
  15.  *
  16.  * SM0RGV 890506, most work done previously by W9NK
  17.  *
  18.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  19.  *      interface code; everything here uses C eol convention (\n)
  20.  *
  21.  *      Numerous new commands and other changes by SM0RGV, 900120
  22.  *
  23.  * Gateway function now support outgoing connects with the user's call
  24.  * with inverted ssid. Users can connect to system alias as well...
  25.  * See also several mods in socket.c,ax25.c and others
  26.  * 11/15/91, WG7J/PA3DIS
  27.  *
  28.  * Userlogging, RM,VM and KM commands, and R:-line interpretation
  29.  * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
  30.  *
  31.  * Inactivity timeout-disconnect added 920325 and later - WG7J
  32.  *
  33.  */
  34. #include <time.h>
  35. #include <ctype.h>
  36. #ifdef MSDOS
  37. #include <alloc.h>
  38. #endif
  39. #ifdef  UNIX
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #endif
  43. #include "global.h"
  44. #ifdef MAILBOX
  45. #include "timer.h"
  46. #include "proc.h"
  47. #include "socket.h"
  48. #include "usock.h"
  49. #include "session.h"
  50. #include "smtp.h"
  51. #include "dirutil.h"
  52. #include "telnet.h"
  53. #include "ftp.h"
  54. #include "ftpserv.h"
  55. #include "commands.h"
  56. #include "netuser.h"
  57. #include "files.h"
  58. #include "bm.h"
  59. #include "pktdrvr.h"
  60. #include "ax25.h"
  61. #include "mailbox.h"
  62. #include "ax25mail.h"
  63. #include "nr4mail.h"
  64. #include "cmdparse.h"
  65. #include "mailfor.h"
  66. #include "mailutil.h"
  67. #include "index.h"
  68.   
  69. struct mbx *Mbox;
  70. int BbsUsers;
  71. int Totallogins;
  72. extern int MbShowAliases;
  73.   
  74. #ifdef RLOGINSERVER
  75. static char DFAR RLoginbanner[] = "\nRemote Login at %s - %s\n\n";
  76. #endif
  77. char Loginbanner[] = "\nJNOS (%s)\n\n";
  78. char Mbwelcome[] = "\nWelcome %s,\n";
  79. char Mbbanner[] = "to the %s TCP/IP Mailbox (JNOS %s).\n";
  80. char CurUsers[] = "Currently %d user%s.\n";
  81.   
  82. #if defined MAILCMDS || defined FILECMDS
  83. char Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
  84. char MsgAborted[] = "Msg aborted\n";
  85. #endif
  86.   
  87. #ifdef MAILCMDS
  88. char MbCurrent[] = "Current msg# %d.\n";
  89. #endif
  90.   
  91. char Mbmenu[] = "?,"
  92. #ifdef MAILCMDS
  93. "A,"
  94. #endif
  95. "ALI,"
  96. "B,"
  97. #ifdef GATECMDS
  98. #if defined NETROM || defined AX25
  99. "C,"
  100. #endif
  101. #endif
  102. #ifdef CONVERS
  103. "CONV,"
  104. #endif
  105. #ifdef FILECMDS
  106. "D,"
  107. #endif
  108. #ifdef GATECMDS
  109. "E,"
  110. #endif
  111. #ifdef FOQ_CMDS
  112. "F,"
  113. #endif
  114. "H,I,IH,IP,J,"
  115. #ifdef MAILCMDS
  116. "K,L,"
  117. #endif
  118. "M,"
  119. #if defined GATECMDS && defined NETROM
  120. "N,NR,"
  121. #endif
  122. #if defined FOQ_CMDS && defined TTYLINKSERVER
  123. "O,"
  124. #endif
  125. #ifdef GATECMDS
  126. "P,PI,"
  127. #endif
  128. #if defined FOQ_CMDS && defined CALLCLI
  129. "Q,"
  130. #endif
  131. #ifdef MAILCMDS
  132. "R,S,"
  133. #endif
  134. #ifdef GATECMDS
  135. "T,"
  136. #endif
  137. #ifdef FILECMDS
  138. "U,"
  139. #endif
  140. #ifdef MAILCMDS
  141. "V,"
  142. #endif
  143. #ifdef FILECMDS
  144. "W,"
  145. #endif
  146. "X"
  147. #ifdef FILECMDS
  148. ",Z"
  149. #endif
  150. " >\n";
  151.   
  152. extern char Mbnrid[];
  153.  
  154. /* This is called by the finger-daemon */
  155. void
  156. listusers(s)
  157. int s;
  158. {
  159.     int outsave;
  160.     struct mbx m;
  161.   
  162.     m.privs = 0;
  163.     m.stype = ' ';
  164.   
  165. #ifdef notdef
  166.     usputs(s,"\nCurrent remote users:\n");
  167. #endif
  168.     outsave = Curproc->output;
  169.     Curproc->output = s;
  170.     dombusers(0,NULLCHARP,&m);
  171.     Curproc->output = outsave;
  172. }
  173.   
  174. struct mbx *
  175. newmbx()
  176. {
  177.     struct mbx *m,*new;
  178.   
  179.     if((new = (struct mbx *) callocw(1,sizeof(struct mbx))) == NULLMBX)
  180.         return NULLMBX;
  181.     BbsUsers++;
  182.     /* add it the list */
  183.     if((m=Mbox) == NULLMBX)
  184.         Mbox = new;
  185.     else {
  186.         while(m->next)
  187.             m=m->next;
  188.         m->next = new;
  189.     }
  190.     return new;
  191. }
  192.   
  193. static int
  194. mbx_getname(m)
  195. struct mbx *m;
  196. {
  197.     char *cp;
  198. #ifdef notdef
  199.     FILE *tfp;
  200. #endif
  201.     union sp sp;
  202.     char tmp[MAXSOCKSIZE];
  203.     int len = MAXSOCKSIZE;
  204.     int anony = 0;
  205.     int oldmode;
  206.     int founddigit=0;
  207.     int count=0;
  208. #ifdef AX25
  209.     int32 flags;
  210.     int ax_25 = 0;
  211.     struct usock *up;
  212. #endif
  213.   
  214.     sp.p = tmp;
  215.     sp.sa->sa_family = AF_LOCAL;    /* default to AF_LOCAL */
  216.     getpeername(m->user,tmp,&len);
  217.     m->family = sp.sa->sa_family;
  218.     m->path = mallocw(MBXLINE);
  219.     /* This is one of the two parts of the mbox code that depends on the
  220.      * underlying protocol. We have to figure out the name of the
  221.      * calling station. This is only practical when AX.25 or NET/ROM is
  222.      * used. Telnet users have to identify themselves by a login procedure.
  223.      */
  224.     switch(sp.sa->sa_family){
  225. #ifdef  AX25
  226.         case AF_AX25:
  227.         /* If this is not to the convers call, and this port is
  228.          * set for NO_AX25, then disconnect ! - WG7J
  229.          */
  230.             if((m->type != CONF_LINK) && ((up = itop(m->user)) != NULLUSOCK) ) {
  231.                 if((flags=up->cb.ax25->iface->flags) & NO_AX25)
  232.                     return -1;
  233.             }
  234.             ax_25 = 1;
  235.         /* note fallthrough */
  236.         case AF_NETROM:
  237.         /* NETROM and AX25 socket address structures are "compatible" */
  238.         /* Save user call, in case user wants to use gateway function */
  239.             memcpy(m->call,sp.ax->ax25_addr,AXALEN);
  240.             m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
  241.             pax25(m->name,sp.ax->ax25_addr);
  242.             cp = strchr(m->name,'-');
  243.             if(cp != NULLCHAR)                      /* get rid of SSID */
  244.                 *cp = '\0';
  245.         /* SMTP wants the name to be in lower case */
  246.             cp = m->name;
  247.             while(*cp){
  248.                 if(isupper(*cp))
  249.                     *cp = tolower(*cp);
  250.                 ++cp;
  251.             }
  252.             anony = 1;
  253.         /* Try to find the privileges of this user from the userfile */
  254.             if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,
  255.             &anony,ax_25 ? "ax25def" : "netdef")) == -1){
  256.                 m->privs = 0;
  257.                 free(m->path);
  258.                 m->path = NULLCHAR;
  259.             }
  260.             if(m->privs & EXCLUDED_CMD)
  261.                 return -1;
  262.             if(ax_25)
  263.                 if(((flags & USERS_ONLY) && (m->privs & IS_BBS)) ||
  264.                     ((flags & BBS_ONLY) && !(m->privs & IS_BBS)) ||
  265.                     ((flags & SYSOP_ONLY) && !(m->privs & SYSOP_CMD)))
  266.                     return -1;
  267.             return 0;
  268. #endif
  269.         case AF_LOCAL:
  270.         case AF_INET:
  271.             m->state = MBX_LOGIN;
  272. #ifdef RLOGINSERVER
  273.             if(m->type == RLOGIN_LINK)
  274.                tprintf(RLoginbanner,Hostname,Version);
  275.             else {
  276. #endif
  277.             tprintf(Loginbanner,Hostname);
  278.             if(Mtmsg != NULLCHAR)
  279.                 tputs(Mtmsg);
  280. #ifdef RLOGINSERVER
  281.             }
  282. #endif
  283.             for(;;){
  284.             /* Maximum of 3 tries - WG7J */
  285.                 if(count++ == 3)
  286.                     return -1;
  287.                 oldmode = sockmode(m->user,SOCK_ASCII);
  288.                 tputs("login: ");
  289.                 usflush(m->user);
  290.                 if(mbxrecvline(m) == -1)
  291.                     return -1;
  292.                 if(*m->line == 4) /* Control-d */
  293.                     return -1;
  294.                 if(*m->line == '\0')
  295.                     continue;
  296.             /* Chop off after name lenght */
  297.                 m->line[MBXNAME] = '\0';
  298.   
  299.             /* add a little test to avoid 'Mailfile busy' syndrome - WG7J
  300.              * Check for characters illegal in MS-DOS file names.
  301.              */
  302.                 for(cp = m->line;*cp != '\0';cp++)
  303.                     if(dosfnchr(*cp) == 0)
  304.                         break;
  305.                 if(*cp != '\0')
  306.                     continue;
  307.                 strcpy(m->name,m->line);
  308.                 tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
  309.                 usflush(m->user);
  310.                 sockmode(m->user,SOCK_BINARY);
  311.                 if(mbxrecvline(m) == -1)
  312.                     return -1;
  313.                 tprintf("%c%c%c",IAC,WONT,TN_ECHO);
  314.                 sockmode(m->user,oldmode);
  315.                 tputc('\n');
  316.                 usflush(m->user);
  317.             /* This is needed if the password was send before the
  318.              * telnet no-echo options were receied. We neeed to
  319.              * flush the eold sequence from the input buffers, sigh
  320.              */
  321.                 if(socklen(m->user,0))/* discard any remaining input */
  322.                     recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  323.                 if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,
  324.                 &anony,"tcpdef")) != -1){
  325.                     if(anony)
  326.                         log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
  327.                     else
  328.                         log(m->user,"MBOX login: %s",m->name);
  329.                     if(m->privs & EXCLUDED_CMD)
  330.                         return -1;
  331. #ifdef AX25
  332.             /*try to set the name as the user-call.
  333.              *this is a very crude test! Be careful...
  334.              *Login must have at leat 1 digit (0-9) in it,
  335.              *and it must be possible to convert it to a call.
  336.              *if this doesn't work, disallow the gateway command,
  337.              *no matter if this was allowed by priviledges or not.
  338.              *Be careful, some one with login name '4us' and
  339.              *permission set to allow gateway/netrom, will
  340.              *go out as '4us-15' or '4us-0' !!!!!
  341.              *11/15/91 WG7J/PA3DIS
  342.              */
  343.                     for(cp=m->name;*cp != '\0';cp++)
  344.                         if(isdigit((int)*cp))
  345.                             break;
  346.                     if(*cp != '\0')
  347.                         founddigit = 1;
  348.                     if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  349.                         m->privs &= ~AX25_CMD;
  350.                         m->privs &= ~NETROM_CMD;
  351.                     }
  352. #else
  353.                     m->privs &= ~AX25_CMD;
  354.                     m->privs &= ~NETROM_CMD;
  355.   
  356. #endif /* AX25 */
  357.             /* Set the morerows - WG7J */
  358.                     m->morerows = 20;
  359.                     return 0;
  360.                 }
  361.                 tputs("Login incorrect\n");
  362.                 log(m->user,"MBOX Login failed: %s, pw %s",m->name,m->line);
  363. #ifdef MAILERROR
  364.                 mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
  365. #endif
  366.                 *m->name = '\0';        /* wipe any garbage */
  367.             }
  368.     }
  369.     return 0;
  370. }
  371.   
  372. /* put up the prompt */
  373. void
  374. putprompt(m)
  375. struct mbx *m;
  376. {
  377.     char area[64];
  378.     char *cp1,*cp2;
  379.   
  380. #ifdef MAILCMDS
  381.     if(m->sid & MBX_SID)
  382.         tputs(">\n");
  383.     else {
  384. #endif
  385.         if(m->sid & MBX_NRID)
  386.             tputs(Mbnrid);
  387. #ifdef MAILCMDS
  388.         if(m->sid & MBX_AREA) {
  389.             cp1 = m->area;
  390.             cp2 = area;
  391.             /* Convert / and \ into . */
  392.             while(*cp1 != '\0') {
  393.                 if(*cp1=='/')
  394.                     *cp2 = '.';
  395.                 else
  396.                     *cp2 = *cp1;
  397.                 cp1++;
  398.                 cp2++;
  399.             }
  400.             *cp2 = '\0';
  401.             tprintf("Area: %s ",area);
  402.         }
  403. #endif
  404.         if(m->sid & MBX_EXPERT)
  405.             tputs(">\n");
  406.         else {
  407. #ifdef MAILCMDS
  408.             tprintf(MbCurrent,m->current);
  409. #endif
  410.             if(MbShowAliases && AliasList) {
  411.                 struct alias *a;
  412.   
  413.                 for(a=AliasList;a;a=a->next)
  414.                     tprintf("%s,",a->name);
  415.             }
  416.             tputs(Mbmenu);
  417.         }
  418.   
  419. #ifdef MAILCMDS
  420.     }
  421. #endif
  422. }
  423.   
  424. /* Incoming mailbox session */
  425. void
  426. mbx_incom(s,t,p)
  427. int s;
  428. void *t;
  429. void *p;
  430. {
  431.     struct tipcb *tip;
  432.     struct mbx *m,*mp,*pp;
  433.     struct usock *up;
  434.     struct alias *a;
  435.     char *buf[3];
  436.     char tmp[AXBUF];
  437.     int rval;
  438.     FILE *fp;
  439.     int newpriv = 0;
  440.   
  441. /*
  442.     if((up = itop(s)) != NULLUSOCK)
  443.     if(up->iface->flags & NO_AX25)
  444.  */
  445.   
  446.     sockmode(s,SOCK_ASCII);
  447.     sockowner(s,Curproc);   /* We own it now */
  448.     /* Secede from the parent's sockets, and use the network socket that
  449.      * was passed to us for both input and output. The reference
  450.      * count on this socket will still be 1; this allows the domboxbye()
  451.      * command to work by closing that socket with a single call.
  452.      * If we return, the socket will be closed automatically.
  453.      */
  454.     close_s(Curproc->output);
  455.     close_s(Curproc->input);
  456.     Curproc->output = Curproc->input = s;
  457.   
  458.     /* We'll do our own flushing right before we read input */
  459.     setflush(s,-1);
  460.   
  461.     if((m = newmbx()) == NULLMBX){
  462.         tputs("Too many mailbox sessions\n");
  463.         return;
  464.     }
  465.   
  466.     m->proc = Curproc;
  467.     m->user = s;
  468.     m->escape = 20;     /* default escape character is Ctrl-T */
  469.     m->type = (t == NULL) ? TELNET_LINK : (int) t;
  470.   
  471. #ifdef TIPSERVER
  472. #ifdef XMODEM
  473.     if(m->type == TIP_LINK) {
  474.         tip = (struct tipcb *) p;
  475.         tip->raw=0;
  476.         m->tip=tip;
  477.     }
  478. #endif
  479. #endif
  480.   
  481.     /* discard any remaining input */
  482.     /*
  483.     while(socklen(s,0))
  484.     recv_mbuf(s,NULL,0,NULLCHAR,0);
  485.     */
  486.   
  487.     /* get the name of the remote station */
  488.     if(mbx_getname(m) == -1) {
  489.         exitbbs(m);
  490.         return;
  491.     }
  492.     Totallogins++;
  493.     log(s,"MBOX open");
  494.   
  495. #ifdef RLOGINSERVER
  496.     if(m->type == RLOGIN_LINK) {
  497.        m->state = MBX_CMD;         /* start in command state */
  498.        tputc ('\n');
  499.        dosysop (1, (char **)0, (void *)m);
  500.        log(m->user, "MBOX exit: %s", m->name);     /* N5KNX: log exits */
  501.        exitbbs(m);
  502.        return;
  503.     }
  504. #endif
  505.  
  506.     if(m->privs & IS_BBS)
  507.         m->sid |= MBX_SID; /*force bbs status*/
  508.     else if(m->privs & IS_EXPERT)
  509.         m->sid |= MBX_EXPERT;
  510.   
  511.     loguser(m);
  512.     m->state = MBX_CMD;     /* start in command state */
  513. #ifdef MAILCMDS
  514.     tputs(MboxId);
  515. #endif
  516.   
  517.     /* Say 'hello' only if user is not a bbs - WG7J */
  518. #ifdef MAILCMDS
  519.     if(!(m->sid & MBX_SID+MBX_EXPERT)) {
  520. #endif
  521.   
  522. #ifdef USERLOG
  523.         tprintf(Mbwelcome,m->username ? m->username : m->name);
  524. #else
  525.         tprintf(Mbwelcome,m->name);
  526. #endif
  527.   
  528. #if defined AX25 || defined NETROM
  529.         if(m->family == AF_INET)
  530. #endif
  531.             tprintf(Mbbanner,Hostname,Version);
  532. #if defined AX25 || defined NETROM
  533.         else
  534.             tprintf(Mbbanner,pax25(tmp,Mycall),Version);
  535. #endif
  536.   
  537.         /* How many users are there currently ? */
  538.         tprintf(CurUsers,BbsUsers,BbsUsers == 1 ? "" : "s");
  539.   
  540. #ifdef MAILCMDS
  541.         /* Do we accept third party mail ? */
  542.         if(!ThirdParty)
  543.             tputs(Mbwarning);
  544. #endif
  545.         tputc('\n');
  546.   
  547.         /* Is there a message of the day ? */
  548.         if((fp = fopen(Motdfile,READ_TEXT)) != NULLFILE) {
  549.             sendfile(fp,m->user,ASCII_TYPE,0, m);
  550.             fclose(fp);
  551.         }
  552.   
  553. #ifdef MAILCMDS
  554.     }
  555.     if(!(m->sid & MBX_SID)) {
  556.         /* Enable our local message area,
  557.          * only if we're not a bbs - WG7J
  558.          */
  559.         buf[1] = m->name;
  560.         doarea(2,buf,m);
  561. #ifdef USERLOG
  562.         /* Tell about new arrived mail in message areas - WG7J */
  563.         if(Mbnewmail)
  564.             listnewmail(m,1);
  565.   
  566. #ifdef REGISTER
  567.         /* See if the username is empty. If so, the user hasn't
  568.          * registerd yet, so we need to beep and remind.
  569.          */
  570.         if(MbRegister && !m->username)
  571.             tprintf("\n\007Please type 'REGISTER' at the > prompt.\n");
  572. #endif /* REGISTER */
  573. #endif /* USERLOG */
  574.     }
  575. #endif /* MAILCMDS */
  576.   
  577.     /* Send prompt */
  578.     putprompt(m);
  579.   
  580.     /* now get commands */
  581.     while(mbxrecvline(m) != -1){
  582. #ifdef MAILCMDS
  583.         /* Only tell about new mail when in our own area - WG7J */
  584.         if(!(m->sid & MBX_SID)){
  585.             if(isnewprivmail(m) > 0L)
  586.                 newpriv = 1;
  587.             else
  588.                 newpriv = 0;
  589.             /* Do not check mailfile if we're bbs - WG7J*/
  590.             scanmail(m);
  591.         }
  592. #endif
  593.         /* check for an alias - WG7J */
  594.         if((a=findalias(m->line)) != NULL)
  595.             strcpy(m->line,a->cmd);
  596.   
  597.         if((rval = mbx_parse(m)) == -2)
  598.             break;
  599.         if(rval == 1)
  600.             tputs("Bad syntax.\n");
  601. #ifdef MAILCMDS
  602.         if(newpriv) {
  603.             tputs("You have new mail. ");
  604.             if(m->areatype != PRIVATE)
  605.                 tprintf("Change area with 'A %s'. ", m->name);
  606.             tputs("Please Kill when read!\n");
  607.         }
  608. #endif
  609.         putprompt(m);
  610.         m->state = MBX_CMD;
  611.     }
  612.     log(m->user, "MBOX exit: %s", m->name);    /* N5KNX: log exits */
  613.     exitbbs(m);
  614. }
  615.   
  616. void
  617. exitbbs(m)
  618. struct mbx *m;
  619. {
  620.     struct mbx *mp,*pp;
  621.     struct usock *up;
  622.   
  623.     /* Moving the socket close call to here
  624.      * will send a disconnect to the user before cleaning up
  625.      * the user's data structure. This gives a faster response perception
  626.      * to the user - WG7J
  627.      * N5KNX: but we must be careful to reset Curproc->{input,output} since
  628.      * otherwise killproc() will try again to close these sockets, and by
  629.      * then some other process may own it.  This sure is a kludge!
  630.      */
  631.     close_s(Curproc->output);
  632.     if (itop(Curproc->output) == NULLUSOCK) {
  633.         if (Curproc->input == Curproc->output) Curproc->input = -1;
  634.         Curproc->output = -1;
  635.     }
  636.   
  637.   
  638. #ifdef MAILCMDS
  639.     closenotes(m);
  640.     free(m->to);
  641.     free(m->tofrom);
  642.     free(m->origto);
  643.     free(m->origbbs);
  644.     free(m->subject);
  645.     free(m->date);
  646.     free(m->tomsgid);
  647. #endif
  648.     free(m->path);
  649.     free(m->startmsg);
  650. #ifdef USERLOG
  651.     free(m->username);
  652.     free(m->IPemail);
  653.     free(m->homebbs);
  654. #endif
  655. #ifdef MAILCMDS
  656.     /* Close the tempfiles if they are not nullpointers - WG7J */
  657.     if(m->tfile != (FILE *) 0)
  658.         fclose(m->tfile);
  659.     if(m->tfp != (FILE *) 0)
  660.         fclose(m->tfp);
  661.     if(m->mfile != (FILE *) 0)
  662.         fclose(m->mfile);
  663.     if(m->stdinbuf != NULLCHAR)
  664.         free(m->stdinbuf);
  665.     if(m->stdoutbuf != NULLCHAR)
  666.         free(m->stdoutbuf);
  667.     free((char *)m->mbox);
  668. #endif
  669.     /* now free it from list */
  670.     for(mp=Mbox,pp=NULLMBX;mp && mp!=m;pp=mp,mp=mp->next);
  671.     if(!mp)
  672.         /* what happened ??? */
  673.         return;
  674.     if(pp==NULLMBX)     /* first one on list */
  675.         Mbox = Mbox->next;
  676.     else
  677.         pp->next = m->next;
  678.     free((char *)m);
  679.     BbsUsers--;
  680. }
  681.   
  682. /**********************************************************************/
  683.   
  684. static struct cmds DFAR Mbcmds[] = {
  685. #ifdef MAILCMDS
  686.     "",             doreadnext,     0, 0, NULLCHAR,
  687. #endif
  688.     "?",            dombhelp,       0, 0, NULLCHAR,
  689. #ifdef MAILCMDS
  690.     "area",     doarea,     0, 0, NULLCHAR,
  691. #endif
  692.     "alias",    dombalias,  0, 0, NULLCHAR,
  693.     "bye",      domboxbye,  0, 0, NULLCHAR,
  694. #ifdef GATECMDS
  695. #if defined AX25 || defined NETROM
  696.     "connect",  dombconnect,0, 0, NULLCHAR,
  697. #endif
  698. #endif
  699. #ifdef CONVERS
  700.     "convers",  dombconvers,0, 0, NULLCHAR,
  701. #endif
  702. #ifdef FILECMDS
  703. #ifdef XMODEM
  704.     "download", dodownload, 0, 2, "D[U|X] <filename>",
  705. #else
  706.     "download", dodownload, 0, 2, "D[U] <filename>",
  707. #endif
  708. #endif
  709. #ifdef GATECMDS
  710.     "escape",       dombescape,     0, 0, NULLCHAR,
  711. #endif
  712. #ifdef FOQ_CMDS
  713.     "finger",       dombfinger,     0, 0, NULLCHAR,
  714. #endif
  715.     "help",         dombhelp,       0, 0, NULLCHAR,
  716.     "info",         dombhelp,       0, 0, NULLCHAR,
  717.     "iheard",   dombipheard,0, 0, NULLCHAR,
  718.     "iproute",  dombiproute,0, 0, NULLCHAR,
  719. #ifdef  AX25
  720.     "jheard",   dombjheard, 0, 0, NULLCHAR,
  721. #endif
  722. #ifdef MAILCMDS
  723.     "kill",     dodelmsg,   0, 0, NULLCHAR,
  724.     "list",     dolistnotes,0, 0, NULLCHAR,
  725. #endif
  726.     "mboxuser", dombusers,  0, 0, NULLCHAR,
  727. #if defined GATECMDS && defined NETROM
  728.     "nodes",    dombnrnodes,0, 0, NULLCHAR,
  729.     "nroutes",  dombnrneighbour, 0, 0, NULLCHAR,
  730. #endif
  731. #if defined FOQ_CMDS && defined TTYLINKSERVER
  732.     "operator", dochat,     0, 0, NULLCHAR,
  733. #endif
  734. #if defined GATECMDS && defined AX25
  735.     "ports",    dombports,  0, 0, NULLCHAR,
  736. #endif
  737. #ifdef GATECMDS
  738.     "ping",     dombping,   0, 2, "PI <host> [<len>] [<timeout>]",
  739. #endif
  740. #if defined FOQ_CMDS && defined CALLCLI
  741.     "query", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
  742. #endif
  743. #ifdef MAILCMDS
  744.     "read",     doreadmsg,  0, 0, NULLCHAR,
  745.     "send",         dosend,         0, 0, NULLCHAR,
  746. #if defined USERLOG && defined REGISTER
  747.     "register",     doregister,     0, 0, NULLCHAR,
  748. #endif
  749. #endif
  750. #ifdef GATECMDS
  751.     "telnet",   dombtelnet, 0, 2, "T hostname",
  752. #endif
  753. #ifdef FILECMDS
  754. #ifdef XMODEM
  755.     "upload",   dombupload, 0, 2, "U[U|X] <filename>",
  756. #else
  757.     "upload",   dombupload, 0, 2, "U[U] <filename>",
  758. #endif
  759. #endif
  760. #ifdef MAILCMDS
  761.     "verbose",  doreadmsg,  0, 0, NULLCHAR,
  762. #endif
  763. #ifdef FILECMDS
  764.     "what",     dowhat,     0, 0, NULLCHAR,
  765. #endif
  766.     "xpert",    dombexpert, 0, 0, NULLCHAR,
  767. #ifdef FILECMDS
  768.     "zap",      dozap,      0, 2, "Z filename",
  769. #endif
  770. #ifdef MAILCMDS
  771.     "[",        dosid,      0, 0, NULLCHAR,
  772. #ifdef MBFWD
  773.     "f>",       dorevfwd,   0, 0, NULLCHAR,
  774. #endif
  775. #endif
  776.     "@",        dosysop,    0, 0, NULLCHAR,
  777.     "***",      dostars,    0, 0, NULLCHAR,
  778.     ";",        dombsemicolon, 0, 0, NULLCHAR,
  779.     NULLCHAR,   NULLFP,     0, 0, "Huh?",
  780. };
  781.   
  782. /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
  783.  * They have to be treated specially since cmdparse() wants a space between
  784.  * the actual command and its arguments.
  785.  * "SP FOO" is converted to "s  foo" and the second command letter is saved
  786.  * in m->stype. Longer commands like "SEND" are unaffected, except for
  787.  * commands starting with "[", i.e. the SID, since we don't know what it will
  788.  * look like.
  789.  */
  790. static char twocmds[] =
  791. #ifdef MAILCMDS
  792. "aklrsv"
  793. #endif
  794. #ifdef FILECMDS
  795. "du"
  796. #endif
  797. "[mx";
  798.   
  799. int
  800. mbx_parse(m)
  801. struct mbx *m;
  802. {
  803.     char *cp;
  804.     int i;
  805.     char *newargv[2];
  806.   
  807.     /* Translate entire buffer to lower case */
  808.     for (cp = m->line; *cp != '\0'; ++cp)
  809.         if(isupper(*cp))
  810.             *cp = tolower(*cp);
  811.     /* Skip any spaces at the begining */
  812.     for(cp = m->line;isspace(*cp);++cp)
  813.         ;
  814.     m->stype = ' ';
  815.     if(*cp != '\0' && *(cp+1) != '\0') {
  816.         for(i=0; i<strlen(twocmds); ++i){
  817.             if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
  818.             || *cp == '[')){
  819.                 if(islower(*(++cp)))
  820.                     m->stype = toupper(*cp); /* Save the second character */
  821.                 else
  822.                     m->stype = *cp;
  823.                 *cp = ' ';
  824.                 break;
  825.             }
  826.         }
  827.     }
  828. #ifdef MAILCMDS
  829.     /* See if the input line consists solely of digits */
  830.     cp = m->line;
  831.     for(cp = m->line;isspace(*cp);++cp)
  832.         ;
  833.     newargv[1] = cp;
  834.     for(;*cp != '\0' && isdigit(*cp);++cp)
  835.         ;
  836.     if(*cp == '\0' && strlen(newargv[1]) > 0) {
  837.         newargv[0] = "r";
  838.         return doreadmsg(2,newargv,(void *)m);
  839.     } else
  840. #endif
  841.         return cmdparse(Mbcmds,m->line,(void *)m);
  842. }
  843.   
  844. /* This works like recvline(), but telnet options are answered and the
  845.  * terminating newline character is not put into the buffer. If the
  846.  * incoming character equals the value of escape, any queued input is
  847.  * flushed and -2 returned.
  848.  *
  849.  * mbxrecvline() now can gobble up suboptions - 94/02/14 VE4WTS
  850.  */
  851. int
  852. mbxrecvline(m)
  853. struct mbx *m;
  854. {
  855.     int s = m->user;
  856.     int escape = m->escape;
  857.     char *buf = m->line;
  858.     int c, cnt = 0, opt,cl;
  859.   
  860.     if(buf == NULLCHAR)
  861.         return 0;
  862.     usflush(Curproc->output);
  863.     alarm(Mbtdiscinit*1000L);   /* Start inactivity timeout - WG7J */
  864.     while((c = recvchar(s)) != EOF){
  865.         alarm(0L);
  866.         if(c == IAC){           /* Telnet command escape */
  867.             if((c = recvchar(s)) == EOF)
  868.                 break;
  869.             if(c >= 250 && c < 255 && (opt = recvchar(s)) != EOF){
  870.                 switch(c){
  871.                     case SB:
  872.                         opt=recvchar(s); /* Get the real option */
  873.                         if(opt==EOF)
  874.                             break;
  875.                         cl=opt;
  876.                         c=recvchar(s);
  877.                     /* Gobble up until we see IAC SE */
  878.                         while((c!=EOF) && !(cl==IAC && c==SE)){
  879.                         /* maybe check for timeout here, in case someone
  880.                            happened to send a binary file with the IAC SB
  881.                            sequence in it. */
  882.                             cl=c; /* keep track of second last char read */
  883.                             c=recvchar(s);
  884.                         }
  885.                     /* and tell the client where to go... */
  886.                     /* tprintf("%c%c%c",IAC,WONT,opt); */
  887.                         break;
  888.                     case WILL:
  889.                         if(opt==TN_LINEMODE){
  890.                         /* we WANT linemode */
  891.                             tprintf("%c%c%c",IAC,DO,opt);
  892.                         /* Tell client to do editing */
  893.                                 tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
  894.                         } else
  895.                             tprintf("%c%c%c",IAC,DONT,opt);
  896.                         break;
  897.                     case WONT:
  898.                         tprintf("%c%c%c",IAC,DONT,opt);
  899.                         break;
  900.                     case DO:
  901.                             tprintf("%c%c%c",IAC,WONT,opt);
  902.                             break;
  903.                     case DONT:
  904.                         tprintf("%c%c%c",IAC,WONT,opt);
  905.                 }
  906. /* to be fixed                  usflush(Curproc->output);*/
  907.                 continue;
  908.             }
  909.             if(c != IAC && (c = recvchar(s)) == EOF)
  910.                 break;
  911.         }
  912.         /* ordinary character */
  913.         if(c == '\r' || c == '\n')
  914.             break;
  915.         if(uchar(c) == escape){
  916.             if(socklen(s,0)) /* discard any remaining input */
  917.                 recv_mbuf(s,NULL,0,NULLCHAR,0);
  918.             cnt = -2;
  919.             break;
  920.         }
  921.         /* Handle <del> chars - from wa7tas */
  922.         if(c == 8 && cnt > 0) {
  923.             *--buf = 0;
  924.             cnt--;
  925.         } else {
  926.             *buf++ = c;
  927.             ++cnt;
  928.         }
  929.         if(cnt == MBXLINE - 1)
  930.             break;
  931.         alarm(Mbtdiscinit*1000L);   /* Restart inactivity timeout - WG7J */
  932.     }
  933.     if(c == EOF && cnt == 0)
  934.         return -1;
  935.     *buf = '\0';
  936.     return cnt;
  937. }
  938.   
  939. /* New forwarding option, simply ignore all data - WG7J */
  940. int
  941. dombsemicolon(int argc,char *argv[],void *p) {
  942.   
  943.     return 0;
  944. }
  945.   
  946. /* Determine what type of prompt is optimal, ie, can we read just one char? */
  947. int
  948. charmode_ok(m)
  949. struct mbx *m;
  950. {
  951.     if (m->type == TELNET_LINK || m->type == TIP_LINK) {
  952. #ifdef notdef
  953.         if ((up=itop(m->proc->output)) != NULLSOCK && up->type == TYPE_TCP) {
  954.             up->cb.tcb->??? can't get to telnet->session->ttystate.echo
  955.         }
  956. #endif
  957.         if (!(m->sid & MBX_LINEMODE)) return 1;   /* char mode OK (see XP cmd) */
  958.     }
  959.     return 0;
  960. }
  961.  
  962.   
  963. int
  964. domboxbye(argc,argv,p)
  965. int argc;
  966. char *argv[];
  967. void *p;
  968. {
  969.     struct mbx *m;
  970.   
  971.     m = (struct mbx *)p;
  972.   
  973.     /* for bbs's, just disconnect */
  974.     if(m->sid & MBX_SID)
  975.         return -2;
  976.   
  977. #ifdef USERLOG
  978. #ifdef MAILCMDS
  979.     setlastread(m);
  980. #endif
  981.     updatedefaults(m);
  982. #endif
  983.     /* Now say goodbye */
  984.     if(!(m->privs & MBX_EXPERT))
  985.         tprintf("\nThank you %s,\nfor calling %s JNOS.\n\n",
  986. #ifdef USERLOG
  987.         m->username ? m->username : m->name,
  988. #else
  989.         m->name,
  990. #endif
  991.         Hostname);
  992. #ifdef TIPSERVER
  993.     if(m->type == TIP_LINK)
  994.         tputs("Please hang up now.\n");
  995. #endif
  996.     usflush(m->user);
  997.     return -2;      /* signal that exitbbs() should be called */
  998. }
  999.   
  1000. static int
  1001. dombhelp(argc,argv,p)
  1002. int argc;
  1003. char *argv[];
  1004. void *p;
  1005. {
  1006.     char buf[FILE_PATH_SIZE];
  1007.     int i;
  1008.     FILE *fp;
  1009.     struct mbx *m = (struct mbx *)p;
  1010.   
  1011.     if(*argv[0] == '?') {
  1012.         if(MbShowAliases && AliasList) {
  1013.             struct alias *a;
  1014.   
  1015.             tputs("Aliases:");
  1016.             for(a=AliasList;a;a=a->next)
  1017.                 tprintf(" %s",a->name);
  1018.             tputc('\n');
  1019.         }
  1020.  
  1021.         sprintf(buf,"%s/longmenu.eng",Helpdir);
  1022.         if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  1023.             sendfile(fp,Curproc->output,ASCII_TYPE,0,m);
  1024.             fclose(fp);
  1025.         } else {
  1026.             tputs("No menu available.\n");
  1027.         }
  1028.         return 0;
  1029.     }
  1030.   
  1031.     buf[0] = '\0';
  1032.     if(argc > 1)
  1033.         for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
  1034.             if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
  1035.                 sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
  1036.                 break;
  1037.             }
  1038.     if(buf[0] == '\0')
  1039.         if(*argv[0] == 'i') {
  1040.             /* INFO command */
  1041.             tprintf(Nosversion,Version);
  1042.             sprintf(buf,"%s/info.hlp",Helpdir);
  1043.         } else
  1044.             sprintf(buf,"%s/help.hlp",Helpdir);
  1045.   
  1046.     if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  1047.         sendfile(fp,Curproc->output,ASCII_TYPE,0,m);
  1048.         fclose(fp);
  1049.     } else {
  1050.         if(*argv[0]!='i')
  1051.             tputs("No help available.\n");
  1052.     }
  1053.     return 0;
  1054. }
  1055.   
  1056. extern void dumproute __ARGS((struct route *rp,char *p));
  1057. extern char RouteHeader[];
  1058.   
  1059. /* Show non-private routes only */
  1060. int
  1061. dombiproute(argc,argv,p)
  1062. int argc;
  1063. char *argv[];
  1064. void *p;
  1065. {
  1066.     int i,bits;
  1067.     struct route *rp;
  1068.     struct mbx *m = (struct mbx *)p;
  1069.     char buf[85];
  1070.   
  1071.     if(m->privs & NO_LISTS) {
  1072.         tputs(Noperm);
  1073.         return 0;
  1074.     }
  1075.   
  1076.     tputs(RouteHeader);
  1077.     for(bits=31;bits>=0;bits--){
  1078.         for(i=0;i<HASHMOD;i++){
  1079.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  1080.                 if(!(rp->flags & RTPRIVATE)) {
  1081.                     dumproute(rp,buf);
  1082.                     if(tprintf("%s\n",&buf[4]) == EOF)
  1083.                         return 0;
  1084.                 }
  1085.             }
  1086.         }
  1087.     }
  1088.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
  1089.         dumproute(&R_default,buf);
  1090.         if(tprintf("%s\n",&buf[4]) == EOF)
  1091.             return 0;
  1092.     }
  1093.     return 0;
  1094. }
  1095.   
  1096.   
  1097. static int
  1098. dombexpert(argc,argv,p)
  1099. int argc;
  1100. char *argv[];
  1101. void *p;
  1102. {
  1103.     struct mbx *m;
  1104.   
  1105.     m = (struct mbx *)p;
  1106.   
  1107.     switch(m->stype) {
  1108.         case 'M':
  1109.             if(argc == 1)
  1110.                 tprintf("-more- after %d lines\n",m->morerows);
  1111.             else {
  1112.                 m->morerows = atoi(argv[1]);
  1113.             }
  1114.             break;
  1115.         case 'A':
  1116.             m->sid ^= MBX_AREA;
  1117.             break;
  1118.         case 'N':
  1119.             m->sid ^= MBX_NRID;
  1120.             break;
  1121.         case 'P':
  1122.             m->sid ^= MBX_LINEMODE;
  1123.             tprintf("LINEMODE is now %sabled\n", m->sid&MBX_LINEMODE ? "en" : "dis");
  1124.             break;
  1125.   
  1126. #if defined USERLOG && defined REGISTER
  1127.         case 'R':
  1128.             if(argc > 1) {
  1129.             /* Change the state of the 'Reply-to' header */
  1130.                 if(!stricmp(argv[1],"on"))
  1131.                     m->sid |= MBX_REPLYADDR;
  1132.                 else if(!stricmp(argv[1],"off"))
  1133.                     m->sid &= ~MBX_REPLYADDR;
  1134.             }
  1135.             tprintf("'Reply-to: %s' header is %sadded when sending mail.\n",
  1136.             ( m->IPemail ?
  1137.             ((m->sid & MBX_REPLYADDR) ? m->IPemail : "") :
  1138.             "" ),
  1139.             (m->sid & MBX_REPLYADDR) ? "" : "not " );
  1140.             if((m->sid & MBX_REPLYADDR) && !m->IPemail)
  1141.                 tprintf("Please 'register' to set your email reply-to address!\n");
  1142.             break;
  1143. #endif
  1144.   
  1145.         default:
  1146.             m->sid ^= MBX_EXPERT;
  1147.             break;
  1148.     }
  1149.     return 0;
  1150. }
  1151.   
  1152. #if defined FOQ_CMDS && defined TTYLINKSERVER
  1153. extern char SysopBusy[];
  1154.   
  1155. static int
  1156. dochat(argc,argv,p)
  1157. int argc;
  1158. char *argv[];
  1159. void *p;
  1160. {
  1161.     char buf[8], *newargv[3];
  1162.     struct mbx *m;
  1163.   
  1164.     m = (struct mbx *)p;
  1165.   
  1166.     if (MAttended) {
  1167.         m->state = MBX_CHAT;
  1168.         newargv[0] = "C";
  1169.         newargv[1] = Hostname;
  1170.         sprintf(buf,"%d",IPPORT_TTYLINK);
  1171.         newargv[2] = buf;
  1172.         m->startmsg = mallocw(50);
  1173.         sprintf(m->startmsg,"*** MBOX Chat with %s\n",m->name);
  1174.         return dombtelnet(3,newargv,p);
  1175.     } else {
  1176.         tputs(SysopBusy);
  1177.     }
  1178.     /* It returns only after a disconnect or refusal */
  1179.     return 0;
  1180. }
  1181. #endif /* TTYLINKSERVER */
  1182.   
  1183. static int
  1184. dombipheard(argc,argv,p)
  1185. int argc;
  1186. char *argv[];
  1187. void *p;
  1188. {
  1189.     struct mbx *m = (struct mbx *)p;
  1190.   
  1191.     if(m->privs & NO_LISTS) {
  1192.         tputs(Noperm);
  1193.         return 0;
  1194.     }
  1195.     return doipheard(argc,argv,NULL);
  1196. }
  1197.   
  1198. #ifdef AX25
  1199. static int
  1200. dombjheard(argc,argv,p)
  1201. int argc;
  1202. char *argv[];
  1203. void *p;
  1204. {
  1205.     struct iface *ifp;
  1206.     struct mbx *m = (struct mbx *)p;
  1207.   
  1208.     if(m->privs & NO_LISTS) {
  1209.         tputs(Noperm);
  1210.         return 0;
  1211.     }
  1212.   
  1213.     if(argc > 1){
  1214.         if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
  1215.         ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
  1216.             tprintf(Badinterface,argv[1]);
  1217.             return 0;
  1218.         }
  1219.         axheard(ifp);
  1220.         return 0;
  1221.     }
  1222.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  1223.         if((ifp->flags & LOG_AXHEARD)  && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
  1224.             if(axheard(ifp) == EOF)
  1225.                 break;
  1226.     }
  1227.     return 0;
  1228. }
  1229. #endif
  1230.   
  1231. #if defined FOQ_CMDS && defined CALLCLI
  1232. static int
  1233. dombcallbook(argc,argv,p)
  1234. int argc;
  1235. char *argv[];
  1236. void *p;
  1237. {
  1238.     struct mbx *m;
  1239.     char buf[8], *newargv[3];
  1240.     extern char *Callserver;
  1241.     int req, ret = 0;
  1242.   
  1243.     m = (struct mbx *) p;
  1244.   
  1245.     sprintf(buf,"%d",IPPORT_CALLDB);
  1246.     newargv[0] = "Q";
  1247.     newargv[1] = Callserver;
  1248.     newargv[2] = buf;
  1249.   
  1250.     for (req = 1; req < argc; req++)  {
  1251.         if(argv[req] == NULLCHAR)
  1252.             return ret;
  1253.         m->startmsg = mallocw(80);  /* is freed each time by gw_connect()         */
  1254.         sprintf(m->startmsg,"%s\n", argv[req]);
  1255.         log(m->user, "MBOX callbook %s: %s",m->name,argv[req]);
  1256.         tprintf("Looking for \" %s \" in the callbook at %s\n",argv[req],Callserver);
  1257.         ret = dombtelnet(3,newargv,p);
  1258.     }
  1259.     return ret; /* It looks like all possible returns are zero anyway!    */
  1260. }
  1261. #endif /* CALLCLI */
  1262.   
  1263. /*Password protection added - 920118, WG7J */
  1264. int
  1265. dosysop(argc,argv,p)
  1266. int argc;
  1267. char *argv[];
  1268. void *p;
  1269. {
  1270.     struct mbx *m;
  1271.     int c;
  1272.     int len,pwdc[5],i,valid=0;
  1273.     char *cp;
  1274.     extern struct cmds DFAR Cmds[];
  1275.   
  1276.     m = (struct mbx *) p;
  1277.     log(m->user,"MBOX: %s attempting SYSOP",m->name);
  1278.   
  1279.     /*If you want anyone with the password to go sysop-mode
  1280.      *comment out the next 4 line ! -WG7J
  1281.      */
  1282.     if(!(m->privs & SYSOP_CMD)){
  1283.         tputs(Noperm);
  1284. #ifdef MAILERROR
  1285.         mail_error("%s: SYSOP denied!\n",m->name);
  1286. #endif
  1287.         return 0;
  1288.     }
  1289.   
  1290.     /*only if set,
  1291.      *check for the password before letting users proceed
  1292.      */
  1293.     m->state = MBX_SYSOPTRY;
  1294.     if((len = strlen(Mbpasswd)) != 0) {;
  1295.         for (i=0;i<5;i++)
  1296.             tprintf("%d ",(pwdc[i]=RANDOM(len))); /*print the random chars*/
  1297.         tputc('\n');
  1298.         while(1) {
  1299.             c = mbxrecvline(m);
  1300.             if(c == EOF || c == -2)
  1301.                 return 0;
  1302.             if(*m->line == '\0')
  1303.                 break;
  1304.             cp = m->line;
  1305.             for(i=0;i<5;i++)
  1306.                 if(*cp++ != Mbpasswd[pwdc[i]])
  1307.                     break;
  1308.             if (i == 5)
  1309.                 valid = 1;
  1310.         }
  1311.         if(!valid)
  1312.             return 0;
  1313.     }
  1314.   
  1315.     log(m->user,"MBOX: %s is now SYSOP",m->name);
  1316.     m->state = MBX_SYSOP;
  1317.     tputs("\n\aType 'exit' to return\n");
  1318.   
  1319.     for(;;){
  1320.         tprintf("%lu Jnos> ",coreleft());
  1321.         usflush(Curproc->output);
  1322.         if(mbxrecvline(m) < 0)
  1323.             break;
  1324.         log(m->user,"MBOX sysop: %s",m->line);
  1325.         if(cmdparse(Cmds,m->line,NULL) == -2)
  1326.             break;
  1327.     }
  1328.     return 0;
  1329. }
  1330.   
  1331. /* Handle the "*** Done" command when reverse forwarding ends or the
  1332.  * "*** LINKED to" command.
  1333.  */
  1334. int
  1335. dostars(argc,argv,p)
  1336. int argc;
  1337. char *argv[];
  1338. void *p;
  1339. {
  1340.     struct mbx *m;
  1341.     int anony = 1;
  1342.     int founddigit = 0;
  1343.     long oldprivs;
  1344.     char *cp;
  1345.   
  1346.     m = (struct mbx *)p;
  1347.   
  1348.     /* Allow 'linked to' from anyone, but reset SYSOP priviledges
  1349.      * when the sysop-password is not set !
  1350.      * Also try to set the new call !
  1351.      * Inspired by Kurt, wb5bbw
  1352.      * Check for the strange TEXNET linked message !
  1353.      * 920220 - WG7J
  1354.      */
  1355.     if((argc >= 4) && !strcmp(argv[1],"linked") && !strcmp(argv[2],"to")) {
  1356.         if(m->privs & NO_LINKEDTO) {
  1357.             puts(Noperm);
  1358. #ifdef GWTRACE
  1359.             log(m->user,"MBOX LINKED: %s permission denied",m->name);
  1360. #endif
  1361.             return 0;
  1362.         }
  1363. #ifdef GWTRACE
  1364.         log(m->user,"MBOX LINKED: %s changed to %s",m->name,argv[3]);
  1365. #endif
  1366. #ifdef USERLOG
  1367. #ifdef MAILCMDS
  1368.         setlastread(m);
  1369. #endif
  1370.         updatedefaults(m);
  1371. #endif
  1372.         strcpy(m->name,argv[3]);
  1373.         oldprivs = m->privs; /*Save this !*/
  1374.         /* Try to find the privileges of this user from the userfile */
  1375.         if((m->privs = userlogin(m->name,NULLCHAR,&m->path,MBXLINE,
  1376.             &anony,"")) == -1)
  1377.             if((m->privs = userlogin("bbs",NULLCHAR,&m->path,
  1378.                 MBXLINE,&anony,"")) == -1)
  1379.                 if((m->privs = userlogin("anonymous",NULLCHAR,
  1380.                 &m->path,MBXLINE,&anony,"")) == -1){
  1381.                     m->privs = 0;
  1382.                     free(m->path);
  1383.                     m->path = NULLCHAR;
  1384.                 }
  1385.         if(m->privs & EXCLUDED_CMD)
  1386.             return domboxbye(0,NULLCHARP,p);
  1387. #ifdef AX25
  1388.     /* Set the call */
  1389.         for(cp=m->name;*cp != '\0';cp++)
  1390.             if(isdigit((int)*cp))
  1391.                 break;
  1392.         if(*cp != '\0')
  1393.             founddigit = 1;
  1394.         if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  1395.             m->privs &= ~AX25_CMD;
  1396.             m->privs &= ~NETROM_CMD;
  1397.         }
  1398. #else
  1399.         m->privs &= ~AX25_CMD;
  1400.         m->privs &= ~NETROM_CMD;
  1401. #endif
  1402.         /*Kill ssid in name, if any*/
  1403.         if((cp=strchr(m->name,'-')) != NULLCHAR)
  1404.             *cp = '\0';
  1405.         /* Check if sysop password is set,
  1406.          * if not, disallow sysop privs no matter what !
  1407.          */
  1408.         if(*Mbpasswd == '\0')
  1409.             m->privs &= ~SYSOP_CMD;
  1410.         /* Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
  1411.          * if so, dis-allow those no matter what
  1412.          * (so that users cannot get priviledges by issuing a ***linked)
  1413.          * 920220 - WG7J
  1414.          */
  1415.         if(oldprivs & NO_SENDCMD)
  1416.             m->privs |= NO_SENDCMD;
  1417.         if(oldprivs & NO_READCMD)
  1418.             m->privs |= NO_READCMD;
  1419.         if(oldprivs & NO_3PARTY)
  1420.             m->privs |= NO_3PARTY;
  1421.         if(oldprivs & NO_CONVERS)
  1422.             m->privs |= NO_CONVERS;
  1423.         if(oldprivs & NO_LISTS)
  1424.             m->privs |= NO_LISTS;
  1425.   
  1426.         /* Log this new user in */
  1427.         loguser(m);
  1428.   
  1429. #ifdef USERLOG
  1430.         tprintf("Oh, hello %s.\n",m->username ? m->username : m->name);
  1431. #else
  1432.         tprintf("Oh, hello %s.\n",m->name);
  1433. #endif
  1434.   
  1435. #ifdef MAILCMDS
  1436.         changearea(m,m->name);
  1437. #endif
  1438.         return 0;
  1439.     }
  1440.   
  1441.     if(argc > 1 && (m->sid & MBX_SID))      /* "*** Done" or similar */
  1442.         return -2;
  1443.     return -1;
  1444. }
  1445.   
  1446. #ifdef FOQ_CMDS
  1447. int
  1448. dombfinger(argc,argv,p)
  1449. int argc;
  1450. char *argv[];
  1451. void *p;
  1452. {
  1453.     struct mbx *m;
  1454.     char *host, *user = NULLCHAR, buf[8], *newargv[3];
  1455.   
  1456.     if(argc > 2){
  1457.         tputs("Usage: F user@host  or  F @host  or  F user.\n");
  1458.         return 0;
  1459.     }
  1460.     host = Hostname;
  1461.     if(argc == 2){
  1462.         if((host = strchr(argv[1], '@')) != NULLCHAR){
  1463.             *host = '\0';
  1464.             host++;
  1465.         } else
  1466.             host = Hostname;
  1467.         user = argv[1];
  1468.     }
  1469.     m = (struct mbx *) p;
  1470.     m->startmsg = mallocw(80);
  1471.     if(user != NULLCHAR)
  1472.         sprintf(m->startmsg,"%s\n",user);
  1473.     else
  1474.         strcpy(m->startmsg,"\n");
  1475.     newargv[0] = "";
  1476.     newargv[1] = host;
  1477.     sprintf(buf,"%d",IPPORT_FINGER);
  1478.     newargv[2] = buf;
  1479.     return dombtelnet(3,newargv,p);
  1480. }
  1481. #endif /* FOQ_CMDS */
  1482.   
  1483. #ifdef  CONVERS
  1484. extern int Mbconverse;
  1485. extern int CDefaultChannel;
  1486.   
  1487. int
  1488. dombconvers(argc,argv,p)
  1489. int argc;
  1490. char *argv[];
  1491. void *p;
  1492. {
  1493.     struct mbx *m = (struct mbx *)p;
  1494.     int channel = 0;
  1495.   
  1496.     if(m->privs & NO_CONVERS) {
  1497.         tputs(Noperm);
  1498. #ifdef MAILERROR
  1499.         mail_error("%s: converse denied\n",m->name);
  1500. #endif
  1501.         return 0;
  1502.     }
  1503.     if(!Mbconverse) {
  1504.         tputs("Mailbox Convers server not enabled\n");
  1505.         return 0;
  1506.     }
  1507.     m->state = MBX_CONVERS;
  1508.     if(argc > 1)
  1509.         channel = atoi(argv[1]);
  1510.     else
  1511.         channel = CDefaultChannel;
  1512. #ifdef GWTRACE
  1513.     log(m->user,"MBOX CONVERS: %s",m->name);
  1514. #endif
  1515.     mbox_converse(m,channel);
  1516.     return 0;
  1517. }
  1518. #endif /* CONVERS */
  1519.   
  1520. #endif /* MAILBOX */
  1521.