home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / main.c < prev    next >
C/C++ Source or Header  |  1991-08-20  |  27KB  |  1,183 lines

  1. /* Main-level network program:
  2.  * initialization
  3.  * keyboard processing
  4.  * generic user commands
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  */
  8. #include <stdio.h>
  9. #include <time.h>
  10. #if    defined(__TURBOC__) && defined(MSDOS)
  11. #include <fcntl.h>
  12. #include <dos.h>
  13. #include <io.h>
  14. #include <conio.h>
  15. #include <ctype.h>
  16. #include <dir.h>
  17. #endif
  18. #include "global.h"
  19. #include "config.h"
  20. #ifdef    ANSIPROTO
  21. #include <stdarg.h>
  22. #endif
  23. #include "mbuf.h"
  24. #include "timer.h"
  25. #include "proc.h"
  26. #include "iface.h"
  27. #include "ip.h"
  28. #include "tcp.h"
  29. #include "udp.h"
  30. #include "ax25.h"
  31. #include "kiss.h"
  32. #include "enet.h"
  33. #include "netrom.h"
  34. #include "ftpcli.h"
  35. #include "telnet.h"
  36. #include "tty.h"
  37. #include "session.h"
  38. #include "hardware.h"
  39. #include "usock.h"
  40. #include "socket.h"
  41. #include "cmdparse.h"
  42. #include "commands.h"
  43. #include "daemon.h"
  44. #include "devparam.h"
  45. #include "domain.h"
  46. #include "files.h"
  47. #include "main.h"
  48. #include "remote.h"
  49. #include "trace.h"
  50.  
  51. extern struct cmds Cmds[],Startcmds[],Stopcmds[],Attab[];
  52.  
  53. #if    (!defined(MSDOS) || defined(ESCAPE))    /* PC uses F-10 key always */
  54. static char Escape = 0x1d;    /* default escape character is ^] */
  55. #endif
  56.  
  57. #ifdef __TURBOC__
  58. int dofstat __ARGS((void));
  59. #endif
  60. char Badhost[] = "Unknown host %s\n";
  61. char *Hostname = NULLCHAR;
  62. char Nospace[] = "No space!!\n";    /* Generic malloc fail message */
  63. char *Motd = NULLCHAR;            /* Message Of The Day */
  64. int Attended = TRUE;            /* default to attended mode */
  65. int ThirdParty = TRUE;            /* Allows 3rd party mail by default */
  66. int main_exit = FALSE;            /* from main program (flag) */
  67. int Mprunning = 0;        /* flag for other parts (domain) to signal
  68.                  * that we are fully configured running.
  69.                  */
  70. struct proc *Cmdpp;
  71. struct proc *Display;
  72.  
  73. static char *DumpAddr = NULL;        /* Memory dump pointer */
  74. static char Prompt[] = "net> ";
  75. static FILE *Logfp;
  76. static time_t StartTime;        /* Time that NOS was started */
  77. static int Verbose;
  78.  
  79. static void ctohex __ARGS((char *buf,int16 c));
  80. static void fmtline __ARGS((int16 addr,char *buf,int16 len));
  81.  
  82. int
  83. main(argc,argv)
  84. int argc;
  85. char *argv[];
  86. {
  87.     char *inbuf,*intmp;
  88.     FILE *fp;
  89.     struct daemon *tp;
  90.     struct mbuf *bp;
  91.     int c;
  92.     int i;
  93.  
  94.     StartTime = time(&StartTime);            /* NOS Start_Up time */
  95.  
  96.     while((c = getopt(argc,argv,"s:d:bv")) != EOF){
  97.         switch(c){
  98.         case 's':    /* Number of sockets */
  99.             Nusock = atoi(optarg);
  100.             break;
  101.         case 'd':    /* Root directory for various files */
  102.             initroot(optarg);
  103.             break;
  104. #ifdef    __TURBOC__
  105.         case 'b':    /* Use BIOS for screen output */
  106.             directvideo = 0;
  107.             break;
  108. #endif
  109.         case 'v':
  110.             Verbose = 1;
  111.             break;
  112.         }
  113.     }
  114.     kinit();
  115.     ipinit();
  116.     ioinit();
  117.     sockinit();
  118.     Cmdpp = mainproc("cmdintrp");
  119.  
  120.     Sessions = (struct session *)callocw(Nsessions,sizeof(struct session));
  121.     Command = Lastcurr = newsession("command interpreter",COMMAND,0);
  122.     Command->flowmode = 1;        /* set 'more' paging on command screen */
  123.     Display = newproc("display",250,display,0,NULLCHAR,NULL,0);
  124.     tprintf("KA9Q NOS version %s\n%s\n",Version, Version2);
  125.     tprintf("Copyright 1990 by Phil Karn (KA9Q) and others.\n");
  126.     rflush();
  127.  
  128.     /* Start background Daemons */
  129.     for(tp=Daemons;;tp++){
  130.         if(tp->name == NULLCHAR)
  131.             break;
  132.         newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
  133.     }
  134.  
  135.     if(optind < argc){
  136.         /* Read startup file named on command line */
  137.         if((fp = fopen(argv[optind],READ_TEXT)) == NULLFILE)
  138.             tprintf("Can't read config file %s: %s\n",
  139.              argv[optind],sys_errlist[errno]);
  140.     } else {
  141.         /* Read default startup file named in files.c (autoexec.nos) */
  142.         if((fp = fopen(Startup,READ_TEXT)) == NULLFILE)
  143.             tprintf("Can't read default config file %s: %s\n",
  144.              Startup,sys_errlist[errno]);
  145.     }
  146.     if(fp != NULLFILE){
  147.         inbuf = mallocw(BUFSIZ);
  148.         intmp = mallocw(BUFSIZ);
  149.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  150.             strcpy(intmp,inbuf);
  151.             if(Verbose){
  152.                 tprintf("%s",intmp);
  153.                 rflush();
  154.             }
  155.             if(cmdparse(Cmds,inbuf,NULL) != 0){
  156.                 tprintf("input line: %s",intmp);
  157.             }
  158.         }
  159.         fclose(fp);
  160.         free(inbuf);
  161.         free(intmp);
  162.     }
  163.  
  164.     Mprunning = 1;    /* we are on speed now */
  165.  
  166.     /* Now loop forever, processing commands */
  167.     for(;;){
  168.         tprintf(Prompt);
  169.         usflush(Command->output);
  170.         if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
  171.             (void)cmdparse(Cmds,bp->data,Lastcurr);
  172.             free_p(bp);
  173.         }
  174.     }
  175. }
  176. /* Keyboard input process */
  177. void
  178. keyboard(i,v1,v2)
  179. int i;
  180. void *v1;
  181. void *v2;
  182. {
  183.     int c;
  184.     struct mbuf *bp;
  185.  
  186.     /* Keyboard process loop */
  187.     for(;;){
  188.         c = kbread();
  189. #if    (!defined(MSDOS) || defined(ESCAPE))
  190.         if(c == Escape && Escape != 0)
  191.             c = -2;
  192. #endif
  193.         if(c == -2 && Current != Command){
  194.             /* Save current tty mode and set cooked */
  195.             swapscreen(Current,Command);
  196.             Lastcurr = Current;
  197.             Current = Command;
  198.             /* set 'more' paging on command screen */
  199.             Command->flowmode = 1;
  200.         }
  201.  
  202.         Current->row = MOREROWS;
  203.         psignal(&Current->row,1);
  204.         if(c >= 0){
  205.             /* If the screen driver was in morewait state, this char
  206.              * has woken him up. Toss it so it doesn't also get taken
  207.              * as normal input. If the char was a command escape,
  208.              * however, it will be accepted; this gives the user
  209.              * a way out of lengthy output.
  210.              */
  211.             if(!Current->morewait
  212.              && (bp = ttydriv(Current,(char)c)) != NULLBUF){
  213.                 send_mbuf(Current->input,bp,0,NULLCHAR,0);
  214.             }
  215.         }
  216.     }
  217. }
  218. /* Standard commands called from main */
  219. int
  220. dodelete(argc,argv,p)
  221. int argc;
  222. char *argv[];
  223. void *p;
  224. {
  225.     int i;
  226.  
  227.     for(i=1;i < argc; i++){
  228.         if(unlink(argv[i]) == -1){
  229.             tprintf("Can't delete %s: %s\n",
  230.              argv[i],sys_errlist[errno]);
  231.         }
  232.     }
  233.     return 0;
  234. }
  235. int
  236. dorename(argc,argv,p)
  237. int argc;
  238. char *argv[];
  239. void *p;
  240. {
  241.     if(rename(argv[1],argv[2]) == -1)
  242.         tprintf("Can't rename: %s\n",sys_errlist[errno]);
  243.     return 0;
  244. }
  245. int
  246. doexit(argc,argv,p)
  247. int argc;
  248. char *argv[];
  249. void *p;
  250. {
  251.     int i;
  252.     time_t StopTime;
  253.  
  254.     StopTime = time(&StopTime);
  255.     main_exit = TRUE;    /* let everyone know we're out of here */
  256.     reset_all();
  257.     if(Dfile_updater != NULLPROC)
  258.         alert(Dfile_updater,0);    /* don't wait for timeout */
  259.     for(i=0;i<100;i++)
  260.         pwait(NULL);    /* Allow tasks to complete */
  261.         shuttrace();
  262.     log(-1,"NOS was stopped at %s", ctime(&StopTime));
  263.     if(Logfp){
  264.         fclose(Logfp);
  265.         Logfp = NULLFILE;
  266.     }
  267.     iostop();
  268.     exit(0);
  269.     return 0;    /* To satisfy lint */
  270. }
  271.  
  272. int
  273. dohostname(argc,argv,p)
  274. int argc;
  275. char *argv[];
  276. void *p;
  277. {
  278.     if(argc < 2)
  279.         tprintf("%s\n",Hostname);
  280.     else {
  281.         struct iface *ifp;
  282.         char *name;
  283.  
  284.                 if((ifp = if_lookup(argv[1])) != NULLIF){
  285.             if((name = resolve_a(ifp->addr, FALSE)) == NULLCHAR){
  286.                 tprintf("Interface address not resolved\n");
  287.                 return 1;
  288.             } else {
  289.                 if(Hostname != NULLCHAR)
  290.                     free(Hostname);
  291.                 Hostname = name;
  292.                 tprintf("Hostname set to %s\n", name );
  293.             }
  294.         } else {
  295.             if(Hostname != NULLCHAR)
  296.                 free(Hostname);
  297.             Hostname = strdup(argv[1]);
  298.             /* Remove trailing dot */
  299.             if(Hostname[strlen(Hostname)] == '.')
  300.                 Hostname[strlen(Hostname)] = '.';
  301.         }
  302.     }
  303.     return 0;
  304. }
  305.  
  306. int
  307. dolog(argc,argv,p)
  308. int argc;
  309. char *argv[];
  310. void *p;
  311. {
  312.     static char *logname;
  313.  
  314.     if(argc < 2){
  315.         if(Logfp)
  316.             tprintf("Logging to %s\n",logname);
  317.         else
  318.             tprintf("Logging off\n");
  319.         return 0;
  320.     }
  321.     if(Logfp){
  322.         log(-1,"NOS log closed");
  323.         fclose(Logfp);
  324.         Logfp = NULLFILE;
  325.         free(logname);
  326.         logname = NULLCHAR;
  327.     }
  328.     if(strcmp(argv[1],"stop") != 0){
  329.         logname = strdup(argv[1]);
  330.         Logfp = fopen(logname,APPEND_TEXT);
  331.         log(-1,"NOS v%s was started at %s", Version, ctime(&StartTime));
  332. #ifdef    MSDOS
  333.         log(-1,"NOS load information: CS=0x%04x DS=0x%04x", _CS, _DS);
  334. #endif
  335.     }
  336.     return 0;
  337. }
  338. int
  339. dohelp(argc,argv,p)
  340. int argc;
  341. char *argv[];
  342. void *p;
  343. {
  344.     register struct cmds *cmdp;
  345.     int i;
  346.     char buf[66];
  347.  
  348.     tprintf("Main commands:\n");
  349.     memset(buf,' ',sizeof(buf));
  350.     buf[64] = '\n';
  351.     buf[65] = '\0';
  352.     for(i=0,cmdp = Cmds;cmdp->name != NULL;cmdp++,i = (i+1)%4){
  353.         strncpy(&buf[i*16],cmdp->name,strlen(cmdp->name));
  354.         if(i == 3){
  355.             tprintf(buf);
  356.             memset(buf,' ',sizeof(buf));
  357.             buf[64] = '\n';
  358.             buf[65] = '\0';
  359.         }
  360.     }
  361.     if(i != 0)
  362.         tprintf(buf);
  363.     return 0;
  364. }
  365.  
  366. /* Attach an interface
  367.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  368.  */
  369. int
  370. doattach(argc,argv,p)
  371. int argc;
  372. char *argv[];
  373. void *p;
  374. {
  375.     return subcmd(Attab,argc,argv,p);
  376. }
  377. /* Manipulate I/O device parameters */
  378. int
  379. doparam(argc,argv,p)
  380. int argc;
  381. char *argv[];
  382. void *p;
  383. {
  384.     int param,set;
  385.     int32 val;
  386.     register struct iface *ifp;
  387.  
  388.     if((ifp = if_lookup(argv[1])) == NULLIF){
  389.         tprintf("Interface \"%s\" unknown\n",argv[1]);
  390.         return 1;
  391.     }
  392.     if(ifp->ioctl == NULL){
  393.         tprintf("Not supported\n");
  394.         return 1;
  395.     }
  396.     if(argc < 3){
  397.         for(param=1;param<=16;param++){
  398.             val = (*ifp->ioctl)(ifp,param,FALSE,0L);
  399.             if(val != -1)
  400.                 tprintf("%s: %ld\n",parmname(param),val);
  401.         }
  402.         return 0;
  403.     }
  404.     param = devparam(argv[2]);
  405.     if(param == -1){
  406.         tprintf("Unknown parameter %s\n",argv[2]);
  407.         return 1;
  408.     }
  409.     if(argc < 4){
  410.         set = FALSE;
  411.         val = 0L;
  412.     } else {
  413.         set = TRUE;
  414.         val = atol(argv[3]);
  415.     }
  416.     val = (*ifp->ioctl)(ifp,param,set,val);
  417.     if(val == -1){
  418.         tprintf("Parameter %s not supported\n",argv[2]);
  419.     } else {
  420.         tprintf("%s: %ld\n",parmname(param),val);
  421.     }
  422.     return 0;    
  423. }
  424.  
  425. /* Display or set IP interface control flags */
  426. int
  427. domode(argc,argv,p)
  428. int argc;
  429. char *argv[];
  430. void *p;
  431. {
  432.     register struct iface *ifp;
  433.  
  434.     if((ifp = if_lookup(argv[1])) == NULLIF){
  435.         tprintf("Interface \"%s\" unknown\n",argv[1]);
  436.         return 1;
  437.     }
  438.     if(argc < 3){
  439.         tprintf("%s: %s\n",ifp->name,
  440.          (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  441.         return 0;
  442.     }
  443.     switch(argv[2][0]){
  444.     case 'v':
  445.     case 'c':
  446.     case 'V':
  447.     case 'C':
  448.         ifp->flags = CONNECT_MODE;
  449.         break;
  450.     case 'd':
  451.     case 'D':
  452.         ifp->flags = DATAGRAM_MODE;
  453.         break;
  454.     default:
  455.         tprintf("Usage: %s [vc | datagram]\n",argv[0]);
  456.         return 1;
  457.     }
  458.     return 0;
  459. }
  460.  
  461. #if    (!defined(MSDOS) || defined(ESCAPE))
  462. int
  463. doescape(argc,argv,p)
  464. int argc;
  465. char *argv[];
  466. void *p;
  467. {
  468.     if(argc < 2)
  469.         tprintf("0x%x\n",Escape);
  470.     else 
  471.         Escape = *argv[1];
  472.     return 0;
  473. }
  474. #endif    MSDOS
  475. /* Generate system command packet. Synopsis:
  476.  * remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
  477.  */
  478. int
  479. doremote(argc,argv,p)
  480. int argc;
  481. char *argv[];
  482. void *p;
  483. {
  484.     struct sockaddr_in fsock;
  485.     int s,c;
  486.     char *data,x;
  487.     int16 port,len;
  488.     char *key = NULLCHAR;
  489.     int klen;
  490.     int32 addr = 0;
  491.     char *cmd,*host;
  492.  
  493.     port = IPPORT_REMOTE;    /* Set default */
  494.     optind = 1;        /* reinit getopt() */
  495.     while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
  496.         switch(c){
  497.         case 'a':
  498.             if((addr = resolve(optarg)) == 0){
  499.                 tprintf("Host %s unknown\n",optarg);
  500.                 return -1;
  501.             }
  502.             break;
  503.         case 'p':
  504.             port = atoi(optarg);
  505.             break;
  506.         case 'k':
  507.             key = optarg;
  508.             klen = strlen(key);
  509.             break;
  510.         case 's':
  511.             Rempass = strdup(optarg);
  512.             return 0;    /* Only set local password */
  513.         }
  514.     }
  515.     if(optind > argc - 2){
  516.         tprintf("Insufficient args\n");
  517.         return -1;
  518.     }
  519.     host = argv[optind++];
  520.     cmd = argv[optind];
  521.     if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
  522.         tprintf("socket failed\n");
  523.         return 1;
  524.     }
  525.     len = 1;
  526.     /* Did the user include a password or kickme target? */
  527.     if(addr != 0 && cmd[0] == 'k')
  528.         len += sizeof(int32);
  529.  
  530.     if(key != NULLCHAR && (cmd[0] == 'r' || cmd[0] == 'e')) 
  531.         len += klen;
  532.  
  533.     if(len == 1)
  534.         data = &x;
  535.     else
  536.         data = mallocw(len);
  537.  
  538.     fsock.sin_family = AF_INET;
  539.     if((fsock.sin_addr.s_addr = resolve(host)) == 0){
  540.         tprintf("Host %s unknown\n",host);
  541.         goto cleanup;
  542.     }
  543.     fsock.sin_port = port;
  544.  
  545.     switch(cmd[0]){
  546.     case 'r':
  547.         data[0] = SYS_RESET;
  548.         if(key != NULLCHAR)
  549.             strncpy(&data[1],key,klen);
  550.         break;
  551.     case 'e':
  552.         data[0] = SYS_EXIT;
  553.         if(key != NULLCHAR)
  554.             strncpy(&data[1],key,klen);
  555.         break;
  556.     case 'k':
  557.         data[0] = KICK_ME;
  558.         if(addr != 0)
  559.             put32(&data[1],addr);
  560.         break;
  561.     default:
  562.         tprintf("Unknown command %s\n",cmd);
  563.         goto cleanup;
  564.     }
  565.     /* Form the command packet and send it */
  566.     if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
  567.         tprintf("sendto failed: %s\n",sys_errlist[errno]);
  568.         goto cleanup;
  569.     }
  570. cleanup:
  571.     if(data != &x)
  572.         free(data);
  573.     close_s(s);
  574.     return 0;
  575. }
  576. int
  577. domore(argc,argv,p)
  578. int argc;
  579. char *argv[];
  580. void *p;
  581. {
  582.     struct session *sp;
  583.     FILE *fp;
  584.     char buf[81];
  585.     int row;
  586.  
  587.     if((sp = newsession(argv[1],MORE,0)) == NULLSESSION){
  588.         return -1;
  589.     }
  590.     /* Put tty into raw mode so single-char responses will work */
  591.     sp->ttystate.echo = sp->ttystate.edit = 0;
  592.     if((fp = fopen(argv[1],READ_TEXT)) == NULLFILE){
  593.         tprintf("Can't read %s\n",argv[1]);
  594.         keywait(NULLCHAR,1);
  595.         freesession(sp);
  596.         return 1;
  597.     }
  598.     row = MOREROWS;
  599.     while(fgets(buf,sizeof(buf),fp),!feof(fp)){
  600.         tprintf("%s",buf);
  601.         if(--row == 0){
  602.             row = keywait("--More--",0);
  603.             switch(row){
  604.             case -1:
  605.             case 'q':
  606.             case 'Q':
  607.                 goto done;
  608.             case '\n':
  609.             case '\r':
  610.                 row = 1;
  611.                 break;
  612.             case ' ':
  613.             default:
  614.                 row = MOREROWS;
  615.             }
  616.         }
  617.     }
  618. done:    fclose(fp);
  619.     keywait(NULLCHAR,1);
  620.     freesession(sp);
  621.     return 0;
  622. }
  623.  
  624. int
  625. dotail(argc,argv,p)
  626. int argc;
  627. char *argv[];
  628. void *p;
  629. {
  630.     register int handle, i;
  631.     register unsigned line = 0, rdsize = 2000;
  632.     long length;
  633.     char *buffer;
  634.  
  635.     buffer = callocw(2000, sizeof (char));
  636.  
  637.     if ((handle = open (argv[1], O_BINARY | O_RDONLY)) == -1) {
  638.         tprintf("Can't open input file %s: %s\n",
  639.          argv[1],sys_errlist[errno]);
  640.         free(buffer);
  641.         return -1;
  642.     }
  643.     length = filelength(handle);
  644.  
  645.     if (length > 2000) {
  646.         length -= 2000;
  647.     } else {
  648.         rdsize = (int) length;
  649.         length = 0;
  650.     }
  651.  
  652.     lseek (handle, length, SEEK_SET);
  653.     if (read (handle, buffer, rdsize) == -1) {
  654.         tprintf("Can't read input file %s: %s\n",
  655.          argv[1],sys_errlist[errno]);
  656.         close(handle);
  657.         free(buffer);
  658.         return -1;
  659.     }
  660.  
  661.     for (i = rdsize - 1; i > 0; i--) {
  662.         if (buffer[i] == '\n')
  663.             line++;
  664.         if (line == 18)
  665.             break;
  666.     }
  667.     for (; i < rdsize; i++)
  668.         tputc(buffer[i]);
  669.  
  670.     tprintf("\n");
  671.     close(handle);
  672.     free(buffer);
  673.     return 0;
  674. }
  675.  
  676. /* No-op command */
  677. int
  678. donothing(argc,argv,p)
  679. int argc;
  680. char *argv[];
  681. void *p;
  682. {
  683.     return 0;
  684. }
  685.  
  686. /* Log messages of the form
  687.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  688.  */
  689. #if    defined(ANSIPROTO)
  690. void
  691. log(int s,char *fmt, ...)
  692. {
  693.     va_list ap;
  694.     char *cp;
  695.     long t;
  696.     int i;
  697.     struct sockaddr fsocket;
  698. #ifdef    MSDOS
  699.     int fd;
  700. #endif
  701.  
  702.     if(Logfp == NULLFILE)
  703.         return;
  704.  
  705.     time(&t);
  706.     cp = ctime(&t);
  707.     rip(cp);
  708.     i = SOCKSIZE;
  709.     fprintf(Logfp,"%s",cp);
  710.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  711.         fprintf(Logfp," %s",psocket(&fsocket));
  712.  
  713.     fprintf(Logfp," - ");
  714.     va_start(ap,fmt);
  715.     vfprintf(Logfp,fmt,ap);
  716.     va_end(ap);
  717.     fprintf(Logfp,"\n");
  718.     fflush(Logfp);
  719. #ifdef    MSDOS
  720.     /* MS-DOS doesn't really flush files until they're closed */
  721.     fd = fileno(Logfp);
  722.     if((fd = dup(fd)) != -1)
  723.         close(fd);
  724. #endif
  725.  
  726. }
  727. #else
  728. /*VARARGS2*/
  729. void
  730. log(s,fmt,arg1,arg2,arg3,arg4,arg5)
  731. int s;
  732. char *fmt;
  733. int arg1,arg2,arg3,arg4,arg5;
  734. {
  735.     char *cp;
  736.     long t;
  737.     int fd,i;
  738.     struct sockaddr fsocket;
  739.  
  740.     if(Logfp == NULLFILE)
  741.         return;
  742.     time(&t);
  743.     cp = ctime(&t);
  744.     rip(cp);
  745.     i = SOCKSIZE;
  746.     fprintf(Logfp,"%s",cp);
  747.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  748.         fprintf(Logfp," %s",psocket(&fsocket));
  749.  
  750.     fprintf(Logfp," - ");
  751.     fprintf(Logfp,fmt,arg1,arg2,arg3,arg4,arg5);
  752.     fprintf(Logfp,"\n");
  753.     fflush(Logfp);
  754. #ifdef    MSDOS
  755.     /* MS-DOS doesn't really flush files until they're closed */
  756.     fd = fileno(Logfp);
  757.     if((fd = dup(fd)) != -1)
  758.         close(fd);
  759. #endif
  760. }
  761. #endif
  762.  
  763. int
  764. dosource(argc,argv,p)
  765. int argc;
  766. char *argv[];
  767. void *p;
  768. {
  769.     int linenum = 0;
  770.     char *inbuf,*intmp;
  771.     FILE *fp;
  772.  
  773.     /* Read command source file */
  774.     if((fp = fopen(argv[1],READ_TEXT)) == NULLFILE){
  775.         tprintf("Can't read source file %s: %s\n",
  776.          argv[1],sys_errlist[errno]);
  777.         return 1;
  778.     }
  779.  
  780.     inbuf = malloc(BUFSIZ);
  781.     intmp = malloc(BUFSIZ);
  782.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  783.         strcpy(intmp,inbuf);
  784.         linenum++;
  785.         if(Verbose)
  786.             tprintf("%s",intmp);
  787.         if(cmdparse(Cmds,inbuf,NULL) != 0){
  788.             tprintf("*** file \"%s\", line %d: %s\n",
  789.                 argv[1],linenum,intmp);
  790.         }
  791.     }
  792.     fclose(fp);
  793.     free(inbuf);
  794.     free(intmp);
  795.     return 0;
  796. }
  797.  
  798. /* if unattended mode is set - restrict ax25, telnet and maybe other sessions */
  799. doattended(argc,argv,p)
  800. int argc;
  801. char *argv[];
  802. void *p;
  803. {
  804.     return setbool(&Attended,"Attended flag",argc,argv);
  805. }
  806.  
  807. /* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
  808. dothirdparty(argc,argv,p)
  809. int argc;
  810. char *argv[];
  811. void *p;
  812. {
  813.     return setbool(&ThirdParty,"Third-Party mail flag",argc,argv);
  814. }
  815.  
  816. int
  817. domdump(argc,argv,p)
  818. int argc;
  819. char *argv[];
  820. void *p;
  821. {
  822.     unsigned int i;
  823.     char * addr;
  824.     unsigned int len = 8 * 16;    /* default is 8 lines of hex dump */
  825.  
  826.     if(argc < 2 || argc > 3) {
  827.         tprintf("Usage:- dump <hex-address | .> [decimal-range] \n");
  828.         return 0;
  829.     }
  830.     if(argv[1][0] == '.')
  831.         addr = DumpAddr;        /* Use last end address */
  832.     else
  833.         addr = ltop(htol(argv[1]));    /* get address of item being dumped */
  834.  
  835.     if(argc == 3) {
  836.         len = atoi(argv[2]);
  837.         len = ((len + 15) >> 4) << 4;    /* round up to modulo 16 */
  838.     }
  839.  
  840.     if(len < 1 || len > 256) {
  841.         tprintf("Invalid dump range. Valid is 1 to 256\n");
  842.         return 0;
  843.     }
  844.     tprintf("            Main Memory Dump Of Location %Fp\n", addr);
  845.     tprintf("Addr (offset)           Hexadecimal                         Ascii\n");
  846.     tprintf("----                    -----------                         -----\n\n");
  847.  
  848.     for(i = 0; i < len; i += 16)
  849.         fmtline(i, (char *)(addr + i), 16);
  850.     DumpAddr = (char *)(addr + i);        /* update address */
  851.     return 0;
  852. }
  853.  
  854. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  855.  * translation, e.g.,
  856.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  857.  */
  858. static void
  859. fmtline(addr,buf,len)
  860. int16 addr;
  861. char *buf;
  862. int16 len;
  863. {
  864.     char line[81];
  865.     register char *aptr,*cptr;
  866.     register char c;
  867.  
  868.     memset(line,' ',sizeof(line));
  869.     ctohex(line,(int16)hibyte(addr));
  870.     ctohex(line+2,(int16)lobyte(addr));
  871.     aptr = &line[6];
  872.     cptr = &line[55];
  873.     while(len-- != 0){
  874.         c = *buf++;
  875.         ctohex(aptr,(int16)uchar(c));
  876.         aptr += 3;
  877.         c &= 0x7f;
  878.         if((c > 0x1f) && (c < 0x7f))
  879.             *cptr++ = c;
  880.         else
  881.             *cptr++ = '.';
  882.     }
  883.     *cptr++ = '\0';
  884.     tprintf("%s\n",line);
  885. }
  886. /* Convert byte to two ascii-hex characters */
  887. static void
  888. ctohex(buf,c)
  889. register char *buf;
  890. register int16 c;
  891. {
  892.     static char hex[] = "0123456789abcdef";
  893.  
  894.     *buf++ = hex[hinibble(c)];
  895.     *buf = hex[lonibble(c)];
  896. }
  897.  
  898. dostatus(argc,argv,p)
  899. int argc;
  900. char *argv[];
  901. void *p;
  902. {
  903.     time_t nowtime, elapsedtime;
  904.     unsigned int days,hrs,mins,secs;
  905.  
  906.     nowtime = time(&nowtime);            /* current time */
  907.     elapsedtime = nowtime - StartTime;        /* nos elapsed time */
  908.  
  909.     tprintf("KA9Q Internet Protocol Package, v%s\n%s\n\n",Version, Version2);
  910.  
  911. #ifdef    MSDOS
  912.     tprintf("NOS load information:   Code Segment = %04x - Data Segment = %04x\n\n", _CS, _DS);
  913. #endif
  914.     tprintf("The system time is %s", ctime(&nowtime));
  915.     tprintf("NOS was started on %s\n", ctime(&StartTime));
  916.     secs = elapsedtime % 60;
  917.     elapsedtime = elapsedtime / 60;
  918.     mins = elapsedtime % 60;
  919.     elapsedtime = elapsedtime / 60;
  920.     hrs = elapsedtime % 24;
  921.     elapsedtime = elapsedtime / 24;
  922.     days = elapsedtime;
  923.     tprintf("Elapsed time => %u days:%02u hours:%02u minutes:%02u seconds.\n\n",days,hrs,mins,secs);
  924.     tprintf("The station is currently %sttended.\n", Attended ? "A" : "Una");
  925.     tprintf("The 'Message Of The Day' is ");
  926.     if(Motd != NULLCHAR)
  927.         tprintf("\n%s",Motd);
  928.     else
  929.         tprintf("not set!\n");
  930. #ifdef    __TURBOC__
  931.     dofstat();        /* print status of open files */
  932. #endif
  933.     return 0;
  934. }
  935.  
  936. int
  937. domotd(argc,argv,p)
  938. int argc;
  939. char *argv[];
  940. void *p;
  941. {
  942.     if(argc > 2) {
  943.         tprintf("Usage: motd \"<your message>\"\n");
  944.         return 1;
  945.     }
  946.  
  947.     if(argc < 2) {
  948.         if(Motd != NULLCHAR) 
  949.             tprintf("%s",Motd);
  950.     } else {
  951.         if(Motd != NULLCHAR){
  952.             free(Motd);
  953.             Motd = NULLCHAR;        /* reset the pointer */
  954.         }
  955.  
  956.         if(!strlen(argv[1]))
  957.             return 0;            /* clearing the buffer */
  958.  
  959.         Motd = mallocw(strlen(argv[1])+5);    /* allow for the EOL char etc */
  960.         strcpy(Motd, argv[1]);
  961.         strcat(Motd, "\n");            /* add the EOL char */
  962.     }
  963.     return 0;
  964. }
  965.  
  966. #ifdef    __TURBOC__
  967. /*
  968.  * Fstat utility code.
  969.  * Converted to go into NOS by Kelvin Hill - G1EMM  April 9, 1990
  970.  */
  971.  
  972. extern unsigned char _osmajor;
  973.  
  974. static char    *localcopy(char far *);
  975. static char    *progname(unsigned int);
  976.  
  977. int
  978. dofstat()
  979. {
  980.     union REGS regs;
  981.     struct SREGS segregs;
  982.     char far *pfiletab, far * pnext, far * fp;
  983.     char far *name, file[13], far * plist, far * entry;
  984.     char ownername[9], ownerext[5];
  985.     int nfiles, i, j, numhandles, entrylen;
  986.     unsigned int access, devinfo, progpsp;
  987.     long length, offset;
  988.     int heading = 0;
  989.  
  990.     regs.h.ah = 0x52;    /* DOS list of lists */
  991.     intdosx(®s, ®s, &segregs);
  992.  
  993.     /* make a pointer to start of master list */
  994.     plist = (char far *) MK_FP(segregs.es, regs.x.bx);
  995.  
  996.     /* pointer to start of file table */
  997.     pfiletab = (char far *) MK_FP(*(int far *) (plist + 6), *(int far *) (plist + 4));
  998.  
  999.     switch (_osmajor) {
  1000.     case 2:
  1001.         entrylen = 40;    /* DOS 2.x */
  1002.         break;
  1003.     case 3:
  1004.         entrylen = 53;    /* DOS 3.x */
  1005.         break;
  1006.     case 4:
  1007.     case 5:            /* DOS 5.x - like dos 4.x */
  1008.         entrylen = 59;    /* DOS 4.x - I do not know what is in the
  1009.                  * extra 6 bytes */
  1010.         break;
  1011.     default:
  1012.         tprintf("Sorry, cannot handle this version of MS-DOS");
  1013.         return 1;
  1014.     }
  1015.  
  1016.     for (;;) {
  1017.         /* pointer to next file table */
  1018.         pnext = (char far *) MK_FP(*(int far *) (pfiletab + 2), *(int far *) (pfiletab + 0));
  1019.         nfiles = *(int far *) (pfiletab + 4);
  1020. #ifdef DEBUG
  1021.         tprintf("\nFile table at %Fp entries for %d files\n", pfiletab, nfiles);
  1022. #endif
  1023.         for (i = 0; i < nfiles; i++) {
  1024.  
  1025.             /*
  1026.              * cycle through all files, quit when we reach an
  1027.              * unused entry
  1028.              */
  1029.             entry = pfiletab + 6 + (i * entrylen);
  1030.             if (_osmajor >= 3) {
  1031.                 name = entry + 32;
  1032.                 strncpy(file, localcopy(name), 11);
  1033.                 file[11] = '\0';
  1034.                 numhandles = *(int far *) (entry + 0);
  1035.                 access = (int) *(char far *) (entry + 2);
  1036.                 length = *(long far *) (entry + 17);
  1037.                 offset = *(long far *) (entry + 21);
  1038.                 devinfo = *(int far *) (entry + 5);
  1039.                 progpsp = *(int far *) (entry + 49);
  1040.             } else {
  1041.                 name = entry + 4;
  1042.                 strncpy(file, localcopy(name), 11);
  1043.                 file[11] = '\0';
  1044.                 numhandles = (int) *(char far *) (entry + 0);
  1045.                 access = (int) *(char far *) (entry + 1);
  1046.                 length = *(long far *) (entry + 19);
  1047.                 offset = *(long far *) (entry + 36);
  1048.                 devinfo = (int) *(char far *) (entry + 27);
  1049.             }
  1050.             if ((strlen(file) > 0) && (numhandles > 0) && !(devinfo & 0x80)) {
  1051.                 if(!heading) {
  1052.                     tprintf("\n");
  1053.                     tprintf("                 Table of Open Files.\n");
  1054.                     tprintf("                 --------------------\n");
  1055.                     tprintf("Name           length   offset hnd acc PSP device type/owner\n");
  1056.                     tprintf("----           ------   ------ --- --- --- -----------------\n");
  1057.                     heading++;        /* header now printed */
  1058.                 }
  1059.                 tprintf("%8.8s.%3.3s %8ld %8ld  %2d ",
  1060.                        file, &file[8], length, offset, numhandles);
  1061.                 switch (access) {
  1062.                 case 0:
  1063.                     tprintf("r  ");
  1064.                     break;
  1065.                 case 1:
  1066.                     tprintf("w  ");
  1067.                     break;
  1068.                 case 2:
  1069.                     tprintf("rw ");
  1070.                     break;
  1071.                 default:
  1072.                     tprintf("   ");
  1073.                 }
  1074.                 if (_osmajor >= 3)
  1075.                     tprintf("%04X ", progpsp);
  1076.                 else
  1077.                     tprintf("---- ");
  1078.                 tprintf("drive %c: ", 'A' + (devinfo & 0x1F));
  1079.                 if (devinfo & 0x8000)
  1080.                     tprintf("(network) ");
  1081.                 if (_osmajor >= 3) {
  1082.                     /*
  1083.                      * only DOS 3+ can find out
  1084.                      * the name of the program
  1085.                      */
  1086.                     fnsplit(progname(progpsp), NULL, NULL, ownername, ownerext);
  1087.                     tprintf("   [%s%s]\n", strlwr(ownername), strlwr(ownerext));
  1088.                 } else {
  1089.                     tprintf("\n");
  1090.                 }
  1091.             }
  1092.             if (strlen(file) == 0)
  1093.                 return 0;
  1094.         }
  1095.         pfiletab = pnext;
  1096.     }
  1097. }
  1098.  
  1099. /* Make a copy of a string pointed to by a far pointer */
  1100. static char *
  1101. localcopy(s)
  1102. char far *s;
  1103. {
  1104.     static char localstring[256];
  1105.     char far *p = s;
  1106.     char *l = localstring;
  1107.     int i = 0;
  1108.  
  1109.     while (*p != NULL && i++ < 255) {
  1110.         *l++ = *p++;
  1111.     }
  1112.  
  1113.     *l = '\0';
  1114.  
  1115.     return (localstring);
  1116. }
  1117.  
  1118. /*
  1119.  * Return a near pointer to a character string with the full path name of the
  1120.  * program whose PSP is given in the argument.  If the argument is invalid,
  1121.  * this may return gibberish but I don't know how to tell Offset 0x2C in the
  1122.  * PSP in the segment address of the environment of a program.  Beyond the
  1123.  * last environment string is a null marker, a word count (usually 1), then
  1124.  * the full pathname of the owner of the environment This only works for DOS
  1125.  * 3+
  1126.  */
  1127. static char *
  1128. progname(pid)
  1129. unsigned int pid;
  1130. {
  1131.     unsigned far   *envsegptr;    /* Pointer to seg address of
  1132.                      * environment */
  1133.     char far       *envptr;    /* Pointer to pid's environment     */
  1134.     unsigned far   *envsizeptr;    /* Pointer to environment size */
  1135.     unsigned        envsize;/* Size of pid's environment */
  1136.     unsigned        ppid;    /* Parent psp address */
  1137.  
  1138.     /* find the parent process psp at offset 0x16 of the psp */
  1139.     ppid = *(unsigned far *) MK_FP(pid, 0x16);
  1140.  
  1141.     /* find the environment at offset 2Ch of the psp */
  1142.     envsegptr = (unsigned far *) MK_FP(pid, 0x2C);
  1143.     envptr = (char far *) MK_FP(*envsegptr, 0);
  1144.  
  1145.     /*
  1146.      * Make a pointer that contains the size of the environment block.
  1147.      * Must point back one paragraph (to the environments MCB plus three
  1148.      * bytes forward (to the MCB block size field).
  1149.      */
  1150.     envsizeptr = (unsigned far *) MK_FP(*envsegptr - 1, 0x3);
  1151.     envsize = *envsizeptr * 16;    /* x 16 turns it into bytes */
  1152.  
  1153.     while (envsize > 0) {
  1154.         /* search for end of environment block, or NULL */
  1155.         while (--envsize && *envptr++);
  1156.  
  1157.         /*
  1158.          * Now check for another NULL immediately following the first
  1159.          * one located and a word count of 0001 following that.
  1160.          */
  1161.         if (!*envptr && *(unsigned far *) (envptr + 1) == 0x1) {
  1162.             envptr += 3;
  1163.             break;
  1164.         }
  1165.     }
  1166.  
  1167.     if (envsize > 0) {
  1168.         /* Owner name found - return it */
  1169.         return (localcopy(envptr));
  1170.     } else {
  1171.         if (pid == ppid) {
  1172.             /*
  1173.              * command.com doesn't leave it's name around, but if
  1174.              * pid = ppid then we know we have a shell
  1175.              */
  1176.             return ("-shell-");
  1177.         } else {
  1178.             return ("unknown");
  1179.         }
  1180.     }
  1181. }
  1182. #endif
  1183.