131894Sminshall /* 231894Sminshall * Copyright (c) 1984-1987 by the Regents of the 331894Sminshall * University of California and by Gregory Glenn Minshall. 431894Sminshall * 531894Sminshall * Permission to use, copy, modify, and distribute these 631894Sminshall * programs and their documentation for any purpose and 731894Sminshall * without fee is hereby granted, provided that this 831894Sminshall * copyright and permission appear on all copies and 931894Sminshall * supporting documentation, the name of the Regents of 1031894Sminshall * the University of California not be used in advertising 1131894Sminshall * or publicity pertaining to distribution of the programs 1231894Sminshall * without specific prior permission, and notice be given in 1331894Sminshall * supporting documentation that copying and distribution is 1431894Sminshall * by permission of the Regents of the University of California 1531894Sminshall * and by Gregory Glenn Minshall. Neither the Regents of the 1631894Sminshall * University of California nor Gregory Glenn Minshall make 1731894Sminshall * representations about the suitability of this software 1831894Sminshall * for any purpose. It is provided "as is" without 1931894Sminshall * express or implied warranty. 2031894Sminshall */ 2131894Sminshall 2231894Sminshall #ifndef lint 23*33269Sminshall static char sccsid[] = "@(#)system.c 3.2 (Berkeley) 01/05/88"; 2431894Sminshall #endif /* not lint */ 2531894Sminshall 2631457Sminshall #include <sys/types.h> 2731863Sminshall 28*33269Sminshall #if defined(pyr) 29*33269Sminshall #define fd_set fdset_t 30*33269Sminshall #endif /* defined(pyr) */ 31*33269Sminshall 32*33269Sminshall #if !defined(sun) && !defined(pyr) 3331798Sminshall #include <sys/inode.h> 3431863Sminshall #else /* !defined(sun) */ 3531863Sminshall #define IREAD 00400 3631863Sminshall #define IWRITE 00200 3731863Sminshall #endif /* !defined(sun) */ 3831863Sminshall 3931798Sminshall #include <sys/file.h> 4031798Sminshall #include <sys/time.h> 4131457Sminshall #include <sys/socket.h> 4231457Sminshall #include <netinet/in.h> 4331455Sminshall #include <sys/wait.h> 4431455Sminshall 4531457Sminshall #include <errno.h> 4631457Sminshall extern int errno; 4731457Sminshall 4831457Sminshall #include <netdb.h> 4931457Sminshall #include <signal.h> 5031455Sminshall #include <stdio.h> 5131457Sminshall #include <pwd.h> 5231455Sminshall 5331455Sminshall #include "../general/general.h" 5431873Sminshall #include "../ctlr/api.h" 5531873Sminshall #include "../api/api_exch.h" 5631455Sminshall 5731455Sminshall #include "../general/globals.h" 5831455Sminshall 5931795Sminshall #ifndef FD_SETSIZE 6031795Sminshall /* 6131795Sminshall * The following is defined just in case someone should want to run 6231795Sminshall * this telnet on a 4.2 system. 6331795Sminshall * 6431795Sminshall */ 6531455Sminshall 6631795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 6731795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 6831795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 6931795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 7031795Sminshall 7131795Sminshall #endif 7231795Sminshall 7331455Sminshall static int shell_pid = 0; 7431798Sminshall static char key[50]; /* Actual key */ 7531798Sminshall static char *keyname; /* Name of file with key in it */ 7631455Sminshall 7731457Sminshall static char *ourENVlist[200]; /* Lots of room */ 7831457Sminshall 7931465Sminshall static int 8031465Sminshall sock = -1, /* Connected socket */ 8131465Sminshall serversock; /* Server (listening) socket */ 8231457Sminshall 8331457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 8431457Sminshall 8531455Sminshall static int 8631463Sminshall storage_location, /* Address we have */ 8731457Sminshall storage_length = 0, /* Length we have */ 8831457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 8931457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 9031457Sminshall 9131503Sminshall static long storage[1000]; 9231457Sminshall 9331463Sminshall static union REGS inputRegs; 9431463Sminshall static struct SREGS inputSregs; 9531457Sminshall 9631463Sminshall 9731463Sminshall static void 9831457Sminshall kill_connection() 9931457Sminshall { 10031465Sminshall state = UNCONNECTED; 10131465Sminshall if (sock != -1) { 10231465Sminshall (void) close(sock); 10331465Sminshall sock = -1; 10431465Sminshall } 10531457Sminshall } 10631457Sminshall 10731457Sminshall 10831457Sminshall static int 10931463Sminshall nextstore() 11031455Sminshall { 11131463Sminshall struct storage_descriptor sd; 11231455Sminshall 11331463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 11431457Sminshall storage_length = 0; 11531457Sminshall return -1; 11631457Sminshall } 11731798Sminshall storage_length = sd.length; 11831798Sminshall storage_location = sd.location; 11931463Sminshall if (storage_length > sizeof storage) { 12031457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 12131457Sminshall storage_length); 12231463Sminshall storage_length = 0; 12331457Sminshall return -1; 12431457Sminshall } 12531511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 12631511Sminshall == -1) { 12731511Sminshall storage_length = 0; 12831511Sminshall return -1; 12931463Sminshall } 13031471Sminshall return 0; 13131457Sminshall } 13231457Sminshall 13331457Sminshall 13431457Sminshall static int 13531457Sminshall doreject(message) 13631457Sminshall char *message; 13731457Sminshall { 13831463Sminshall struct storage_descriptor sd; 13931457Sminshall int length = strlen(message); 14031457Sminshall 14131492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 14231457Sminshall return -1; 14331457Sminshall } 14431798Sminshall sd.length = length; 14531465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 14631463Sminshall return -1; 14731463Sminshall } 14831463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 14931463Sminshall return -1; 15031463Sminshall } 15131457Sminshall return 0; 15231457Sminshall } 15331457Sminshall 15431457Sminshall 15531455Sminshall /* 15631465Sminshall * doassociate() 15731457Sminshall * 15831457Sminshall * Negotiate with the other side and try to do something. 15931798Sminshall * 16031798Sminshall * Returns: 16131798Sminshall * 16231798Sminshall * -1: Error in processing 16331798Sminshall * 0: Invalid password entered 16431798Sminshall * 1: Association OK 16531457Sminshall */ 16631457Sminshall 16731457Sminshall static int 16831465Sminshall doassociate() 16931457Sminshall { 17031457Sminshall struct passwd *pwent; 17131457Sminshall char 17231457Sminshall promptbuf[100], 17331457Sminshall buffer[200]; 17431457Sminshall int length; 17531457Sminshall int was; 17631463Sminshall struct storage_descriptor sd; 17731457Sminshall 17831463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 17931463Sminshall return -1; 18031457Sminshall } 18131798Sminshall sd.length = sd.length; 18231463Sminshall if (sd.length > sizeof buffer) { 18331798Sminshall doreject("(internal error) Authentication key too long"); 18431465Sminshall return -1; 18531457Sminshall } 18631463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 18731457Sminshall return -1; 18831457Sminshall } 18931463Sminshall buffer[sd.length] = 0; 19031457Sminshall 19131798Sminshall if (strcmp(buffer, key) != 0) { 19231798Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 19331798Sminshall return -1; 19431798Sminshall } 19531798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 19631798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 19731798Sminshall return -1; 19831798Sminshall } 19931798Sminshall sd.length = strlen(promptbuf); 20031798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 20131798Sminshall == -1) { 20231798Sminshall return -1; 20331798Sminshall } 20431798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 20531798Sminshall == -1) { 20631798Sminshall return -1; 20731798Sminshall } 20831798Sminshall sd.length = strlen(pwent->pw_name); 20931798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 21031798Sminshall == -1) { 21131798Sminshall return -1; 21231798Sminshall } 21331798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 21431798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 21531798Sminshall return -1; 21631798Sminshall } 21731798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 21831798Sminshall return -1; 21931798Sminshall } 22031798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 22131798Sminshall == -1) { 22231798Sminshall return -1; 22331798Sminshall } 22431798Sminshall sd.length = sd.length; 22531798Sminshall if (sd.length > sizeof buffer) { 22631798Sminshall doreject("Password entered was too long"); 22731798Sminshall return -1; 22831798Sminshall } 22931798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 23031798Sminshall return -1; 23131798Sminshall } 23231798Sminshall buffer[sd.length] = 0; 23331465Sminshall 23431798Sminshall /* Is this the correct password? */ 23531798Sminshall if (strlen(pwent->pw_name)) { 23631798Sminshall char *ptr; 23731798Sminshall int i; 23831798Sminshall 23931798Sminshall ptr = pwent->pw_name; 24031798Sminshall i = 0; 24131798Sminshall while (i < sd.length) { 24231798Sminshall buffer[i++] ^= *ptr++; 24331798Sminshall if (*ptr == 0) { 24431798Sminshall ptr = pwent->pw_name; 24531798Sminshall } 24631465Sminshall } 24731465Sminshall } 24831798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 24931798Sminshall doreject("Invalid password"); 25031798Sminshall sleep(10); /* Don't let us do too many of these */ 25131798Sminshall return 0; 25231798Sminshall } 25331465Sminshall } 25431798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 25531798Sminshall return -1; 25631457Sminshall } else { 25731798Sminshall return 1; 25831457Sminshall } 25931457Sminshall } 26031457Sminshall 26131457Sminshall 26231457Sminshall void 26331457Sminshall freestorage() 26431457Sminshall { 26531457Sminshall char buffer[40]; 26631463Sminshall struct storage_descriptor sd; 26731457Sminshall 26831457Sminshall if (storage_accessed) { 26931457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 27031503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 27131457Sminshall __FILE__, __LINE__); 27231457Sminshall quit(); 27331457Sminshall } 27431457Sminshall if (storage_must_send == 0) { 27531457Sminshall return; 27631457Sminshall } 27731457Sminshall storage_must_send = 0; 27831492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 27931457Sminshall kill_connection(); 28031457Sminshall return; 28131457Sminshall } 28231798Sminshall sd.length = storage_length; 28331798Sminshall sd.location = storage_location; 28431463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 28531457Sminshall kill_connection(); 28631457Sminshall return; 28731457Sminshall } 28831511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 28931511Sminshall == -1) { 29031511Sminshall kill_connection(); 29131511Sminshall return; 29231463Sminshall } 29331457Sminshall } 29431457Sminshall 29531457Sminshall 29631463Sminshall static int 29731508Sminshall getstorage(address, length, copyin) 29831508Sminshall int 29931508Sminshall address, 30031508Sminshall length, 30131508Sminshall copyin; 30231457Sminshall { 30331463Sminshall struct storage_descriptor sd; 30431457Sminshall char buffer[40]; 30531457Sminshall 30631457Sminshall freestorage(); 30731457Sminshall if (storage_accessed) { 30831457Sminshall fprintf(stderr, 30931457Sminshall "Internal error - attempt to get while storage accessed.\n"); 31031503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 31131457Sminshall __FILE__, __LINE__); 31231457Sminshall quit(); 31331457Sminshall } 31431457Sminshall storage_must_send = 0; 31531492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 31631457Sminshall kill_connection(); 31731463Sminshall return -1; 31831457Sminshall } 31931471Sminshall storage_location = address; 32031471Sminshall storage_length = length; 32131508Sminshall if (copyin) { 32231798Sminshall sd.location = storage_location; 32331798Sminshall sd.length = storage_length; 32431508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 32531508Sminshall sizeof sd, (char *)&sd) == -1) { 32631508Sminshall kill_connection(); 32731508Sminshall return -1; 32831508Sminshall } 32931508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 33031508Sminshall fprintf(stderr, "Bad data from other side.\n"); 33131508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 33231508Sminshall return -1; 33331508Sminshall } 33431508Sminshall if (nextstore() == -1) { 33531508Sminshall kill_connection(); 33631508Sminshall return -1; 33731508Sminshall } 33831463Sminshall } 33931463Sminshall return 0; 34031457Sminshall } 34131457Sminshall 34231457Sminshall void 34331457Sminshall movetous(local, es, di, length) 34431457Sminshall char 34531457Sminshall *local; 34631457Sminshall int 34731457Sminshall es, 34831457Sminshall di; 34931457Sminshall int 35031457Sminshall length; 35131457Sminshall { 35231457Sminshall if (length > sizeof storage) { 35331457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 35431457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 35531457Sminshall quit(); 35631457Sminshall } else if (length == 0) { 35731457Sminshall return; 35831457Sminshall } 35931508Sminshall getstorage(di, length, 1); 36031463Sminshall memcpy(local, storage+(di-storage_location), length); 36131457Sminshall } 36231457Sminshall 36331457Sminshall void 36431457Sminshall movetothem(es, di, local, length) 36531457Sminshall int 36631457Sminshall es, 36731457Sminshall di; 36831457Sminshall char 36931457Sminshall *local; 37031457Sminshall int 37131457Sminshall length; 37231457Sminshall { 37331457Sminshall if (length > sizeof storage) { 37431457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 37531457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 37631457Sminshall quit(); 37731457Sminshall } else if (length == 0) { 37831457Sminshall return; 37931457Sminshall } 38031457Sminshall freestorage(); 38131457Sminshall memcpy((char *)storage, local, length); 38231457Sminshall storage_length = length; 38331463Sminshall storage_location = di; 38431457Sminshall storage_must_send = 1; 38531457Sminshall } 38631457Sminshall 38731457Sminshall 38831457Sminshall char * 38931508Sminshall access_api(location, length, copyin) 39031457Sminshall int 39131457Sminshall location, 39231508Sminshall length, 39331508Sminshall copyin; /* Do we need to copy in initially? */ 39431457Sminshall { 39531457Sminshall if (storage_accessed) { 39631457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 39731503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 39831457Sminshall __FILE__, __LINE__); 39931457Sminshall quit(); 40031457Sminshall } else if (length != 0) { 40131457Sminshall freestorage(); 40231508Sminshall getstorage(location, length, copyin); 40331503Sminshall storage_accessed = 1; 40431457Sminshall } 40531457Sminshall return (char *) storage; 40631457Sminshall } 40731457Sminshall 40831508Sminshall unaccess_api(location, local, length, copyout) 40931457Sminshall int location; 41031457Sminshall char *local; 41131457Sminshall int length; 41231457Sminshall { 41331457Sminshall if (storage_accessed == 0) { 41431457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 41531503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 41631457Sminshall __FILE__, __LINE__); 41731457Sminshall quit(); 41831457Sminshall } 41931457Sminshall storage_accessed = 0; 42031508Sminshall storage_must_send = copyout; /* if needs to go back */ 42131457Sminshall } 42231457Sminshall 42331465Sminshall /* 42431465Sminshall * Accept a connection from an API client, aborting if the child dies. 42531465Sminshall */ 42631457Sminshall 42731465Sminshall static int 42831465Sminshall doconnect() 42931465Sminshall { 43031465Sminshall fd_set fdset; 43131465Sminshall int i; 43231465Sminshall 43331465Sminshall sock = -1; 43431465Sminshall FD_ZERO(&fdset); 43531465Sminshall while (shell_active && (sock == -1)) { 43631465Sminshall FD_SET(serversock, &fdset); 43731465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 43831465Sminshall if (errno = EINTR) { 43931465Sminshall continue; 44031465Sminshall } else { 44131465Sminshall perror("in select waiting for API connection"); 44231465Sminshall return -1; 44331465Sminshall } 44431465Sminshall } else { 44531465Sminshall i = accept(serversock, 0, 0); 44631465Sminshall if (i == -1) { 44731465Sminshall perror("accepting API connection"); 44831465Sminshall return -1; 44931465Sminshall } 45031465Sminshall sock = i; 45131465Sminshall } 45231465Sminshall } 45331465Sminshall /* If the process has already exited, we may need to close */ 45431465Sminshall if ((shell_active == 0) && (sock != -1)) { 45531465Sminshall (void) close(sock); 45631465Sminshall sock = -1; 45731465Sminshall setcommandmode(); /* In case child_died sneaked in */ 45831465Sminshall } 45931465Sminshall } 46031465Sminshall 46131457Sminshall /* 46231455Sminshall * shell_continue() actually runs the command, and looks for API 46331455Sminshall * requests coming back in. 46431455Sminshall * 46531455Sminshall * We are called from the main loop in telnet.c. 46631455Sminshall */ 46731455Sminshall 46831455Sminshall int 46931455Sminshall shell_continue() 47031455Sminshall { 47131492Sminshall int i; 47231492Sminshall 47331457Sminshall switch (state) { 47431457Sminshall case DEAD: 47531457Sminshall pause(); /* Nothing to do */ 47631457Sminshall break; 47731457Sminshall case UNCONNECTED: 47831465Sminshall if (doconnect() == -1) { 47931457Sminshall kill_connection(); 48031465Sminshall return -1; 48131465Sminshall } 48231492Sminshall if (api_exch_init(sock, "server") == -1) { 48331465Sminshall return -1; 48431465Sminshall } 48531465Sminshall while (state == UNCONNECTED) { 48631492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 48731457Sminshall kill_connection(); 48831465Sminshall return -1; 48931465Sminshall } else { 49031465Sminshall switch (doassociate()) { 49131465Sminshall case -1: 49231465Sminshall kill_connection(); 49331465Sminshall return -1; 49431465Sminshall case 0: 49531465Sminshall break; 49631465Sminshall case 1: 49731465Sminshall state = CONNECTED; 49831465Sminshall } 49931457Sminshall } 50031457Sminshall } 50131457Sminshall break; 50231457Sminshall case CONNECTED: 50331492Sminshall switch (i = api_exch_nextcommand()) { 50431492Sminshall case EXCH_CMD_REQUEST: 50531492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 50631492Sminshall (char *)&inputRegs) == -1) { 50731463Sminshall kill_connection(); 50831492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 50931492Sminshall (char *)&inputSregs) == -1) { 51031463Sminshall kill_connection(); 51131492Sminshall } else if (nextstore() == -1) { 51231463Sminshall kill_connection(); 51331492Sminshall } else { 51431492Sminshall handle_api(&inputRegs, &inputSregs); 51531492Sminshall freestorage(); /* Send any storage back */ 51631492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 51731492Sminshall kill_connection(); 51831492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 51931492Sminshall (char *)&inputRegs) == -1) { 52031492Sminshall kill_connection(); 52131492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 52231492Sminshall (char *)&inputSregs) == -1) { 52331492Sminshall kill_connection(); 52431492Sminshall } 52531492Sminshall /* Done, and it all worked! */ 52631463Sminshall } 52731492Sminshall break; 52831492Sminshall case EXCH_CMD_DISASSOCIATE: 52931492Sminshall kill_connection(); 53031492Sminshall break; 53131492Sminshall default: 53231503Sminshall if (i != -1) { 53331503Sminshall fprintf(stderr, 53431503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 53531503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 53631503Sminshall } 53731492Sminshall kill_connection(); 53831503Sminshall break; 53931457Sminshall } 54031457Sminshall } 54131455Sminshall return shell_active; 54231455Sminshall } 54331455Sminshall 54431455Sminshall 54531463Sminshall static int 54631463Sminshall child_died() 54731463Sminshall { 54831463Sminshall union wait *status; 54931463Sminshall register int pid; 55031463Sminshall 55131463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 55231463Sminshall if (pid == shell_pid) { 55331463Sminshall char inputbuffer[100]; 55431463Sminshall 55531463Sminshall shell_active = 0; 55631463Sminshall if (sock != -1) { 55731463Sminshall (void) close(sock); 55831463Sminshall sock = -1; 55931463Sminshall } 56031471Sminshall printf("[Hit return to continue]"); 56131471Sminshall fflush(stdout); 56231471Sminshall (void) gets(inputbuffer); 56331465Sminshall setconnmode(); 56431465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 56531465Sminshall (void) close(serversock); 56631798Sminshall (void) unlink(keyname); 56731463Sminshall } 56831463Sminshall } 56931463Sminshall signal(SIGCHLD, child_died); 57031463Sminshall } 57131463Sminshall 57231463Sminshall 57331455Sminshall /* 57431455Sminshall * Called from telnet.c to fork a lower command.com. We 57531455Sminshall * use the spint... routines so that we can pick up 57631455Sminshall * interrupts generated by application programs. 57731455Sminshall */ 57831455Sminshall 57931455Sminshall 58031455Sminshall int 58131455Sminshall shell(argc,argv) 58231455Sminshall int argc; 58331455Sminshall char *argv[]; 58431455Sminshall { 58531465Sminshall int length; 58631457Sminshall struct sockaddr_in server; 58731457Sminshall char sockNAME[100]; 58831457Sminshall static char **whereAPI = 0; 58931798Sminshall int fd; 59031798Sminshall struct timeval tv; 59131798Sminshall long ikey; 59231798Sminshall extern long random(); 59331798Sminshall extern char *mktemp(); 59431457Sminshall 59531798Sminshall /* First, create verification file. */ 59631798Sminshall do { 59731798Sminshall keyname = mktemp("/tmp/apiXXXXXX"); 59831798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 59931798Sminshall } while ((fd == -1) && (errno == EEXIST)); 60031798Sminshall 60131798Sminshall if (fd == -1) { 60231798Sminshall perror("open"); 60331798Sminshall return 0; 60431798Sminshall } 60531798Sminshall 60631798Sminshall /* Now, get seed for random */ 60731798Sminshall 60831798Sminshall if (gettimeofday(&tv, 0) == -1) { 60931798Sminshall perror("gettimeofday"); 61031798Sminshall return 0; 61131798Sminshall } 61231798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 61331798Sminshall do { 61431798Sminshall ikey = random(); 61531798Sminshall } while (ikey == 0); 61631798Sminshall sprintf(key, "%lu\n", ikey); 61731798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 61831798Sminshall perror("write"); 61931798Sminshall return 0; 62031798Sminshall } 62131798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 62231798Sminshall 62331798Sminshall if (close(fd) == -1) { 62431798Sminshall perror("close"); 62531798Sminshall return 0; 62631798Sminshall } 62731798Sminshall 62831798Sminshall /* Next, create the socket which will be connected to */ 62931457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 63031457Sminshall if (serversock < 0) { 63131457Sminshall perror("opening API socket"); 63231457Sminshall return 0; 63331457Sminshall } 63431457Sminshall server.sin_family = AF_INET; 63531457Sminshall server.sin_addr.s_addr = INADDR_ANY; 63631457Sminshall server.sin_port = 0; 63731457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 63831457Sminshall perror("binding API socket"); 63931457Sminshall return 0; 64031457Sminshall } 64131457Sminshall length = sizeof server; 64231457Sminshall if (getsockname(serversock, &server, &length) < 0) { 64331457Sminshall perror("getting API socket name"); 64431457Sminshall (void) close(serversock); 64531457Sminshall } 64631457Sminshall listen(serversock, 1); 64731457Sminshall /* Get name to advertise in address list */ 64831457Sminshall strcpy(sockNAME, "API3270="); 64931457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 65031798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 65131457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 65231457Sminshall strcpy(sockNAME, "localhost"); 65331457Sminshall } 65431457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 65531798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 65631457Sminshall 65731457Sminshall if (whereAPI == 0) { 65831457Sminshall char **ptr, **nextenv; 65931457Sminshall extern char **environ; 66031457Sminshall 66131457Sminshall ptr = environ; 66231457Sminshall nextenv = ourENVlist; 66331457Sminshall while (*ptr) { 66431457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 66531457Sminshall fprintf(stderr, "Too many environmental variables\n"); 66631457Sminshall break; 66731457Sminshall } 66831457Sminshall *nextenv++ = *ptr++; 66931457Sminshall } 67031457Sminshall whereAPI = nextenv++; 67131457Sminshall *nextenv++ = 0; 67231457Sminshall environ = ourENVlist; /* New environment */ 67331457Sminshall } 67431457Sminshall *whereAPI = sockNAME; 67531457Sminshall 67631457Sminshall child_died(); /* Start up signal handler */ 67731457Sminshall shell_active = 1; /* We are running down below */ 67831457Sminshall if (shell_pid = vfork()) { 67931457Sminshall if (shell_pid == -1) { 68031457Sminshall perror("vfork"); 68131457Sminshall (void) close(serversock); 68231457Sminshall } else { 68331465Sminshall state = UNCONNECTED; 68431457Sminshall } 68531455Sminshall } else { /* New process */ 68631455Sminshall register int i; 68731455Sminshall 68831455Sminshall for (i = 3; i < 30; i++) { 68931455Sminshall (void) close(i); 69031455Sminshall } 69131455Sminshall if (argc == 1) { /* Just get a shell */ 69231455Sminshall char *cmdname; 69331457Sminshall extern char *getenv(); 69431455Sminshall 69531455Sminshall cmdname = getenv("SHELL"); 69631455Sminshall execlp(cmdname, cmdname, 0); 69731455Sminshall perror("Exec'ing new shell...\n"); 69831455Sminshall exit(1); 69931455Sminshall } else { 70031455Sminshall execvp(argv[1], &argv[1]); 70131455Sminshall perror("Exec'ing command.\n"); 70231455Sminshall exit(1); 70331455Sminshall } 70431455Sminshall /*NOTREACHED*/ 70531455Sminshall } 70631457Sminshall return shell_active; /* Go back to main loop */ 70731455Sminshall } 708