131457Sminshall #include <sys/types.h> 2*31798Sminshall #include <sys/inode.h> 3*31798Sminshall #include <sys/file.h> 4*31798Sminshall #include <sys/time.h> 531457Sminshall #include <sys/socket.h> 631457Sminshall #include <netinet/in.h> 731455Sminshall #include <sys/wait.h> 831455Sminshall 931457Sminshall #include <errno.h> 1031457Sminshall extern int errno; 1131457Sminshall 1231457Sminshall #include <netdb.h> 1331457Sminshall #include <signal.h> 1431455Sminshall #include <stdio.h> 1531457Sminshall #include <pwd.h> 1631455Sminshall 1731455Sminshall #include "../general/general.h" 1831455Sminshall #include "../api/api.h" 1931463Sminshall #include "../apilib/api_exch.h" 2031455Sminshall 2131455Sminshall #include "../general/globals.h" 2231455Sminshall 2331795Sminshall #ifndef FD_SETSIZE 2431795Sminshall /* 2531795Sminshall * The following is defined just in case someone should want to run 2631795Sminshall * this telnet on a 4.2 system. 2731795Sminshall * 2831795Sminshall */ 2931455Sminshall 3031795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 3131795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 3231795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 3331795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 3431795Sminshall 3531795Sminshall #endif 3631795Sminshall 3731455Sminshall static int shell_pid = 0; 38*31798Sminshall static char key[50]; /* Actual key */ 39*31798Sminshall static char *keyname; /* Name of file with key in it */ 4031455Sminshall 4131457Sminshall static char *ourENVlist[200]; /* Lots of room */ 4231457Sminshall 4331465Sminshall static int 4431465Sminshall sock = -1, /* Connected socket */ 4531465Sminshall serversock; /* Server (listening) socket */ 4631457Sminshall 4731457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 4831457Sminshall 4931455Sminshall static int 5031463Sminshall storage_location, /* Address we have */ 5131457Sminshall storage_length = 0, /* Length we have */ 5231457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 5331457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 5431457Sminshall 5531503Sminshall static long storage[1000]; 5631457Sminshall 5731463Sminshall static union REGS inputRegs; 5831463Sminshall static struct SREGS inputSregs; 5931457Sminshall 6031463Sminshall 6131463Sminshall static void 6231457Sminshall kill_connection() 6331457Sminshall { 6431465Sminshall state = UNCONNECTED; 6531465Sminshall if (sock != -1) { 6631465Sminshall (void) close(sock); 6731465Sminshall sock = -1; 6831465Sminshall } 6931457Sminshall } 7031457Sminshall 7131457Sminshall 7231457Sminshall static int 7331463Sminshall nextstore() 7431455Sminshall { 7531463Sminshall struct storage_descriptor sd; 7631455Sminshall 7731463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 7831457Sminshall storage_length = 0; 7931457Sminshall return -1; 8031457Sminshall } 81*31798Sminshall storage_length = sd.length; 82*31798Sminshall storage_location = sd.location; 8331463Sminshall if (storage_length > sizeof storage) { 8431457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 8531457Sminshall storage_length); 8631463Sminshall storage_length = 0; 8731457Sminshall return -1; 8831457Sminshall } 8931511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 9031511Sminshall == -1) { 9131511Sminshall storage_length = 0; 9231511Sminshall return -1; 9331463Sminshall } 9431471Sminshall return 0; 9531457Sminshall } 9631457Sminshall 9731457Sminshall 9831457Sminshall static int 9931457Sminshall doreject(message) 10031457Sminshall char *message; 10131457Sminshall { 10231463Sminshall struct storage_descriptor sd; 10331457Sminshall int length = strlen(message); 10431457Sminshall 10531492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 10631457Sminshall return -1; 10731457Sminshall } 108*31798Sminshall sd.length = length; 10931465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 11031463Sminshall return -1; 11131463Sminshall } 11231463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 11331463Sminshall return -1; 11431463Sminshall } 11531457Sminshall return 0; 11631457Sminshall } 11731457Sminshall 11831457Sminshall 11931455Sminshall /* 12031465Sminshall * doassociate() 12131457Sminshall * 12231457Sminshall * Negotiate with the other side and try to do something. 123*31798Sminshall * 124*31798Sminshall * Returns: 125*31798Sminshall * 126*31798Sminshall * -1: Error in processing 127*31798Sminshall * 0: Invalid password entered 128*31798Sminshall * 1: Association OK 12931457Sminshall */ 13031457Sminshall 13131457Sminshall static int 13231465Sminshall doassociate() 13331457Sminshall { 13431457Sminshall struct passwd *pwent; 13531457Sminshall char 13631457Sminshall promptbuf[100], 13731457Sminshall buffer[200]; 13831457Sminshall int length; 13931457Sminshall int was; 14031463Sminshall struct storage_descriptor sd; 14131457Sminshall 14231463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 14331463Sminshall return -1; 14431457Sminshall } 145*31798Sminshall sd.length = sd.length; 14631463Sminshall if (sd.length > sizeof buffer) { 147*31798Sminshall doreject("(internal error) Authentication key too long"); 14831465Sminshall return -1; 14931457Sminshall } 15031463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 15131457Sminshall return -1; 15231457Sminshall } 15331463Sminshall buffer[sd.length] = 0; 15431457Sminshall 155*31798Sminshall if (strcmp(buffer, key) != 0) { 156*31798Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 157*31798Sminshall return -1; 158*31798Sminshall } 159*31798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 160*31798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 161*31798Sminshall return -1; 162*31798Sminshall } 163*31798Sminshall sd.length = strlen(promptbuf); 164*31798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 165*31798Sminshall == -1) { 166*31798Sminshall return -1; 167*31798Sminshall } 168*31798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 169*31798Sminshall == -1) { 170*31798Sminshall return -1; 171*31798Sminshall } 172*31798Sminshall sd.length = strlen(pwent->pw_name); 173*31798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 174*31798Sminshall == -1) { 175*31798Sminshall return -1; 176*31798Sminshall } 177*31798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 178*31798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 179*31798Sminshall return -1; 180*31798Sminshall } 181*31798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 182*31798Sminshall return -1; 183*31798Sminshall } 184*31798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 185*31798Sminshall == -1) { 186*31798Sminshall return -1; 187*31798Sminshall } 188*31798Sminshall sd.length = sd.length; 189*31798Sminshall if (sd.length > sizeof buffer) { 190*31798Sminshall doreject("Password entered was too long"); 191*31798Sminshall return -1; 192*31798Sminshall } 193*31798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 194*31798Sminshall return -1; 195*31798Sminshall } 196*31798Sminshall buffer[sd.length] = 0; 19731465Sminshall 198*31798Sminshall /* Is this the correct password? */ 199*31798Sminshall if (strlen(pwent->pw_name)) { 200*31798Sminshall char *ptr; 201*31798Sminshall int i; 202*31798Sminshall 203*31798Sminshall ptr = pwent->pw_name; 204*31798Sminshall i = 0; 205*31798Sminshall while (i < sd.length) { 206*31798Sminshall buffer[i++] ^= *ptr++; 207*31798Sminshall if (*ptr == 0) { 208*31798Sminshall ptr = pwent->pw_name; 209*31798Sminshall } 21031465Sminshall } 21131465Sminshall } 212*31798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 213*31798Sminshall doreject("Invalid password"); 214*31798Sminshall sleep(10); /* Don't let us do too many of these */ 215*31798Sminshall return 0; 216*31798Sminshall } 21731465Sminshall } 218*31798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 219*31798Sminshall return -1; 22031457Sminshall } else { 221*31798Sminshall return 1; 22231457Sminshall } 22331457Sminshall } 22431457Sminshall 22531457Sminshall 22631457Sminshall void 22731457Sminshall freestorage() 22831457Sminshall { 22931457Sminshall char buffer[40]; 23031463Sminshall struct storage_descriptor sd; 23131457Sminshall 23231457Sminshall if (storage_accessed) { 23331457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 23431503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 23531457Sminshall __FILE__, __LINE__); 23631457Sminshall quit(); 23731457Sminshall } 23831457Sminshall if (storage_must_send == 0) { 23931457Sminshall return; 24031457Sminshall } 24131457Sminshall storage_must_send = 0; 24231492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 24331457Sminshall kill_connection(); 24431457Sminshall return; 24531457Sminshall } 246*31798Sminshall sd.length = storage_length; 247*31798Sminshall sd.location = storage_location; 24831463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 24931457Sminshall kill_connection(); 25031457Sminshall return; 25131457Sminshall } 25231511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 25331511Sminshall == -1) { 25431511Sminshall kill_connection(); 25531511Sminshall return; 25631463Sminshall } 25731457Sminshall } 25831457Sminshall 25931457Sminshall 26031463Sminshall static int 26131508Sminshall getstorage(address, length, copyin) 26231508Sminshall int 26331508Sminshall address, 26431508Sminshall length, 26531508Sminshall copyin; 26631457Sminshall { 26731463Sminshall struct storage_descriptor sd; 26831457Sminshall char buffer[40]; 26931457Sminshall 27031457Sminshall freestorage(); 27131457Sminshall if (storage_accessed) { 27231457Sminshall fprintf(stderr, 27331457Sminshall "Internal error - attempt to get while storage accessed.\n"); 27431503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 27531457Sminshall __FILE__, __LINE__); 27631457Sminshall quit(); 27731457Sminshall } 27831457Sminshall storage_must_send = 0; 27931492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 28031457Sminshall kill_connection(); 28131463Sminshall return -1; 28231457Sminshall } 28331471Sminshall storage_location = address; 28431471Sminshall storage_length = length; 28531508Sminshall if (copyin) { 286*31798Sminshall sd.location = storage_location; 287*31798Sminshall sd.length = storage_length; 28831508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 28931508Sminshall sizeof sd, (char *)&sd) == -1) { 29031508Sminshall kill_connection(); 29131508Sminshall return -1; 29231508Sminshall } 29331508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 29431508Sminshall fprintf(stderr, "Bad data from other side.\n"); 29531508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 29631508Sminshall return -1; 29731508Sminshall } 29831508Sminshall if (nextstore() == -1) { 29931508Sminshall kill_connection(); 30031508Sminshall return -1; 30131508Sminshall } 30231463Sminshall } 30331463Sminshall return 0; 30431457Sminshall } 30531457Sminshall 30631457Sminshall void 30731457Sminshall movetous(local, es, di, length) 30831457Sminshall char 30931457Sminshall *local; 31031457Sminshall int 31131457Sminshall es, 31231457Sminshall di; 31331457Sminshall int 31431457Sminshall length; 31531457Sminshall { 31631457Sminshall if (length > sizeof storage) { 31731457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 31831457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 31931457Sminshall quit(); 32031457Sminshall } else if (length == 0) { 32131457Sminshall return; 32231457Sminshall } 32331508Sminshall getstorage(di, length, 1); 32431463Sminshall memcpy(local, storage+(di-storage_location), length); 32531457Sminshall } 32631457Sminshall 32731457Sminshall void 32831457Sminshall movetothem(es, di, local, length) 32931457Sminshall int 33031457Sminshall es, 33131457Sminshall di; 33231457Sminshall char 33331457Sminshall *local; 33431457Sminshall int 33531457Sminshall length; 33631457Sminshall { 33731457Sminshall if (length > sizeof storage) { 33831457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 33931457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 34031457Sminshall quit(); 34131457Sminshall } else if (length == 0) { 34231457Sminshall return; 34331457Sminshall } 34431457Sminshall freestorage(); 34531457Sminshall memcpy((char *)storage, local, length); 34631457Sminshall storage_length = length; 34731463Sminshall storage_location = di; 34831457Sminshall storage_must_send = 1; 34931457Sminshall } 35031457Sminshall 35131457Sminshall 35231457Sminshall char * 35331508Sminshall access_api(location, length, copyin) 35431457Sminshall int 35531457Sminshall location, 35631508Sminshall length, 35731508Sminshall copyin; /* Do we need to copy in initially? */ 35831457Sminshall { 35931457Sminshall if (storage_accessed) { 36031457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 36131503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 36231457Sminshall __FILE__, __LINE__); 36331457Sminshall quit(); 36431457Sminshall } else if (length != 0) { 36531457Sminshall freestorage(); 36631508Sminshall getstorage(location, length, copyin); 36731503Sminshall storage_accessed = 1; 36831457Sminshall } 36931457Sminshall return (char *) storage; 37031457Sminshall } 37131457Sminshall 37231508Sminshall unaccess_api(location, local, length, copyout) 37331457Sminshall int location; 37431457Sminshall char *local; 37531457Sminshall int length; 37631457Sminshall { 37731457Sminshall if (storage_accessed == 0) { 37831457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 37931503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 38031457Sminshall __FILE__, __LINE__); 38131457Sminshall quit(); 38231457Sminshall } 38331457Sminshall storage_accessed = 0; 38431508Sminshall storage_must_send = copyout; /* if needs to go back */ 38531457Sminshall } 38631457Sminshall 38731465Sminshall /* 38831465Sminshall * Accept a connection from an API client, aborting if the child dies. 38931465Sminshall */ 39031457Sminshall 39131465Sminshall static int 39231465Sminshall doconnect() 39331465Sminshall { 39431465Sminshall fd_set fdset; 39531465Sminshall int i; 39631465Sminshall 39731465Sminshall sock = -1; 39831465Sminshall FD_ZERO(&fdset); 39931465Sminshall while (shell_active && (sock == -1)) { 40031465Sminshall FD_SET(serversock, &fdset); 40131465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 40231465Sminshall if (errno = EINTR) { 40331465Sminshall continue; 40431465Sminshall } else { 40531465Sminshall perror("in select waiting for API connection"); 40631465Sminshall return -1; 40731465Sminshall } 40831465Sminshall } else { 40931465Sminshall i = accept(serversock, 0, 0); 41031465Sminshall if (i == -1) { 41131465Sminshall perror("accepting API connection"); 41231465Sminshall return -1; 41331465Sminshall } 41431465Sminshall sock = i; 41531465Sminshall } 41631465Sminshall } 41731465Sminshall /* If the process has already exited, we may need to close */ 41831465Sminshall if ((shell_active == 0) && (sock != -1)) { 41931465Sminshall (void) close(sock); 42031465Sminshall sock = -1; 42131465Sminshall setcommandmode(); /* In case child_died sneaked in */ 42231465Sminshall } 42331465Sminshall } 42431465Sminshall 42531457Sminshall /* 42631455Sminshall * shell_continue() actually runs the command, and looks for API 42731455Sminshall * requests coming back in. 42831455Sminshall * 42931455Sminshall * We are called from the main loop in telnet.c. 43031455Sminshall */ 43131455Sminshall 43231455Sminshall int 43331455Sminshall shell_continue() 43431455Sminshall { 43531492Sminshall int i; 43631492Sminshall 43731457Sminshall switch (state) { 43831457Sminshall case DEAD: 43931457Sminshall pause(); /* Nothing to do */ 44031457Sminshall break; 44131457Sminshall case UNCONNECTED: 44231465Sminshall if (doconnect() == -1) { 44331457Sminshall kill_connection(); 44431465Sminshall return -1; 44531465Sminshall } 44631492Sminshall if (api_exch_init(sock, "server") == -1) { 44731465Sminshall return -1; 44831465Sminshall } 44931465Sminshall while (state == UNCONNECTED) { 45031492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 45131457Sminshall kill_connection(); 45231465Sminshall return -1; 45331465Sminshall } else { 45431465Sminshall switch (doassociate()) { 45531465Sminshall case -1: 45631465Sminshall kill_connection(); 45731465Sminshall return -1; 45831465Sminshall case 0: 45931465Sminshall break; 46031465Sminshall case 1: 46131465Sminshall state = CONNECTED; 46231465Sminshall } 46331457Sminshall } 46431457Sminshall } 46531457Sminshall break; 46631457Sminshall case CONNECTED: 46731492Sminshall switch (i = api_exch_nextcommand()) { 46831492Sminshall case EXCH_CMD_REQUEST: 46931492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 47031492Sminshall (char *)&inputRegs) == -1) { 47131463Sminshall kill_connection(); 47231492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 47331492Sminshall (char *)&inputSregs) == -1) { 47431463Sminshall kill_connection(); 47531492Sminshall } else if (nextstore() == -1) { 47631463Sminshall kill_connection(); 47731492Sminshall } else { 47831492Sminshall handle_api(&inputRegs, &inputSregs); 47931492Sminshall freestorage(); /* Send any storage back */ 48031492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 48131492Sminshall kill_connection(); 48231492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 48331492Sminshall (char *)&inputRegs) == -1) { 48431492Sminshall kill_connection(); 48531492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 48631492Sminshall (char *)&inputSregs) == -1) { 48731492Sminshall kill_connection(); 48831492Sminshall } 48931492Sminshall /* Done, and it all worked! */ 49031463Sminshall } 49131492Sminshall break; 49231492Sminshall case EXCH_CMD_DISASSOCIATE: 49331492Sminshall kill_connection(); 49431492Sminshall break; 49531492Sminshall default: 49631503Sminshall if (i != -1) { 49731503Sminshall fprintf(stderr, 49831503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 49931503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 50031503Sminshall } 50131492Sminshall kill_connection(); 50231503Sminshall break; 50331457Sminshall } 50431457Sminshall } 50531455Sminshall return shell_active; 50631455Sminshall } 50731455Sminshall 50831455Sminshall 50931463Sminshall static int 51031463Sminshall child_died() 51131463Sminshall { 51231463Sminshall union wait *status; 51331463Sminshall register int pid; 51431463Sminshall 51531463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 51631463Sminshall if (pid == shell_pid) { 51731463Sminshall char inputbuffer[100]; 51831463Sminshall 51931463Sminshall shell_active = 0; 52031463Sminshall if (sock != -1) { 52131463Sminshall (void) close(sock); 52231463Sminshall sock = -1; 52331463Sminshall } 52431471Sminshall printf("[Hit return to continue]"); 52531471Sminshall fflush(stdout); 52631471Sminshall (void) gets(inputbuffer); 52731465Sminshall setconnmode(); 52831465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 52931465Sminshall (void) close(serversock); 530*31798Sminshall (void) unlink(keyname); 53131463Sminshall } 53231463Sminshall } 53331463Sminshall signal(SIGCHLD, child_died); 53431463Sminshall } 53531463Sminshall 53631463Sminshall 53731455Sminshall /* 53831455Sminshall * Called from telnet.c to fork a lower command.com. We 53931455Sminshall * use the spint... routines so that we can pick up 54031455Sminshall * interrupts generated by application programs. 54131455Sminshall */ 54231455Sminshall 54331455Sminshall 54431455Sminshall int 54531455Sminshall shell(argc,argv) 54631455Sminshall int argc; 54731455Sminshall char *argv[]; 54831455Sminshall { 54931465Sminshall int length; 55031457Sminshall struct sockaddr_in server; 55131457Sminshall char sockNAME[100]; 55231457Sminshall static char **whereAPI = 0; 553*31798Sminshall int fd; 554*31798Sminshall struct timeval tv; 555*31798Sminshall long ikey; 556*31798Sminshall extern long random(); 557*31798Sminshall extern char *mktemp(); 55831457Sminshall 559*31798Sminshall /* First, create verification file. */ 560*31798Sminshall do { 561*31798Sminshall keyname = mktemp("/tmp/apiXXXXXX"); 562*31798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 563*31798Sminshall } while ((fd == -1) && (errno == EEXIST)); 564*31798Sminshall 565*31798Sminshall if (fd == -1) { 566*31798Sminshall perror("open"); 567*31798Sminshall return 0; 568*31798Sminshall } 569*31798Sminshall 570*31798Sminshall /* Now, get seed for random */ 571*31798Sminshall 572*31798Sminshall if (gettimeofday(&tv, 0) == -1) { 573*31798Sminshall perror("gettimeofday"); 574*31798Sminshall return 0; 575*31798Sminshall } 576*31798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 577*31798Sminshall do { 578*31798Sminshall ikey = random(); 579*31798Sminshall } while (ikey == 0); 580*31798Sminshall sprintf(key, "%lu\n", ikey); 581*31798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 582*31798Sminshall perror("write"); 583*31798Sminshall return 0; 584*31798Sminshall } 585*31798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 586*31798Sminshall 587*31798Sminshall if (close(fd) == -1) { 588*31798Sminshall perror("close"); 589*31798Sminshall return 0; 590*31798Sminshall } 591*31798Sminshall 592*31798Sminshall /* Next, create the socket which will be connected to */ 59331457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 59431457Sminshall if (serversock < 0) { 59531457Sminshall perror("opening API socket"); 59631457Sminshall return 0; 59731457Sminshall } 59831457Sminshall server.sin_family = AF_INET; 59931457Sminshall server.sin_addr.s_addr = INADDR_ANY; 60031457Sminshall server.sin_port = 0; 60131457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 60231457Sminshall perror("binding API socket"); 60331457Sminshall return 0; 60431457Sminshall } 60531457Sminshall length = sizeof server; 60631457Sminshall if (getsockname(serversock, &server, &length) < 0) { 60731457Sminshall perror("getting API socket name"); 60831457Sminshall (void) close(serversock); 60931457Sminshall } 61031457Sminshall listen(serversock, 1); 61131457Sminshall /* Get name to advertise in address list */ 61231457Sminshall strcpy(sockNAME, "API3270="); 61331457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 614*31798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 61531457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 61631457Sminshall strcpy(sockNAME, "localhost"); 61731457Sminshall } 61831457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 619*31798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 62031457Sminshall 62131457Sminshall if (whereAPI == 0) { 62231457Sminshall char **ptr, **nextenv; 62331457Sminshall extern char **environ; 62431457Sminshall 62531457Sminshall ptr = environ; 62631457Sminshall nextenv = ourENVlist; 62731457Sminshall while (*ptr) { 62831457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 62931457Sminshall fprintf(stderr, "Too many environmental variables\n"); 63031457Sminshall break; 63131457Sminshall } 63231457Sminshall *nextenv++ = *ptr++; 63331457Sminshall } 63431457Sminshall whereAPI = nextenv++; 63531457Sminshall *nextenv++ = 0; 63631457Sminshall environ = ourENVlist; /* New environment */ 63731457Sminshall } 63831457Sminshall *whereAPI = sockNAME; 63931457Sminshall 64031457Sminshall child_died(); /* Start up signal handler */ 64131457Sminshall shell_active = 1; /* We are running down below */ 64231457Sminshall if (shell_pid = vfork()) { 64331457Sminshall if (shell_pid == -1) { 64431457Sminshall perror("vfork"); 64531457Sminshall (void) close(serversock); 64631457Sminshall } else { 64731465Sminshall state = UNCONNECTED; 64831457Sminshall } 64931455Sminshall } else { /* New process */ 65031455Sminshall register int i; 65131455Sminshall 65231455Sminshall for (i = 3; i < 30; i++) { 65331455Sminshall (void) close(i); 65431455Sminshall } 65531455Sminshall if (argc == 1) { /* Just get a shell */ 65631455Sminshall char *cmdname; 65731457Sminshall extern char *getenv(); 65831455Sminshall 65931455Sminshall cmdname = getenv("SHELL"); 66031455Sminshall execlp(cmdname, cmdname, 0); 66131455Sminshall perror("Exec'ing new shell...\n"); 66231455Sminshall exit(1); 66331455Sminshall } else { 66431455Sminshall execvp(argv[1], &argv[1]); 66531455Sminshall perror("Exec'ing command.\n"); 66631455Sminshall exit(1); 66731455Sminshall } 66831455Sminshall /*NOTREACHED*/ 66931455Sminshall } 67031457Sminshall return shell_active; /* Go back to main loop */ 67131455Sminshall } 672