1*31894Sminshall /* 2*31894Sminshall * Copyright (c) 1984-1987 by the Regents of the 3*31894Sminshall * University of California and by Gregory Glenn Minshall. 4*31894Sminshall * 5*31894Sminshall * Permission to use, copy, modify, and distribute these 6*31894Sminshall * programs and their documentation for any purpose and 7*31894Sminshall * without fee is hereby granted, provided that this 8*31894Sminshall * copyright and permission appear on all copies and 9*31894Sminshall * supporting documentation, the name of the Regents of 10*31894Sminshall * the University of California not be used in advertising 11*31894Sminshall * or publicity pertaining to distribution of the programs 12*31894Sminshall * without specific prior permission, and notice be given in 13*31894Sminshall * supporting documentation that copying and distribution is 14*31894Sminshall * by permission of the Regents of the University of California 15*31894Sminshall * and by Gregory Glenn Minshall. Neither the Regents of the 16*31894Sminshall * University of California nor Gregory Glenn Minshall make 17*31894Sminshall * representations about the suitability of this software 18*31894Sminshall * for any purpose. It is provided "as is" without 19*31894Sminshall * express or implied warranty. 20*31894Sminshall */ 21*31894Sminshall 22*31894Sminshall #ifndef lint 23*31894Sminshall static char sccsid[] = "@(#)system.c 1.14 (Berkeley) 07/17/87"; 24*31894Sminshall #endif /* not lint */ 25*31894Sminshall 2631457Sminshall #include <sys/types.h> 2731863Sminshall 2831863Sminshall #if !defined(sun) 2931798Sminshall #include <sys/inode.h> 3031863Sminshall #else /* !defined(sun) */ 3131863Sminshall #define IREAD 00400 3231863Sminshall #define IWRITE 00200 3331863Sminshall #endif /* !defined(sun) */ 3431863Sminshall 3531798Sminshall #include <sys/file.h> 3631798Sminshall #include <sys/time.h> 3731457Sminshall #include <sys/socket.h> 3831457Sminshall #include <netinet/in.h> 3931455Sminshall #include <sys/wait.h> 4031455Sminshall 4131457Sminshall #include <errno.h> 4231457Sminshall extern int errno; 4331457Sminshall 4431457Sminshall #include <netdb.h> 4531457Sminshall #include <signal.h> 4631455Sminshall #include <stdio.h> 4731457Sminshall #include <pwd.h> 4831455Sminshall 4931455Sminshall #include "../general/general.h" 5031873Sminshall #include "../ctlr/api.h" 5131873Sminshall #include "../api/api_exch.h" 5231455Sminshall 5331455Sminshall #include "../general/globals.h" 5431455Sminshall 5531795Sminshall #ifndef FD_SETSIZE 5631795Sminshall /* 5731795Sminshall * The following is defined just in case someone should want to run 5831795Sminshall * this telnet on a 4.2 system. 5931795Sminshall * 6031795Sminshall */ 6131455Sminshall 6231795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 6331795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 6431795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 6531795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 6631795Sminshall 6731795Sminshall #endif 6831795Sminshall 6931455Sminshall static int shell_pid = 0; 7031798Sminshall static char key[50]; /* Actual key */ 7131798Sminshall static char *keyname; /* Name of file with key in it */ 7231455Sminshall 7331457Sminshall static char *ourENVlist[200]; /* Lots of room */ 7431457Sminshall 7531465Sminshall static int 7631465Sminshall sock = -1, /* Connected socket */ 7731465Sminshall serversock; /* Server (listening) socket */ 7831457Sminshall 7931457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 8031457Sminshall 8131455Sminshall static int 8231463Sminshall storage_location, /* Address we have */ 8331457Sminshall storage_length = 0, /* Length we have */ 8431457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 8531457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 8631457Sminshall 8731503Sminshall static long storage[1000]; 8831457Sminshall 8931463Sminshall static union REGS inputRegs; 9031463Sminshall static struct SREGS inputSregs; 9131457Sminshall 9231463Sminshall 9331463Sminshall static void 9431457Sminshall kill_connection() 9531457Sminshall { 9631465Sminshall state = UNCONNECTED; 9731465Sminshall if (sock != -1) { 9831465Sminshall (void) close(sock); 9931465Sminshall sock = -1; 10031465Sminshall } 10131457Sminshall } 10231457Sminshall 10331457Sminshall 10431457Sminshall static int 10531463Sminshall nextstore() 10631455Sminshall { 10731463Sminshall struct storage_descriptor sd; 10831455Sminshall 10931463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 11031457Sminshall storage_length = 0; 11131457Sminshall return -1; 11231457Sminshall } 11331798Sminshall storage_length = sd.length; 11431798Sminshall storage_location = sd.location; 11531463Sminshall if (storage_length > sizeof storage) { 11631457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 11731457Sminshall storage_length); 11831463Sminshall storage_length = 0; 11931457Sminshall return -1; 12031457Sminshall } 12131511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 12231511Sminshall == -1) { 12331511Sminshall storage_length = 0; 12431511Sminshall return -1; 12531463Sminshall } 12631471Sminshall return 0; 12731457Sminshall } 12831457Sminshall 12931457Sminshall 13031457Sminshall static int 13131457Sminshall doreject(message) 13231457Sminshall char *message; 13331457Sminshall { 13431463Sminshall struct storage_descriptor sd; 13531457Sminshall int length = strlen(message); 13631457Sminshall 13731492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 13831457Sminshall return -1; 13931457Sminshall } 14031798Sminshall sd.length = length; 14131465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 14231463Sminshall return -1; 14331463Sminshall } 14431463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 14531463Sminshall return -1; 14631463Sminshall } 14731457Sminshall return 0; 14831457Sminshall } 14931457Sminshall 15031457Sminshall 15131455Sminshall /* 15231465Sminshall * doassociate() 15331457Sminshall * 15431457Sminshall * Negotiate with the other side and try to do something. 15531798Sminshall * 15631798Sminshall * Returns: 15731798Sminshall * 15831798Sminshall * -1: Error in processing 15931798Sminshall * 0: Invalid password entered 16031798Sminshall * 1: Association OK 16131457Sminshall */ 16231457Sminshall 16331457Sminshall static int 16431465Sminshall doassociate() 16531457Sminshall { 16631457Sminshall struct passwd *pwent; 16731457Sminshall char 16831457Sminshall promptbuf[100], 16931457Sminshall buffer[200]; 17031457Sminshall int length; 17131457Sminshall int was; 17231463Sminshall struct storage_descriptor sd; 17331457Sminshall 17431463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 17531463Sminshall return -1; 17631457Sminshall } 17731798Sminshall sd.length = sd.length; 17831463Sminshall if (sd.length > sizeof buffer) { 17931798Sminshall doreject("(internal error) Authentication key too long"); 18031465Sminshall return -1; 18131457Sminshall } 18231463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 18331457Sminshall return -1; 18431457Sminshall } 18531463Sminshall buffer[sd.length] = 0; 18631457Sminshall 18731798Sminshall if (strcmp(buffer, key) != 0) { 18831798Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 18931798Sminshall return -1; 19031798Sminshall } 19131798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 19231798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 19331798Sminshall return -1; 19431798Sminshall } 19531798Sminshall sd.length = strlen(promptbuf); 19631798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 19731798Sminshall == -1) { 19831798Sminshall return -1; 19931798Sminshall } 20031798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 20131798Sminshall == -1) { 20231798Sminshall return -1; 20331798Sminshall } 20431798Sminshall sd.length = strlen(pwent->pw_name); 20531798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 20631798Sminshall == -1) { 20731798Sminshall return -1; 20831798Sminshall } 20931798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 21031798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 21131798Sminshall return -1; 21231798Sminshall } 21331798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 21431798Sminshall return -1; 21531798Sminshall } 21631798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 21731798Sminshall == -1) { 21831798Sminshall return -1; 21931798Sminshall } 22031798Sminshall sd.length = sd.length; 22131798Sminshall if (sd.length > sizeof buffer) { 22231798Sminshall doreject("Password entered was too long"); 22331798Sminshall return -1; 22431798Sminshall } 22531798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 22631798Sminshall return -1; 22731798Sminshall } 22831798Sminshall buffer[sd.length] = 0; 22931465Sminshall 23031798Sminshall /* Is this the correct password? */ 23131798Sminshall if (strlen(pwent->pw_name)) { 23231798Sminshall char *ptr; 23331798Sminshall int i; 23431798Sminshall 23531798Sminshall ptr = pwent->pw_name; 23631798Sminshall i = 0; 23731798Sminshall while (i < sd.length) { 23831798Sminshall buffer[i++] ^= *ptr++; 23931798Sminshall if (*ptr == 0) { 24031798Sminshall ptr = pwent->pw_name; 24131798Sminshall } 24231465Sminshall } 24331465Sminshall } 24431798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 24531798Sminshall doreject("Invalid password"); 24631798Sminshall sleep(10); /* Don't let us do too many of these */ 24731798Sminshall return 0; 24831798Sminshall } 24931465Sminshall } 25031798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 25131798Sminshall return -1; 25231457Sminshall } else { 25331798Sminshall return 1; 25431457Sminshall } 25531457Sminshall } 25631457Sminshall 25731457Sminshall 25831457Sminshall void 25931457Sminshall freestorage() 26031457Sminshall { 26131457Sminshall char buffer[40]; 26231463Sminshall struct storage_descriptor sd; 26331457Sminshall 26431457Sminshall if (storage_accessed) { 26531457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 26631503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 26731457Sminshall __FILE__, __LINE__); 26831457Sminshall quit(); 26931457Sminshall } 27031457Sminshall if (storage_must_send == 0) { 27131457Sminshall return; 27231457Sminshall } 27331457Sminshall storage_must_send = 0; 27431492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 27531457Sminshall kill_connection(); 27631457Sminshall return; 27731457Sminshall } 27831798Sminshall sd.length = storage_length; 27931798Sminshall sd.location = storage_location; 28031463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 28131457Sminshall kill_connection(); 28231457Sminshall return; 28331457Sminshall } 28431511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 28531511Sminshall == -1) { 28631511Sminshall kill_connection(); 28731511Sminshall return; 28831463Sminshall } 28931457Sminshall } 29031457Sminshall 29131457Sminshall 29231463Sminshall static int 29331508Sminshall getstorage(address, length, copyin) 29431508Sminshall int 29531508Sminshall address, 29631508Sminshall length, 29731508Sminshall copyin; 29831457Sminshall { 29931463Sminshall struct storage_descriptor sd; 30031457Sminshall char buffer[40]; 30131457Sminshall 30231457Sminshall freestorage(); 30331457Sminshall if (storage_accessed) { 30431457Sminshall fprintf(stderr, 30531457Sminshall "Internal error - attempt to get while storage accessed.\n"); 30631503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 30731457Sminshall __FILE__, __LINE__); 30831457Sminshall quit(); 30931457Sminshall } 31031457Sminshall storage_must_send = 0; 31131492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 31231457Sminshall kill_connection(); 31331463Sminshall return -1; 31431457Sminshall } 31531471Sminshall storage_location = address; 31631471Sminshall storage_length = length; 31731508Sminshall if (copyin) { 31831798Sminshall sd.location = storage_location; 31931798Sminshall sd.length = storage_length; 32031508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 32131508Sminshall sizeof sd, (char *)&sd) == -1) { 32231508Sminshall kill_connection(); 32331508Sminshall return -1; 32431508Sminshall } 32531508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 32631508Sminshall fprintf(stderr, "Bad data from other side.\n"); 32731508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 32831508Sminshall return -1; 32931508Sminshall } 33031508Sminshall if (nextstore() == -1) { 33131508Sminshall kill_connection(); 33231508Sminshall return -1; 33331508Sminshall } 33431463Sminshall } 33531463Sminshall return 0; 33631457Sminshall } 33731457Sminshall 33831457Sminshall void 33931457Sminshall movetous(local, es, di, length) 34031457Sminshall char 34131457Sminshall *local; 34231457Sminshall int 34331457Sminshall es, 34431457Sminshall di; 34531457Sminshall int 34631457Sminshall length; 34731457Sminshall { 34831457Sminshall if (length > sizeof storage) { 34931457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 35031457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 35131457Sminshall quit(); 35231457Sminshall } else if (length == 0) { 35331457Sminshall return; 35431457Sminshall } 35531508Sminshall getstorage(di, length, 1); 35631463Sminshall memcpy(local, storage+(di-storage_location), length); 35731457Sminshall } 35831457Sminshall 35931457Sminshall void 36031457Sminshall movetothem(es, di, local, length) 36131457Sminshall int 36231457Sminshall es, 36331457Sminshall di; 36431457Sminshall char 36531457Sminshall *local; 36631457Sminshall int 36731457Sminshall length; 36831457Sminshall { 36931457Sminshall if (length > sizeof storage) { 37031457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 37131457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 37231457Sminshall quit(); 37331457Sminshall } else if (length == 0) { 37431457Sminshall return; 37531457Sminshall } 37631457Sminshall freestorage(); 37731457Sminshall memcpy((char *)storage, local, length); 37831457Sminshall storage_length = length; 37931463Sminshall storage_location = di; 38031457Sminshall storage_must_send = 1; 38131457Sminshall } 38231457Sminshall 38331457Sminshall 38431457Sminshall char * 38531508Sminshall access_api(location, length, copyin) 38631457Sminshall int 38731457Sminshall location, 38831508Sminshall length, 38931508Sminshall copyin; /* Do we need to copy in initially? */ 39031457Sminshall { 39131457Sminshall if (storage_accessed) { 39231457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 39331503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 39431457Sminshall __FILE__, __LINE__); 39531457Sminshall quit(); 39631457Sminshall } else if (length != 0) { 39731457Sminshall freestorage(); 39831508Sminshall getstorage(location, length, copyin); 39931503Sminshall storage_accessed = 1; 40031457Sminshall } 40131457Sminshall return (char *) storage; 40231457Sminshall } 40331457Sminshall 40431508Sminshall unaccess_api(location, local, length, copyout) 40531457Sminshall int location; 40631457Sminshall char *local; 40731457Sminshall int length; 40831457Sminshall { 40931457Sminshall if (storage_accessed == 0) { 41031457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 41131503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 41231457Sminshall __FILE__, __LINE__); 41331457Sminshall quit(); 41431457Sminshall } 41531457Sminshall storage_accessed = 0; 41631508Sminshall storage_must_send = copyout; /* if needs to go back */ 41731457Sminshall } 41831457Sminshall 41931465Sminshall /* 42031465Sminshall * Accept a connection from an API client, aborting if the child dies. 42131465Sminshall */ 42231457Sminshall 42331465Sminshall static int 42431465Sminshall doconnect() 42531465Sminshall { 42631465Sminshall fd_set fdset; 42731465Sminshall int i; 42831465Sminshall 42931465Sminshall sock = -1; 43031465Sminshall FD_ZERO(&fdset); 43131465Sminshall while (shell_active && (sock == -1)) { 43231465Sminshall FD_SET(serversock, &fdset); 43331465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 43431465Sminshall if (errno = EINTR) { 43531465Sminshall continue; 43631465Sminshall } else { 43731465Sminshall perror("in select waiting for API connection"); 43831465Sminshall return -1; 43931465Sminshall } 44031465Sminshall } else { 44131465Sminshall i = accept(serversock, 0, 0); 44231465Sminshall if (i == -1) { 44331465Sminshall perror("accepting API connection"); 44431465Sminshall return -1; 44531465Sminshall } 44631465Sminshall sock = i; 44731465Sminshall } 44831465Sminshall } 44931465Sminshall /* If the process has already exited, we may need to close */ 45031465Sminshall if ((shell_active == 0) && (sock != -1)) { 45131465Sminshall (void) close(sock); 45231465Sminshall sock = -1; 45331465Sminshall setcommandmode(); /* In case child_died sneaked in */ 45431465Sminshall } 45531465Sminshall } 45631465Sminshall 45731457Sminshall /* 45831455Sminshall * shell_continue() actually runs the command, and looks for API 45931455Sminshall * requests coming back in. 46031455Sminshall * 46131455Sminshall * We are called from the main loop in telnet.c. 46231455Sminshall */ 46331455Sminshall 46431455Sminshall int 46531455Sminshall shell_continue() 46631455Sminshall { 46731492Sminshall int i; 46831492Sminshall 46931457Sminshall switch (state) { 47031457Sminshall case DEAD: 47131457Sminshall pause(); /* Nothing to do */ 47231457Sminshall break; 47331457Sminshall case UNCONNECTED: 47431465Sminshall if (doconnect() == -1) { 47531457Sminshall kill_connection(); 47631465Sminshall return -1; 47731465Sminshall } 47831492Sminshall if (api_exch_init(sock, "server") == -1) { 47931465Sminshall return -1; 48031465Sminshall } 48131465Sminshall while (state == UNCONNECTED) { 48231492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 48331457Sminshall kill_connection(); 48431465Sminshall return -1; 48531465Sminshall } else { 48631465Sminshall switch (doassociate()) { 48731465Sminshall case -1: 48831465Sminshall kill_connection(); 48931465Sminshall return -1; 49031465Sminshall case 0: 49131465Sminshall break; 49231465Sminshall case 1: 49331465Sminshall state = CONNECTED; 49431465Sminshall } 49531457Sminshall } 49631457Sminshall } 49731457Sminshall break; 49831457Sminshall case CONNECTED: 49931492Sminshall switch (i = api_exch_nextcommand()) { 50031492Sminshall case EXCH_CMD_REQUEST: 50131492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 50231492Sminshall (char *)&inputRegs) == -1) { 50331463Sminshall kill_connection(); 50431492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 50531492Sminshall (char *)&inputSregs) == -1) { 50631463Sminshall kill_connection(); 50731492Sminshall } else if (nextstore() == -1) { 50831463Sminshall kill_connection(); 50931492Sminshall } else { 51031492Sminshall handle_api(&inputRegs, &inputSregs); 51131492Sminshall freestorage(); /* Send any storage back */ 51231492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 51331492Sminshall kill_connection(); 51431492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 51531492Sminshall (char *)&inputRegs) == -1) { 51631492Sminshall kill_connection(); 51731492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 51831492Sminshall (char *)&inputSregs) == -1) { 51931492Sminshall kill_connection(); 52031492Sminshall } 52131492Sminshall /* Done, and it all worked! */ 52231463Sminshall } 52331492Sminshall break; 52431492Sminshall case EXCH_CMD_DISASSOCIATE: 52531492Sminshall kill_connection(); 52631492Sminshall break; 52731492Sminshall default: 52831503Sminshall if (i != -1) { 52931503Sminshall fprintf(stderr, 53031503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 53131503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 53231503Sminshall } 53331492Sminshall kill_connection(); 53431503Sminshall break; 53531457Sminshall } 53631457Sminshall } 53731455Sminshall return shell_active; 53831455Sminshall } 53931455Sminshall 54031455Sminshall 54131463Sminshall static int 54231463Sminshall child_died() 54331463Sminshall { 54431463Sminshall union wait *status; 54531463Sminshall register int pid; 54631463Sminshall 54731463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 54831463Sminshall if (pid == shell_pid) { 54931463Sminshall char inputbuffer[100]; 55031463Sminshall 55131463Sminshall shell_active = 0; 55231463Sminshall if (sock != -1) { 55331463Sminshall (void) close(sock); 55431463Sminshall sock = -1; 55531463Sminshall } 55631471Sminshall printf("[Hit return to continue]"); 55731471Sminshall fflush(stdout); 55831471Sminshall (void) gets(inputbuffer); 55931465Sminshall setconnmode(); 56031465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 56131465Sminshall (void) close(serversock); 56231798Sminshall (void) unlink(keyname); 56331463Sminshall } 56431463Sminshall } 56531463Sminshall signal(SIGCHLD, child_died); 56631463Sminshall } 56731463Sminshall 56831463Sminshall 56931455Sminshall /* 57031455Sminshall * Called from telnet.c to fork a lower command.com. We 57131455Sminshall * use the spint... routines so that we can pick up 57231455Sminshall * interrupts generated by application programs. 57331455Sminshall */ 57431455Sminshall 57531455Sminshall 57631455Sminshall int 57731455Sminshall shell(argc,argv) 57831455Sminshall int argc; 57931455Sminshall char *argv[]; 58031455Sminshall { 58131465Sminshall int length; 58231457Sminshall struct sockaddr_in server; 58331457Sminshall char sockNAME[100]; 58431457Sminshall static char **whereAPI = 0; 58531798Sminshall int fd; 58631798Sminshall struct timeval tv; 58731798Sminshall long ikey; 58831798Sminshall extern long random(); 58931798Sminshall extern char *mktemp(); 59031457Sminshall 59131798Sminshall /* First, create verification file. */ 59231798Sminshall do { 59331798Sminshall keyname = mktemp("/tmp/apiXXXXXX"); 59431798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 59531798Sminshall } while ((fd == -1) && (errno == EEXIST)); 59631798Sminshall 59731798Sminshall if (fd == -1) { 59831798Sminshall perror("open"); 59931798Sminshall return 0; 60031798Sminshall } 60131798Sminshall 60231798Sminshall /* Now, get seed for random */ 60331798Sminshall 60431798Sminshall if (gettimeofday(&tv, 0) == -1) { 60531798Sminshall perror("gettimeofday"); 60631798Sminshall return 0; 60731798Sminshall } 60831798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 60931798Sminshall do { 61031798Sminshall ikey = random(); 61131798Sminshall } while (ikey == 0); 61231798Sminshall sprintf(key, "%lu\n", ikey); 61331798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 61431798Sminshall perror("write"); 61531798Sminshall return 0; 61631798Sminshall } 61731798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 61831798Sminshall 61931798Sminshall if (close(fd) == -1) { 62031798Sminshall perror("close"); 62131798Sminshall return 0; 62231798Sminshall } 62331798Sminshall 62431798Sminshall /* Next, create the socket which will be connected to */ 62531457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 62631457Sminshall if (serversock < 0) { 62731457Sminshall perror("opening API socket"); 62831457Sminshall return 0; 62931457Sminshall } 63031457Sminshall server.sin_family = AF_INET; 63131457Sminshall server.sin_addr.s_addr = INADDR_ANY; 63231457Sminshall server.sin_port = 0; 63331457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 63431457Sminshall perror("binding API socket"); 63531457Sminshall return 0; 63631457Sminshall } 63731457Sminshall length = sizeof server; 63831457Sminshall if (getsockname(serversock, &server, &length) < 0) { 63931457Sminshall perror("getting API socket name"); 64031457Sminshall (void) close(serversock); 64131457Sminshall } 64231457Sminshall listen(serversock, 1); 64331457Sminshall /* Get name to advertise in address list */ 64431457Sminshall strcpy(sockNAME, "API3270="); 64531457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 64631798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 64731457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 64831457Sminshall strcpy(sockNAME, "localhost"); 64931457Sminshall } 65031457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 65131798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 65231457Sminshall 65331457Sminshall if (whereAPI == 0) { 65431457Sminshall char **ptr, **nextenv; 65531457Sminshall extern char **environ; 65631457Sminshall 65731457Sminshall ptr = environ; 65831457Sminshall nextenv = ourENVlist; 65931457Sminshall while (*ptr) { 66031457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 66131457Sminshall fprintf(stderr, "Too many environmental variables\n"); 66231457Sminshall break; 66331457Sminshall } 66431457Sminshall *nextenv++ = *ptr++; 66531457Sminshall } 66631457Sminshall whereAPI = nextenv++; 66731457Sminshall *nextenv++ = 0; 66831457Sminshall environ = ourENVlist; /* New environment */ 66931457Sminshall } 67031457Sminshall *whereAPI = sockNAME; 67131457Sminshall 67231457Sminshall child_died(); /* Start up signal handler */ 67331457Sminshall shell_active = 1; /* We are running down below */ 67431457Sminshall if (shell_pid = vfork()) { 67531457Sminshall if (shell_pid == -1) { 67631457Sminshall perror("vfork"); 67731457Sminshall (void) close(serversock); 67831457Sminshall } else { 67931465Sminshall state = UNCONNECTED; 68031457Sminshall } 68131455Sminshall } else { /* New process */ 68231455Sminshall register int i; 68331455Sminshall 68431455Sminshall for (i = 3; i < 30; i++) { 68531455Sminshall (void) close(i); 68631455Sminshall } 68731455Sminshall if (argc == 1) { /* Just get a shell */ 68831455Sminshall char *cmdname; 68931457Sminshall extern char *getenv(); 69031455Sminshall 69131455Sminshall cmdname = getenv("SHELL"); 69231455Sminshall execlp(cmdname, cmdname, 0); 69331455Sminshall perror("Exec'ing new shell...\n"); 69431455Sminshall exit(1); 69531455Sminshall } else { 69631455Sminshall execvp(argv[1], &argv[1]); 69731455Sminshall perror("Exec'ing command.\n"); 69831455Sminshall exit(1); 69931455Sminshall } 70031455Sminshall /*NOTREACHED*/ 70131455Sminshall } 70231457Sminshall return shell_active; /* Go back to main loop */ 70331455Sminshall } 704