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