Annotation of OpenXM/src/ox_toolkit/oxf.c, Revision 1.19
1.1 ohara 1: /* -*- mode: C; coding: euc-japan -*- */
1.19 ! ohara 2: /* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.18 2003/09/15 09:31:42 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>
1.19 ! ohara 18: #include <limits.h>
1.12 ohara 19:
20: #if defined(__sun__)
21: #include <netdb.h>
22: #include <sys/types.h>
23: #include <netinet/in.h>
24: #endif
1.1 ohara 25:
1.19 ! ohara 26: #if defined(__sun__)
! 27: #include <synch.h>
! 28: #else
! 29: #include <inttypes.h>
! 30: #endif
! 31:
1.1 ohara 32: #include "mysocket.h"
33: #include "ox_toolkit.h"
34:
1.6 ohara 35: static mathcap *oxf_mathcap(OXFILE *oxfp);
36:
1.4 ohara 37: static int send_int32_lbo(OXFILE *oxfp, int int32);
38: static int send_int32_nbo(OXFILE *oxfp, int int32);
39: static int receive_int32_lbo(OXFILE *oxfp);
40: static int receive_int32_nbo(OXFILE *oxfp);
41:
1.19 ! ohara 42: static int send_int64_nbo_le(OXFILE *oxfp, double int64);
! 43: static int send_int64_lbo(OXFILE *oxfp, double int64);
! 44: static int receive_int64_nbo_le(OXFILE *oxfp);
! 45: static int receive_int64_lbo(OXFILE *oxfp);
! 46:
1.18 ohara 47: static void pipe_send_info(int fd, char *hostname, int port, char *password);
48:
1.19 ! ohara 49: /* translating double of little endian byte order to one of big endian. */
! 50: double htonll_le(double n)
! 51: {
! 52: int i;
! 53: double r;
! 54: char *sp = (char *)&n, *dp = (char *)&r + sizeof(double)-1;
! 55: for(i=0; i<sizeof(double); i++) {
! 56: *dp-- = *sp++;
! 57: }
! 58: return r;
! 59: }
! 60:
1.16 ohara 61: /* enable write buffering */
62: int oxf_setbuffer(OXFILE *oxfp, char *buf, int size)
63: {
64: if (buf == NULL && size > 0) {
1.17 ohara 65: buf = MALLOC(size);
1.16 ohara 66: }
67: if (oxfp->wbuf != NULL) {
68: oxf_flush(oxfp);
69: }
70: oxfp->wbuf = buf;
71: oxfp->wbuf_size = size;
72: oxfp->wbuf_count = 0;
1.18 ohara 73: return 0;
1.16 ohara 74: }
75:
1.2 ohara 76: int oxf_read(void *buffer, size_t size, size_t num, OXFILE *oxfp)
77: {
1.5 ohara 78: int n = read(oxfp->fd, buffer, size*num);
79: if (n <= 0) {
80: oxfp->error = 1;
81: }
1.2 ohara 82: return n;
83: }
84:
85: int oxf_write(void *buffer, size_t size, size_t num, OXFILE *oxfp)
86: {
1.16 ohara 87: size_t sz = size*num;
88: if (oxfp->wbuf == NULL) { /* no buffering */
89: return write(oxfp->fd, buffer, sz);
90: }
91: if ((oxfp->wbuf_count + sz) >= oxfp->wbuf_size) {
92: oxf_flush(oxfp);
93: return write(oxfp->fd, buffer, sz);
94: }
95: memcpy(oxfp->wbuf + oxfp->wbuf_count, buffer, sz);
96: oxfp->wbuf_count += sz;
97: return sz;
1.2 ohara 98: }
99:
1.19 ! ohara 100: /* sending an object of int64 type with Network Byte Order. */
! 101: static int send_int64_nbo_le(OXFILE *oxfp, double int64)
! 102: {
! 103: int64 = htonll_le(int64);
! 104: return oxf_write(&int64, sizeof(double), 1, oxfp);
! 105: }
! 106:
! 107: /* sending an object of int64 type with Local Byte Order. */
! 108: static int send_int64_lbo(OXFILE *oxfp, double int64)
! 109: {
! 110: return oxf_write(&int64, sizeof(double), 1, oxfp);
! 111: }
! 112:
! 113: /* receiving an object of int64 type with Network Byte Order. */
! 114: static int receive_int64_nbo_le(OXFILE *oxfp)
! 115: {
! 116: int tag;
! 117: oxf_read(&tag, sizeof(double), 1, oxfp);
! 118: return htonll_le(tag);
! 119: }
! 120:
! 121: /* receiving an object of int64 type with Local Byte Order. */
! 122: static int receive_int64_lbo(OXFILE *oxfp)
! 123: {
! 124: int tag;
! 125: oxf_read(&tag, sizeof(double), 1, oxfp);
! 126: return tag;
! 127: }
! 128:
1.4 ohara 129: /* sending an object of int32 type with Network Byte Order.
130: (not equal to cmo_int32 type) */
131: static int send_int32_nbo(OXFILE *oxfp, int int32)
132: {
133: int32 = htonl(int32);
134: return oxf_write(&int32, sizeof(int), 1, oxfp);
135: }
136:
137: /* sending an object of int32 type with Local Byte Order.
138: (not equal to cmo_int32 type) */
139: static int send_int32_lbo(OXFILE *oxfp, int int32)
140: {
141: return oxf_write(&int32, sizeof(int), 1, oxfp);
142: }
143:
144: /* receiving an object of int32 type with Network Byte Order.
145: (not equal to cmo_int32 type) */
146: static int receive_int32_nbo(OXFILE *oxfp)
147: {
148: int tag;
149: oxf_read(&tag, sizeof(int), 1, oxfp);
150: return ntohl(tag);
151: }
152:
153: /* receiving an object of int32 type with Local Byte Order.
154: (not equal to cmo_int32 type) */
155: static int receive_int32_lbo(OXFILE *oxfp)
156: {
157: int tag;
158: oxf_read(&tag, sizeof(int), 1, oxfp);
159: return tag;
160: }
161:
1.9 ohara 162: /* (1) getting the fd by socket(2).
163: (2) preparing a buffer by fdopen(fd, "a+"). (not "w+")
164: (3) determing the byte order of the OX connection.
165: (4) setting function pointers by oxf_setopt().
166: */
1.1 ohara 167: OXFILE *oxf_open(int fd)
168: {
1.17 ohara 169: OXFILE *oxfp = (OXFILE *)MALLOC(sizeof(OXFILE));
170: oxfp = (OXFILE *)MALLOC(sizeof(OXFILE));
1.1 ohara 171: oxfp->fd = fd;
172: oxfp->send_int32 = send_int32_nbo;
173: oxfp->receive_int32 = receive_int32_nbo;
1.7 ohara 174: oxfp->serial_number = 0;
1.5 ohara 175: oxfp->control = NULL;
176: oxfp->error = 0;
177: oxfp->mathcap = NULL;
1.16 ohara 178: oxfp->wbuf = NULL;
179: oxfp->wbuf_size = 0;
180: oxfp->wbuf_count = 0;
1.19 ! ohara 181: oxfp->send_double = send_int64_lbo;
! 182: oxfp->receive_double = receive_int64_lbo;
1.1 ohara 183: return oxfp;
184: /* oxfp->fp = fdopen(fd, "a+"); */
185: /* return (oxfp->fp != NULL)? oxfp: NULL; */
1.7 ohara 186: }
187:
188: int oxf_fileno(OXFILE *oxfp)
189: {
190: return oxfp->fd;
1.1 ohara 191: }
192:
193: OXFILE *oxf_control(OXFILE *oxfp)
194: {
1.5 ohara 195: return oxfp->control;
1.1 ohara 196: }
197:
198: /* The function determines a byte order of integer on the OpenXM
199: connection `oxfp'. */
200: /* REMARKS:
201: we request the byte order of macine integer on a local machine by
202: (*(char *)&offer). The fact depends on OX_BYTE_LITTLE_ENDIAN==1. */
203: void oxf_determine_byteorder_client(OXFILE *oxfp)
204: {
205: int offer = OX_BYTE_LITTLE_ENDIAN;
206: char receiv;
207: int mode;
208:
209: oxf_read(&receiv, 1, 1, oxfp);
210: oxf_write(&offer, 1, 1, oxfp);
211: mode = (receiv == *(char *)&offer);
212: oxf_setopt(oxfp, mode);
213: }
214:
1.9 ohara 215: /* If the program is an OX server, then you must use this function. */
1.1 ohara 216: void oxf_determine_byteorder_server(OXFILE *oxfp)
217: {
218: int offer = OX_BYTE_LITTLE_ENDIAN;
219: char receiv;
220: int mode;
221:
222: oxf_write(&offer, 1, 1, oxfp);
223: oxf_read(&receiv, 1, 1, oxfp);
224: mode = (receiv == *(char *)&offer);
225: oxf_setopt(oxfp, mode);
226: }
227:
228: void oxf_flush(OXFILE *oxfp)
229: {
1.16 ohara 230: if (oxfp->wbuf != NULL) {
231: write(oxfp->fd, oxfp->wbuf, oxfp->wbuf_count);
232: oxfp->wbuf_count = 0;
233: }
1.1 ohara 234: }
235:
236: void oxf_close(OXFILE *oxfp)
237: {
1.16 ohara 238: oxf_flush(oxfp);
1.1 ohara 239: close(oxfp->fd);
240: }
241:
242: #define OXF_SETOPT_NBO 0
243: #define OXF_SETOPT_LBO 1
244:
245: void oxf_setopt(OXFILE *oxfp, int mode)
246: {
1.19 ! ohara 247: int m = 1;
! 248: if (mode == OXF_SETOPT_NBO && *(char *)&m) {
! 249: /* Little endian architecture. */
! 250: oxfp->send_int32 = send_int32_nbo;
! 251: oxfp->receive_int32 = receive_int32_nbo;
! 252: oxfp->send_double = send_int64_nbo_le;
! 253: oxfp->receive_double = receive_int64_nbo_le;
! 254: }else {
! 255: oxfp->send_int32 = send_int32_lbo;
! 256: oxfp->receive_int32 = receive_int32_lbo;
! 257: oxfp->send_double = send_int64_lbo;
! 258: oxfp->receive_double = receive_int64_lbo;
1.1 ohara 259: }
260: }
261:
1.18 ohara 262: int oxf_listen(int *portp)
1.4 ohara 263: {
264: char localhost[MAXHOSTNAMELEN];
265: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
1.5 ohara 266: return mysocketListen(localhost, portp);
267: }
268: return -1;
1.4 ohara 269: }
270:
1.1 ohara 271: OXFILE *oxf_connect_active(char *hostname, short port)
272: {
273: int fd = mysocketOpen(hostname, port);
1.11 ohara 274: return (fd < 0)? NULL: oxf_open(fd);
1.1 ohara 275: }
276:
277: OXFILE *oxf_connect_passive(int listened)
278: {
279: int fd = mysocketAccept(listened);
1.11 ohara 280: return (fd < 0)? NULL: oxf_open(fd);
1.1 ohara 281: }
282:
283: #define LENGTH_OF_ONETIME_PASSWORD 64
284:
285: /* a password generator. */
286: char *generate_otp()
287: {
1.5 ohara 288: static char crypto[] = "%.,^_+-=/@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1.1 ohara 289: static char otp[LENGTH_OF_ONETIME_PASSWORD+1] = {0};
290: int i;
291:
292: srandom(time(NULL));
293: for(i=0; i<LENGTH_OF_ONETIME_PASSWORD; i++) {
294: otp[i] = crypto[random() % (sizeof(crypto)-1)];
295: }
296: return otp;
297: }
298:
299: /* proceeding a one time password. */
300: /* if the password is right,
301: then the function returns 1, if otherwise, then 0. */
302: int oxf_confirm_client(OXFILE *oxfp, char *passwd)
303: {
304: int len = strlen(passwd)+1;
1.17 ohara 305: char *buf = ALLOCA(len);
1.1 ohara 306:
307: oxf_read(buf, 1, len, oxfp);
308: return !strcmp(passwd, buf);
309: }
310:
311: int oxf_confirm_server(OXFILE *oxfp, char *passwd)
312: {
313: return oxf_write(passwd, 1, strlen(passwd)+1, oxfp);
314: }
315:
1.6 ohara 316: __inline__
317: static mathcap *oxf_mathcap(OXFILE *oxfp)
1.5 ohara 318: {
319: if (oxfp->mathcap == NULL) {
320: oxfp->mathcap = new_mathcap();
321: }
1.6 ohara 322: return oxfp->mathcap;
323: }
324:
325: cmo_mathcap *oxf_cmo_mathcap(OXFILE *oxfp)
326: {
327: return mathcap_get(oxf_mathcap(oxfp));
328: }
329:
330: void oxf_mathcap_update(OXFILE *oxfp, cmo_mathcap *ob)
331: {
332: mathcap_update(oxf_mathcap(oxfp), ob);
1.5 ohara 333: }
334:
1.1 ohara 335: /* example: which("xterm", getenv("PATH")); */
336: char *which(char *exe, const char *env)
337: {
338: char *tok;
339: char *path;
340: char delim[] = ":";
1.17 ohara 341: char *e = ALLOCA(strlen(env)+1);
1.1 ohara 342: strcpy(e, env);
343: tok = strtok(e, delim);
344: while (tok != NULL) {
1.17 ohara 345: path = MALLOC(strlen(tok)+strlen(exe)+2);
1.1 ohara 346: sprintf(path, "%s/%s", tok, exe);
347: if (access(path, X_OK&R_OK) == 0) {
348: return path;
349: }
1.17 ohara 350: FREE(path);
1.1 ohara 351: tok = strtok(NULL, delim);
352: }
353: return NULL;
354: }
355:
356: /* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */
1.18 ohara 357: int oxc_start(char *remote_host, int port, char *passwd)
1.1 ohara 358: {
359: char localhost[MAXHOSTNAMELEN];
360: char ports[128];
361: int pid = 0;
1.2 ohara 362: char *cmd = "oxc";
1.1 ohara 363:
364: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
365: if ((pid = fork()) == 0) {
366: sprintf(ports, "%d", port);
1.14 ohara 367: ox_printf("oxf.c:: oxc_start() does %s(ssh) -f %s -h %s -p %s -c %s\n", remote_host, cmd, localhost, ports, passwd);
1.1 ohara 368: execlp("ssh", remote_host, "-f", cmd,
369: "-h", localhost, "-p", ports,"-c", passwd, NULL);
370: }
371: }
372: return pid;
1.8 ohara 373: }
374:
375: /* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */
376: int oxc_start_with_pipe(char *remote_host, int port, char *passwd)
377: {
378: char localhost[MAXHOSTNAMELEN];
379: int pid = 0;
380: char *cmd = "oxc";
381: int pipefd[2];
382:
383: if (gethostname(localhost, MAXHOSTNAMELEN)==0) {
384: if (pipe(pipefd) < 0) {
385: return -1;
386: }
387: if ((pid = fork()) == 0) {
388: dup2(pipefd[1], 0);
389: close(pipefd[0]);
390: close(pipefd[1]);
391: execlp("ssh", remote_host, cmd, NULL);
392: exit(1);
393: }
394: close(pipefd[1]);
395: pipe_send_info(pipefd[0], localhost, port, passwd);
396: }
397: return pid;
398: }
399:
400: static void pipe_send_string(int fd, char *s)
401: {
1.9 ohara 402: int len = strlen(s);
1.8 ohara 403: int lenN = htonl(len);
404: write(fd, &lenN, sizeof(int));
1.9 ohara 405: write(fd, s, len+1);
1.8 ohara 406: }
407:
408: static char *pipe_read_string()
409: {
410: int len;
411: char *s;
412: read(0, &len, sizeof(int));
1.9 ohara 413: len = ntohl(len)+1;
1.17 ohara 414: s = MALLOC(len);
1.8 ohara 415: read(0, s, len);
416: return s;
417: }
418:
1.9 ohara 419: /* The data format used by pipe_send_info() is defined in OX-RFC-101. */
1.8 ohara 420: void pipe_send_info(int fd, char *hostname, int port, char *password)
421: {
422: port = htonl(port);
423: write(fd, &port, sizeof(int));
424: pipe_send_string(fd, hostname);
425: pipe_send_string(fd, password);
426: }
427:
1.18 ohara 428: int pipe_read_info(char **hostname, int *port, char **password)
1.8 ohara 429: {
430: if (read(0, port, sizeof(int)) > 0) {
431: *port = ntohl(*port);
432: *hostname = pipe_read_string();
433: *password = pipe_read_string();
434: return 0;
435: }
436: return -1;
1.4 ohara 437: }
438:
439: /* Example: oxf_execute_cmd(oxfp, "ox_sm1"); */
440: OXFILE *oxf_execute_cmd(OXFILE *oxfp, char *cmd)
441: {
1.18 ohara 442: int port = 0;
1.5 ohara 443: int listened;
1.4 ohara 444:
1.5 ohara 445: if ((listened = oxf_listen(&port)) != -1) {
1.18 ohara 446: cmo_list *args = list_appendl(NULL, list_append(new_cmo_list(), (cmo *)new_cmo_int32(port)), new_cmo_string(cmd), NULL);
1.10 ohara 447: send_ox_cmo(oxfp, (cmo *)args);
448: send_ox_command(oxfp, SM_control_spawn_server);
1.5 ohara 449: return oxf_connect_passive(listened);
450: }
451: return NULL;
1.1 ohara 452: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>