home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / MAIN.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  15KB  |  726 lines

  1. /* Main-level NOS program:
  2.  *  initialization
  3.  *  keyboard processing
  4.  *  generic user commands
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  */
  8.  
  9. /****************************************************************************
  10. *    $Id: main.c 1.4 93/07/16 11:46:42 ROOT_DOS Exp $
  11. *    14 Jul 93    1.4        GT    Banner changes.                                    *
  12. ****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <time.h>
  16. #if    defined(__TURBOC__) && defined(MSDOS)
  17. #include <io.h>
  18. #include <conio.h>
  19. #endif
  20. #include "global.h"
  21. #ifdef    ANSIPROTO
  22. #include <stdarg.h>
  23. #endif
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #include "ip.h"
  29. #include "tcp.h"
  30. #include "udp.h"
  31. #include "ax25.h"
  32. #include "kiss.h"
  33. #include "enet.h"
  34. #include "netrom.h"
  35. #include "ftpcli.h"
  36. #include "telnet.h"
  37. #include "tty.h"
  38. #include "session.h"
  39. #include "hardware.h"
  40. #include "usock.h"
  41. #include "socket.h"
  42. #include "cmdparse.h"
  43. #include "commands.h"
  44. #include "daemon.h"
  45. #include "devparam.h"
  46. #include "domain.h"
  47. #include "files.h"
  48. #include "main.h"
  49. #include "remote.h"
  50. #include "trace.h"
  51.  
  52. extern struct cmds Cmds[],Startcmds[],Stopcmds[],Attab[];
  53.  
  54. #ifdef MSDOS
  55. int Escape = 324;    /* MSDOS escape character is F10 */
  56. #else
  57. char Escape = 0x1d;    /* default escape character is ^] */
  58. #endif
  59.  
  60. char Badhost[] = "Unknown host %s\n";
  61. char *Hostname;
  62. char Nospace[] = "No space!!\n";    /* Generic malloc fail message */
  63. struct proc *Cmdpp;
  64. struct proc *Display;
  65. int main_exit = FALSE;            /* from main program (flag) */
  66.  
  67. static char Prompt[] = "net> ";
  68. static FILE *Logfp;
  69. static time_t StartTime;        /* time that NOS was started */
  70. static int Verbose;
  71.  
  72. static char banner1[] = "KA9Q NOS version %s\n";
  73. static char banner2[] = "Copyright 1991 by Phil Karn, KA9Q\n";
  74. static char banner3[] = "Parts copyright 1992, 1993 Demon Internet and members\n";
  75. static char banner4[] = "Support: mail internet@demon.net or phone 081 343 3881\n";
  76.  
  77. int
  78. main(argc,argv)
  79. int argc;
  80. char *argv[];
  81. {
  82.     char *inbuf,*intmp;
  83.     FILE *fp;
  84.     struct daemon *tp;
  85.     struct mbuf *bp;
  86.     int c;
  87.  
  88.     StartTime = time(&StartTime);
  89.  
  90.     while((c = getopt(argc,argv,"s:d:bv")) != EOF){
  91.         switch(c){
  92.         case 's':    /* Number of sockets */
  93.             Nusock = atoi(optarg);
  94.             break;
  95.         case 'd':    /* Root directory for various files */
  96.             initroot(optarg);
  97.             break;
  98. #ifdef    __TURBOC__
  99.         case 'b':    /* Use BIOS for screen output */
  100.             directvideo = 0;
  101.             break;
  102. #endif
  103.         case 'v':
  104.             Verbose = 1;
  105.             break;
  106.         }
  107.     }
  108.     kinit();
  109.     ipinit();
  110.     ioinit();
  111.     sockinit();
  112.     Cmdpp = mainproc("cmdintrp");
  113.  
  114.     Sessions = (struct session *)callocw(Nsessions,sizeof(struct session));
  115.     Command = Lastcurr = newsession("command interpreter",COMMAND);
  116.     Display = newproc("display",250,display,0,NULLCHAR,NULL,0);
  117.     tprintf(banner1, Version);
  118.     tprintf(banner2);
  119.     tprintf(banner3);
  120.     tprintf(banner4);
  121.     rflush();
  122.  
  123.     /* Start background Daemons */
  124.     for(tp=Daemons;;tp++){
  125.         if(tp->name == NULLCHAR)
  126.             break;
  127.         newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
  128.     }
  129.  
  130.     if(optind < argc){
  131.         /* Read startup file named on command line */
  132.         if((fp = fopen(argv[optind],READ_TEXT)) == NULLFILE)
  133.             tprintf("Can't read config file %s: %s\n",
  134.              argv[optind],sys_errlist[errno]);
  135.     } else {
  136.         fp = fopen(Startup,READ_TEXT);
  137.     }
  138.     if(fp != NULLFILE){
  139.         inbuf = mallocw(BUFSIZ);
  140.         intmp = mallocw(BUFSIZ);
  141.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  142.             strcpy(intmp,inbuf);
  143.             if(Verbose)
  144.                 tprintf("%s",intmp);
  145.             if(cmdparse(Cmds,inbuf,NULL) != 0){
  146.                 tprintf("input line: %s",intmp);
  147.             }
  148.         }
  149.         fclose(fp);
  150.         free(inbuf);
  151.         free(intmp);
  152.     }
  153.     /* Now loop forever, processing commands */
  154.     for(;;){
  155.         tprintf(Prompt);
  156.         usflush(Command->output);
  157.         if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
  158.             (void)cmdparse(Cmds,bp->data,Lastcurr);
  159.             free_p(bp);
  160.         }
  161.     }
  162. }
  163. /* Keyboard input process */
  164. void
  165. keyboard(i,v1,v2)
  166. int i;
  167. void *v1;
  168. void *v2;
  169.     {
  170.     int c;
  171.     struct mbuf *bp;
  172.     /* Keyboard process loop */
  173.     Current->cur_pos = 0;
  174.     for(;;)
  175.         {
  176.         c = kbread();
  177.         if(c == -2 && Current != Command)
  178.             {
  179.             /* Save current tty mode and set cooked */
  180.             swapscreen(Current,Command);
  181.             Lastcurr = Current;
  182.             Current = Command;
  183.             }
  184.         Current->row = MOREROWS;
  185.         psignal(&Current->row,1);
  186.         if(c >= 0)
  187.             {
  188.             /* If the screen driver was in morewait state, this char
  189.              * has woken him up. Toss it so it doesn't also get taken
  190.              * as normal input. If the char was a command escape,
  191.              * however, it will be accepted; this gives the user
  192.              * a way out of lengthy output.
  193.              */
  194.             if (!Current->morewait
  195.                 && (bp = ttydriv(Current,c)) != NULLBUF)
  196.                 {
  197.                 send_mbuf(Current->input,bp,0,NULLCHAR,0);
  198.                 Current->cur_pos = 0;
  199.                 }
  200.             }
  201.         }
  202.     }
  203. /* Standard commands called from main */
  204. int
  205. dodelete(argc,argv,p)
  206. int argc;
  207. char *argv[];
  208. void *p;
  209. {
  210.     int i;
  211.  
  212.     for(i=1;i < argc; i++){
  213.         if(unlink(argv[i]) == -1){
  214.             tprintf("Can't delete %s: %s\n",
  215.              argv[i],sys_errlist[errno]);
  216.         }
  217.     }
  218.     return 0;
  219. }
  220. int
  221. dorename(argc,argv,p)
  222. int argc;
  223. char *argv[];
  224. void *p;
  225. {
  226.     if(rename(argv[1],argv[2]) == -1)
  227.         tprintf("Can't rename: %s\n",sys_errlist[errno]);
  228.     return 0;
  229. }
  230. int
  231. doexit(argc,argv,p)
  232. int argc;
  233. char *argv[];
  234. void *p;
  235. {
  236.     int i;
  237.     time_t StopTime;
  238.  
  239.     StopTime = time(&StopTime);
  240.     main_exit = TRUE;    /* let everyone know we're out of here */
  241.     reset_all();
  242.     if(Dfile_updater != NULLPROC)
  243.         alert(Dfile_updater,0);    /* don't wait for timeout */
  244.     for(i=0;i<100;i++)
  245.         pwait(NULL);    /* Allow tasks to complete */
  246.     shuttrace();
  247.     log(-1,"NOS was stopped at %s", ctime(&StopTime));
  248.     if(Logfp){
  249.         fclose(Logfp);
  250.         Logfp = NULLFILE;
  251.     }
  252.     iostop();
  253.     exit(0);
  254.     return 0;    /* To satisfy lint */
  255. }
  256. int
  257. dohostname(argc,argv,p)
  258. int argc;
  259. char *argv[];
  260. void *p;
  261. {
  262.     if(argc < 2)
  263.         tprintf("%s\n",Hostname);
  264.     else {
  265.         struct iface *ifp;
  266.         char *name;
  267.  
  268.         if((ifp = if_lookup(argv[1])) != NULLIF){
  269.             if((name = resolve_a(ifp->addr, FALSE)) == NULLCHAR){
  270.                 tprintf("Interface address not resolved\n");
  271.                 return 1;
  272.             } else {
  273.                 if(Hostname != NULLCHAR)
  274.                     free(Hostname);
  275.                 Hostname = name;
  276.  
  277.                 /* remove trailing dot */
  278.                 if ( Hostname[strlen(Hostname)] == '.' ) {
  279.                     Hostname[strlen(Hostname)] = '\0';
  280.                 }
  281.                 tprintf("Hostname set to %s\n", name );
  282.             }
  283.         } else {
  284.             if(Hostname != NULLCHAR)
  285.                 free(Hostname);
  286.             Hostname = strdup(argv[1]);
  287.         }
  288.     }
  289.     return 0;
  290. }
  291. int
  292. dolog(argc,argv,p)
  293. int argc;
  294. char *argv[];
  295. void *p;
  296. {
  297.     static char *logname;
  298.  
  299.     if(argc < 2){
  300.         if(Logfp)
  301.             tprintf("Logging to %s\n",logname);
  302.         else
  303.             tprintf("Logging off\n");
  304.         return 0;
  305.     }
  306.     if(Logfp){
  307.         log(-1,"NOS log closed");
  308.         fclose(Logfp);
  309.         Logfp = NULLFILE;
  310.         free(logname);
  311.         logname = NULLCHAR;
  312.     }
  313.     if(strcmp(argv[1],"stop") != 0){
  314.         logname = strdup(argv[1]);
  315.         Logfp = fopen(logname,APPEND_TEXT);
  316.         log(-1,"NOS was started at %s", ctime(&StartTime));
  317. #ifdef MSDOS
  318.         log(-1,"NOS load information: CS=0x%04x DS=0x%04x", _CS, _DS);
  319. #endif
  320.     }
  321.     return 0;
  322. }
  323.  
  324. int
  325. dosource(argc,argv,p)
  326. int argc;
  327. char *argv[];
  328. void *p;
  329. {
  330.     int linenum = 0;
  331.     char *inbuf,*intmp, *p1, *p2;
  332.     FILE *fp;
  333.  
  334.     /* Read command source file */
  335.     if((fp = fopen(argv[1],READ_TEXT)) == NULLFILE){
  336.         tprintf("Can't read %s: %s\n",argv[1],sys_errlist[errno]);
  337.         return 1;
  338.     }
  339.  
  340.     p1 = inbuf = malloc(BUFSIZ);
  341.     p2 = intmp = malloc(BUFSIZ);
  342.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  343.         strcpy(intmp,inbuf);
  344.         linenum++;
  345.         if(Verbose)
  346.             tprintf("%s",intmp);
  347.         if(cmdparse(Cmds,inbuf,NULL) != 0){
  348.             tprintf("*** file \"%s\", line %d: %s\n",
  349.                 argv[1],linenum,intmp);
  350.         }
  351.     }
  352.     fclose(fp);
  353.     free(p1);
  354.     free(p2);
  355.     return 0;
  356. }
  357.  
  358. int
  359. dohelp(argc,argv,p)
  360. int argc;
  361. char *argv[];
  362. void *p;
  363. {
  364.     register struct cmds *cmdp;
  365.     int i;
  366.     char buf[66];
  367.  
  368.     tprintf(banner1, Version);
  369.     tprintf(banner2);
  370.     tprintf(banner3);
  371.     tprintf(banner4);
  372.     tprintf("Main commands:\n");
  373.     memset(buf,' ',sizeof(buf));
  374.     buf[64] = '\n';
  375.     buf[65] = '\0';
  376.     for(i=0,cmdp = Cmds;cmdp->name != NULL;cmdp++,i = (i+1)%4){
  377.         strncpy(&buf[i*16],cmdp->name,strlen(cmdp->name));
  378.         if(i == 3){
  379.             tprintf(buf);
  380.             memset(buf,' ',sizeof(buf));
  381.             buf[64] = '\n';
  382.             buf[65] = '\0';
  383.         }
  384.     }
  385.     if(i != 0)
  386.         tprintf(buf);
  387.     return 0;
  388. }
  389. /* Attach an interface
  390.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  391.  */
  392. int
  393. doattach(argc,argv,p)
  394. int argc;
  395. char *argv[];
  396. void *p;
  397. {
  398.     return subcmd(Attab,argc,argv,p);
  399. }
  400. /* Manipulate I/O device parameters */
  401. int
  402. doparam(argc,argv,p)
  403. int argc;
  404. char *argv[];
  405. void *p;
  406. {
  407.     register struct iface *ifp;
  408.     int param,set;
  409.     int32 val;
  410.  
  411.     if((ifp = if_lookup(argv[1])) == NULLIF){
  412.         tprintf("Interface \"%s\" unknown\n",argv[1]);
  413.         return 1;
  414.     }
  415.     if(ifp->ioctl == NULL){
  416.         tprintf("Not supported\n");
  417.         return 1;
  418.     }
  419.     if(argc < 3){
  420.         for(param=1;param<=16;param++){
  421.             val = (*ifp->ioctl)(ifp,param,FALSE,0L);
  422.             if(val != -1)
  423.                 tprintf("%s: %ld\n",parmname(param),val);
  424.         }
  425.         return 0;
  426.     }
  427.     param = devparam(argv[2]);
  428.     if(param == -1){
  429.         tprintf("Unknown parameter %s\n",argv[2]);
  430.         return 1;
  431.     }
  432.     if(argc < 4){
  433.         set = FALSE;
  434.         val = 0L;
  435.     } else {
  436.         set = TRUE;
  437.         val = atol(argv[3]);
  438.     }
  439.     val = (*ifp->ioctl)(ifp,param,set,val);
  440.     if(val == -1){
  441.         tprintf("Parameter %s not supported\n",argv[2]);
  442.     } else {
  443.         tprintf("%s: %ld\n",parmname(param),val);
  444.     }
  445.     return 0;
  446. }
  447.  
  448. /* Display or set IP interface control flags */
  449. int
  450. domode(argc,argv,p)
  451. int argc;
  452. char *argv[];
  453. void *p;
  454. {
  455.     register struct iface *ifp;
  456.  
  457.     if((ifp = if_lookup(argv[1])) == NULLIF){
  458.         tprintf("Interface \"%s\" unknown\n",argv[1]);
  459.         return 1;
  460.     }
  461.     if(argc < 3){
  462.         tprintf("%s: %s\n",ifp->name,
  463.          (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  464.         return 0;
  465.     }
  466.     switch(argv[2][0]){
  467.     case 'v':
  468.     case 'c':
  469.     case 'V':
  470.     case 'C':
  471.         ifp->flags = CONNECT_MODE;
  472.         break;
  473.     case 'd':
  474.     case 'D':
  475.         ifp->flags = DATAGRAM_MODE;
  476.         break;
  477.     default:
  478.         tprintf("Usage: %s [vc | datagram]\n",argv[0]);
  479.         return 1;
  480.     }
  481.     return 0;
  482. }
  483.  
  484. int
  485. doescape(argc,argv,p)
  486. int argc;
  487. char *argv[];
  488. void *p;
  489. {
  490.     if(argc < 2)
  491.         tprintf("%d\n",Escape);
  492.     else if (strlen(argv[1]) == 1)
  493.         Escape = *argv[1];
  494.     else Escape = atoi(argv[1]);
  495.     return 0;
  496. }
  497.  
  498. /* Generate system command packet. Synopsis:
  499.  * remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
  500.  */
  501. int
  502. doremote(argc,argv,p)
  503. int argc;
  504. char *argv[];
  505. void *p;
  506. {
  507.     struct sockaddr_in fsock;
  508.     int s,c;
  509.     char *data,x;
  510.     int16 port,len;
  511.     char *key = NULLCHAR;
  512.     int klen;
  513.     int32 addr = 0;
  514.     char *cmd,*host;
  515.  
  516.     port = IPPORT_REMOTE;    /* Set default */
  517.     optind = 1;        /* reinit getopt() */
  518.     while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
  519.         switch(c){
  520.         case 'a':
  521.             addr = resolve(optarg);
  522.             break;
  523.         case 'p':
  524.             port = atoi(optarg);
  525.             break;
  526.         case 'k':
  527.             key = optarg;
  528.             klen = strlen(key);
  529.             break;
  530.         case 's':
  531.             Rempass = strdup(optarg);
  532.             return 0;    /* Only set local password */
  533.         }
  534.     }
  535.     if(optind > argc - 2){
  536.         tprintf("Insufficient args\n");
  537.         return -1;
  538.     }
  539.     host = argv[optind++];
  540.     cmd = argv[optind];
  541.     if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
  542.         tprintf("socket failed\n");
  543.         return 1;
  544.     }
  545.     len = 1;
  546.     /* Did the user include a password or kickme target? */
  547.     if(addr != 0)
  548.         len += sizeof(int32);
  549.  
  550.     if(key != NULLCHAR)
  551.         len += klen;
  552.  
  553.     if(len == 1)
  554.         data = &x;
  555.     else
  556.         data = mallocw(len);
  557.  
  558.     fsock.sin_family = AF_INET;
  559.     fsock.sin_addr.s_addr = resolve(host);
  560.     fsock.sin_port = port;
  561.  
  562.     switch(cmd[0]){
  563.     case 'r':
  564.         data[0] = SYS_RESET;
  565.         if(key != NULLCHAR)
  566.             strncpy(&data[1],key,klen);
  567.         break;
  568.     case 'e':
  569.         data[0] = SYS_EXIT;
  570.         if(key != NULLCHAR)
  571.             strncpy(&data[1],key,klen);
  572.         break;
  573.     case 'k':
  574.         data[0] = KICK_ME;
  575.         if(addr != 0)
  576.             put32(&data[1],addr);
  577.         break;
  578.     default:
  579.         tprintf("Unknown command %s\n",cmd);
  580.         goto cleanup;
  581.     }
  582.     /* Form the command packet and send it */
  583.     if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
  584.         tprintf("sendto failed: %s\n",sys_errlist[errno]);
  585.         goto cleanup;
  586.     }
  587. cleanup:
  588.     if(data != &x)
  589.         free(data);
  590.     close_s(s);
  591.     return 0;
  592. }
  593. int
  594. domore(argc,argv,p)
  595. int argc;
  596. char *argv[];
  597. void *p;
  598. {
  599.     struct session *sp;
  600.     FILE *fp;
  601.     char buf[81];
  602.     int row;
  603.  
  604.     if((sp = newsession(argv[1],MORE)) == NULLSESSION){
  605.         return -1;
  606.     }
  607.     /* Put tty into raw mode so single-char responses will work */
  608.     sp->ttystate.echo = sp->ttystate.edit = 0;
  609.     if((fp = fopen(argv[1],READ_TEXT)) == NULLFILE){
  610.         tprintf("Can't read %s\n",argv[1]);
  611.         keywait(NULLCHAR,1);
  612.         freesession(sp);
  613.         return 1;
  614.     }
  615.     row = MOREROWS;
  616.     while(fgets(buf,sizeof(buf),fp),!feof(fp)){
  617.         tprintf("%s",buf);
  618.         if(--row == 0){
  619.             row = keywait("--More--",0);
  620.             switch(row){
  621.             case -1:
  622.             case 'q':
  623.             case 'Q':
  624.                 goto done;
  625.             case '\n':
  626.             case '\r':
  627.                 row = 1;
  628.                 break;
  629.             case ' ':
  630.             default:
  631.                 row = MOREROWS;
  632.             }
  633.         }
  634.     }
  635. done:    fclose(fp);
  636.     keywait(NULLCHAR,1);
  637.     freesession(sp);
  638.     return 0;
  639. }
  640. /* No-op command */
  641. int
  642. donothing(argc,argv,p)
  643. int argc;
  644. char *argv[];
  645. void *p;
  646. {
  647.     return 0;
  648. }
  649.  
  650. /* Log messages of the form
  651.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  652.  */
  653. #if    defined(ANSIPROTO)
  654. void
  655. log(int s,char *fmt, ...)
  656. {
  657.     va_list ap;
  658.     char *cp;
  659.     long t;
  660.     int i;
  661.     struct sockaddr fsocket;
  662. #ifdef    MSDOS
  663.     int fd;
  664. #endif
  665.  
  666.     if(Logfp == NULLFILE)
  667.         return;
  668.  
  669.     time(&t);
  670.     cp = ctime(&t);
  671.     rip(cp);
  672.     i = SOCKSIZE;
  673.     fprintf(Logfp,"%s",cp);
  674.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  675.         fprintf(Logfp," %s",psocket(&fsocket));
  676.  
  677.     fprintf(Logfp," - ");
  678.     va_start(ap,fmt);
  679.     vfprintf(Logfp,fmt,ap);
  680.     va_end(ap);
  681.     fprintf(Logfp,"\n");
  682.     fflush(Logfp);
  683. #ifdef    MSDOS
  684.     /* MS-DOS doesn't really flush files until they're closed */
  685.     fd = fileno(Logfp);
  686.     if((fd = dup(fd)) != -1)
  687.         close(fd);
  688. #endif
  689. }
  690. #else
  691. /*VARARGS2*/
  692. void
  693. log(s,fmt,arg1,arg2,arg3,arg4,arg5)
  694. int s;
  695. char *fmt;
  696. int arg1,arg2,arg3,arg4,arg5;
  697. {
  698.     char *cp;
  699.     long t;
  700.     int fd,i;
  701.     struct sockaddr fsocket;
  702.  
  703.     if(Logfp == NULLFILE)
  704.         return;
  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.     fprintf(Logfp,fmt,arg1,arg2,arg3,arg4,arg5);
  715.     fprintf(Logfp,"\n");
  716.     fflush(Logfp);
  717. #ifdef    MSDOS
  718.     /* MS-DOS doesn't really flush files until they're closed */
  719.     fd = fileno(Logfp);
  720.     if((fd = dup(fd)) != -1)
  721.         close(fd);
  722. #endif
  723. }
  724. #endif
  725.  
  726.