131894Sminshall /* 233810Sbostic * Copyright (c) 1988 Regents of the University of California. 333810Sbostic * All rights reserved. 431894Sminshall * 533810Sbostic * Redistribution and use in source and binary forms are permitted 635423Sminshall * provided that the above copyright notice and this paragraph are 735423Sminshall * duplicated in all such forms and that any documentation, 835423Sminshall * advertising materials, and other materials related to such 935423Sminshall * distribution and use acknowledge that the software was developed 1035423Sminshall * by the University of California, Berkeley. The name of the 1135423Sminshall * University may not be used to endorse or promote products derived 1235423Sminshall * from this software without specific prior written permission. 1335423Sminshall * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435423Sminshall * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535423Sminshall * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1631894Sminshall */ 1731894Sminshall 1831894Sminshall #ifndef lint 19*47031Sdonn static char sccsid[] = "@(#)system.c 4.4 (Berkeley) 03/06/91"; 2033810Sbostic #endif /* not lint */ 2131894Sminshall 2231457Sminshall #include <sys/types.h> 2331863Sminshall 2433269Sminshall #if defined(pyr) 2533269Sminshall #define fd_set fdset_t 2633269Sminshall #endif /* defined(pyr) */ 2733269Sminshall 2838211Sminshall /* 2938211Sminshall * Wouldn't it be nice if these REALLY were in <sys/inode.h>? Or, 3038211Sminshall * equivalently, if <sys/inode.h> REALLY existed? 3138211Sminshall */ 3231863Sminshall #define IREAD 00400 3331863Sminshall #define IWRITE 00200 3431863Sminshall 3531798Sminshall #include <sys/file.h> 3631798Sminshall #include <sys/time.h> 3731457Sminshall #include <sys/socket.h> 3831457Sminshall #include <netinet/in.h> 3931455Sminshall #include <sys/wait.h> 4031455Sminshall 4131457Sminshall #include <errno.h> 4231457Sminshall extern int errno; 4331457Sminshall 4431457Sminshall #include <netdb.h> 4531457Sminshall #include <signal.h> 4631455Sminshall #include <stdio.h> 47*47031Sdonn #include <string.h> 4831457Sminshall #include <pwd.h> 4931455Sminshall 5031455Sminshall #include "../general/general.h" 5131873Sminshall #include "../ctlr/api.h" 5231873Sminshall #include "../api/api_exch.h" 5331455Sminshall 5431455Sminshall #include "../general/globals.h" 5531455Sminshall 5631795Sminshall #ifndef FD_SETSIZE 5731795Sminshall /* 5831795Sminshall * The following is defined just in case someone should want to run 5931795Sminshall * this telnet on a 4.2 system. 6031795Sminshall * 6131795Sminshall */ 6231455Sminshall 6331795Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 6431795Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 6531795Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 6631795Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 6731795Sminshall 6831795Sminshall #endif 6931795Sminshall 7031455Sminshall static int shell_pid = 0; 7131798Sminshall static char key[50]; /* Actual key */ 7231798Sminshall static char *keyname; /* Name of file with key in it */ 7331455Sminshall 7431457Sminshall static char *ourENVlist[200]; /* Lots of room */ 7531457Sminshall 7631465Sminshall static int 7731465Sminshall sock = -1, /* Connected socket */ 7831465Sminshall serversock; /* Server (listening) socket */ 7931457Sminshall 8031457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state; 8131457Sminshall 8235423Sminshall static long 8335423Sminshall storage_location; /* Address we have */ 8435423Sminshall static short 8535423Sminshall storage_length = 0; /* Length we have */ 8631455Sminshall static int 8731457Sminshall storage_must_send = 0, /* Storage belongs on other side of wire */ 8831457Sminshall storage_accessed = 0; /* The storage is accessed (so leave alone)! */ 8931457Sminshall 9031503Sminshall static long storage[1000]; 9131457Sminshall 9231463Sminshall static union REGS inputRegs; 9331463Sminshall static struct SREGS inputSregs; 9431457Sminshall 9538923Sminshall extern int apitrace; 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]; 17431463Sminshall struct storage_descriptor sd; 17535423Sminshall extern char *crypt(); 17631457Sminshall 17731463Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 17831463Sminshall return -1; 17931457Sminshall } 18031798Sminshall sd.length = sd.length; 18131463Sminshall if (sd.length > sizeof buffer) { 18231798Sminshall doreject("(internal error) Authentication key too long"); 18331465Sminshall return -1; 18431457Sminshall } 18531463Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 18631457Sminshall return -1; 18731457Sminshall } 18831463Sminshall buffer[sd.length] = 0; 18931457Sminshall 19031798Sminshall if (strcmp(buffer, key) != 0) { 19135493Sminshall #if (!defined(sun)) || defined(BSD) && (BSD >= 43) 19235423Sminshall extern uid_t geteuid(); 19335493Sminshall #endif /* (!defined(sun)) || defined(BSD) && (BSD >= 43) */ 19435423Sminshall 19535423Sminshall if ((pwent = getpwuid((int)geteuid())) == 0) { 19631798Sminshall return -1; 19731798Sminshall } 19831798Sminshall sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); 19931798Sminshall if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { 20031798Sminshall return -1; 20131798Sminshall } 20231798Sminshall sd.length = strlen(promptbuf); 20331798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 20431798Sminshall == -1) { 20531798Sminshall return -1; 20631798Sminshall } 20731798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) 20831798Sminshall == -1) { 20931798Sminshall return -1; 21031798Sminshall } 21131798Sminshall sd.length = strlen(pwent->pw_name); 21231798Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 21331798Sminshall == -1) { 21431798Sminshall return -1; 21531798Sminshall } 21631798Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, 21731798Sminshall strlen(pwent->pw_name), pwent->pw_name) == -1) { 21831798Sminshall return -1; 21931798Sminshall } 22031798Sminshall if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { 22131798Sminshall return -1; 22231798Sminshall } 22331798Sminshall if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) 22431798Sminshall == -1) { 22531798Sminshall return -1; 22631798Sminshall } 22731798Sminshall sd.length = sd.length; 22831798Sminshall if (sd.length > sizeof buffer) { 22931798Sminshall doreject("Password entered was too long"); 23031798Sminshall return -1; 23131798Sminshall } 23231798Sminshall if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { 23331798Sminshall return -1; 23431798Sminshall } 23531798Sminshall buffer[sd.length] = 0; 23631465Sminshall 23731798Sminshall /* Is this the correct password? */ 23831798Sminshall if (strlen(pwent->pw_name)) { 23931798Sminshall char *ptr; 24031798Sminshall int i; 24131798Sminshall 24231798Sminshall ptr = pwent->pw_name; 24331798Sminshall i = 0; 24431798Sminshall while (i < sd.length) { 24531798Sminshall buffer[i++] ^= *ptr++; 24631798Sminshall if (*ptr == 0) { 24731798Sminshall ptr = pwent->pw_name; 24831798Sminshall } 24931465Sminshall } 25031465Sminshall } 25131798Sminshall if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { 25231798Sminshall doreject("Invalid password"); 25331798Sminshall sleep(10); /* Don't let us do too many of these */ 25431798Sminshall return 0; 25531798Sminshall } 25631465Sminshall } 25731798Sminshall if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { 25831798Sminshall return -1; 25931457Sminshall } else { 26031798Sminshall return 1; 26131457Sminshall } 26231457Sminshall } 26331457Sminshall 26431457Sminshall 26531457Sminshall void 26631457Sminshall freestorage() 26731457Sminshall { 26831463Sminshall struct storage_descriptor sd; 26931457Sminshall 27031457Sminshall if (storage_accessed) { 27131457Sminshall fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); 27231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 27331457Sminshall __FILE__, __LINE__); 27431457Sminshall quit(); 27531457Sminshall } 27631457Sminshall if (storage_must_send == 0) { 27731457Sminshall return; 27831457Sminshall } 27931457Sminshall storage_must_send = 0; 28031492Sminshall if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { 28131457Sminshall kill_connection(); 28231457Sminshall return; 28331457Sminshall } 28431798Sminshall sd.length = storage_length; 28531798Sminshall sd.location = storage_location; 28631463Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { 28731457Sminshall kill_connection(); 28831457Sminshall return; 28931457Sminshall } 29031511Sminshall if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) 29131511Sminshall == -1) { 29231511Sminshall kill_connection(); 29331511Sminshall return; 29431463Sminshall } 29531457Sminshall } 29631457Sminshall 29731457Sminshall 29831463Sminshall static int 29931508Sminshall getstorage(address, length, copyin) 30035423Sminshall long 30135423Sminshall address; 30231508Sminshall int 30331508Sminshall length, 30431508Sminshall copyin; 30531457Sminshall { 30631463Sminshall struct storage_descriptor sd; 30731457Sminshall 30831457Sminshall freestorage(); 30931457Sminshall if (storage_accessed) { 31031457Sminshall fprintf(stderr, 31131457Sminshall "Internal error - attempt to get while storage accessed.\n"); 31231503Sminshall fprintf(stderr, "(Encountered in file %s at line %d.)\n", 31331457Sminshall __FILE__, __LINE__); 31431457Sminshall quit(); 31531457Sminshall } 31631457Sminshall storage_must_send = 0; 31731492Sminshall if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { 31831457Sminshall kill_connection(); 31931463Sminshall return -1; 32031457Sminshall } 32131471Sminshall storage_location = address; 32231471Sminshall storage_length = length; 32331508Sminshall if (copyin) { 32435423Sminshall sd.location = (long)storage_location; 32531798Sminshall sd.length = storage_length; 32631508Sminshall if (api_exch_outtype(EXCH_TYPE_STORE_DESC, 32731508Sminshall sizeof sd, (char *)&sd) == -1) { 32831508Sminshall kill_connection(); 32931508Sminshall return -1; 33031508Sminshall } 33131508Sminshall if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { 33231508Sminshall fprintf(stderr, "Bad data from other side.\n"); 33331508Sminshall fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); 33431508Sminshall return -1; 33531508Sminshall } 33631508Sminshall if (nextstore() == -1) { 33731508Sminshall kill_connection(); 33831508Sminshall return -1; 33931508Sminshall } 34031463Sminshall } 34131463Sminshall return 0; 34231457Sminshall } 34331457Sminshall 34435423Sminshall /*ARGSUSED*/ 34531457Sminshall void 34631457Sminshall movetous(local, es, di, length) 34731457Sminshall char 34831457Sminshall *local; 34935423Sminshall unsigned int 35031457Sminshall es, 35131457Sminshall di; 35231457Sminshall int 35331457Sminshall length; 35431457Sminshall { 35535423Sminshall long where = SEG_OFF_BACK(es, di); 35635423Sminshall 35731457Sminshall if (length > sizeof storage) { 35831457Sminshall fprintf(stderr, "Internal API error - movetous() length too long.\n"); 35931457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 36031457Sminshall quit(); 36131457Sminshall } else if (length == 0) { 36231457Sminshall return; 36331457Sminshall } 36435423Sminshall getstorage(where, length, 1); 36535423Sminshall memcpy(local, (char *)(storage+((where-storage_location))), length); 36638923Sminshall if (apitrace) { 36738923Sminshall Dump('(', local, length); 36838923Sminshall } 36931457Sminshall } 37031457Sminshall 37135423Sminshall /*ARGSUSED*/ 37231457Sminshall void 37331457Sminshall movetothem(es, di, local, length) 37435423Sminshall unsigned int 37531457Sminshall es, 37631457Sminshall di; 37731457Sminshall char 37831457Sminshall *local; 37931457Sminshall int 38031457Sminshall length; 38131457Sminshall { 38235423Sminshall long where = SEG_OFF_BACK(es, di); 38335423Sminshall 38431457Sminshall if (length > sizeof storage) { 38531457Sminshall fprintf(stderr, "Internal API error - movetothem() length too long.\n"); 38631457Sminshall fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); 38731457Sminshall quit(); 38831457Sminshall } else if (length == 0) { 38931457Sminshall return; 39031457Sminshall } 39131457Sminshall freestorage(); 39231457Sminshall memcpy((char *)storage, local, length); 39338923Sminshall if (apitrace) { 39438923Sminshall Dump(')', local, length); 39538923Sminshall } 39631457Sminshall storage_length = length; 39735423Sminshall storage_location = where; 39831457Sminshall storage_must_send = 1; 39931457Sminshall } 40031457Sminshall 40131457Sminshall 40231457Sminshall char * 40331508Sminshall access_api(location, length, copyin) 40435423Sminshall char * 40535423Sminshall location; 40631457Sminshall int 40731508Sminshall length, 40831508Sminshall copyin; /* Do we need to copy in initially? */ 40931457Sminshall { 41031457Sminshall if (storage_accessed) { 41131457Sminshall fprintf(stderr, "Internal error - storage accessed twice\n"); 41231503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 41331457Sminshall __FILE__, __LINE__); 41431457Sminshall quit(); 41531457Sminshall } else if (length != 0) { 41631457Sminshall freestorage(); 41735423Sminshall getstorage((long)location, length, copyin); 41831503Sminshall storage_accessed = 1; 41931457Sminshall } 42031457Sminshall return (char *) storage; 42131457Sminshall } 42231457Sminshall 42335423Sminshall /*ARGSUSED*/ 42435423Sminshall void 42531508Sminshall unaccess_api(location, local, length, copyout) 42635423Sminshall char *location; 42731457Sminshall char *local; 42831457Sminshall int length; 42935423Sminshall int copyout; 43031457Sminshall { 43131457Sminshall if (storage_accessed == 0) { 43231457Sminshall fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); 43331503Sminshall fprintf(stderr, "(Encountered in file %s, line %d.)\n", 43431457Sminshall __FILE__, __LINE__); 43531457Sminshall quit(); 43631457Sminshall } 43731457Sminshall storage_accessed = 0; 43831508Sminshall storage_must_send = copyout; /* if needs to go back */ 43931457Sminshall } 44031457Sminshall 44131465Sminshall /* 44231465Sminshall * Accept a connection from an API client, aborting if the child dies. 44331465Sminshall */ 44431457Sminshall 44531465Sminshall static int 44631465Sminshall doconnect() 44731465Sminshall { 44831465Sminshall fd_set fdset; 44931465Sminshall int i; 45031465Sminshall 45131465Sminshall sock = -1; 45231465Sminshall FD_ZERO(&fdset); 45331465Sminshall while (shell_active && (sock == -1)) { 45431465Sminshall FD_SET(serversock, &fdset); 45535423Sminshall if ((i = select(serversock+1, &fdset, 45635423Sminshall (fd_set *)0, (fd_set *)0, (struct timeval *)0)) < 0) { 45731465Sminshall if (errno = EINTR) { 45831465Sminshall continue; 45931465Sminshall } else { 46031465Sminshall perror("in select waiting for API connection"); 46131465Sminshall return -1; 46231465Sminshall } 46331465Sminshall } else { 46435423Sminshall i = accept(serversock, (struct sockaddr *)0, (int *)0); 46531465Sminshall if (i == -1) { 46631465Sminshall perror("accepting API connection"); 46731465Sminshall return -1; 46831465Sminshall } 46931465Sminshall sock = i; 47031465Sminshall } 47131465Sminshall } 47231465Sminshall /* If the process has already exited, we may need to close */ 47331465Sminshall if ((shell_active == 0) && (sock != -1)) { 47435423Sminshall extern void setcommandmode(); 47535423Sminshall 47631465Sminshall (void) close(sock); 47731465Sminshall sock = -1; 47831465Sminshall setcommandmode(); /* In case child_died sneaked in */ 47931465Sminshall } 48035423Sminshall return 0; 48131465Sminshall } 48231465Sminshall 48331457Sminshall /* 48431455Sminshall * shell_continue() actually runs the command, and looks for API 48531455Sminshall * requests coming back in. 48631455Sminshall * 48731455Sminshall * We are called from the main loop in telnet.c. 48831455Sminshall */ 48931455Sminshall 49031455Sminshall int 49131455Sminshall shell_continue() 49231455Sminshall { 49331492Sminshall int i; 49431492Sminshall 49531457Sminshall switch (state) { 49631457Sminshall case DEAD: 49731457Sminshall pause(); /* Nothing to do */ 49831457Sminshall break; 49931457Sminshall case UNCONNECTED: 50031465Sminshall if (doconnect() == -1) { 50131457Sminshall kill_connection(); 50231465Sminshall return -1; 50331465Sminshall } 50438211Sminshall /* At this point, it is possible that we've gone away */ 50538211Sminshall if (shell_active == 0) { 50638211Sminshall kill_connection(); 50738211Sminshall return -1; 50838211Sminshall } 50931492Sminshall if (api_exch_init(sock, "server") == -1) { 51031465Sminshall return -1; 51131465Sminshall } 51231465Sminshall while (state == UNCONNECTED) { 51331492Sminshall if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { 51431457Sminshall kill_connection(); 51531465Sminshall return -1; 51631465Sminshall } else { 51731465Sminshall switch (doassociate()) { 51831465Sminshall case -1: 51931465Sminshall kill_connection(); 52031465Sminshall return -1; 52131465Sminshall case 0: 52231465Sminshall break; 52331465Sminshall case 1: 52431465Sminshall state = CONNECTED; 52531465Sminshall } 52631457Sminshall } 52731457Sminshall } 52831457Sminshall break; 52931457Sminshall case CONNECTED: 53031492Sminshall switch (i = api_exch_nextcommand()) { 53131492Sminshall case EXCH_CMD_REQUEST: 53231492Sminshall if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, 53331492Sminshall (char *)&inputRegs) == -1) { 53431463Sminshall kill_connection(); 53531492Sminshall } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, 53631492Sminshall (char *)&inputSregs) == -1) { 53731463Sminshall kill_connection(); 53831492Sminshall } else if (nextstore() == -1) { 53931463Sminshall kill_connection(); 54031492Sminshall } else { 54131492Sminshall handle_api(&inputRegs, &inputSregs); 54231492Sminshall freestorage(); /* Send any storage back */ 54331492Sminshall if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { 54431492Sminshall kill_connection(); 54531492Sminshall } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, 54631492Sminshall (char *)&inputRegs) == -1) { 54731492Sminshall kill_connection(); 54831492Sminshall } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, 54931492Sminshall (char *)&inputSregs) == -1) { 55031492Sminshall kill_connection(); 55131492Sminshall } 55231492Sminshall /* Done, and it all worked! */ 55331463Sminshall } 55431492Sminshall break; 55531492Sminshall case EXCH_CMD_DISASSOCIATE: 55631492Sminshall kill_connection(); 55731492Sminshall break; 55831492Sminshall default: 55931503Sminshall if (i != -1) { 56031503Sminshall fprintf(stderr, 56131503Sminshall "Looking for a REQUEST or DISASSOCIATE command\n"); 56231503Sminshall fprintf(stderr, "\treceived 0x%02x.\n", i); 56331503Sminshall } 56431492Sminshall kill_connection(); 56531503Sminshall break; 56631457Sminshall } 56731457Sminshall } 56831455Sminshall return shell_active; 56931455Sminshall } 57031455Sminshall 57131455Sminshall 572*47031Sdonn static void 573*47031Sdonn child_died(code) 57431463Sminshall { 57535423Sminshall union wait status; 57631463Sminshall register int pid; 57731463Sminshall 578*47031Sdonn while ((pid = wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) { 57931463Sminshall if (pid == shell_pid) { 58031463Sminshall char inputbuffer[100]; 58135423Sminshall extern void setconnmode(); 58235423Sminshall extern void ConnectScreen(); 58331463Sminshall 58431463Sminshall shell_active = 0; 58531463Sminshall if (sock != -1) { 58631463Sminshall (void) close(sock); 58731463Sminshall sock = -1; 58831463Sminshall } 58931471Sminshall printf("[Hit return to continue]"); 59031471Sminshall fflush(stdout); 59131471Sminshall (void) gets(inputbuffer); 59231465Sminshall setconnmode(); 59331465Sminshall ConnectScreen(); /* Turn screen on (if need be) */ 59431465Sminshall (void) close(serversock); 59531798Sminshall (void) unlink(keyname); 59631463Sminshall } 59731463Sminshall } 59831463Sminshall signal(SIGCHLD, child_died); 59931463Sminshall } 60031463Sminshall 60131463Sminshall 60231455Sminshall /* 60331455Sminshall * Called from telnet.c to fork a lower command.com. We 60431455Sminshall * use the spint... routines so that we can pick up 60531455Sminshall * interrupts generated by application programs. 60631455Sminshall */ 60731455Sminshall 60831455Sminshall 60931455Sminshall int 61031455Sminshall shell(argc,argv) 61131455Sminshall int argc; 61231455Sminshall char *argv[]; 61331455Sminshall { 61431465Sminshall int length; 61531457Sminshall struct sockaddr_in server; 61631457Sminshall char sockNAME[100]; 61731457Sminshall static char **whereAPI = 0; 61831798Sminshall int fd; 61931798Sminshall struct timeval tv; 62031798Sminshall long ikey; 62131798Sminshall extern long random(); 62231798Sminshall extern char *mktemp(); 62335423Sminshall extern char *strcpy(); 62431457Sminshall 62531798Sminshall /* First, create verification file. */ 62631798Sminshall do { 627*47031Sdonn keyname = mktemp(strdup("/tmp/apiXXXXXX")); 62831798Sminshall fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); 62931798Sminshall } while ((fd == -1) && (errno == EEXIST)); 63031798Sminshall 63131798Sminshall if (fd == -1) { 63231798Sminshall perror("open"); 63331798Sminshall return 0; 63431798Sminshall } 63531798Sminshall 63631798Sminshall /* Now, get seed for random */ 63731798Sminshall 63835423Sminshall if (gettimeofday(&tv, (struct timezone *)0) == -1) { 63931798Sminshall perror("gettimeofday"); 64031798Sminshall return 0; 64131798Sminshall } 64231798Sminshall srandom(tv.tv_usec); /* seed random number generator */ 64331798Sminshall do { 64431798Sminshall ikey = random(); 64531798Sminshall } while (ikey == 0); 64635423Sminshall sprintf(key, "%lu\n", (unsigned long) ikey); 64731798Sminshall if (write(fd, key, strlen(key)) != strlen(key)) { 64831798Sminshall perror("write"); 64931798Sminshall return 0; 65031798Sminshall } 65131798Sminshall key[strlen(key)-1] = 0; /* Get rid of newline */ 65231798Sminshall 65331798Sminshall if (close(fd) == -1) { 65431798Sminshall perror("close"); 65531798Sminshall return 0; 65631798Sminshall } 65731798Sminshall 65831798Sminshall /* Next, create the socket which will be connected to */ 65931457Sminshall serversock = socket(AF_INET, SOCK_STREAM, 0); 66031457Sminshall if (serversock < 0) { 66131457Sminshall perror("opening API socket"); 66231457Sminshall return 0; 66331457Sminshall } 66431457Sminshall server.sin_family = AF_INET; 66531457Sminshall server.sin_addr.s_addr = INADDR_ANY; 66631457Sminshall server.sin_port = 0; 66735423Sminshall if (bind(serversock, (struct sockaddr *)&server, sizeof server) < 0) { 66831457Sminshall perror("binding API socket"); 66931457Sminshall return 0; 67031457Sminshall } 67131457Sminshall length = sizeof server; 67235423Sminshall if (getsockname(serversock, (struct sockaddr *)&server, &length) < 0) { 67331457Sminshall perror("getting API socket name"); 67431457Sminshall (void) close(serversock); 67531457Sminshall } 67631457Sminshall listen(serversock, 1); 67731457Sminshall /* Get name to advertise in address list */ 67831457Sminshall strcpy(sockNAME, "API3270="); 67931457Sminshall gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); 68031798Sminshall if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { 68131457Sminshall fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); 68231457Sminshall strcpy(sockNAME, "localhost"); 68331457Sminshall } 68435423Sminshall sprintf(sockNAME+strlen(sockNAME), ":%u", ntohs(server.sin_port)); 68531798Sminshall sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); 68631457Sminshall 68731457Sminshall if (whereAPI == 0) { 68831457Sminshall char **ptr, **nextenv; 68931457Sminshall extern char **environ; 69031457Sminshall 69131457Sminshall ptr = environ; 69231457Sminshall nextenv = ourENVlist; 69331457Sminshall while (*ptr) { 69431457Sminshall if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { 69531457Sminshall fprintf(stderr, "Too many environmental variables\n"); 69631457Sminshall break; 69731457Sminshall } 69831457Sminshall *nextenv++ = *ptr++; 69931457Sminshall } 70031457Sminshall whereAPI = nextenv++; 70131457Sminshall *nextenv++ = 0; 70231457Sminshall environ = ourENVlist; /* New environment */ 70331457Sminshall } 70431457Sminshall *whereAPI = sockNAME; 70531457Sminshall 70631457Sminshall child_died(); /* Start up signal handler */ 70731457Sminshall shell_active = 1; /* We are running down below */ 70831457Sminshall if (shell_pid = vfork()) { 70931457Sminshall if (shell_pid == -1) { 71031457Sminshall perror("vfork"); 71131457Sminshall (void) close(serversock); 71231457Sminshall } else { 71331465Sminshall state = UNCONNECTED; 71431457Sminshall } 71531455Sminshall } else { /* New process */ 71631455Sminshall register int i; 71731455Sminshall 71831455Sminshall for (i = 3; i < 30; i++) { 71931455Sminshall (void) close(i); 72031455Sminshall } 72131455Sminshall if (argc == 1) { /* Just get a shell */ 72231455Sminshall char *cmdname; 72331457Sminshall extern char *getenv(); 72431455Sminshall 72531455Sminshall cmdname = getenv("SHELL"); 72631455Sminshall execlp(cmdname, cmdname, 0); 72731455Sminshall perror("Exec'ing new shell...\n"); 72831455Sminshall exit(1); 72931455Sminshall } else { 73031455Sminshall execvp(argv[1], &argv[1]); 73131455Sminshall perror("Exec'ing command.\n"); 73231455Sminshall exit(1); 73331455Sminshall } 73431455Sminshall /*NOTREACHED*/ 73531455Sminshall } 73631457Sminshall return shell_active; /* Go back to main loop */ 73731455Sminshall } 738