131457Sminshall #include <sys/types.h> 231457Sminshall #include <sys/socket.h> 331457Sminshall #include <netinet/in.h> 431455Sminshall #include <sys/wait.h> 531455Sminshall 631457Sminshall #include <errno.h> 731457Sminshall extern int errno; 831457Sminshall 931457Sminshall #include <netdb.h> 1031457Sminshall #include <signal.h> 1131455Sminshall #include <stdio.h> 1231457Sminshall #include <pwd.h> 1331455Sminshall 1431455Sminshall #include "../general/general.h" 1531455Sminshall #include "../api/api.h" 1631463Sminshall #include "../apilib/api_exch.h" 1731455Sminshall 1831455Sminshall #include "../general/globals.h" 1931455Sminshall 2031455Sminshall 2131455Sminshall static int shell_pid = 0; 2231455Sminshall 2331457Sminshall static char *ourENVlist[200]; /* Lots of room */ 2431457Sminshall 2531465Sminshall static int 2631465Sminshall sock = -1, /* Connected socket */ 2731465Sminshall serversock; /* Server (listening) socket */ 2831457Sminshall 2931457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 3031457Sminshall 3131455Sminshall static int 3231463Sminshall storage_location, /* Address we have */ 3331457Sminshall storage_length = 0, /* Length we have */ 3431457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 3531457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 3631457Sminshall 3731503Sminshall static long storage[1000]; 3831457Sminshall 3931463Sminshall static union REGS inputRegs; 4031463Sminshall static struct SREGS inputSregs; 4131457Sminshall 4231463Sminshall 4331463Sminshall static void 4431457Sminshall kill_connection() 4531457Sminshall { 4631465Sminshall state = UNCONNECTED; 4731465Sminshall if (sock != -1) { 4831465Sminshall (void) close(sock); 4931465Sminshall sock = -1; 5031465Sminshall } 5131457Sminshall } 5231457Sminshall 5331457Sminshall 5431457Sminshall static int 5531463Sminshall nextstore() 5631455Sminshall { 5731463Sminshall struct storage_descriptor sd; 5831455Sminshall 5931463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 6031457Sminshall storage_length = 0; 6131457Sminshall return -1; 6231457Sminshall } 6331463Sminshall storage_length = ntohs(sd.length); 6431463Sminshall storage_location = ntohl(sd.location); 6531463Sminshall if (storage_length > sizeof storage) { 6631457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 6731457Sminshall storage_length); 6831463Sminshall storage_length = 0; 6931457Sminshall return -1; 7031457Sminshall } 71*31511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 72*31511Sminshall == -1) { 73*31511Sminshall storage_length = 0; 74*31511Sminshall return -1; 7531463Sminshall } 7631471Sminshall return 0; 7731457Sminshall } 7831457Sminshall 7931457Sminshall 8031457Sminshall static int 8131457Sminshall doreject(message) 8231457Sminshall char *message; 8331457Sminshall { 8431463Sminshall struct storage_descriptor sd; 8531457Sminshall int length = strlen(message); 8631457Sminshall 8731492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 8831457Sminshall return -1; 8931457Sminshall } 9031463Sminshall sd.length = htons(length); 9131465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 9231463Sminshall return -1; 9331463Sminshall } 9431463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 9531463Sminshall return -1; 9631463Sminshall } 9731457Sminshall return 0; 9831457Sminshall } 9931457Sminshall 10031457Sminshall 10131455Sminshall /* 10231465Sminshall * doassociate() 10331457Sminshall * 10431457Sminshall * Negotiate with the other side and try to do something. 10531457Sminshall */ 10631457Sminshall 10731457Sminshall static int 10831465Sminshall doassociate() 10931457Sminshall { 11031457Sminshall struct passwd *pwent; 11131457Sminshall char 11231457Sminshall promptbuf[100], 11331457Sminshall buffer[200]; 11431457Sminshall int length; 11531457Sminshall int was; 11631463Sminshall struct storage_descriptor sd; 11731457Sminshall 11831457Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 11931457Sminshall return -1; 12031457Sminshall } 12131457Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 12231492Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 12331465Sminshall return -1; 12431465Sminshall } 12531465Sminshall sd.length = htons(strlen(promptbuf)); 12631465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 12731465Sminshall return -1; 12831465Sminshall } 12931465Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) == -1) { 13031465Sminshall return -1; 13131465Sminshall } 13231465Sminshall sd.length = htons(strlen(pwent->pw_name)); 13331465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 13431465Sminshall return -1; 13531465Sminshall } 13631465Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 13731465Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 13831465Sminshall return -1; 13931465Sminshall } 14031492Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 14131457Sminshall return -1; 14231457Sminshall } 14331463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 14431463Sminshall return -1; 14531457Sminshall } 14631463Sminshall sd.length = ntohs(sd.length); 14731463Sminshall if (sd.length > sizeof buffer) { 14831457Sminshall doreject("Password entered was too long"); 14931465Sminshall return -1; 15031457Sminshall } 15131463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 15231457Sminshall return -1; 15331457Sminshall } 15431463Sminshall buffer[sd.length] = 0; 15531457Sminshall 15631457Sminshall /* Is this the correct password? */ 15731465Sminshall if (strlen(pwent->pw_name)) { 15831465Sminshall char *ptr; 15931465Sminshall int i; 16031465Sminshall 16131465Sminshall ptr = pwent->pw_name; 16231465Sminshall i = 0; 16331465Sminshall while (i < sd.length) { 16431465Sminshall buffer[i++] ^= *ptr++; 16531465Sminshall if (*ptr == 0) { 16631465Sminshall ptr = pwent->pw_name; 16731465Sminshall } 16831465Sminshall } 16931465Sminshall } 17031457Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) { 17131492Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 17231465Sminshall return -1; 17331471Sminshall } else { 17431471Sminshall return 1; 17531465Sminshall } 17631457Sminshall } else { 17731457Sminshall doreject("Invalid password"); 17831457Sminshall sleep(10); /* Don't let us do too many of these */ 17931471Sminshall return 0; 18031457Sminshall } 18131457Sminshall } 18231457Sminshall 18331457Sminshall 18431457Sminshall void 18531457Sminshall freestorage() 18631457Sminshall { 18731457Sminshall char buffer[40]; 18831463Sminshall struct storage_descriptor sd; 18931457Sminshall 19031457Sminshall if (storage_accessed) { 19131457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 19231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 19331457Sminshall __FILE__, __LINE__); 19431457Sminshall quit(); 19531457Sminshall } 19631457Sminshall if (storage_must_send == 0) { 19731457Sminshall return; 19831457Sminshall } 19931457Sminshall storage_must_send = 0; 20031492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 20131457Sminshall kill_connection(); 20231457Sminshall return; 20331457Sminshall } 20431463Sminshall sd.length = htons(storage_length); 20531463Sminshall sd.location = htonl(storage_location); 20631463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 20731457Sminshall kill_connection(); 20831457Sminshall return; 20931457Sminshall } 210*31511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 211*31511Sminshall == -1) { 212*31511Sminshall kill_connection(); 213*31511Sminshall return; 21431463Sminshall } 21531457Sminshall } 21631457Sminshall 21731457Sminshall 21831463Sminshall static int 21931508Sminshall getstorage(address, length, copyin) 22031508Sminshall int 22131508Sminshall address, 22231508Sminshall length, 22331508Sminshall copyin; 22431457Sminshall { 22531463Sminshall struct storage_descriptor sd; 22631457Sminshall char buffer[40]; 22731457Sminshall 22831457Sminshall freestorage(); 22931457Sminshall if (storage_accessed) { 23031457Sminshall fprintf(stderr, 23131457Sminshall "Internal error - attempt to get while storage accessed.\n"); 23231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 23331457Sminshall __FILE__, __LINE__); 23431457Sminshall quit(); 23531457Sminshall } 23631457Sminshall storage_must_send = 0; 23731492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 23831457Sminshall kill_connection(); 23931463Sminshall return -1; 24031457Sminshall } 24131471Sminshall storage_location = address; 24231471Sminshall storage_length = length; 24331508Sminshall if (copyin) { 24431508Sminshall sd.location = htonl(storage_location); 24531508Sminshall sd.length = htons(storage_length); 24631508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 24731508Sminshall sizeof sd, (char *)&sd) == -1) { 24831508Sminshall kill_connection(); 24931508Sminshall return -1; 25031508Sminshall } 25131508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 25231508Sminshall fprintf(stderr, "Bad data from other side.\n"); 25331508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 25431508Sminshall return -1; 25531508Sminshall } 25631508Sminshall if (nextstore() == -1) { 25731508Sminshall kill_connection(); 25831508Sminshall return -1; 25931508Sminshall } 26031463Sminshall } 26131463Sminshall return 0; 26231457Sminshall } 26331457Sminshall 26431457Sminshall void 26531457Sminshall movetous(local, es, di, length) 26631457Sminshall char 26731457Sminshall *local; 26831457Sminshall int 26931457Sminshall es, 27031457Sminshall di; 27131457Sminshall int 27231457Sminshall length; 27331457Sminshall { 27431457Sminshall if (length > sizeof storage) { 27531457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 27631457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 27731457Sminshall quit(); 27831457Sminshall } else if (length == 0) { 27931457Sminshall return; 28031457Sminshall } 28131508Sminshall getstorage(di, length, 1); 28231463Sminshall memcpy(local, storage+(di-storage_location), length); 28331457Sminshall } 28431457Sminshall 28531457Sminshall void 28631457Sminshall movetothem(es, di, local, length) 28731457Sminshall int 28831457Sminshall es, 28931457Sminshall di; 29031457Sminshall char 29131457Sminshall *local; 29231457Sminshall int 29331457Sminshall length; 29431457Sminshall { 29531457Sminshall if (length > sizeof storage) { 29631457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 29731457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 29831457Sminshall quit(); 29931457Sminshall } else if (length == 0) { 30031457Sminshall return; 30131457Sminshall } 30231457Sminshall freestorage(); 30331457Sminshall memcpy((char *)storage, local, length); 30431457Sminshall storage_length = length; 30531463Sminshall storage_location = di; 30631457Sminshall storage_must_send = 1; 30731457Sminshall } 30831457Sminshall 30931457Sminshall 31031457Sminshall char * 31131508Sminshall access_api(location, length, copyin) 31231457Sminshall int 31331457Sminshall location, 31431508Sminshall length, 31531508Sminshall copyin; /* Do we need to copy in initially? */ 31631457Sminshall { 31731457Sminshall if (storage_accessed) { 31831457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 31931503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 32031457Sminshall __FILE__, __LINE__); 32131457Sminshall quit(); 32231457Sminshall } else if (length != 0) { 32331457Sminshall freestorage(); 32431508Sminshall getstorage(location, length, copyin); 32531503Sminshall storage_accessed = 1; 32631457Sminshall } 32731457Sminshall return (char *) storage; 32831457Sminshall } 32931457Sminshall 33031508Sminshall unaccess_api(location, local, length, copyout) 33131457Sminshall int location; 33231457Sminshall char *local; 33331457Sminshall int length; 33431457Sminshall { 33531457Sminshall if (storage_accessed == 0) { 33631457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 33731503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 33831457Sminshall __FILE__, __LINE__); 33931457Sminshall quit(); 34031457Sminshall } 34131457Sminshall storage_accessed = 0; 34231508Sminshall storage_must_send = copyout; /* if needs to go back */ 34331457Sminshall } 34431457Sminshall 34531465Sminshall /* 34631465Sminshall * Accept a connection from an API client, aborting if the child dies. 34731465Sminshall */ 34831457Sminshall 34931465Sminshall static int 35031465Sminshall doconnect() 35131465Sminshall { 35231465Sminshall fd_set fdset; 35331465Sminshall int i; 35431465Sminshall 35531465Sminshall sock = -1; 35631465Sminshall FD_ZERO(&fdset); 35731465Sminshall while (shell_active && (sock == -1)) { 35831465Sminshall FD_SET(serversock, &fdset); 35931465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 36031465Sminshall if (errno = EINTR) { 36131465Sminshall continue; 36231465Sminshall } else { 36331465Sminshall perror("in select waiting for API connection"); 36431465Sminshall return -1; 36531465Sminshall } 36631465Sminshall } else { 36731465Sminshall i = accept(serversock, 0, 0); 36831465Sminshall if (i == -1) { 36931465Sminshall perror("accepting API connection"); 37031465Sminshall return -1; 37131465Sminshall } 37231465Sminshall sock = i; 37331465Sminshall } 37431465Sminshall } 37531465Sminshall /* If the process has already exited, we may need to close */ 37631465Sminshall if ((shell_active == 0) && (sock != -1)) { 37731465Sminshall (void) close(sock); 37831465Sminshall sock = -1; 37931465Sminshall setcommandmode(); /* In case child_died sneaked in */ 38031465Sminshall } 38131465Sminshall } 38231465Sminshall 38331457Sminshall /* 38431455Sminshall * shell_continue() actually runs the command, and looks for API 38531455Sminshall * requests coming back in. 38631455Sminshall * 38731455Sminshall * We are called from the main loop in telnet.c. 38831455Sminshall */ 38931455Sminshall 39031455Sminshall int 39131455Sminshall shell_continue() 39231455Sminshall { 39331492Sminshall int i; 39431492Sminshall 39531457Sminshall switch (state) { 39631457Sminshall case DEAD: 39731457Sminshall pause(); /* Nothing to do */ 39831457Sminshall break; 39931457Sminshall case UNCONNECTED: 40031465Sminshall if (doconnect() == -1) { 40131457Sminshall kill_connection(); 40231465Sminshall return -1; 40331465Sminshall } 40431492Sminshall if (api_exch_init(sock, "server") == -1) { 40531465Sminshall return -1; 40631465Sminshall } 40731465Sminshall while (state == UNCONNECTED) { 40831492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 40931457Sminshall kill_connection(); 41031465Sminshall return -1; 41131465Sminshall } else { 41231465Sminshall switch (doassociate()) { 41331465Sminshall case -1: 41431465Sminshall kill_connection(); 41531465Sminshall return -1; 41631465Sminshall case 0: 41731465Sminshall break; 41831465Sminshall case 1: 41931465Sminshall state = CONNECTED; 42031465Sminshall } 42131457Sminshall } 42231457Sminshall } 42331457Sminshall break; 42431457Sminshall case CONNECTED: 42531492Sminshall switch (i = api_exch_nextcommand()) { 42631492Sminshall case EXCH_CMD_REQUEST: 42731492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 42831492Sminshall (char *)&inputRegs) == -1) { 42931463Sminshall kill_connection(); 43031492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 43131492Sminshall (char *)&inputSregs) == -1) { 43231463Sminshall kill_connection(); 43331492Sminshall } else if (nextstore() == -1) { 43431463Sminshall kill_connection(); 43531492Sminshall } else { 43631492Sminshall handle_api(&inputRegs, &inputSregs); 43731492Sminshall freestorage(); /* Send any storage back */ 43831492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 43931492Sminshall kill_connection(); 44031492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 44131492Sminshall (char *)&inputRegs) == -1) { 44231492Sminshall kill_connection(); 44331492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 44431492Sminshall (char *)&inputSregs) == -1) { 44531492Sminshall kill_connection(); 44631492Sminshall } 44731492Sminshall /* Done, and it all worked! */ 44831463Sminshall } 44931492Sminshall break; 45031492Sminshall case EXCH_CMD_DISASSOCIATE: 45131492Sminshall kill_connection(); 45231492Sminshall break; 45331492Sminshall default: 45431503Sminshall if (i != -1) { 45531503Sminshall fprintf(stderr, 45631503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 45731503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 45831503Sminshall } 45931492Sminshall kill_connection(); 46031503Sminshall break; 46131457Sminshall } 46231457Sminshall } 46331455Sminshall return shell_active; 46431455Sminshall } 46531455Sminshall 46631455Sminshall 46731463Sminshall static int 46831463Sminshall child_died() 46931463Sminshall { 47031463Sminshall union wait *status; 47131463Sminshall register int pid; 47231463Sminshall 47331463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 47431463Sminshall if (pid == shell_pid) { 47531463Sminshall char inputbuffer[100]; 47631463Sminshall 47731463Sminshall shell_active = 0; 47831463Sminshall if (sock != -1) { 47931463Sminshall (void) close(sock); 48031463Sminshall sock = -1; 48131463Sminshall } 48231471Sminshall printf("[Hit return to continue]"); 48331471Sminshall fflush(stdout); 48431471Sminshall (void) gets(inputbuffer); 48531465Sminshall setconnmode(); 48631465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 48731465Sminshall (void) close(serversock); 48831463Sminshall } 48931463Sminshall } 49031463Sminshall signal(SIGCHLD, child_died); 49131463Sminshall } 49231463Sminshall 49331463Sminshall 49431455Sminshall /* 49531455Sminshall * Called from telnet.c to fork a lower command.com. We 49631455Sminshall * use the spint... routines so that we can pick up 49731455Sminshall * interrupts generated by application programs. 49831455Sminshall */ 49931455Sminshall 50031455Sminshall 50131455Sminshall int 50231455Sminshall shell(argc,argv) 50331455Sminshall int argc; 50431455Sminshall char *argv[]; 50531455Sminshall { 50631465Sminshall int length; 50731457Sminshall struct sockaddr_in server; 50831457Sminshall char sockNAME[100]; 50931457Sminshall static char **whereAPI = 0; 51031457Sminshall 51131457Sminshall /* First, create the socket which will be connected to */ 51231457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 51331457Sminshall if (serversock < 0) { 51431457Sminshall perror("opening API socket"); 51531457Sminshall return 0; 51631457Sminshall } 51731457Sminshall server.sin_family = AF_INET; 51831457Sminshall server.sin_addr.s_addr = INADDR_ANY; 51931457Sminshall server.sin_port = 0; 52031457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 52131457Sminshall perror("binding API socket"); 52231457Sminshall return 0; 52331457Sminshall } 52431457Sminshall length = sizeof server; 52531457Sminshall if (getsockname(serversock, &server, &length) < 0) { 52631457Sminshall perror("getting API socket name"); 52731457Sminshall (void) close(serversock); 52831457Sminshall } 52931457Sminshall listen(serversock, 1); 53031457Sminshall /* Get name to advertise in address list */ 53131457Sminshall strcpy(sockNAME, "API3270="); 53231457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 53331457Sminshall if (strlen(sockNAME) > (sizeof sockNAME-10)) { 53431457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 53531457Sminshall strcpy(sockNAME, "localhost"); 53631457Sminshall } 53731457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 53831457Sminshall 53931457Sminshall if (whereAPI == 0) { 54031457Sminshall char **ptr, **nextenv; 54131457Sminshall extern char **environ; 54231457Sminshall 54331457Sminshall ptr = environ; 54431457Sminshall nextenv = ourENVlist; 54531457Sminshall while (*ptr) { 54631457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 54731457Sminshall fprintf(stderr, "Too many environmental variables\n"); 54831457Sminshall break; 54931457Sminshall } 55031457Sminshall *nextenv++ = *ptr++; 55131457Sminshall } 55231457Sminshall whereAPI = nextenv++; 55331457Sminshall *nextenv++ = 0; 55431457Sminshall environ = ourENVlist; /* New environment */ 55531457Sminshall } 55631457Sminshall *whereAPI = sockNAME; 55731457Sminshall 55831457Sminshall child_died(); /* Start up signal handler */ 55931457Sminshall shell_active = 1; /* We are running down below */ 56031457Sminshall if (shell_pid = vfork()) { 56131457Sminshall if (shell_pid == -1) { 56231457Sminshall perror("vfork"); 56331457Sminshall (void) close(serversock); 56431457Sminshall } else { 56531465Sminshall state = UNCONNECTED; 56631457Sminshall } 56731455Sminshall } else { /* New process */ 56831455Sminshall register int i; 56931455Sminshall 57031455Sminshall for (i = 3; i < 30; i++) { 57131455Sminshall (void) close(i); 57231455Sminshall } 57331455Sminshall if (argc == 1) { /* Just get a shell */ 57431455Sminshall char *cmdname; 57531457Sminshall extern char *getenv(); 57631455Sminshall 57731455Sminshall cmdname = getenv("SHELL"); 57831455Sminshall execlp(cmdname, cmdname, 0); 57931455Sminshall perror("Exec'ing new shell...\n"); 58031455Sminshall exit(1); 58131455Sminshall } else { 58231455Sminshall execvp(argv[1], &argv[1]); 58331455Sminshall perror("Exec'ing command.\n"); 58431455Sminshall exit(1); 58531455Sminshall } 58631455Sminshall /*NOTREACHED*/ 58731455Sminshall } 58831457Sminshall return shell_active; /* Go back to main loop */ 58931455Sminshall } 590