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