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