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