home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / REXEC / REXEC.C
C/C++ Source or Header  |  1991-12-15  |  14KB  |  476 lines

  1. /*
  2.     rexec.c
  3.     Provides a rexec client services for NCSA 2.3.
  4.  
  5.     By James Nau, College of Engineering,
  6.     University of Nebraska--Lincoln
  7. */
  8.  
  9. #define EXEC_PORT 512
  10.  
  11. #define ALARM 128
  12.  
  13. #include <stdio.h>
  14. #include <conio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <dos.h>
  18. #include <ctype.h>
  19. #ifdef __TURBOC__
  20. #include "turboc.h"
  21. #endif
  22. #ifdef MSC
  23. #include <signal.h>
  24. #include <time.h>
  25. #endif
  26.  
  27.  
  28. #ifdef MEMORY_DEBUG
  29. #include "memdebug.h"
  30. #endif
  31. #include "netevent.h"
  32. #include "hostform.h"
  33. #include "whatami.h"
  34. #include "externs.h"
  35.  
  36. #include "netutils.h"
  37.  
  38. int debug = 0;          /* enable with -D option */
  39. int bypass_passwd=0;    /* whether to bypass the password check, not used */
  40.  
  41. unsigned char path_name[_MAX_DRIVE+_MAX_DIR],        /* character storage for the path name */
  42.     temp_str[20],buf[_MAX_DIR],temp_data[30];
  43.  
  44. /* Function Prototypes */
  45. int main(int argc, char *argv[]);
  46. #ifndef __TURBOC__
  47. static void randomize(void );
  48. #endif
  49. void usage(void);
  50. void do_rexec(char *host, char *line);
  51. int rexec(char *host, int port, char *user, char *passwd, char *cmd,
  52.           int *errchan);
  53.  
  54. /*
  55.    rexec [-h filename] [-D] host command
  56.    -h        filename is alternative CONFIG.TEL file
  57.    -D        Debug Flag
  58.    host      the NAME (or Number?) of a machine to execute command
  59.    command   a command to pass to the remote host
  60. */
  61.  
  62. int main(int argc, char *argv[])
  63. {
  64.    int i;
  65.    int switchcount=1;   /* How many switches and switch args are present */
  66.    int switchlimit;     /* How far into argc am I allowed to find switches */
  67.  
  68.    char command[80];    /* Text to send to remote host */
  69.  
  70.    char *ptr=0;         /* pointer to CONFIG.TEL file */
  71.  
  72.    char remote_host[256];    /* address of remote host */
  73.  
  74. #ifdef __TURBOC__
  75.     fnsplit(argv[0],path_name,buf,temp_str,temp_data);     /* split path up */
  76. #else
  77.    _splitpath(argv[0],path_name,buf,temp_str,temp_data);   /* split path up */
  78. #endif
  79.    strcat(path_name,buf);         /* append the path name */
  80.    strcat(path_name,temp_str);    /* append filename */
  81.  
  82.    if (argc < 3) usage();    /* Oops, they haven't got it right */
  83. /* rexec host cmd [-args] */
  84. /* rexec -h file host cmd [-args] */
  85. /* rexec -h file -D host cmd [-args] */
  86. /* rexec -D host cmd [-args] */
  87.  
  88. /*     switchlimit = (argc<5 ? argc-2 : 4); */
  89.    switchlimit = 3;     /* Assume -D has to come first :) */
  90.    if (debug) printf("Switchlimit [%d]\n", switchlimit);
  91.  
  92. /* get the command line arguments */
  93. /* Can't parse entire command line-- what if command is ps -eaf
  94.    so, this appears to do the job for the number of switches allowed */
  95.    for (i=1; i< switchlimit; i++)     /* Switches have to be first 3 */
  96.       if (argv[i][0] == '-')
  97.       {
  98.          switch (argv[i][1])
  99.          {
  100.             case 'D':        /* Debug switch */
  101.                debug = 1;
  102.                if (debug) printf("Debugging now ON\n");
  103.                switchcount++;
  104.                break;
  105.             case 'h':        /* Alternate CONFIG.TEL file switch */
  106.                if (i+1 < switchlimit)
  107.                   ptr = argv[i+1];
  108.                else
  109.                   usage();
  110.                if (debug) printf("Using config file [%s]\n",ptr);
  111.                switchcount += 2;
  112.                break;
  113.             default:
  114.                usage ();   /* Tell user how to use it */
  115.          }
  116.          if (debug) printf("argv[%d][1]=-%c\n", i, argv[i][1]);
  117.       }
  118.  
  119.    if ((switchcount+2) > argc) usage ();    /* do we have the rest ?? */
  120.  
  121.    strcpy(remote_host, argv[switchcount++]);     /* the Host to execute */
  122.  
  123.    strcpy(command, argv[switchcount++]);         /* The Command */
  124.    for (; switchcount < argc;)    /* How much command */
  125.    {
  126.       strcat(command, " ");
  127.       strcat(command, argv[switchcount++]);
  128.    }
  129.  
  130.    if (debug) printf("sending [%s] to [%s]\n",command, remote_host);
  131.  
  132. /* exit (0);  */ /* For debugging if you have no network! (No E-Net at home :( */
  133.  
  134.    signal(SIGINT,SIG_IGN);   /* Microsoft intercept of break */
  135.  
  136. /* Do session initialization.  Snetinit reads config file. */
  137.    /* go find a valid CONFIG.TEL file */
  138.    if (ptr == (char *)NULL) ptr = getenv("CONFIG.TEL");
  139.    if (debug) printf("ptr after getenv [%s]\n",ptr);
  140.    if (ptr != (char *)NULL) Shostfile(ptr);
  141.  
  142.    if (Snetinit()) /* Should return 0 if network is OK */
  143.    {
  144.       printf("network init failed\n");
  145.       exit (1);
  146.    }
  147.  
  148. /* Just Do It */
  149.    do_rexec(remote_host, command);
  150.  
  151.    exit(0);
  152.    return(0);
  153. }
  154.  
  155.  
  156. void do_rexec(char *remote_host, char *cmd)
  157. {
  158.    char user[33];       /* Username */
  159.    char passwd[17];     /* Password for said user */
  160.    int errchan;         /* Dummy error channel, for now at least */
  161.    int conn_id;         /* Connection ID from rexec */
  162.  
  163.    char netbuf[512];    /* buffer for netread */
  164.    int netbuflen=512;   /* Length of netbuf */
  165.    int len;             /* length of data read from net */
  166.  
  167.    int event;           /* event from Sgetevent */
  168.    int theclass;        /* class that is returned */
  169.    int dat;             /* for Sgetevent info too */
  170.  
  171.    char ch;             /* Byte to send from kbhit()/getch */
  172.  
  173.    user[0] = '\0';           /* Init to NULL */
  174.    passwd[0] = '\0';         /* Init to NULL */
  175.  
  176. /* Establish connection and all that stuff... */
  177.    conn_id = rexec(remote_host, EXEC_PORT, user, passwd, cmd, &errchan);
  178.    if (conn_id < 0)
  179.    {
  180.       printf("Couldn't rexec\n");
  181.       printf("rexec returned %d\n", conn_id);
  182.       exit (1);
  183.    }
  184.  
  185.    theclass = 0;
  186.    event = 0;
  187.  
  188. /*     while ((theclass == CONCLASS && event != CONCLOSE)  && !netest(conn_id)) */
  189.    while (!netest(conn_id))
  190.                 /* No CONnection info and good connection */
  191.    {
  192.       if (kbhit())      /* Keyboard hit, let's send it */
  193.       {
  194.          ch = (char)getch();           /* gotta get it */
  195.          netwrite (conn_id, &ch, 1);   /* out it goes */
  196.          netpush(conn_id);
  197.       }
  198.  
  199.       Stask();     /* I think I have to call this to post my alarm? */
  200.       event = Sgetevent(CONCLASS | USERCLASS, &theclass, &dat);
  201.       if (debug)
  202.          printf("event[%d] theclass[%d] dat[%d] [%d]\n",event, theclass, dat, conn_id);
  203.       if (!event) continue;
  204.       if (conn_id != dat) continue;
  205.  
  206.       if (event == CONDATA)
  207.       {
  208.          len = netread(conn_id, netbuf, netbuflen);
  209.          if (!len) continue;
  210.          printf("%.*s", len, netbuf);
  211.       }
  212.       else if (event == CONCLOSE)      /* I guess we're done */
  213.       {
  214.         netclose(conn_id);
  215.          netshut();     /* Shut down the network */
  216.          break;
  217.       }
  218.       else
  219.       {
  220.          printf("Unexpected event: [%d]\n", event);
  221.       }
  222.    }
  223. /*     printf("out of while loop theclass[%d] event[%d] ntest[%d]\n",theclass, event, netest(conn_id)); */
  224.     netclose(conn_id);
  225.     netshut();
  226. }
  227.  
  228.  
  229. #if defined(MSC) && !defined(__TURBOC__)
  230. /******************************************************************
  231. *
  232. * randomize()
  233. *
  234. * replicates the randomize function of Turbo C
  235. * MSC 5.1 does not contain it so we have to write it ourselves.
  236. *
  237. */
  238.  
  239. static void randomize(void )
  240. {
  241.     srand((unsigned)time(NULL));
  242. }
  243. #endif
  244.  
  245.  
  246. void filter (char *buffer, int buffer_len)
  247. /* filter out control characters, escape sequences, etc
  248.    keeps from reprogramming keys, ...
  249. */
  250. {
  251.    int i;
  252.    char ch;
  253.  
  254.    for (i=0; i<buffer_len; i++)
  255.    {
  256.       ch = *(buffer+i);
  257.       if (!(isprint(ch) || isspace(ch))) *(buffer+i) = '?';
  258.    }
  259. }
  260.  
  261.  
  262. void usage()
  263. {
  264. /*
  265.    rexec [-h filename] [-D] host command
  266.    -h        filename is alternative CONFIG.TEL file
  267.    -D        Debug Flag
  268.    host      the NAME (or Number?) of a machine to execute command
  269.    command   a command to pass to the remote host
  270. */
  271.  
  272.    printf("Usage: %s [-h filename] host command\n\n", path_name);
  273.  
  274.    printf("   -h        filename is alternative CONFIG.TEL file\n");
  275.    printf("   host      the host to execute command\n");
  276.    printf("   command   command for remote system to execute\n");
  277.    printf("\nNOTE:  This program (rexec) is flakey right now\n");
  278.    printf("       it seems to work fine for OUTPUT only commands\n");
  279.    printf("       (such as who, ps).  But, commands requiring input\n");
  280.    printf("       do NOT work correctly  (it seems to end properly, but\n");
  281.    printf("       it never kills the process).\n\n");
  282.    exit (-1);
  283. }
  284.  
  285.  
  286. int rexec(char *host, int port, char *user, char *passwd, char *cmd,
  287.           int *errchan)
  288. /* implement a Un*x like rexec function.
  289.       host is the host we want to rexec to
  290.       port is the destination port (usually 512 for rexec)
  291.       user is the username on host
  292.       passwd is the password on host
  293.       cmd is command to pass to host
  294.       errchan is where to route stderr to (see below)
  295.  
  296.    if username and passwd are NULL, then we prompt for them
  297.    from stdin.  Maybe should have a USER environ var for a default
  298.    user, but NEVER have a passwd scanned from anywhere since we're on
  299.    a PC with No File Security...
  300.  
  301.    Also, currently, errchan is ignored.  It's supposed to be:  If errchan
  302.    is non-zero, then open another socket back to the system to process
  303.    stderr on.
  304.  
  305.    Return value is the connection id that we established.
  306.                 or negative if an error somewhere.
  307.  
  308. */
  309.  
  310. {
  311.    int i;          /* scratch variable */
  312.    int from_port;  /* where to come from */
  313.    struct machinfo *host_info;    /* structure to return machine info in */
  314.    int conn_id;         /* Connection id from connect_sock */
  315.    char buff[256];      /* Command to send to remote host */
  316.    int ubase;           /* how far into buff we are */
  317.    int timeout=100;     /* timeout period */
  318.  
  319.    int event;           /* event from Sgetevent */
  320.    int theclass;        /* class that is returned */
  321.    int dat;             /* for Sgetevent info too */
  322.  
  323.    char nullbyte;       /* NULL byte we are supposed to get back */
  324.    int len;             /* length of data back from netread */
  325.  
  326.  
  327.    if (!*errchan) printf("Unsupported errchan right now--Continuing\n");
  328.  
  329.  
  330. /* Hmm, may get into trouble if we run out of space, or are passed
  331.    **pointers, instead of having space available???? */
  332.  
  333. /*     if (user == (char *)NULL)       */ /* no user specified, go get it */
  334.    if (!strlen(user))        /* no user specified, go get it */
  335.    {
  336.       printf("Enter Username: ");
  337.       gets(user);
  338.    }
  339. /*     if (passwd == (char *)NULL)   */ /* no passwd specified, go get one */
  340.    if (!strlen(passwd))      /* no passwd specified, go get one */
  341.    {
  342.       printf("Enter password: ");
  343.       i = 0;
  344.       while ((passwd[i] = (char)getch()) != '\xd') i++;    /* get w/o echo */
  345.       passwd[i] = '\0';
  346.       putchar('\n');
  347.    }
  348.  
  349.  
  350.    buff[0] = '\0';  /* Null, since we want to leave stderr alone */
  351.  
  352.    ubase = 1;
  353.    for (i=0; i<(int)strlen(user); i++)      /* Add username */
  354.       buff[i+ubase] = user[i];
  355.    ubase += strlen(user);
  356.  
  357.    buff[ubase] = '\0';       /* Terminate with NULL */
  358.    ubase++;
  359.  
  360.    for (i=0; i<(int)strlen(passwd); i++)  /* add the password */
  361.       buff[i+ubase] = passwd[i];
  362.    ubase += strlen(passwd);
  363.  
  364.    buff[ubase] = '\0';       /* Terminate with NULL */
  365.    ubase++;
  366.  
  367.    for (i=0; i<(int)strlen(cmd); i++)       /* add the command to execute */
  368.       buff[i+ubase] = cmd[i];
  369.    ubase += strlen(cmd);
  370.  
  371.    buff[ubase] = '\0';       /* Terminate with NULL */
  372.    ubase++;
  373.  
  374.    if (debug)
  375.    {
  376.       for (i=0; i<ubase; i++)
  377.          printf("%d ", buff[i]);
  378.       printf("\n");
  379.  
  380.       for (i=0; i<ubase; i++)
  381.          printf("%c", buff[i]);
  382.       printf("\n");
  383.    }
  384.  
  385.    /* pick a source port at random from the set of privileged ports */
  386.    randomize();
  387.    from_port = rand() % 1023;
  388.  
  389.    /* do name lookup for server */
  390.    host_info = gethostinfo(host);
  391.    if (host_info == (struct machinfo *)NULL)     /* couldn't do it, message in gethostinfo */
  392.    {
  393.       printf("Couldn't lookup host [%s]\n", host);
  394.       return(-1);
  395.    }
  396.  
  397. /* print out the IP number of the destination host */
  398. /* this should come out in production.  Leave for debugging though */
  399.    if (debug)
  400.    {
  401.       printf("[");
  402.       for (i=0; i<4; i++)
  403.          printf("%d.",host_info->hostip[i]);
  404.       printf("]\n");
  405.    }
  406.  
  407.    /* open the connection */
  408.    conn_id = connect_sock(host_info, port, EXEC_PORT);
  409.    if (conn_id < 0)
  410.    {
  411.       netshut();        /* Shut down the network */
  412.       printf("connect_sock returned %d, exiting\n",conn_id);
  413.       return (-2);
  414.    }
  415.    if (debug) printf("connection ident [%d]\n",conn_id);
  416.  
  417.    /* send the request */
  418.    netwrite(conn_id, buff, ubase);
  419.    if (debug) printf("netwrite succeeded--flushing buffer\n");
  420.  
  421.    netpush(conn_id);
  422.  
  423.    if (debug)
  424.       if (!netest(conn_id))
  425.          printf("Connection OK\n");
  426.       else
  427.          printf("nettest: %d\n", netest(conn_id));
  428.  
  429. /* OK, now, we'll attempt to set an alarm to time out in timeout seconds
  430.    if we get a connection, but no response */
  431.  
  432.    Stimerset(USERCLASS, ALARM, 0, timeout);
  433.    if (debug) printf("timer set to go off in %d seconds\n", timeout);
  434.  
  435.    theclass = 0;
  436.    event = 0;
  437.    while ((theclass != USERCLASS || event != ALARM) && !netest(conn_id))
  438.                 /* no alarm and good connection */
  439.    {
  440.       Stask();     /* I think I have to call this to post my alarm? */
  441.       event = Sgetevent(CONCLASS | USERCLASS, &theclass, &dat);
  442.       if (debug)
  443.          printf("event[%d] theclass[%d] dat[%d] [%d]\n",event, theclass, dat, conn_id);
  444.       if (!event) continue;
  445.       if (conn_id != dat) continue;
  446.  
  447.       if (event == CONDATA)
  448.       {
  449.          len = netread(conn_id, &nullbyte, 1);
  450.          if (len == 0) continue;
  451.          if (nullbyte != 0) printf( "Byte != 0 [%d]\n", nullbyte);
  452.          Stimerunset(USERCLASS, ALARM, 0);
  453.          return (conn_id);
  454.       }
  455.       else if (event == CONCLOSE)
  456.       {
  457.          printf("Unexpected closing of connection!\n");
  458.          netshut();          /* Shut down the network */
  459.          return (-3);
  460.       }
  461.       else
  462.       {
  463.          printf("Unexpected event: [%d]\n", event);
  464.       }
  465.    }
  466.    if (theclass == USERCLASS && event == ALARM)
  467.    {
  468.       printf("Connection timed out in %d seconds\n", timeout);
  469.       netshut();        /* Shut down the network */
  470.       return (-4);
  471.    }
  472.    netshut();      /* Shut down the network */
  473.    return (-5);
  474. }
  475.  
  476.