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