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