148761Sbostic /*-
2*62368Sbostic * Copyright (c) 1988, 1993
3*62368Sbostic * The Regents of the University of California. All rights reserved.
431894Sminshall *
548761Sbostic * %sccs.include.redist.c%
631894Sminshall */
731894Sminshall
831894Sminshall #ifndef lint
9*62368Sbostic static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 06/06/93";
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
kill_connection()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
nextstore()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
doreject(message)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
doassociate()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
freestorage()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
getstorage(address,length,copyin)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
movetous(local,es,di,length)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
movetothem(es,di,local,length)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 *
access_api(location,length,copyin)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
unaccess_api(location,local,length,copyout)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
doconnect()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
shell_continue()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
child_died(code)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
shell(argc,argv)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