131457Sminshall #include <sys/types.h> 2*31863Sminshall 3*31863Sminshall #if !defined(sun) 431798Sminshall #include <sys/inode.h> 5*31863Sminshall #else /* !defined(sun) */ 6*31863Sminshall #define IREAD 00400 7*31863Sminshall #define IWRITE 00200 8*31863Sminshall #endif /* !defined(sun) */ 9*31863Sminshall 1031798Sminshall #include <sys/file.h> 1131798Sminshall #include <sys/time.h> 1231457Sminshall #include <sys/socket.h> 1331457Sminshall #include <netinet/in.h> 1431455Sminshall #include <sys/wait.h> 1531455Sminshall 1631457Sminshall #include <errno.h> 1731457Sminshall extern int errno; 1831457Sminshall 1931457Sminshall #include <netdb.h> 2031457Sminshall #include <signal.h> 2131455Sminshall #include <stdio.h> 2231457Sminshall #include <pwd.h> 2331455Sminshall 2431455Sminshall #include "../general/general.h" 2531455Sminshall #include "../api/api.h" 2631463Sminshall #include "../apilib/api_exch.h" 2731455Sminshall 2831455Sminshall #include "../general/globals.h" 2931455Sminshall 3031795Sminshall #ifndef FD_SETSIZE 3131795Sminshall /* 3231795Sminshall * The following is defined just in case someone should want to run 3331795Sminshall * this telnet on a 4.2 system. 3431795Sminshall * 3531795Sminshall */ 3631455Sminshall 3731795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 3831795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 3931795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 4031795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 4131795Sminshall 4231795Sminshall #endif 4331795Sminshall 4431455Sminshall static int shell_pid = 0; 4531798Sminshall static char key[50]; /* Actual key */ 4631798Sminshall static char *keyname; /* Name of file with key in it */ 4731455Sminshall 4831457Sminshall static char *ourENVlist[200]; /* Lots of room */ 4931457Sminshall 5031465Sminshall static int 5131465Sminshall sock = -1, /* Connected socket */ 5231465Sminshall serversock; /* Server (listening) socket */ 5331457Sminshall 5431457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 5531457Sminshall 5631455Sminshall static int 5731463Sminshall storage_location, /* Address we have */ 5831457Sminshall storage_length = 0, /* Length we have */ 5931457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 6031457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 6131457Sminshall 6231503Sminshall static long storage[1000]; 6331457Sminshall 6431463Sminshall static union REGS inputRegs; 6531463Sminshall static struct SREGS inputSregs; 6631457Sminshall 6731463Sminshall 6831463Sminshall static void 6931457Sminshall kill_connection() 7031457Sminshall { 7131465Sminshall state = UNCONNECTED; 7231465Sminshall if (sock != -1) { 7331465Sminshall (void) close(sock); 7431465Sminshall sock = -1; 7531465Sminshall } 7631457Sminshall } 7731457Sminshall 7831457Sminshall 7931457Sminshall static int 8031463Sminshall nextstore() 8131455Sminshall { 8231463Sminshall struct storage_descriptor sd; 8331455Sminshall 8431463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 8531457Sminshall storage_length = 0; 8631457Sminshall return -1; 8731457Sminshall } 8831798Sminshall storage_length = sd.length; 8931798Sminshall storage_location = sd.location; 9031463Sminshall if (storage_length > sizeof storage) { 9131457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 9231457Sminshall storage_length); 9331463Sminshall storage_length = 0; 9431457Sminshall return -1; 9531457Sminshall } 9631511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 9731511Sminshall == -1) { 9831511Sminshall storage_length = 0; 9931511Sminshall return -1; 10031463Sminshall } 10131471Sminshall return 0; 10231457Sminshall } 10331457Sminshall 10431457Sminshall 10531457Sminshall static int 10631457Sminshall doreject(message) 10731457Sminshall char *message; 10831457Sminshall { 10931463Sminshall struct storage_descriptor sd; 11031457Sminshall int length = strlen(message); 11131457Sminshall 11231492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 11331457Sminshall return -1; 11431457Sminshall } 11531798Sminshall sd.length = length; 11631465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 11731463Sminshall return -1; 11831463Sminshall } 11931463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 12031463Sminshall return -1; 12131463Sminshall } 12231457Sminshall return 0; 12331457Sminshall } 12431457Sminshall 12531457Sminshall 12631455Sminshall /* 12731465Sminshall * doassociate() 12831457Sminshall * 12931457Sminshall * Negotiate with the other side and try to do something. 13031798Sminshall * 13131798Sminshall * Returns: 13231798Sminshall * 13331798Sminshall * -1: Error in processing 13431798Sminshall * 0: Invalid password entered 13531798Sminshall * 1: Association OK 13631457Sminshall */ 13731457Sminshall 13831457Sminshall static int 13931465Sminshall doassociate() 14031457Sminshall { 14131457Sminshall struct passwd *pwent; 14231457Sminshall char 14331457Sminshall promptbuf[100], 14431457Sminshall buffer[200]; 14531457Sminshall int length; 14631457Sminshall int was; 14731463Sminshall struct storage_descriptor sd; 14831457Sminshall 14931463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 15031463Sminshall return -1; 15131457Sminshall } 15231798Sminshall sd.length = sd.length; 15331463Sminshall if (sd.length > sizeof buffer) { 15431798Sminshall doreject("(internal error) Authentication key too long"); 15531465Sminshall return -1; 15631457Sminshall } 15731463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 15831457Sminshall return -1; 15931457Sminshall } 16031463Sminshall buffer[sd.length] = 0; 16131457Sminshall 16231798Sminshall if (strcmp(buffer, key) != 0) { 16331798Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 16431798Sminshall return -1; 16531798Sminshall } 16631798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 16731798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 16831798Sminshall return -1; 16931798Sminshall } 17031798Sminshall sd.length = strlen(promptbuf); 17131798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 17231798Sminshall == -1) { 17331798Sminshall return -1; 17431798Sminshall } 17531798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 17631798Sminshall == -1) { 17731798Sminshall return -1; 17831798Sminshall } 17931798Sminshall sd.length = strlen(pwent->pw_name); 18031798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 18131798Sminshall == -1) { 18231798Sminshall return -1; 18331798Sminshall } 18431798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 18531798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 18631798Sminshall return -1; 18731798Sminshall } 18831798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 18931798Sminshall return -1; 19031798Sminshall } 19131798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 19231798Sminshall == -1) { 19331798Sminshall return -1; 19431798Sminshall } 19531798Sminshall sd.length = sd.length; 19631798Sminshall if (sd.length > sizeof buffer) { 19731798Sminshall doreject("Password entered was too long"); 19831798Sminshall return -1; 19931798Sminshall } 20031798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 20131798Sminshall return -1; 20231798Sminshall } 20331798Sminshall buffer[sd.length] = 0; 20431465Sminshall 20531798Sminshall /* Is this the correct password? */ 20631798Sminshall if (strlen(pwent->pw_name)) { 20731798Sminshall char *ptr; 20831798Sminshall int i; 20931798Sminshall 21031798Sminshall ptr = pwent->pw_name; 21131798Sminshall i = 0; 21231798Sminshall while (i < sd.length) { 21331798Sminshall buffer[i++] ^= *ptr++; 21431798Sminshall if (*ptr == 0) { 21531798Sminshall ptr = pwent->pw_name; 21631798Sminshall } 21731465Sminshall } 21831465Sminshall } 21931798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 22031798Sminshall doreject("Invalid password"); 22131798Sminshall sleep(10); /* Don't let us do too many of these */ 22231798Sminshall return 0; 22331798Sminshall } 22431465Sminshall } 22531798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 22631798Sminshall return -1; 22731457Sminshall } else { 22831798Sminshall return 1; 22931457Sminshall } 23031457Sminshall } 23131457Sminshall 23231457Sminshall 23331457Sminshall void 23431457Sminshall freestorage() 23531457Sminshall { 23631457Sminshall char buffer[40]; 23731463Sminshall struct storage_descriptor sd; 23831457Sminshall 23931457Sminshall if (storage_accessed) { 24031457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 24131503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 24231457Sminshall __FILE__, __LINE__); 24331457Sminshall quit(); 24431457Sminshall } 24531457Sminshall if (storage_must_send == 0) { 24631457Sminshall return; 24731457Sminshall } 24831457Sminshall storage_must_send = 0; 24931492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 25031457Sminshall kill_connection(); 25131457Sminshall return; 25231457Sminshall } 25331798Sminshall sd.length = storage_length; 25431798Sminshall sd.location = storage_location; 25531463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 25631457Sminshall kill_connection(); 25731457Sminshall return; 25831457Sminshall } 25931511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 26031511Sminshall == -1) { 26131511Sminshall kill_connection(); 26231511Sminshall return; 26331463Sminshall } 26431457Sminshall } 26531457Sminshall 26631457Sminshall 26731463Sminshall static int 26831508Sminshall getstorage(address, length, copyin) 26931508Sminshall int 27031508Sminshall address, 27131508Sminshall length, 27231508Sminshall copyin; 27331457Sminshall { 27431463Sminshall struct storage_descriptor sd; 27531457Sminshall char buffer[40]; 27631457Sminshall 27731457Sminshall freestorage(); 27831457Sminshall if (storage_accessed) { 27931457Sminshall fprintf(stderr, 28031457Sminshall "Internal error - attempt to get while storage accessed.\n"); 28131503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 28231457Sminshall __FILE__, __LINE__); 28331457Sminshall quit(); 28431457Sminshall } 28531457Sminshall storage_must_send = 0; 28631492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 28731457Sminshall kill_connection(); 28831463Sminshall return -1; 28931457Sminshall } 29031471Sminshall storage_location = address; 29131471Sminshall storage_length = length; 29231508Sminshall if (copyin) { 29331798Sminshall sd.location = storage_location; 29431798Sminshall sd.length = storage_length; 29531508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 29631508Sminshall sizeof sd, (char *)&sd) == -1) { 29731508Sminshall kill_connection(); 29831508Sminshall return -1; 29931508Sminshall } 30031508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 30131508Sminshall fprintf(stderr, "Bad data from other side.\n"); 30231508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 30331508Sminshall return -1; 30431508Sminshall } 30531508Sminshall if (nextstore() == -1) { 30631508Sminshall kill_connection(); 30731508Sminshall return -1; 30831508Sminshall } 30931463Sminshall } 31031463Sminshall return 0; 31131457Sminshall } 31231457Sminshall 31331457Sminshall void 31431457Sminshall movetous(local, es, di, length) 31531457Sminshall char 31631457Sminshall *local; 31731457Sminshall int 31831457Sminshall es, 31931457Sminshall di; 32031457Sminshall int 32131457Sminshall length; 32231457Sminshall { 32331457Sminshall if (length > sizeof storage) { 32431457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 32531457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 32631457Sminshall quit(); 32731457Sminshall } else if (length == 0) { 32831457Sminshall return; 32931457Sminshall } 33031508Sminshall getstorage(di, length, 1); 33131463Sminshall memcpy(local, storage+(di-storage_location), length); 33231457Sminshall } 33331457Sminshall 33431457Sminshall void 33531457Sminshall movetothem(es, di, local, length) 33631457Sminshall int 33731457Sminshall es, 33831457Sminshall di; 33931457Sminshall char 34031457Sminshall *local; 34131457Sminshall int 34231457Sminshall length; 34331457Sminshall { 34431457Sminshall if (length > sizeof storage) { 34531457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 34631457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 34731457Sminshall quit(); 34831457Sminshall } else if (length == 0) { 34931457Sminshall return; 35031457Sminshall } 35131457Sminshall freestorage(); 35231457Sminshall memcpy((char *)storage, local, length); 35331457Sminshall storage_length = length; 35431463Sminshall storage_location = di; 35531457Sminshall storage_must_send = 1; 35631457Sminshall } 35731457Sminshall 35831457Sminshall 35931457Sminshall char * 36031508Sminshall access_api(location, length, copyin) 36131457Sminshall int 36231457Sminshall location, 36331508Sminshall length, 36431508Sminshall copyin; /* Do we need to copy in initially? */ 36531457Sminshall { 36631457Sminshall if (storage_accessed) { 36731457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 36831503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 36931457Sminshall __FILE__, __LINE__); 37031457Sminshall quit(); 37131457Sminshall } else if (length != 0) { 37231457Sminshall freestorage(); 37331508Sminshall getstorage(location, length, copyin); 37431503Sminshall storage_accessed = 1; 37531457Sminshall } 37631457Sminshall return (char *) storage; 37731457Sminshall } 37831457Sminshall 37931508Sminshall unaccess_api(location, local, length, copyout) 38031457Sminshall int location; 38131457Sminshall char *local; 38231457Sminshall int length; 38331457Sminshall { 38431457Sminshall if (storage_accessed == 0) { 38531457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 38631503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 38731457Sminshall __FILE__, __LINE__); 38831457Sminshall quit(); 38931457Sminshall } 39031457Sminshall storage_accessed = 0; 39131508Sminshall storage_must_send = copyout; /* if needs to go back */ 39231457Sminshall } 39331457Sminshall 39431465Sminshall /* 39531465Sminshall * Accept a connection from an API client, aborting if the child dies. 39631465Sminshall */ 39731457Sminshall 39831465Sminshall static int 39931465Sminshall doconnect() 40031465Sminshall { 40131465Sminshall fd_set fdset; 40231465Sminshall int i; 40331465Sminshall 40431465Sminshall sock = -1; 40531465Sminshall FD_ZERO(&fdset); 40631465Sminshall while (shell_active && (sock == -1)) { 40731465Sminshall FD_SET(serversock, &fdset); 40831465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 40931465Sminshall if (errno = EINTR) { 41031465Sminshall continue; 41131465Sminshall } else { 41231465Sminshall perror("in select waiting for API connection"); 41331465Sminshall return -1; 41431465Sminshall } 41531465Sminshall } else { 41631465Sminshall i = accept(serversock, 0, 0); 41731465Sminshall if (i == -1) { 41831465Sminshall perror("accepting API connection"); 41931465Sminshall return -1; 42031465Sminshall } 42131465Sminshall sock = i; 42231465Sminshall } 42331465Sminshall } 42431465Sminshall /* If the process has already exited, we may need to close */ 42531465Sminshall if ((shell_active == 0) && (sock != -1)) { 42631465Sminshall (void) close(sock); 42731465Sminshall sock = -1; 42831465Sminshall setcommandmode(); /* In case child_died sneaked in */ 42931465Sminshall } 43031465Sminshall } 43131465Sminshall 43231457Sminshall /* 43331455Sminshall * shell_continue() actually runs the command, and looks for API 43431455Sminshall * requests coming back in. 43531455Sminshall * 43631455Sminshall * We are called from the main loop in telnet.c. 43731455Sminshall */ 43831455Sminshall 43931455Sminshall int 44031455Sminshall shell_continue() 44131455Sminshall { 44231492Sminshall int i; 44331492Sminshall 44431457Sminshall switch (state) { 44531457Sminshall case DEAD: 44631457Sminshall pause(); /* Nothing to do */ 44731457Sminshall break; 44831457Sminshall case UNCONNECTED: 44931465Sminshall if (doconnect() == -1) { 45031457Sminshall kill_connection(); 45131465Sminshall return -1; 45231465Sminshall } 45331492Sminshall if (api_exch_init(sock, "server") == -1) { 45431465Sminshall return -1; 45531465Sminshall } 45631465Sminshall while (state == UNCONNECTED) { 45731492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 45831457Sminshall kill_connection(); 45931465Sminshall return -1; 46031465Sminshall } else { 46131465Sminshall switch (doassociate()) { 46231465Sminshall case -1: 46331465Sminshall kill_connection(); 46431465Sminshall return -1; 46531465Sminshall case 0: 46631465Sminshall break; 46731465Sminshall case 1: 46831465Sminshall state = CONNECTED; 46931465Sminshall } 47031457Sminshall } 47131457Sminshall } 47231457Sminshall break; 47331457Sminshall case CONNECTED: 47431492Sminshall switch (i = api_exch_nextcommand()) { 47531492Sminshall case EXCH_CMD_REQUEST: 47631492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 47731492Sminshall (char *)&inputRegs) == -1) { 47831463Sminshall kill_connection(); 47931492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 48031492Sminshall (char *)&inputSregs) == -1) { 48131463Sminshall kill_connection(); 48231492Sminshall } else if (nextstore() == -1) { 48331463Sminshall kill_connection(); 48431492Sminshall } else { 48531492Sminshall handle_api(&inputRegs, &inputSregs); 48631492Sminshall freestorage(); /* Send any storage back */ 48731492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 48831492Sminshall kill_connection(); 48931492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 49031492Sminshall (char *)&inputRegs) == -1) { 49131492Sminshall kill_connection(); 49231492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 49331492Sminshall (char *)&inputSregs) == -1) { 49431492Sminshall kill_connection(); 49531492Sminshall } 49631492Sminshall /* Done, and it all worked! */ 49731463Sminshall } 49831492Sminshall break; 49931492Sminshall case EXCH_CMD_DISASSOCIATE: 50031492Sminshall kill_connection(); 50131492Sminshall break; 50231492Sminshall default: 50331503Sminshall if (i != -1) { 50431503Sminshall fprintf(stderr, 50531503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 50631503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 50731503Sminshall } 50831492Sminshall kill_connection(); 50931503Sminshall break; 51031457Sminshall } 51131457Sminshall } 51231455Sminshall return shell_active; 51331455Sminshall } 51431455Sminshall 51531455Sminshall 51631463Sminshall static int 51731463Sminshall child_died() 51831463Sminshall { 51931463Sminshall union wait *status; 52031463Sminshall register int pid; 52131463Sminshall 52231463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 52331463Sminshall if (pid == shell_pid) { 52431463Sminshall char inputbuffer[100]; 52531463Sminshall 52631463Sminshall shell_active = 0; 52731463Sminshall if (sock != -1) { 52831463Sminshall (void) close(sock); 52931463Sminshall sock = -1; 53031463Sminshall } 53131471Sminshall printf("[Hit return to continue]"); 53231471Sminshall fflush(stdout); 53331471Sminshall (void) gets(inputbuffer); 53431465Sminshall setconnmode(); 53531465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 53631465Sminshall (void) close(serversock); 53731798Sminshall (void) unlink(keyname); 53831463Sminshall } 53931463Sminshall } 54031463Sminshall signal(SIGCHLD, child_died); 54131463Sminshall } 54231463Sminshall 54331463Sminshall 54431455Sminshall /* 54531455Sminshall * Called from telnet.c to fork a lower command.com. We 54631455Sminshall * use the spint... routines so that we can pick up 54731455Sminshall * interrupts generated by application programs. 54831455Sminshall */ 54931455Sminshall 55031455Sminshall 55131455Sminshall int 55231455Sminshall shell(argc,argv) 55331455Sminshall int argc; 55431455Sminshall char *argv[]; 55531455Sminshall { 55631465Sminshall int length; 55731457Sminshall struct sockaddr_in server; 55831457Sminshall char sockNAME[100]; 55931457Sminshall static char **whereAPI = 0; 56031798Sminshall int fd; 56131798Sminshall struct timeval tv; 56231798Sminshall long ikey; 56331798Sminshall extern long random(); 56431798Sminshall extern char *mktemp(); 56531457Sminshall 56631798Sminshall /* First, create verification file. */ 56731798Sminshall do { 56831798Sminshall keyname = mktemp("/tmp/apiXXXXXX"); 56931798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 57031798Sminshall } while ((fd == -1) && (errno == EEXIST)); 57131798Sminshall 57231798Sminshall if (fd == -1) { 57331798Sminshall perror("open"); 57431798Sminshall return 0; 57531798Sminshall } 57631798Sminshall 57731798Sminshall /* Now, get seed for random */ 57831798Sminshall 57931798Sminshall if (gettimeofday(&tv, 0) == -1) { 58031798Sminshall perror("gettimeofday"); 58131798Sminshall return 0; 58231798Sminshall } 58331798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 58431798Sminshall do { 58531798Sminshall ikey = random(); 58631798Sminshall } while (ikey == 0); 58731798Sminshall sprintf(key, "%lu\n", ikey); 58831798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 58931798Sminshall perror("write"); 59031798Sminshall return 0; 59131798Sminshall } 59231798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 59331798Sminshall 59431798Sminshall if (close(fd) == -1) { 59531798Sminshall perror("close"); 59631798Sminshall return 0; 59731798Sminshall } 59831798Sminshall 59931798Sminshall /* Next, create the socket which will be connected to */ 60031457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 60131457Sminshall if (serversock < 0) { 60231457Sminshall perror("opening API socket"); 60331457Sminshall return 0; 60431457Sminshall } 60531457Sminshall server.sin_family = AF_INET; 60631457Sminshall server.sin_addr.s_addr = INADDR_ANY; 60731457Sminshall server.sin_port = 0; 60831457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 60931457Sminshall perror("binding API socket"); 61031457Sminshall return 0; 61131457Sminshall } 61231457Sminshall length = sizeof server; 61331457Sminshall if (getsockname(serversock, &server, &length) < 0) { 61431457Sminshall perror("getting API socket name"); 61531457Sminshall (void) close(serversock); 61631457Sminshall } 61731457Sminshall listen(serversock, 1); 61831457Sminshall /* Get name to advertise in address list */ 61931457Sminshall strcpy(sockNAME, "API3270="); 62031457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 62131798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 62231457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 62331457Sminshall strcpy(sockNAME, "localhost"); 62431457Sminshall } 62531457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 62631798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 62731457Sminshall 62831457Sminshall if (whereAPI == 0) { 62931457Sminshall char **ptr, **nextenv; 63031457Sminshall extern char **environ; 63131457Sminshall 63231457Sminshall ptr = environ; 63331457Sminshall nextenv = ourENVlist; 63431457Sminshall while (*ptr) { 63531457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 63631457Sminshall fprintf(stderr, "Too many environmental variables\n"); 63731457Sminshall break; 63831457Sminshall } 63931457Sminshall *nextenv++ = *ptr++; 64031457Sminshall } 64131457Sminshall whereAPI = nextenv++; 64231457Sminshall *nextenv++ = 0; 64331457Sminshall environ = ourENVlist; /* New environment */ 64431457Sminshall } 64531457Sminshall *whereAPI = sockNAME; 64631457Sminshall 64731457Sminshall child_died(); /* Start up signal handler */ 64831457Sminshall shell_active = 1; /* We are running down below */ 64931457Sminshall if (shell_pid = vfork()) { 65031457Sminshall if (shell_pid == -1) { 65131457Sminshall perror("vfork"); 65231457Sminshall (void) close(serversock); 65331457Sminshall } else { 65431465Sminshall state = UNCONNECTED; 65531457Sminshall } 65631455Sminshall } else { /* New process */ 65731455Sminshall register int i; 65831455Sminshall 65931455Sminshall for (i = 3; i < 30; i++) { 66031455Sminshall (void) close(i); 66131455Sminshall } 66231455Sminshall if (argc == 1) { /* Just get a shell */ 66331455Sminshall char *cmdname; 66431457Sminshall extern char *getenv(); 66531455Sminshall 66631455Sminshall cmdname = getenv("SHELL"); 66731455Sminshall execlp(cmdname, cmdname, 0); 66831455Sminshall perror("Exec'ing new shell...\n"); 66931455Sminshall exit(1); 67031455Sminshall } else { 67131455Sminshall execvp(argv[1], &argv[1]); 67231455Sminshall perror("Exec'ing command.\n"); 67331455Sminshall exit(1); 67431455Sminshall } 67531455Sminshall /*NOTREACHED*/ 67631455Sminshall } 67731457Sminshall return shell_active; /* Go back to main loop */ 67831455Sminshall } 679