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