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