home *** CD-ROM | disk | FTP | other *** search
- /*
- rexec.c
- Provides a rexec client services for NCSA 2.3.
-
- By James Nau, College of Engineering,
- University of Nebraska--Lincoln
- */
-
- #define EXEC_PORT 512
-
- #define ALARM 128
-
- #include <stdio.h>
- #include <conio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <ctype.h>
- #ifdef __TURBOC__
- #include "turboc.h"
- #endif
- #ifdef MSC
- #include <signal.h>
- #include <time.h>
- #endif
-
-
- #ifdef MEMORY_DEBUG
- #include "memdebug.h"
- #endif
- #include "netevent.h"
- #include "hostform.h"
- #include "whatami.h"
- #include "externs.h"
-
- #include "netutils.h"
-
- int debug = 0; /* enable with -D option */
- int bypass_passwd=0; /* whether to bypass the password check, not used */
-
- unsigned char path_name[_MAX_DRIVE+_MAX_DIR], /* character storage for the path name */
- temp_str[20],buf[_MAX_DIR],temp_data[30];
-
- /* Function Prototypes */
- int main(int argc, char *argv[]);
- #ifndef __TURBOC__
- static void randomize(void );
- #endif
- void usage(void);
- void do_rexec(char *host, char *line);
- int rexec(char *host, int port, char *user, char *passwd, char *cmd,
- int *errchan);
-
- /*
- rexec [-h filename] [-D] host command
- -h filename is alternative CONFIG.TEL file
- -D Debug Flag
- host the NAME (or Number?) of a machine to execute command
- command a command to pass to the remote host
- */
-
- int main(int argc, char *argv[])
- {
- int i;
- int switchcount=1; /* How many switches and switch args are present */
- int switchlimit; /* How far into argc am I allowed to find switches */
-
- char command[80]; /* Text to send to remote host */
-
- char *ptr=0; /* pointer to CONFIG.TEL file */
-
- char remote_host[256]; /* address of remote host */
-
- #ifdef __TURBOC__
- fnsplit(argv[0],path_name,buf,temp_str,temp_data); /* split path up */
- #else
- _splitpath(argv[0],path_name,buf,temp_str,temp_data); /* split path up */
- #endif
- strcat(path_name,buf); /* append the path name */
- strcat(path_name,temp_str); /* append filename */
-
- if (argc < 3) usage(); /* Oops, they haven't got it right */
- /* rexec host cmd [-args] */
- /* rexec -h file host cmd [-args] */
- /* rexec -h file -D host cmd [-args] */
- /* rexec -D host cmd [-args] */
-
- /* switchlimit = (argc<5 ? argc-2 : 4); */
- switchlimit = 3; /* Assume -D has to come first :) */
- if (debug) printf("Switchlimit [%d]\n", switchlimit);
-
- /* get the command line arguments */
- /* Can't parse entire command line-- what if command is ps -eaf
- so, this appears to do the job for the number of switches allowed */
- for (i=1; i< switchlimit; i++) /* Switches have to be first 3 */
- if (argv[i][0] == '-')
- {
- switch (argv[i][1])
- {
- case 'D': /* Debug switch */
- debug = 1;
- if (debug) printf("Debugging now ON\n");
- switchcount++;
- break;
- case 'h': /* Alternate CONFIG.TEL file switch */
- if (i+1 < switchlimit)
- ptr = argv[i+1];
- else
- usage();
- if (debug) printf("Using config file [%s]\n",ptr);
- switchcount += 2;
- break;
- default:
- usage (); /* Tell user how to use it */
- }
- if (debug) printf("argv[%d][1]=-%c\n", i, argv[i][1]);
- }
-
- if ((switchcount+2) > argc) usage (); /* do we have the rest ?? */
-
- strcpy(remote_host, argv[switchcount++]); /* the Host to execute */
-
- strcpy(command, argv[switchcount++]); /* The Command */
- for (; switchcount < argc;) /* How much command */
- {
- strcat(command, " ");
- strcat(command, argv[switchcount++]);
- }
-
- if (debug) printf("sending [%s] to [%s]\n",command, remote_host);
-
- /* exit (0); */ /* For debugging if you have no network! (No E-Net at home :( */
-
- signal(SIGINT,SIG_IGN); /* Microsoft intercept of break */
-
- /* Do session initialization. Snetinit reads config file. */
- /* go find a valid CONFIG.TEL file */
- if (ptr == (char *)NULL) ptr = getenv("CONFIG.TEL");
- if (debug) printf("ptr after getenv [%s]\n",ptr);
- if (ptr != (char *)NULL) Shostfile(ptr);
-
- if (Snetinit()) /* Should return 0 if network is OK */
- {
- printf("network init failed\n");
- exit (1);
- }
-
- /* Just Do It */
- do_rexec(remote_host, command);
-
- exit(0);
- return(0);
- }
-
-
- void do_rexec(char *remote_host, char *cmd)
- {
- char user[33]; /* Username */
- char passwd[17]; /* Password for said user */
- int errchan; /* Dummy error channel, for now at least */
- int conn_id; /* Connection ID from rexec */
-
- char netbuf[512]; /* buffer for netread */
- int netbuflen=512; /* Length of netbuf */
- int len; /* length of data read from net */
-
- int event; /* event from Sgetevent */
- int theclass; /* class that is returned */
- int dat; /* for Sgetevent info too */
-
- char ch; /* Byte to send from kbhit()/getch */
-
- user[0] = '\0'; /* Init to NULL */
- passwd[0] = '\0'; /* Init to NULL */
-
- /* Establish connection and all that stuff... */
- conn_id = rexec(remote_host, EXEC_PORT, user, passwd, cmd, &errchan);
- if (conn_id < 0)
- {
- printf("Couldn't rexec\n");
- printf("rexec returned %d\n", conn_id);
- exit (1);
- }
-
- theclass = 0;
- event = 0;
-
- /* while ((theclass == CONCLASS && event != CONCLOSE) && !netest(conn_id)) */
- while (!netest(conn_id))
- /* No CONnection info and good connection */
- {
- if (kbhit()) /* Keyboard hit, let's send it */
- {
- ch = (char)getch(); /* gotta get it */
- netwrite (conn_id, &ch, 1); /* out it goes */
- netpush(conn_id);
- }
-
- Stask(); /* I think I have to call this to post my alarm? */
- event = Sgetevent(CONCLASS | USERCLASS, &theclass, &dat);
- if (debug)
- printf("event[%d] theclass[%d] dat[%d] [%d]\n",event, theclass, dat, conn_id);
- if (!event) continue;
- if (conn_id != dat) continue;
-
- if (event == CONDATA)
- {
- len = netread(conn_id, netbuf, netbuflen);
- if (!len) continue;
- printf("%.*s", len, netbuf);
- }
- else if (event == CONCLOSE) /* I guess we're done */
- {
- netshut(); /* Shut down the network */
- break;
- }
- else
- {
- printf("Unexpected event: [%d]\n", event);
- }
- }
- /* printf("out of while loop theclass[%d] event[%d] ntest[%d]\n",theclass, event, netest(conn_id)); */
- }
-
-
- #if defined(MSC) && !defined(__TURBOC__)
- /******************************************************************
- *
- * randomize()
- *
- * replicates the randomize function of Turbo C
- * MSC 5.1 does not contain it so we have to write it ourselves.
- *
- */
-
- static void randomize(void )
- {
- srand((unsigned)time(NULL));
- }
- #endif
-
-
- void filter (char *buffer, int buffer_len)
- /* filter out control characters, escape sequences, etc
- keeps from reprogramming keys, ...
- */
- {
- int i;
- char ch;
-
- for (i=0; i<buffer_len; i++)
- {
- ch = *(buffer+i);
- if (!(isprint(ch) || isspace(ch))) *(buffer+i) = '?';
- }
- }
-
-
- void usage()
- {
- /*
- rexec [-h filename] [-D] host command
- -h filename is alternative CONFIG.TEL file
- -D Debug Flag
- host the NAME (or Number?) of a machine to execute command
- command a command to pass to the remote host
- */
-
- printf("Usage: %s [-h filename] host command\n\n", path_name);
-
- printf(" -h filename is alternative CONFIG.TEL file\n");
- printf(" host the host to execute command\n");
- printf(" command command for remote system to execute\n");
- printf("\nNOTE: This program (rexec) is flakey right now\n");
- printf(" it seems to work fine for OUTPUT only commands\n");
- printf(" (such as who, ps). But, commands requiring input\n");
- printf(" do NOT work correctly (it seems to end properly, but\n");
- printf(" it never kills the process).\n\n");
- exit (-1);
- }
-
-
- int rexec(char *host, int port, char *user, char *passwd, char *cmd,
- int *errchan)
- /* implement a Un*x like rexec function.
- host is the host we want to rexec to
- port is the destination port (usually 512 for rexec)
- user is the username on host
- passwd is the password on host
- cmd is command to pass to host
- errchan is where to route stderr to (see below)
-
- if username and passwd are NULL, then we prompt for them
- from stdin. Maybe should have a USER environ var for a default
- user, but NEVER have a passwd scanned from anywhere since we're on
- a PC with No File Security...
-
- Also, currently, errchan is ignored. It's supposed to be: If errchan
- is non-zero, then open another socket back to the system to process
- stderr on.
-
- Return value is the connection id that we established.
- or negative if an error somewhere.
-
- */
-
- {
- int i; /* scratch variable */
- int from_port; /* where to come from */
- struct machinfo *host_info; /* structure to return machine info in */
- int conn_id; /* Connection id from connect_sock */
- char buff[256]; /* Command to send to remote host */
- int ubase; /* how far into buff we are */
- int timeout=100; /* timeout period */
-
- int event; /* event from Sgetevent */
- int theclass; /* class that is returned */
- int dat; /* for Sgetevent info too */
-
- char nullbyte; /* NULL byte we are supposed to get back */
- int len; /* length of data back from netread */
-
-
- if (!*errchan) printf("Unsupported errchan right now--Continuing\n");
-
-
- /* Hmm, may get into trouble if we run out of space, or are passed
- **pointers, instead of having space available???? */
-
- /* if (user == (char *)NULL) */ /* no user specified, go get it */
- if (!strlen(user)) /* no user specified, go get it */
- {
- printf("Enter Username: ");
- gets(user);
- }
- /* if (passwd == (char *)NULL) */ /* no passwd specified, go get one */
- if (!strlen(passwd)) /* no passwd specified, go get one */
- {
- printf("Enter password: ");
- i = 0;
- while ((passwd[i] = (char)getch()) != '\xd') i++; /* get w/o echo */
- passwd[i] = '\0';
- putchar('\n');
- }
-
-
- buff[0] = '\0'; /* Null, since we want to leave stderr alone */
-
- ubase = 1;
- for (i=0; i<(int)strlen(user); i++) /* Add username */
- buff[i+ubase] = user[i];
- ubase += strlen(user);
-
- buff[ubase] = '\0'; /* Terminate with NULL */
- ubase++;
-
- for (i=0; i<(int)strlen(passwd); i++) /* add the password */
- buff[i+ubase] = passwd[i];
- ubase += strlen(passwd);
-
- buff[ubase] = '\0'; /* Terminate with NULL */
- ubase++;
-
- for (i=0; i<(int)strlen(cmd); i++) /* add the command to execute */
- buff[i+ubase] = cmd[i];
- ubase += strlen(cmd);
-
- buff[ubase] = '\0'; /* Terminate with NULL */
- ubase++;
-
- if (debug)
- {
- for (i=0; i<ubase; i++)
- printf("%d ", buff[i]);
- printf("\n");
-
- for (i=0; i<ubase; i++)
- printf("%c", buff[i]);
- printf("\n");
- }
-
- /* pick a source port at random from the set of privileged ports */
- randomize();
- from_port = rand() % 1023;
-
- /* do name lookup for server */
- host_info = gethostinfo(host);
- if (host_info == (struct machinfo *)NULL) /* couldn't do it, message in gethostinfo */
- {
- printf("Couldn't lookup host [%s]\n", host);
- return(-1);
- }
-
- /* print out the IP number of the destination host */
- /* this should come out in production. Leave for debugging though */
- if (debug)
- {
- printf("[");
- for (i=0; i<4; i++)
- printf("%d.",host_info->hostip[i]);
- printf("]\n");
- }
-
- /* open the connection */
- conn_id = connect_sock(host_info, port, EXEC_PORT);
- if (conn_id < 0)
- {
- netshut(); /* Shut down the network */
- printf("connect_sock returned %d, exiting\n",conn_id);
- return (-2);
- }
- if (debug) printf("connection ident [%d]\n",conn_id);
-
- /* send the request */
- netwrite(conn_id, buff, ubase);
- if (debug) printf("netwrite succeeded--flushing buffer\n");
-
- netpush(conn_id);
-
- if (debug)
- if (!netest(conn_id))
- printf("Connection OK\n");
- else
- printf("nettest: %d\n", netest(conn_id));
-
- /* OK, now, we'll attempt to set an alarm to time out in timeout seconds
- if we get a connection, but no response */
-
- Stimerset(USERCLASS, ALARM, 0, timeout);
- if (debug) printf("timer set to go off in %d seconds\n", timeout);
-
- theclass = 0;
- event = 0;
- while ((theclass != USERCLASS || event != ALARM) && !netest(conn_id))
- /* no alarm and good connection */
- {
- Stask(); /* I think I have to call this to post my alarm? */
- event = Sgetevent(CONCLASS | USERCLASS, &theclass, &dat);
- if (debug)
- printf("event[%d] theclass[%d] dat[%d] [%d]\n",event, theclass, dat, conn_id);
- if (!event) continue;
- if (conn_id != dat) continue;
-
- if (event == CONDATA)
- {
- len = netread(conn_id, &nullbyte, 1);
- if (len == 0) continue;
- if (nullbyte != 0) printf( "Byte != 0 [%d]\n", nullbyte);
- Stimerunset(USERCLASS, ALARM, 0);
- return (conn_id);
- }
- else if (event == CONCLOSE)
- {
- printf("Unexpected closing of connection!\n");
- netshut(); /* Shut down the network */
- return (-3);
- }
- else
- {
- printf("Unexpected event: [%d]\n", event);
- }
- }
- if (theclass == USERCLASS && event == ALARM)
- {
- printf("Connection timed out in %d seconds\n", timeout);
- netshut(); /* Shut down the network */
- return (-4);
- }
- netshut(); /* Shut down the network */
- return (-5);
- }
-
-