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