home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / main.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  13KB  |  671 lines

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