1*48761Sbostic /*- 2*48761Sbostic * Copyright (c) 1988 The Regents of the University of California. 333810Sbostic * All rights reserved. 431894Sminshall * 5*48761Sbostic * %sccs.include.redist.c% 631894Sminshall */ 731894Sminshall 831894Sminshall #ifndef lint 9*48761Sbostic static char sccsid[] = "@(#)system.c 4.5 (Berkeley) 04/26/91"; 1033810Sbostic #endif /* not lint */ 1131894Sminshall 1231457Sminshall #include <sys/types.h> 1331863Sminshall 1433269Sminshall #if defined(pyr) 1533269Sminshall #define fd_set fdset_t 1633269Sminshall #endif /* defined(pyr) */ 1733269Sminshall 1838211Sminshall /* 1938211Sminshall * Wouldn't it be nice if these REALLY were in <sys/inode.h>? Or, 2038211Sminshall * equivalently, if <sys/inode.h> REALLY existed? 2138211Sminshall */ 2231863Sminshall #define IREAD 00400 2331863Sminshall #define IWRITE 00200 2431863Sminshall 2531798Sminshall #include <sys/file.h> 2631798Sminshall #include <sys/time.h> 2731457Sminshall #include <sys/socket.h> 2831457Sminshall #include <netinet/in.h> 2931455Sminshall #include <sys/wait.h> 3031455Sminshall 3131457Sminshall #include <errno.h> 3231457Sminshall extern int errno; 3331457Sminshall 3431457Sminshall #include <netdb.h> 3531457Sminshall #include <signal.h> 3631455Sminshall #include <stdio.h> 3747031Sdonn #include <string.h> 3831457Sminshall #include <pwd.h> 3931455Sminshall 4031455Sminshall #include "../general/general.h" 4131873Sminshall #include "../ctlr/api.h" 4231873Sminshall #include "../api/api_exch.h" 4331455Sminshall 4431455Sminshall #include "../general/globals.h" 4531455Sminshall 4631795Sminshall #ifndef FD_SETSIZE 4731795Sminshall /* 4831795Sminshall * The following is defined just in case someone should want to run 4931795Sminshall * this telnet on a 4.2 system. 5031795Sminshall * 5131795Sminshall */ 5231455Sminshall 5331795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 5431795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 5531795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 5631795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 5731795Sminshall 5831795Sminshall #endif 5931795Sminshall 6031455Sminshall static int shell_pid = 0; 6131798Sminshall static char key[50]; /* Actual key */ 6231798Sminshall static char *keyname; /* Name of file with key in it */ 6331455Sminshall 6431457Sminshall static char *ourENVlist[200]; /* Lots of room */ 6531457Sminshall 6631465Sminshall static int 6731465Sminshall sock = -1, /* Connected socket */ 6831465Sminshall serversock; /* Server (listening) socket */ 6931457Sminshall 7031457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 7131457Sminshall 7235423Sminshall static long 7335423Sminshall storage_location; /* Address we have */ 7435423Sminshall static short 7535423Sminshall storage_length = 0; /* Length we have */ 7631455Sminshall static int 7731457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 7831457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 7931457Sminshall 8031503Sminshall static long storage[1000]; 8131457Sminshall 8231463Sminshall static union REGS inputRegs; 8331463Sminshall static struct SREGS inputSregs; 8431457Sminshall 8538923Sminshall extern int apitrace; 8631463Sminshall 8731463Sminshall static void 8831457Sminshall kill_connection() 8931457Sminshall { 9031465Sminshall state = UNCONNECTED; 9131465Sminshall if (sock != -1) { 9231465Sminshall (void) close(sock); 9331465Sminshall sock = -1; 9431465Sminshall } 9531457Sminshall } 9631457Sminshall 9731457Sminshall 9831457Sminshall static int 9931463Sminshall nextstore() 10031455Sminshall { 10131463Sminshall struct storage_descriptor sd; 10231455Sminshall 10331463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 10431457Sminshall storage_length = 0; 10531457Sminshall return -1; 10631457Sminshall } 10731798Sminshall storage_length = sd.length; 10831798Sminshall storage_location = sd.location; 10931463Sminshall if (storage_length > sizeof storage) { 11031457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 11131457Sminshall storage_length); 11231463Sminshall storage_length = 0; 11331457Sminshall return -1; 11431457Sminshall } 11531511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 11631511Sminshall == -1) { 11731511Sminshall storage_length = 0; 11831511Sminshall return -1; 11931463Sminshall } 12031471Sminshall return 0; 12131457Sminshall } 12231457Sminshall 12331457Sminshall 12431457Sminshall static int 12531457Sminshall doreject(message) 12631457Sminshall char *message; 12731457Sminshall { 12831463Sminshall struct storage_descriptor sd; 12931457Sminshall int length = strlen(message); 13031457Sminshall 13131492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 13231457Sminshall return -1; 13331457Sminshall } 13431798Sminshall sd.length = length; 13531465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 13631463Sminshall return -1; 13731463Sminshall } 13831463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 13931463Sminshall return -1; 14031463Sminshall } 14131457Sminshall return 0; 14231457Sminshall } 14331457Sminshall 14431457Sminshall 14531455Sminshall /* 14631465Sminshall * doassociate() 14731457Sminshall * 14831457Sminshall * Negotiate with the other side and try to do something. 14931798Sminshall * 15031798Sminshall * Returns: 15131798Sminshall * 15231798Sminshall * -1: Error in processing 15331798Sminshall * 0: Invalid password entered 15431798Sminshall * 1: Association OK 15531457Sminshall */ 15631457Sminshall 15731457Sminshall static int 15831465Sminshall doassociate() 15931457Sminshall { 16031457Sminshall struct passwd *pwent; 16131457Sminshall char 16231457Sminshall promptbuf[100], 16331457Sminshall buffer[200]; 16431463Sminshall struct storage_descriptor sd; 16535423Sminshall extern char *crypt(); 16631457Sminshall 16731463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 16831463Sminshall return -1; 16931457Sminshall } 17031798Sminshall sd.length = sd.length; 17131463Sminshall if (sd.length > sizeof buffer) { 17231798Sminshall doreject("(internal error) Authentication key too long"); 17331465Sminshall return -1; 17431457Sminshall } 17531463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 17631457Sminshall return -1; 17731457Sminshall } 17831463Sminshall buffer[sd.length] = 0; 17931457Sminshall 18031798Sminshall if (strcmp(buffer, key) != 0) { 18135493Sminshall #if (!defined(sun)) || defined(BSD) && (BSD >= 43) 18235423Sminshall extern uid_t geteuid(); 18335493Sminshall #endif /* (!defined(sun)) || defined(BSD) && (BSD >= 43) */ 18435423Sminshall 18535423Sminshall if ((pwent = getpwuid((int)geteuid())) == 0) { 18631798Sminshall return -1; 18731798Sminshall } 18831798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 18931798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 19031798Sminshall return -1; 19131798Sminshall } 19231798Sminshall sd.length = strlen(promptbuf); 19331798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 19431798Sminshall == -1) { 19531798Sminshall return -1; 19631798Sminshall } 19731798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 19831798Sminshall == -1) { 19931798Sminshall return -1; 20031798Sminshall } 20131798Sminshall sd.length = strlen(pwent->pw_name); 20231798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 20331798Sminshall == -1) { 20431798Sminshall return -1; 20531798Sminshall } 20631798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 20731798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 20831798Sminshall return -1; 20931798Sminshall } 21031798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 21131798Sminshall return -1; 21231798Sminshall } 21331798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 21431798Sminshall == -1) { 21531798Sminshall return -1; 21631798Sminshall } 21731798Sminshall sd.length = sd.length; 21831798Sminshall if (sd.length > sizeof buffer) { 21931798Sminshall doreject("Password entered was too long"); 22031798Sminshall return -1; 22131798Sminshall } 22231798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 22331798Sminshall return -1; 22431798Sminshall } 22531798Sminshall buffer[sd.length] = 0; 22631465Sminshall 22731798Sminshall /* Is this the correct password? */ 22831798Sminshall if (strlen(pwent->pw_name)) { 22931798Sminshall char *ptr; 23031798Sminshall int i; 23131798Sminshall 23231798Sminshall ptr = pwent->pw_name; 23331798Sminshall i = 0; 23431798Sminshall while (i < sd.length) { 23531798Sminshall buffer[i++] ^= *ptr++; 23631798Sminshall if (*ptr == 0) { 23731798Sminshall ptr = pwent->pw_name; 23831798Sminshall } 23931465Sminshall } 24031465Sminshall } 24131798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 24231798Sminshall doreject("Invalid password"); 24331798Sminshall sleep(10); /* Don't let us do too many of these */ 24431798Sminshall return 0; 24531798Sminshall } 24631465Sminshall } 24731798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 24831798Sminshall return -1; 24931457Sminshall } else { 25031798Sminshall return 1; 25131457Sminshall } 25231457Sminshall } 25331457Sminshall 25431457Sminshall 25531457Sminshall void 25631457Sminshall freestorage() 25731457Sminshall { 25831463Sminshall struct storage_descriptor sd; 25931457Sminshall 26031457Sminshall if (storage_accessed) { 26131457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 26231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 26331457Sminshall __FILE__, __LINE__); 26431457Sminshall quit(); 26531457Sminshall } 26631457Sminshall if (storage_must_send == 0) { 26731457Sminshall return; 26831457Sminshall } 26931457Sminshall storage_must_send = 0; 27031492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 27131457Sminshall kill_connection(); 27231457Sminshall return; 27331457Sminshall } 27431798Sminshall sd.length = storage_length; 27531798Sminshall sd.location = storage_location; 27631463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 27731457Sminshall kill_connection(); 27831457Sminshall return; 27931457Sminshall } 28031511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 28131511Sminshall == -1) { 28231511Sminshall kill_connection(); 28331511Sminshall return; 28431463Sminshall } 28531457Sminshall } 28631457Sminshall 28731457Sminshall 28831463Sminshall static int 28931508Sminshall getstorage(address, length, copyin) 29035423Sminshall long 29135423Sminshall address; 29231508Sminshall int 29331508Sminshall length, 29431508Sminshall copyin; 29531457Sminshall { 29631463Sminshall struct storage_descriptor sd; 29731457Sminshall 29831457Sminshall freestorage(); 29931457Sminshall if (storage_accessed) { 30031457Sminshall fprintf(stderr, 30131457Sminshall "Internal error - attempt to get while storage accessed.\n"); 30231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 30331457Sminshall __FILE__, __LINE__); 30431457Sminshall quit(); 30531457Sminshall } 30631457Sminshall storage_must_send = 0; 30731492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 30831457Sminshall kill_connection(); 30931463Sminshall return -1; 31031457Sminshall } 31131471Sminshall storage_location = address; 31231471Sminshall storage_length = length; 31331508Sminshall if (copyin) { 31435423Sminshall sd.location = (long)storage_location; 31531798Sminshall sd.length = storage_length; 31631508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 31731508Sminshall sizeof sd, (char *)&sd) == -1) { 31831508Sminshall kill_connection(); 31931508Sminshall return -1; 32031508Sminshall } 32131508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 32231508Sminshall fprintf(stderr, "Bad data from other side.\n"); 32331508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 32431508Sminshall return -1; 32531508Sminshall } 32631508Sminshall if (nextstore() == -1) { 32731508Sminshall kill_connection(); 32831508Sminshall return -1; 32931508Sminshall } 33031463Sminshall } 33131463Sminshall return 0; 33231457Sminshall } 33331457Sminshall 33435423Sminshall /*ARGSUSED*/ 33531457Sminshall void 33631457Sminshall movetous(local, es, di, length) 33731457Sminshall char 33831457Sminshall *local; 33935423Sminshall unsigned int 34031457Sminshall es, 34131457Sminshall di; 34231457Sminshall int 34331457Sminshall length; 34431457Sminshall { 34535423Sminshall long where = SEG_OFF_BACK(es, di); 34635423Sminshall 34731457Sminshall if (length > sizeof storage) { 34831457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 34931457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 35031457Sminshall quit(); 35131457Sminshall } else if (length == 0) { 35231457Sminshall return; 35331457Sminshall } 35435423Sminshall getstorage(where, length, 1); 35535423Sminshall memcpy(local, (char *)(storage+((where-storage_location))), length); 35638923Sminshall if (apitrace) { 35738923Sminshall Dump('(', local, length); 35838923Sminshall } 35931457Sminshall } 36031457Sminshall 36135423Sminshall /*ARGSUSED*/ 36231457Sminshall void 36331457Sminshall movetothem(es, di, local, length) 36435423Sminshall unsigned int 36531457Sminshall es, 36631457Sminshall di; 36731457Sminshall char 36831457Sminshall *local; 36931457Sminshall int 37031457Sminshall length; 37131457Sminshall { 37235423Sminshall long where = SEG_OFF_BACK(es, di); 37335423Sminshall 37431457Sminshall if (length > sizeof storage) { 37531457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 37631457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 37731457Sminshall quit(); 37831457Sminshall } else if (length == 0) { 37931457Sminshall return; 38031457Sminshall } 38131457Sminshall freestorage(); 38231457Sminshall memcpy((char *)storage, local, length); 38338923Sminshall if (apitrace) { 38438923Sminshall Dump(')', local, length); 38538923Sminshall } 38631457Sminshall storage_length = length; 38735423Sminshall storage_location = where; 38831457Sminshall storage_must_send = 1; 38931457Sminshall } 39031457Sminshall 39131457Sminshall 39231457Sminshall char * 39331508Sminshall access_api(location, length, copyin) 39435423Sminshall char * 39535423Sminshall location; 39631457Sminshall int 39731508Sminshall length, 39831508Sminshall copyin; /* Do we need to copy in initially? */ 39931457Sminshall { 40031457Sminshall if (storage_accessed) { 40131457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 40231503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 40331457Sminshall __FILE__, __LINE__); 40431457Sminshall quit(); 40531457Sminshall } else if (length != 0) { 40631457Sminshall freestorage(); 40735423Sminshall getstorage((long)location, length, copyin); 40831503Sminshall storage_accessed = 1; 40931457Sminshall } 41031457Sminshall return (char *) storage; 41131457Sminshall } 41231457Sminshall 41335423Sminshall /*ARGSUSED*/ 41435423Sminshall void 41531508Sminshall unaccess_api(location, local, length, copyout) 41635423Sminshall char *location; 41731457Sminshall char *local; 41831457Sminshall int length; 41935423Sminshall int copyout; 42031457Sminshall { 42131457Sminshall if (storage_accessed == 0) { 42231457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 42331503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 42431457Sminshall __FILE__, __LINE__); 42531457Sminshall quit(); 42631457Sminshall } 42731457Sminshall storage_accessed = 0; 42831508Sminshall storage_must_send = copyout; /* if needs to go back */ 42931457Sminshall } 43031457Sminshall 43131465Sminshall /* 43231465Sminshall * Accept a connection from an API client, aborting if the child dies. 43331465Sminshall */ 43431457Sminshall 43531465Sminshall static int 43631465Sminshall doconnect() 43731465Sminshall { 43831465Sminshall fd_set fdset; 43931465Sminshall int i; 44031465Sminshall 44131465Sminshall sock = -1; 44231465Sminshall FD_ZERO(&fdset); 44331465Sminshall while (shell_active && (sock == -1)) { 44431465Sminshall FD_SET(serversock, &fdset); 44535423Sminshall if ((i = select(serversock+1, &fdset, 44635423Sminshall (fd_set *)0, (fd_set *)0, (struct timeval *)0)) < 0) { 44731465Sminshall if (errno = EINTR) { 44831465Sminshall continue; 44931465Sminshall } else { 45031465Sminshall perror("in select waiting for API connection"); 45131465Sminshall return -1; 45231465Sminshall } 45331465Sminshall } else { 45435423Sminshall i = accept(serversock, (struct sockaddr *)0, (int *)0); 45531465Sminshall if (i == -1) { 45631465Sminshall perror("accepting API connection"); 45731465Sminshall return -1; 45831465Sminshall } 45931465Sminshall sock = i; 46031465Sminshall } 46131465Sminshall } 46231465Sminshall /* If the process has already exited, we may need to close */ 46331465Sminshall if ((shell_active == 0) && (sock != -1)) { 46435423Sminshall extern void setcommandmode(); 46535423Sminshall 46631465Sminshall (void) close(sock); 46731465Sminshall sock = -1; 46831465Sminshall setcommandmode(); /* In case child_died sneaked in */ 46931465Sminshall } 47035423Sminshall return 0; 47131465Sminshall } 47231465Sminshall 47331457Sminshall /* 47431455Sminshall * shell_continue() actually runs the command, and looks for API 47531455Sminshall * requests coming back in. 47631455Sminshall * 47731455Sminshall * We are called from the main loop in telnet.c. 47831455Sminshall */ 47931455Sminshall 48031455Sminshall int 48131455Sminshall shell_continue() 48231455Sminshall { 48331492Sminshall int i; 48431492Sminshall 48531457Sminshall switch (state) { 48631457Sminshall case DEAD: 48731457Sminshall pause(); /* Nothing to do */ 48831457Sminshall break; 48931457Sminshall case UNCONNECTED: 49031465Sminshall if (doconnect() == -1) { 49131457Sminshall kill_connection(); 49231465Sminshall return -1; 49331465Sminshall } 49438211Sminshall /* At this point, it is possible that we've gone away */ 49538211Sminshall if (shell_active == 0) { 49638211Sminshall kill_connection(); 49738211Sminshall return -1; 49838211Sminshall } 49931492Sminshall if (api_exch_init(sock, "server") == -1) { 50031465Sminshall return -1; 50131465Sminshall } 50231465Sminshall while (state == UNCONNECTED) { 50331492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 50431457Sminshall kill_connection(); 50531465Sminshall return -1; 50631465Sminshall } else { 50731465Sminshall switch (doassociate()) { 50831465Sminshall case -1: 50931465Sminshall kill_connection(); 51031465Sminshall return -1; 51131465Sminshall case 0: 51231465Sminshall break; 51331465Sminshall case 1: 51431465Sminshall state = CONNECTED; 51531465Sminshall } 51631457Sminshall } 51731457Sminshall } 51831457Sminshall break; 51931457Sminshall case CONNECTED: 52031492Sminshall switch (i = api_exch_nextcommand()) { 52131492Sminshall case EXCH_CMD_REQUEST: 52231492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 52331492Sminshall (char *)&inputRegs) == -1) { 52431463Sminshall kill_connection(); 52531492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 52631492Sminshall (char *)&inputSregs) == -1) { 52731463Sminshall kill_connection(); 52831492Sminshall } else if (nextstore() == -1) { 52931463Sminshall kill_connection(); 53031492Sminshall } else { 53131492Sminshall handle_api(&inputRegs, &inputSregs); 53231492Sminshall freestorage(); /* Send any storage back */ 53331492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 53431492Sminshall kill_connection(); 53531492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 53631492Sminshall (char *)&inputRegs) == -1) { 53731492Sminshall kill_connection(); 53831492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 53931492Sminshall (char *)&inputSregs) == -1) { 54031492Sminshall kill_connection(); 54131492Sminshall } 54231492Sminshall /* Done, and it all worked! */ 54331463Sminshall } 54431492Sminshall break; 54531492Sminshall case EXCH_CMD_DISASSOCIATE: 54631492Sminshall kill_connection(); 54731492Sminshall break; 54831492Sminshall default: 54931503Sminshall if (i != -1) { 55031503Sminshall fprintf(stderr, 55131503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 55231503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 55331503Sminshall } 55431492Sminshall kill_connection(); 55531503Sminshall break; 55631457Sminshall } 55731457Sminshall } 55831455Sminshall return shell_active; 55931455Sminshall } 56031455Sminshall 56131455Sminshall 56247031Sdonn static void 56347031Sdonn child_died(code) 56431463Sminshall { 56535423Sminshall union wait status; 56631463Sminshall register int pid; 56731463Sminshall 56847031Sdonn while ((pid = wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) { 56931463Sminshall if (pid == shell_pid) { 57031463Sminshall char inputbuffer[100]; 57135423Sminshall extern void setconnmode(); 57235423Sminshall extern void ConnectScreen(); 57331463Sminshall 57431463Sminshall shell_active = 0; 57531463Sminshall if (sock != -1) { 57631463Sminshall (void) close(sock); 57731463Sminshall sock = -1; 57831463Sminshall } 57931471Sminshall printf("[Hit return to continue]"); 58031471Sminshall fflush(stdout); 58131471Sminshall (void) gets(inputbuffer); 58231465Sminshall setconnmode(); 58331465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 58431465Sminshall (void) close(serversock); 58531798Sminshall (void) unlink(keyname); 58631463Sminshall } 58731463Sminshall } 58831463Sminshall signal(SIGCHLD, child_died); 58931463Sminshall } 59031463Sminshall 59131463Sminshall 59231455Sminshall /* 59331455Sminshall * Called from telnet.c to fork a lower command.com. We 59431455Sminshall * use the spint... routines so that we can pick up 59531455Sminshall * interrupts generated by application programs. 59631455Sminshall */ 59731455Sminshall 59831455Sminshall 59931455Sminshall int 60031455Sminshall shell(argc,argv) 60131455Sminshall int argc; 60231455Sminshall char *argv[]; 60331455Sminshall { 60431465Sminshall int length; 60531457Sminshall struct sockaddr_in server; 60631457Sminshall char sockNAME[100]; 60731457Sminshall static char **whereAPI = 0; 60831798Sminshall int fd; 60931798Sminshall struct timeval tv; 61031798Sminshall long ikey; 61131798Sminshall extern long random(); 61231798Sminshall extern char *mktemp(); 61335423Sminshall extern char *strcpy(); 61431457Sminshall 61531798Sminshall /* First, create verification file. */ 61631798Sminshall do { 61747031Sdonn keyname = mktemp(strdup("/tmp/apiXXXXXX")); 61831798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 61931798Sminshall } while ((fd == -1) && (errno == EEXIST)); 62031798Sminshall 62131798Sminshall if (fd == -1) { 62231798Sminshall perror("open"); 62331798Sminshall return 0; 62431798Sminshall } 62531798Sminshall 62631798Sminshall /* Now, get seed for random */ 62731798Sminshall 62835423Sminshall if (gettimeofday(&tv, (struct timezone *)0) == -1) { 62931798Sminshall perror("gettimeofday"); 63031798Sminshall return 0; 63131798Sminshall } 63231798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 63331798Sminshall do { 63431798Sminshall ikey = random(); 63531798Sminshall } while (ikey == 0); 63635423Sminshall sprintf(key, "%lu\n", (unsigned long) ikey); 63731798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 63831798Sminshall perror("write"); 63931798Sminshall return 0; 64031798Sminshall } 64131798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 64231798Sminshall 64331798Sminshall if (close(fd) == -1) { 64431798Sminshall perror("close"); 64531798Sminshall return 0; 64631798Sminshall } 64731798Sminshall 64831798Sminshall /* Next, create the socket which will be connected to */ 64931457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 65031457Sminshall if (serversock < 0) { 65131457Sminshall perror("opening API socket"); 65231457Sminshall return 0; 65331457Sminshall } 65431457Sminshall server.sin_family = AF_INET; 65531457Sminshall server.sin_addr.s_addr = INADDR_ANY; 65631457Sminshall server.sin_port = 0; 65735423Sminshall if (bind(serversock, (struct sockaddr *)&server, sizeof server) < 0) { 65831457Sminshall perror("binding API socket"); 65931457Sminshall return 0; 66031457Sminshall } 66131457Sminshall length = sizeof server; 66235423Sminshall if (getsockname(serversock, (struct sockaddr *)&server, &length) < 0) { 66331457Sminshall perror("getting API socket name"); 66431457Sminshall (void) close(serversock); 66531457Sminshall } 66631457Sminshall listen(serversock, 1); 66731457Sminshall /* Get name to advertise in address list */ 66831457Sminshall strcpy(sockNAME, "API3270="); 66931457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 67031798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 67131457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 67231457Sminshall strcpy(sockNAME, "localhost"); 67331457Sminshall } 67435423Sminshall sprintf(sockNAME+strlen(sockNAME), ":%u", ntohs(server.sin_port)); 67531798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 67631457Sminshall 67731457Sminshall if (whereAPI == 0) { 67831457Sminshall char **ptr, **nextenv; 67931457Sminshall extern char **environ; 68031457Sminshall 68131457Sminshall ptr = environ; 68231457Sminshall nextenv = ourENVlist; 68331457Sminshall while (*ptr) { 68431457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 68531457Sminshall fprintf(stderr, "Too many environmental variables\n"); 68631457Sminshall break; 68731457Sminshall } 68831457Sminshall *nextenv++ = *ptr++; 68931457Sminshall } 69031457Sminshall whereAPI = nextenv++; 69131457Sminshall *nextenv++ = 0; 69231457Sminshall environ = ourENVlist; /* New environment */ 69331457Sminshall } 69431457Sminshall *whereAPI = sockNAME; 69531457Sminshall 69631457Sminshall child_died(); /* Start up signal handler */ 69731457Sminshall shell_active = 1; /* We are running down below */ 69831457Sminshall if (shell_pid = vfork()) { 69931457Sminshall if (shell_pid == -1) { 70031457Sminshall perror("vfork"); 70131457Sminshall (void) close(serversock); 70231457Sminshall } else { 70331465Sminshall state = UNCONNECTED; 70431457Sminshall } 70531455Sminshall } else { /* New process */ 70631455Sminshall register int i; 70731455Sminshall 70831455Sminshall for (i = 3; i < 30; i++) { 70931455Sminshall (void) close(i); 71031455Sminshall } 71131455Sminshall if (argc == 1) { /* Just get a shell */ 71231455Sminshall char *cmdname; 71331457Sminshall extern char *getenv(); 71431455Sminshall 71531455Sminshall cmdname = getenv("SHELL"); 71631455Sminshall execlp(cmdname, cmdname, 0); 71731455Sminshall perror("Exec'ing new shell...\n"); 71831455Sminshall exit(1); 71931455Sminshall } else { 72031455Sminshall execvp(argv[1], &argv[1]); 72131455Sminshall perror("Exec'ing command.\n"); 72231455Sminshall exit(1); 72331455Sminshall } 72431455Sminshall /*NOTREACHED*/ 72531455Sminshall } 72631457Sminshall return shell_active; /* Go back to main loop */ 72731455Sminshall } 728