131894Sminshall /* 2*33810Sbostic * Copyright (c) 1988 Regents of the University of California. 3*33810Sbostic * All rights reserved. 431894Sminshall * 5*33810Sbostic * Redistribution and use in source and binary forms are permitted 6*33810Sbostic * provided that this notice is preserved and that due credit is given 7*33810Sbostic * to the University of California at Berkeley. The name of the University 8*33810Sbostic * may not be used to endorse or promote products derived from this 9*33810Sbostic * software without specific prior written permission. This software 10*33810Sbostic * is provided ``as is'' without express or implied warranty. 1131894Sminshall */ 1231894Sminshall 1331894Sminshall #ifndef lint 14*33810Sbostic static char sccsid[] = "@(#)system.c 3.3 (Berkeley) 03/28/88"; 15*33810Sbostic #endif /* not lint */ 1631894Sminshall 1731457Sminshall #include <sys/types.h> 1831863Sminshall 1933269Sminshall #if defined(pyr) 2033269Sminshall #define fd_set fdset_t 2133269Sminshall #endif /* defined(pyr) */ 2233269Sminshall 2333269Sminshall #if !defined(sun) && !defined(pyr) 2431798Sminshall #include <sys/inode.h> 2531863Sminshall #else /* !defined(sun) */ 2631863Sminshall #define IREAD 00400 2731863Sminshall #define IWRITE 00200 2831863Sminshall #endif /* !defined(sun) */ 2931863Sminshall 3031798Sminshall #include <sys/file.h> 3131798Sminshall #include <sys/time.h> 3231457Sminshall #include <sys/socket.h> 3331457Sminshall #include <netinet/in.h> 3431455Sminshall #include <sys/wait.h> 3531455Sminshall 3631457Sminshall #include <errno.h> 3731457Sminshall extern int errno; 3831457Sminshall 3931457Sminshall #include <netdb.h> 4031457Sminshall #include <signal.h> 4131455Sminshall #include <stdio.h> 4231457Sminshall #include <pwd.h> 4331455Sminshall 4431455Sminshall #include "../general/general.h" 4531873Sminshall #include "../ctlr/api.h" 4631873Sminshall #include "../api/api_exch.h" 4731455Sminshall 4831455Sminshall #include "../general/globals.h" 4931455Sminshall 5031795Sminshall #ifndef FD_SETSIZE 5131795Sminshall /* 5231795Sminshall * The following is defined just in case someone should want to run 5331795Sminshall * this telnet on a 4.2 system. 5431795Sminshall * 5531795Sminshall */ 5631455Sminshall 5731795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 5831795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 5931795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 6031795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 6131795Sminshall 6231795Sminshall #endif 6331795Sminshall 6431455Sminshall static int shell_pid = 0; 6531798Sminshall static char key[50]; /* Actual key */ 6631798Sminshall static char *keyname; /* Name of file with key in it */ 6731455Sminshall 6831457Sminshall static char *ourENVlist[200]; /* Lots of room */ 6931457Sminshall 7031465Sminshall static int 7131465Sminshall sock = -1, /* Connected socket */ 7231465Sminshall serversock; /* Server (listening) socket */ 7331457Sminshall 7431457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 7531457Sminshall 7631455Sminshall static int 7731463Sminshall storage_location, /* Address we have */ 7831457Sminshall storage_length = 0, /* Length we have */ 7931457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 8031457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 8131457Sminshall 8231503Sminshall static long storage[1000]; 8331457Sminshall 8431463Sminshall static union REGS inputRegs; 8531463Sminshall static struct SREGS inputSregs; 8631457Sminshall 8731463Sminshall 8831463Sminshall static void 8931457Sminshall kill_connection() 9031457Sminshall { 9131465Sminshall state = UNCONNECTED; 9231465Sminshall if (sock != -1) { 9331465Sminshall (void) close(sock); 9431465Sminshall sock = -1; 9531465Sminshall } 9631457Sminshall } 9731457Sminshall 9831457Sminshall 9931457Sminshall static int 10031463Sminshall nextstore() 10131455Sminshall { 10231463Sminshall struct storage_descriptor sd; 10331455Sminshall 10431463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 10531457Sminshall storage_length = 0; 10631457Sminshall return -1; 10731457Sminshall } 10831798Sminshall storage_length = sd.length; 10931798Sminshall storage_location = sd.location; 11031463Sminshall if (storage_length > sizeof storage) { 11131457Sminshall fprintf(stderr, "API client tried to send too much storage (%d).\n", 11231457Sminshall storage_length); 11331463Sminshall storage_length = 0; 11431457Sminshall return -1; 11531457Sminshall } 11631511Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 11731511Sminshall == -1) { 11831511Sminshall storage_length = 0; 11931511Sminshall return -1; 12031463Sminshall } 12131471Sminshall return 0; 12231457Sminshall } 12331457Sminshall 12431457Sminshall 12531457Sminshall static int 12631457Sminshall doreject(message) 12731457Sminshall char *message; 12831457Sminshall { 12931463Sminshall struct storage_descriptor sd; 13031457Sminshall int length = strlen(message); 13131457Sminshall 13231492Sminshall if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { 13331457Sminshall return -1; 13431457Sminshall } 13531798Sminshall sd.length = length; 13631465Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 13731463Sminshall return -1; 13831463Sminshall } 13931463Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { 14031463Sminshall return -1; 14131463Sminshall } 14231457Sminshall return 0; 14331457Sminshall } 14431457Sminshall 14531457Sminshall 14631455Sminshall /* 14731465Sminshall * doassociate() 14831457Sminshall * 14931457Sminshall * Negotiate with the other side and try to do something. 15031798Sminshall * 15131798Sminshall * Returns: 15231798Sminshall * 15331798Sminshall * -1: Error in processing 15431798Sminshall * 0: Invalid password entered 15531798Sminshall * 1: Association OK 15631457Sminshall */ 15731457Sminshall 15831457Sminshall static int 15931465Sminshall doassociate() 16031457Sminshall { 16131457Sminshall struct passwd *pwent; 16231457Sminshall char 16331457Sminshall promptbuf[100], 16431457Sminshall buffer[200]; 16531457Sminshall int length; 16631457Sminshall int was; 16731463Sminshall struct storage_descriptor sd; 16831457Sminshall 16931463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 17031463Sminshall return -1; 17131457Sminshall } 17231798Sminshall sd.length = sd.length; 17331463Sminshall if (sd.length > sizeof buffer) { 17431798Sminshall doreject("(internal error) Authentication key too long"); 17531465Sminshall return -1; 17631457Sminshall } 17731463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 17831457Sminshall return -1; 17931457Sminshall } 18031463Sminshall buffer[sd.length] = 0; 18131457Sminshall 18231798Sminshall if (strcmp(buffer, key) != 0) { 18331798Sminshall if ((pwent = getpwuid(geteuid())) == 0) { 18431798Sminshall return -1; 18531798Sminshall } 18631798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 18731798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 18831798Sminshall return -1; 18931798Sminshall } 19031798Sminshall sd.length = strlen(promptbuf); 19131798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 19231798Sminshall == -1) { 19331798Sminshall return -1; 19431798Sminshall } 19531798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 19631798Sminshall == -1) { 19731798Sminshall return -1; 19831798Sminshall } 19931798Sminshall sd.length = strlen(pwent->pw_name); 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, 20531798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 20631798Sminshall return -1; 20731798Sminshall } 20831798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 20931798Sminshall return -1; 21031798Sminshall } 21131798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 21231798Sminshall == -1) { 21331798Sminshall return -1; 21431798Sminshall } 21531798Sminshall sd.length = sd.length; 21631798Sminshall if (sd.length > sizeof buffer) { 21731798Sminshall doreject("Password entered was too long"); 21831798Sminshall return -1; 21931798Sminshall } 22031798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 22131798Sminshall return -1; 22231798Sminshall } 22331798Sminshall buffer[sd.length] = 0; 22431465Sminshall 22531798Sminshall /* Is this the correct password? */ 22631798Sminshall if (strlen(pwent->pw_name)) { 22731798Sminshall char *ptr; 22831798Sminshall int i; 22931798Sminshall 23031798Sminshall ptr = pwent->pw_name; 23131798Sminshall i = 0; 23231798Sminshall while (i < sd.length) { 23331798Sminshall buffer[i++] ^= *ptr++; 23431798Sminshall if (*ptr == 0) { 23531798Sminshall ptr = pwent->pw_name; 23631798Sminshall } 23731465Sminshall } 23831465Sminshall } 23931798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 24031798Sminshall doreject("Invalid password"); 24131798Sminshall sleep(10); /* Don't let us do too many of these */ 24231798Sminshall return 0; 24331798Sminshall } 24431465Sminshall } 24531798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 24631798Sminshall return -1; 24731457Sminshall } else { 24831798Sminshall return 1; 24931457Sminshall } 25031457Sminshall } 25131457Sminshall 25231457Sminshall 25331457Sminshall void 25431457Sminshall freestorage() 25531457Sminshall { 25631457Sminshall char buffer[40]; 25731463Sminshall struct storage_descriptor sd; 25831457Sminshall 25931457Sminshall if (storage_accessed) { 26031457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 26131503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 26231457Sminshall __FILE__, __LINE__); 26331457Sminshall quit(); 26431457Sminshall } 26531457Sminshall if (storage_must_send == 0) { 26631457Sminshall return; 26731457Sminshall } 26831457Sminshall storage_must_send = 0; 26931492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 27031457Sminshall kill_connection(); 27131457Sminshall return; 27231457Sminshall } 27331798Sminshall sd.length = storage_length; 27431798Sminshall sd.location = storage_location; 27531463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 27631457Sminshall kill_connection(); 27731457Sminshall return; 27831457Sminshall } 27931511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 28031511Sminshall == -1) { 28131511Sminshall kill_connection(); 28231511Sminshall return; 28331463Sminshall } 28431457Sminshall } 28531457Sminshall 28631457Sminshall 28731463Sminshall static int 28831508Sminshall getstorage(address, length, copyin) 28931508Sminshall int 29031508Sminshall address, 29131508Sminshall length, 29231508Sminshall copyin; 29331457Sminshall { 29431463Sminshall struct storage_descriptor sd; 29531457Sminshall char buffer[40]; 29631457Sminshall 29731457Sminshall freestorage(); 29831457Sminshall if (storage_accessed) { 29931457Sminshall fprintf(stderr, 30031457Sminshall "Internal error - attempt to get while storage accessed.\n"); 30131503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 30231457Sminshall __FILE__, __LINE__); 30331457Sminshall quit(); 30431457Sminshall } 30531457Sminshall storage_must_send = 0; 30631492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 30731457Sminshall kill_connection(); 30831463Sminshall return -1; 30931457Sminshall } 31031471Sminshall storage_location = address; 31131471Sminshall storage_length = length; 31231508Sminshall if (copyin) { 31331798Sminshall sd.location = storage_location; 31431798Sminshall sd.length = storage_length; 31531508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 31631508Sminshall sizeof sd, (char *)&sd) == -1) { 31731508Sminshall kill_connection(); 31831508Sminshall return -1; 31931508Sminshall } 32031508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 32131508Sminshall fprintf(stderr, "Bad data from other side.\n"); 32231508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 32331508Sminshall return -1; 32431508Sminshall } 32531508Sminshall if (nextstore() == -1) { 32631508Sminshall kill_connection(); 32731508Sminshall return -1; 32831508Sminshall } 32931463Sminshall } 33031463Sminshall return 0; 33131457Sminshall } 33231457Sminshall 33331457Sminshall void 33431457Sminshall movetous(local, es, di, length) 33531457Sminshall char 33631457Sminshall *local; 33731457Sminshall int 33831457Sminshall es, 33931457Sminshall di; 34031457Sminshall int 34131457Sminshall length; 34231457Sminshall { 34331457Sminshall if (length > sizeof storage) { 34431457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 34531457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 34631457Sminshall quit(); 34731457Sminshall } else if (length == 0) { 34831457Sminshall return; 34931457Sminshall } 35031508Sminshall getstorage(di, length, 1); 35131463Sminshall memcpy(local, storage+(di-storage_location), length); 35231457Sminshall } 35331457Sminshall 35431457Sminshall void 35531457Sminshall movetothem(es, di, local, length) 35631457Sminshall int 35731457Sminshall es, 35831457Sminshall di; 35931457Sminshall char 36031457Sminshall *local; 36131457Sminshall int 36231457Sminshall length; 36331457Sminshall { 36431457Sminshall if (length > sizeof storage) { 36531457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 36631457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 36731457Sminshall quit(); 36831457Sminshall } else if (length == 0) { 36931457Sminshall return; 37031457Sminshall } 37131457Sminshall freestorage(); 37231457Sminshall memcpy((char *)storage, local, length); 37331457Sminshall storage_length = length; 37431463Sminshall storage_location = di; 37531457Sminshall storage_must_send = 1; 37631457Sminshall } 37731457Sminshall 37831457Sminshall 37931457Sminshall char * 38031508Sminshall access_api(location, length, copyin) 38131457Sminshall int 38231457Sminshall location, 38331508Sminshall length, 38431508Sminshall copyin; /* Do we need to copy in initially? */ 38531457Sminshall { 38631457Sminshall if (storage_accessed) { 38731457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 38831503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 38931457Sminshall __FILE__, __LINE__); 39031457Sminshall quit(); 39131457Sminshall } else if (length != 0) { 39231457Sminshall freestorage(); 39331508Sminshall getstorage(location, length, copyin); 39431503Sminshall storage_accessed = 1; 39531457Sminshall } 39631457Sminshall return (char *) storage; 39731457Sminshall } 39831457Sminshall 39931508Sminshall unaccess_api(location, local, length, copyout) 40031457Sminshall int location; 40131457Sminshall char *local; 40231457Sminshall int length; 40331457Sminshall { 40431457Sminshall if (storage_accessed == 0) { 40531457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 40631503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 40731457Sminshall __FILE__, __LINE__); 40831457Sminshall quit(); 40931457Sminshall } 41031457Sminshall storage_accessed = 0; 41131508Sminshall storage_must_send = copyout; /* if needs to go back */ 41231457Sminshall } 41331457Sminshall 41431465Sminshall /* 41531465Sminshall * Accept a connection from an API client, aborting if the child dies. 41631465Sminshall */ 41731457Sminshall 41831465Sminshall static int 41931465Sminshall doconnect() 42031465Sminshall { 42131465Sminshall fd_set fdset; 42231465Sminshall int i; 42331465Sminshall 42431465Sminshall sock = -1; 42531465Sminshall FD_ZERO(&fdset); 42631465Sminshall while (shell_active && (sock == -1)) { 42731465Sminshall FD_SET(serversock, &fdset); 42831465Sminshall if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) { 42931465Sminshall if (errno = EINTR) { 43031465Sminshall continue; 43131465Sminshall } else { 43231465Sminshall perror("in select waiting for API connection"); 43331465Sminshall return -1; 43431465Sminshall } 43531465Sminshall } else { 43631465Sminshall i = accept(serversock, 0, 0); 43731465Sminshall if (i == -1) { 43831465Sminshall perror("accepting API connection"); 43931465Sminshall return -1; 44031465Sminshall } 44131465Sminshall sock = i; 44231465Sminshall } 44331465Sminshall } 44431465Sminshall /* If the process has already exited, we may need to close */ 44531465Sminshall if ((shell_active == 0) && (sock != -1)) { 44631465Sminshall (void) close(sock); 44731465Sminshall sock = -1; 44831465Sminshall setcommandmode(); /* In case child_died sneaked in */ 44931465Sminshall } 45031465Sminshall } 45131465Sminshall 45231457Sminshall /* 45331455Sminshall * shell_continue() actually runs the command, and looks for API 45431455Sminshall * requests coming back in. 45531455Sminshall * 45631455Sminshall * We are called from the main loop in telnet.c. 45731455Sminshall */ 45831455Sminshall 45931455Sminshall int 46031455Sminshall shell_continue() 46131455Sminshall { 46231492Sminshall int i; 46331492Sminshall 46431457Sminshall switch (state) { 46531457Sminshall case DEAD: 46631457Sminshall pause(); /* Nothing to do */ 46731457Sminshall break; 46831457Sminshall case UNCONNECTED: 46931465Sminshall if (doconnect() == -1) { 47031457Sminshall kill_connection(); 47131465Sminshall return -1; 47231465Sminshall } 47331492Sminshall if (api_exch_init(sock, "server") == -1) { 47431465Sminshall return -1; 47531465Sminshall } 47631465Sminshall while (state == UNCONNECTED) { 47731492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 47831457Sminshall kill_connection(); 47931465Sminshall return -1; 48031465Sminshall } else { 48131465Sminshall switch (doassociate()) { 48231465Sminshall case -1: 48331465Sminshall kill_connection(); 48431465Sminshall return -1; 48531465Sminshall case 0: 48631465Sminshall break; 48731465Sminshall case 1: 48831465Sminshall state = CONNECTED; 48931465Sminshall } 49031457Sminshall } 49131457Sminshall } 49231457Sminshall break; 49331457Sminshall case CONNECTED: 49431492Sminshall switch (i = api_exch_nextcommand()) { 49531492Sminshall case EXCH_CMD_REQUEST: 49631492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 49731492Sminshall (char *)&inputRegs) == -1) { 49831463Sminshall kill_connection(); 49931492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 50031492Sminshall (char *)&inputSregs) == -1) { 50131463Sminshall kill_connection(); 50231492Sminshall } else if (nextstore() == -1) { 50331463Sminshall kill_connection(); 50431492Sminshall } else { 50531492Sminshall handle_api(&inputRegs, &inputSregs); 50631492Sminshall freestorage(); /* Send any storage back */ 50731492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 50831492Sminshall kill_connection(); 50931492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 51031492Sminshall (char *)&inputRegs) == -1) { 51131492Sminshall kill_connection(); 51231492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 51331492Sminshall (char *)&inputSregs) == -1) { 51431492Sminshall kill_connection(); 51531492Sminshall } 51631492Sminshall /* Done, and it all worked! */ 51731463Sminshall } 51831492Sminshall break; 51931492Sminshall case EXCH_CMD_DISASSOCIATE: 52031492Sminshall kill_connection(); 52131492Sminshall break; 52231492Sminshall default: 52331503Sminshall if (i != -1) { 52431503Sminshall fprintf(stderr, 52531503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 52631503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 52731503Sminshall } 52831492Sminshall kill_connection(); 52931503Sminshall break; 53031457Sminshall } 53131457Sminshall } 53231455Sminshall return shell_active; 53331455Sminshall } 53431455Sminshall 53531455Sminshall 53631463Sminshall static int 53731463Sminshall child_died() 53831463Sminshall { 53931463Sminshall union wait *status; 54031463Sminshall register int pid; 54131463Sminshall 54231463Sminshall while ((pid = wait3(&status, WNOHANG, 0)) > 0) { 54331463Sminshall if (pid == shell_pid) { 54431463Sminshall char inputbuffer[100]; 54531463Sminshall 54631463Sminshall shell_active = 0; 54731463Sminshall if (sock != -1) { 54831463Sminshall (void) close(sock); 54931463Sminshall sock = -1; 55031463Sminshall } 55131471Sminshall printf("[Hit return to continue]"); 55231471Sminshall fflush(stdout); 55331471Sminshall (void) gets(inputbuffer); 55431465Sminshall setconnmode(); 55531465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 55631465Sminshall (void) close(serversock); 55731798Sminshall (void) unlink(keyname); 55831463Sminshall } 55931463Sminshall } 56031463Sminshall signal(SIGCHLD, child_died); 56131463Sminshall } 56231463Sminshall 56331463Sminshall 56431455Sminshall /* 56531455Sminshall * Called from telnet.c to fork a lower command.com. We 56631455Sminshall * use the spint... routines so that we can pick up 56731455Sminshall * interrupts generated by application programs. 56831455Sminshall */ 56931455Sminshall 57031455Sminshall 57131455Sminshall int 57231455Sminshall shell(argc,argv) 57331455Sminshall int argc; 57431455Sminshall char *argv[]; 57531455Sminshall { 57631465Sminshall int length; 57731457Sminshall struct sockaddr_in server; 57831457Sminshall char sockNAME[100]; 57931457Sminshall static char **whereAPI = 0; 58031798Sminshall int fd; 58131798Sminshall struct timeval tv; 58231798Sminshall long ikey; 58331798Sminshall extern long random(); 58431798Sminshall extern char *mktemp(); 58531457Sminshall 58631798Sminshall /* First, create verification file. */ 58731798Sminshall do { 58831798Sminshall keyname = mktemp("/tmp/apiXXXXXX"); 58931798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 59031798Sminshall } while ((fd == -1) && (errno == EEXIST)); 59131798Sminshall 59231798Sminshall if (fd == -1) { 59331798Sminshall perror("open"); 59431798Sminshall return 0; 59531798Sminshall } 59631798Sminshall 59731798Sminshall /* Now, get seed for random */ 59831798Sminshall 59931798Sminshall if (gettimeofday(&tv, 0) == -1) { 60031798Sminshall perror("gettimeofday"); 60131798Sminshall return 0; 60231798Sminshall } 60331798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 60431798Sminshall do { 60531798Sminshall ikey = random(); 60631798Sminshall } while (ikey == 0); 60731798Sminshall sprintf(key, "%lu\n", ikey); 60831798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 60931798Sminshall perror("write"); 61031798Sminshall return 0; 61131798Sminshall } 61231798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 61331798Sminshall 61431798Sminshall if (close(fd) == -1) { 61531798Sminshall perror("close"); 61631798Sminshall return 0; 61731798Sminshall } 61831798Sminshall 61931798Sminshall /* Next, create the socket which will be connected to */ 62031457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 62131457Sminshall if (serversock < 0) { 62231457Sminshall perror("opening API socket"); 62331457Sminshall return 0; 62431457Sminshall } 62531457Sminshall server.sin_family = AF_INET; 62631457Sminshall server.sin_addr.s_addr = INADDR_ANY; 62731457Sminshall server.sin_port = 0; 62831457Sminshall if (bind(serversock, &server, sizeof server) < 0) { 62931457Sminshall perror("binding API socket"); 63031457Sminshall return 0; 63131457Sminshall } 63231457Sminshall length = sizeof server; 63331457Sminshall if (getsockname(serversock, &server, &length) < 0) { 63431457Sminshall perror("getting API socket name"); 63531457Sminshall (void) close(serversock); 63631457Sminshall } 63731457Sminshall listen(serversock, 1); 63831457Sminshall /* Get name to advertise in address list */ 63931457Sminshall strcpy(sockNAME, "API3270="); 64031457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 64131798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 64231457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 64331457Sminshall strcpy(sockNAME, "localhost"); 64431457Sminshall } 64531457Sminshall sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port)); 64631798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 64731457Sminshall 64831457Sminshall if (whereAPI == 0) { 64931457Sminshall char **ptr, **nextenv; 65031457Sminshall extern char **environ; 65131457Sminshall 65231457Sminshall ptr = environ; 65331457Sminshall nextenv = ourENVlist; 65431457Sminshall while (*ptr) { 65531457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 65631457Sminshall fprintf(stderr, "Too many environmental variables\n"); 65731457Sminshall break; 65831457Sminshall } 65931457Sminshall *nextenv++ = *ptr++; 66031457Sminshall } 66131457Sminshall whereAPI = nextenv++; 66231457Sminshall *nextenv++ = 0; 66331457Sminshall environ = ourENVlist; /* New environment */ 66431457Sminshall } 66531457Sminshall *whereAPI = sockNAME; 66631457Sminshall 66731457Sminshall child_died(); /* Start up signal handler */ 66831457Sminshall shell_active = 1; /* We are running down below */ 66931457Sminshall if (shell_pid = vfork()) { 67031457Sminshall if (shell_pid == -1) { 67131457Sminshall perror("vfork"); 67231457Sminshall (void) close(serversock); 67331457Sminshall } else { 67431465Sminshall state = UNCONNECTED; 67531457Sminshall } 67631455Sminshall } else { /* New process */ 67731455Sminshall register int i; 67831455Sminshall 67931455Sminshall for (i = 3; i < 30; i++) { 68031455Sminshall (void) close(i); 68131455Sminshall } 68231455Sminshall if (argc == 1) { /* Just get a shell */ 68331455Sminshall char *cmdname; 68431457Sminshall extern char *getenv(); 68531455Sminshall 68631455Sminshall cmdname = getenv("SHELL"); 68731455Sminshall execlp(cmdname, cmdname, 0); 68831455Sminshall perror("Exec'ing new shell...\n"); 68931455Sminshall exit(1); 69031455Sminshall } else { 69131455Sminshall execvp(argv[1], &argv[1]); 69231455Sminshall perror("Exec'ing command.\n"); 69331455Sminshall exit(1); 69431455Sminshall } 69531455Sminshall /*NOTREACHED*/ 69631455Sminshall } 69731457Sminshall return shell_active; /* Go back to main loop */ 69831455Sminshall } 699