Annotation of OpenXM/src/ox_toolkit/oxf.c, Revision 1.11
1.1 ohara 1: /* -*- mode: C; coding: euc-japan -*- */
1.11 ! ohara 2: /* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.10 2000/12/14 01:41:03 ohara Exp $ */
1.1 ohara 3:
4: /*
5: This module includes functions for sending/receiveng CMO's.
1.9 ohara 6: Some commnets are written in Japanese by the EUC-JP coded
1.1 ohara 7: character set.
8: */
9:
10: #include <stdio.h>
11: #include <stdlib.h>
12: #include <string.h>
13: #include <unistd.h>
14: #include <fcntl.h>
15: #include <sys/file.h>
16: #include <sys/param.h>
17: #include <time.h>
18:
19: #include "mysocket.h"
20: #include "ox_toolkit.h"
21:
1.6 ohara 22: static mathcap *oxf_mathcap(OXFILE *oxfp);
23:
1.4 ohara 24: static int send_int32_lbo(OXFILE *oxfp, int int32);
25: static int send_int32_nbo(OXFILE *oxfp, int int32);
26: static int receive_int32_lbo(OXFILE *oxfp);
27: static int receive_int32_nbo(OXFILE *oxfp);
28:
1.2 ohara 29: int oxf_read(void *buffer, size_t size, size_t num, OXFILE *oxfp)
30: {
1.5 ohara 31: int n = read(oxfp->fd, buffer, size*num);
32: if (n <= 0) {
33: oxfp->error = 1;
34: }
1.2 ohara 35: return n;
36: }
37:
38: int oxf_write(void *buffer, size_t size, size_t num, OXFILE *oxfp)
39: {
40: return write(oxfp->fd, buffer, size*num);
41: }
42:
1.4 ohara 43: /* sending an object of int32 type with Network Byte Order.
44: (not equal to cmo_int32 type) */
45: static int send_int32_nbo(OXFILE *oxfp, int int32)
46: {
47: int32 = htonl(int32);
48: return oxf_write(&int32, sizeof(int), 1, oxfp);
49: }
50:
51: /* sending an object of int32 type with Local Byte Order.
52: (not equal to cmo_int32 type) */
53: static int send_int32_lbo(OXFILE *oxfp, int int32)
54: {
55: return oxf_write(&int32, sizeof(int), 1, oxfp);
56: }
57:
58: /* receiving an object of int32 type with Network Byte Order.
59: (not equal to cmo_int32 type) */
60: static int receive_int32_nbo(OXFILE *oxfp)
61: {
62: int tag;
63: oxf_read(&tag, sizeof(int), 1, oxfp);
64: return ntohl(tag);
65: }
66:
67: /* receiving an object of int32 type with Local Byte Order.
68: (not equal to cmo_int32 type) */
69: static int receive_int32_lbo(OXFILE *oxfp)
70: {
71: int tag;
72: oxf_read(&tag, sizeof(int), 1, oxfp);
73: return tag;
74: }
75:
1.9 ohara 76: /* (1) getting the fd by socket(2).
77: (2) preparing a buffer by fdopen(fd, "a+"). (not "w+")
78: (3) determing the byte order of the OX connection.
79: (4) setting function pointers by oxf_setopt().
80: */
1.1 ohara 81: OXFILE *oxf_open(int fd)
82: {
83: OXFILE *oxfp = (OXFILE *)malloc(sizeof(OXFILE));
1.11 ! ohara 84: oxfp = (OXFILE *)malloc(sizeof(OXFILE));
1.1 ohara 85: oxfp->fd = fd;
86: oxfp->send_int32 = send_int32_nbo;
87: oxfp->receive_int32 = receive_int32_nbo;
1.7 ohara 88: oxfp->serial_number = 0;
1.5 ohara 89: oxfp->control = NULL;
90: oxfp->error = 0;
91: oxfp->mathcap = NULL;
1.1 ohara 92: return oxfp;
93: /* oxfp->fp = fdopen(fd, "a+"); */
94: /* return (oxfp->fp != NULL)? oxfp: NULL; */
1.7 ohara 95: }
96:
97: int oxf_fileno(OXFILE *oxfp)
98: {
99: return oxfp->fd;
1.1 ohara 100: }
101:
102: OXFILE *oxf_control(OXFILE *oxfp)
103: {
1.5 ohara 104: return oxfp->control;
1.1 ohara 105: }
106:
107: /* The function determines a byte order of integer on the OpenXM
108: connection `oxfp'. */
109: /* REMARKS:
110: we request the byte order of macine integer on a local machine by
111: (*(char *)&offer). The fact depends on OX_BYTE_LITTLE_ENDIAN==1. */
112: void oxf_determine_byteorder_client(OXFILE *oxfp)
113: {
114: int offer = OX_BYTE_LITTLE_ENDIAN;
115: char receiv;
116: int mode;
117:
118: oxf_read(&receiv, 1, 1, oxfp);
119: oxf_write(&offer, 1, 1, oxfp);
120: mode = (receiv == *(char *)&offer);
121: oxf_setopt(oxfp, mode);
122: }
123:
1.9 ohara 124: /* If the program is an OX server, then you must use this function. */
1.1 ohara 125: void oxf_determine_byteorder_server(OXFILE *oxfp)
126: {
127: int offer = OX_BYTE_LITTLE_ENDIAN;
128: char receiv;
129: int mode;
130:
131: oxf_write(&offer, 1, 1, oxfp);
132: oxf_read(&receiv, 1, 1, oxfp);
133: mode = (receiv == *(char *)&offer);
134: oxf_setopt(oxfp, mode);
135: }
136:
137: void oxf_flush(OXFILE *oxfp)
138: {
139: /* fflush(oxfp->fp); */
140: }
141:
142: void oxf_close(OXFILE *oxfp)
143: {
144: close(oxfp->fd);
145: /* fclose(oxfp->fp); */
146: }
147:
148: #define OXF_SETOPT_NBO 0
149: #define OXF_SETOPT_LBO 1
150:
151: void oxf_setopt(OXFILE *oxfp, int mode)
152: {
153: if (mode == OXF_SETOPT_LBO) {
154: oxfp->send_int32 = send_int32_lbo;
155: oxfp->receive_int32 = receive_int32_lbo;
156: }else if (mode == OXF_SETOPT_NBO) {
157: oxfp->send_int32 = send_int32_nbo;
158: oxfp->receive_int32 = receive_int32_nbo;
159: }
160: }
161:
1.4 ohara 162: int oxf_listen(short *portp)
163: {
164: char localhost[MAXHOSTNAMELEN];
165: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
1.5 ohara 166: return mysocketListen(localhost, portp);
167: }
168: return -1;
1.4 ohara 169: }
170:
1.1 ohara 171: OXFILE *oxf_connect_active(char *hostname, short port)
172: {
173: int fd = mysocketOpen(hostname, port);
1.11 ! ohara 174: return (fd < 0)? NULL: oxf_open(fd);
1.1 ohara 175: }
176:
177: OXFILE *oxf_connect_passive(int listened)
178: {
179: int fd = mysocketAccept(listened);
1.11 ! ohara 180: return (fd < 0)? NULL: oxf_open(fd);
1.1 ohara 181: }
182:
183: #define LENGTH_OF_ONETIME_PASSWORD 64
184:
185: /* a password generator. */
186: char *generate_otp()
187: {
1.5 ohara 188: static char crypto[] = "%.,^_+-=/@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1.1 ohara 189: static char otp[LENGTH_OF_ONETIME_PASSWORD+1] = {0};
190: int i;
191:
192: srandom(time(NULL));
193: for(i=0; i<LENGTH_OF_ONETIME_PASSWORD; i++) {
194: otp[i] = crypto[random() % (sizeof(crypto)-1)];
195: }
196: return otp;
197: }
198:
199: /* proceeding a one time password. */
200: /* if the password is right,
201: then the function returns 1, if otherwise, then 0. */
202: int oxf_confirm_client(OXFILE *oxfp, char *passwd)
203: {
204: int len = strlen(passwd)+1;
205: char *buf = alloca(len);
206:
207: oxf_read(buf, 1, len, oxfp);
208: return !strcmp(passwd, buf);
209: }
210:
211: int oxf_confirm_server(OXFILE *oxfp, char *passwd)
212: {
213: return oxf_write(passwd, 1, strlen(passwd)+1, oxfp);
214: }
215:
1.6 ohara 216: __inline__
217: static mathcap *oxf_mathcap(OXFILE *oxfp)
1.5 ohara 218: {
219: if (oxfp->mathcap == NULL) {
220: oxfp->mathcap = new_mathcap();
221: }
1.6 ohara 222: return oxfp->mathcap;
223: }
224:
225: cmo_mathcap *oxf_cmo_mathcap(OXFILE *oxfp)
226: {
227: return mathcap_get(oxf_mathcap(oxfp));
228: }
229:
230: void oxf_mathcap_update(OXFILE *oxfp, cmo_mathcap *ob)
231: {
232: mathcap_update(oxf_mathcap(oxfp), ob);
1.5 ohara 233: }
234:
1.1 ohara 235: /* example: which("xterm", getenv("PATH")); */
236: char *which(char *exe, const char *env)
237: {
238: char *tok;
239: char *path;
240: char delim[] = ":";
241: char *e = alloca(strlen(env)+1);
242: strcpy(e, env);
243: tok = strtok(e, delim);
244: while (tok != NULL) {
245: path = malloc(strlen(tok)+strlen(exe)+2);
246: sprintf(path, "%s/%s", tok, exe);
247: if (access(path, X_OK&R_OK) == 0) {
248: return path;
249: }
250: free(path);
251: tok = strtok(NULL, delim);
252: }
253: return NULL;
254: }
255:
256: /* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */
257: int oxc_start(char *remote_host, short port, char *passwd)
258: {
259: char localhost[MAXHOSTNAMELEN];
260: char ports[128];
261: int pid = 0;
1.2 ohara 262: char *cmd = "oxc";
1.1 ohara 263:
264: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
265: if ((pid = fork()) == 0) {
266: sprintf(ports, "%d", port);
267: #ifdef DEBUG
268: fprintf(stderr, "oxf.c:: oxc_start() does %s(ssh) -f %s -h %s -p %s -c %s\n", remote_host, cmd, localhost, ports, passwd);
269: #endif
270: execlp("ssh", remote_host, "-f", cmd,
271: "-h", localhost, "-p", ports,"-c", passwd, NULL);
272: }
273: }
274: return pid;
1.8 ohara 275: }
276:
277: /* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */
278: int oxc_start_with_pipe(char *remote_host, int port, char *passwd)
279: {
280: char localhost[MAXHOSTNAMELEN];
281: char ports[128];
282: int pid = 0;
283: char *cmd = "oxc";
284: int pipefd[2];
285:
286: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
287: if (pipe(pipefd) < 0) {
288: return -1;
289: }
290: if ((pid = fork()) == 0) {
291: dup2(pipefd[1], 0);
292: close(pipefd[0]);
293: close(pipefd[1]);
294: execlp("ssh", remote_host, cmd, NULL);
295: exit(1);
296: }
297: close(pipefd[1]);
298: pipe_send_info(pipefd[0], localhost, port, passwd);
299: }
300: return pid;
301: }
302:
303: static void pipe_send_string(int fd, char *s)
304: {
1.9 ohara 305: int len = strlen(s);
1.8 ohara 306: int lenN = htonl(len);
307: write(fd, &lenN, sizeof(int));
1.9 ohara 308: write(fd, s, len+1);
1.8 ohara 309: }
310:
311: static char *pipe_read_string()
312: {
313: int len;
314: char *s;
315: read(0, &len, sizeof(int));
1.9 ohara 316: len = ntohl(len)+1;
1.8 ohara 317: s = malloc(len);
318: read(0, s, len);
319: return s;
320: }
321:
1.9 ohara 322: /* The data format used by pipe_send_info() is defined in OX-RFC-101. */
1.8 ohara 323: void pipe_send_info(int fd, char *hostname, int port, char *password)
324: {
325: port = htonl(port);
326: write(fd, &port, sizeof(int));
327: pipe_send_string(fd, hostname);
328: pipe_send_string(fd, password);
329: }
330:
331: void pipe_read_info(char **hostname, int *port, char **password)
332: {
333: if (read(0, port, sizeof(int)) > 0) {
334: *port = ntohl(*port);
335: *hostname = pipe_read_string();
336: *password = pipe_read_string();
337: return 0;
338: }
339: return -1;
1.4 ohara 340: }
341:
342: /* Example: oxf_execute_cmd(oxfp, "ox_sm1"); */
343: OXFILE *oxf_execute_cmd(OXFILE *oxfp, char *cmd)
344: {
1.5 ohara 345: short port = 0;
346: int listened;
1.4 ohara 347:
1.5 ohara 348: if ((listened = oxf_listen(&port)) != -1) {
1.10 ohara 349: cmo_list *args = list_appendl(NULL, list_append(new_cmo_list(), new_cmo_int32(port)), new_cmo_string(cmd), NULL);
350: send_ox_cmo(oxfp, (cmo *)args);
351: send_ox_command(oxfp, SM_control_spawn_server);
1.5 ohara 352: return oxf_connect_passive(listened);
353: }
354: return NULL;
1.1 ohara 355: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>