xref: /original-bsd/usr.bin/tn3270/api/api_bsd.c (revision a9c19d04)
1 /*
2  *	Copyright (c) 1984-1987 by the Regents of the
3  *	University of California and by Gregory Glenn Minshall.
4  *
5  *	Permission to use, copy, modify, and distribute these
6  *	programs and their documentation for any purpose and
7  *	without fee is hereby granted, provided that this
8  *	copyright and permission appear on all copies and
9  *	supporting documentation, the name of the Regents of
10  *	the University of California not be used in advertising
11  *	or publicity pertaining to distribution of the programs
12  *	without specific prior permission, and notice be given in
13  *	supporting documentation that copying and distribution is
14  *	by permission of the Regents of the University of California
15  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16  *	University of California nor Gregory Glenn Minshall make
17  *	representations about the suitability of this software
18  *	for any purpose.  It is provided "as is" without
19  *	express or implied warranty.
20  */
21 
22 #ifndef lint
23 static char sccsid[] = "@(#)api_bsd.c	3.1 (Berkeley) 08/11/87";
24 #endif	/* not lint */
25 
26 #if	defined(unix)
27 
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <netdb.h>
32 #include <stdio.h>
33 
34 #include "../ctlr/api.h"
35 #include "api_exch.h"
36 
37 
38 int
39 api_close_api()
40 {
41     if (api_exch_outcommand(EXCH_CMD_DISASSOCIATE) == -1) {
42 	return -1;
43     } else if (api_exch_flush() == -1) {
44 	return -1;
45     } else {
46 	return 0;
47     }
48 }
49 
50 
51 int
52 api_open_api(string)
53 char	*string;		/* if non-zero, where to connect to */
54 {
55     struct sockaddr_in server;
56     struct hostent *hp;
57     struct storage_descriptor sd;
58     char *getenv();
59     char thehostname[100];
60     char keyname[100];
61     char inkey[100];
62     FILE *keyfile;
63     int sock;
64     int port;
65     int i;
66 
67     if (string == 0) {
68 	string = getenv("API3270");	/* Get API */
69 	if (string == 0) {
70 	    fprintf(stderr,
71 			"API3270 environmental variable not set - no API.\n");
72 	    return -1;			/* Nothing */
73 	}
74     }
75 
76     if (sscanf(string, "%[^:]:%d:%s", thehostname, &port, keyname) != 3) {
77 	fprintf(stderr, "API3270 environmental variable has bad format.\n");
78 	return -1;
79     }
80     /* Now, try to connect */
81     sock = socket(AF_INET, SOCK_STREAM, 0);
82     if (sock < 0) {
83 	perror("opening API socket");
84 	return -1;
85     }
86     server.sin_family = AF_INET;
87     hp = gethostbyname(thehostname);
88     if (hp == 0) {
89 	fprintf(stderr, "%s specifies bad host name.\n", string);
90 	return -1;
91     }
92     bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
93     server.sin_port = htons(port);
94 
95     if (connect(sock, &server, sizeof server) < 0) {
96 	perror("connecting to API server");
97 	return -1;
98     }
99     /* Now, try application level connection */
100     if (api_exch_init(sock, "client") == -1) {
101 	return -1;
102     }
103     if (api_exch_outcommand(EXCH_CMD_ASSOCIATE) == -1) {
104 	return -1;
105     }
106     keyfile = fopen(keyname, "r");
107     if (keyfile == 0) {
108 	perror("fopen");
109 	return -1;
110     }
111     if (fscanf(keyfile, "%s\n", inkey) != 1) {
112 	perror("fscanf");
113 	return -1;
114     }
115     sd.length = strlen(inkey)+1;
116     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
117 	return -1;
118     }
119     if (api_exch_outtype(EXCH_TYPE_BYTES, sd.length, inkey) == -1) {
120 	return -1;
121     }
122     while ((i = api_exch_nextcommand()) != EXCH_CMD_ASSOCIATED) {
123 	int passwd_length;
124 	char *passwd, *getpass();
125 	char buffer[200];
126 
127 	switch (i) {
128 	case EXCH_CMD_REJECTED:
129 	    if (api_exch_intype(EXCH_TYPE_STORE_DESC,
130 					sizeof sd, (char *)&sd) == -1) {
131 		return -1;
132 	    }
133 	    if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
134 		return -1;
135 	    }
136 	    buffer[sd.length] = 0;
137 	    fprintf(stderr, "%s\n", buffer);
138 	    if (api_exch_outcommand(EXCH_CMD_ASSOCIATE) == -1) {
139 		return -1;
140 	    }
141 	    break;
142 	case EXCH_CMD_SEND_AUTH:
143 	    if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
144 		return -1;
145 	    }
146 	    if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
147 		return -1;
148 	    }
149 	    buffer[sd.length] = 0;
150 	    passwd = getpass(buffer);		/* Go to terminal */
151 	    passwd_length = strlen(passwd);
152 	    if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
153 		return -1;
154 	    }
155 	    if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
156 		return -1;
157 	    }
158 	    buffer[sd.length] = 0;
159 	    if (sd.length) {
160 		char *ptr;
161 
162 		ptr = passwd;
163 		i = 0;
164 		while (*ptr) {
165 		    *ptr++ ^= buffer[i++];
166 		    if (i >= sd.length) {
167 			i = 0;
168 		    }
169 		}
170 	    }
171 	    sd.length = passwd_length;
172 	    if (api_exch_outcommand(EXCH_CMD_AUTH) == -1) {
173 		return -1;
174 	    }
175 	    if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
176 		return -1;
177 	    }
178 	    if (api_exch_outtype(EXCH_TYPE_BYTES, passwd_length, passwd) == -1) {
179 		return -1;
180 	    }
181 	    break;
182 	case -1:
183 	    return -1;
184 	default:
185 	    fprintf(stderr,
186 		    "Waiting for connection indicator, received 0x%x.\n", i);
187 	    break;
188 	}
189     }
190     /* YEAH */
191     return 0;		/* Happiness! */
192 }
193 
194 
195 api_exch_api(regs, sregs, parms, length)
196 union REGS *regs;
197 struct SREGS *sregs;
198 char *parms;
199 int length;
200 {
201     struct storage_descriptor sd;
202     int i;
203 
204     if (api_exch_outcommand(EXCH_CMD_REQUEST) == -1) {
205 	return -1;
206     }
207     if (api_exch_outtype(EXCH_TYPE_REGS, sizeof *regs, (char *)regs) == -1) {
208 	return -1;
209     }
210     if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof *sregs, (char *)sregs) == -1) {
211 	return -1;
212     }
213     sd.length = length;
214     sd.location = (long) parms;
215     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
216 	return -1;
217     }
218     if (api_exch_outtype(EXCH_TYPE_BYTES, length, parms) == -1) {
219 	return -1;
220     }
221     while ((i = api_exch_nextcommand()) != EXCH_CMD_REPLY) {
222 	switch (i) {
223 	case EXCH_CMD_GIMME:
224 	    if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
225 					== -1) {
226 		return -1;
227 	    }
228 	    /*XXX validity check GIMME? */
229 	    if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
230 		return -1;
231 	    }
232 	    if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
233 				== -1) {
234 		return -1;
235 	    }
236 	    if (api_exch_outtype(EXCH_TYPE_BYTES, sd.length,
237 			    sd.location) == -1) {
238 		return -1;
239 	    }
240 	    break;
241 	case EXCH_CMD_HEREIS:
242 	    if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
243 					== -1) {
244 		return -1;
245 	    }
246 	    /* XXX Validty check HEREIS? */
247 	    if (api_exch_intype(EXCH_TYPE_BYTES, sd.length,
248 			    sd.location) == -1) {
249 		return -1;
250 	    }
251 	    break;
252 	default:
253 	    fprintf(stderr, "Waiting for reply command, we got command %d.\n",
254 			i);
255 	    return -1;
256 	}
257     }
258     if (api_exch_intype(EXCH_TYPE_REGS, sizeof *regs, (char *)regs) == -1) {
259 	return -1;
260     }
261     if (api_exch_intype(EXCH_TYPE_SREGS, sizeof *sregs, (char *)sregs) == -1) {
262 	return -1;
263     }
264     /* YEAH */
265     return 0;		/* Happiness! */
266 }
267 
268 #endif	/* unix */
269