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

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