/* 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 #include #include #include #include #include #ifdef __TURBOC__ #include "turboc.h" #endif #ifdef MSC #include #include #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 */ extern int bypass_passwd; /* 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 */ { netclose(conn_id); 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)); */ netclose(conn_id); netshut(); } #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; ihostip[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); }