=================================================================== RCS file: /home/cvs/OpenXM/src/ox_toolkit/oxf.c,v retrieving revision 1.3 retrieving revision 1.24 diff -u -p -r1.3 -r1.24 --- OpenXM/src/ox_toolkit/oxf.c 2000/10/11 08:22:58 1.3 +++ OpenXM/src/ox_toolkit/oxf.c 2016/06/30 01:14:00 1.24 @@ -1,54 +1,220 @@ /* -*- mode: C; coding: euc-japan -*- */ -/* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.2 2000/10/11 06:56:03 ohara Exp $ */ +/* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.23 2015/08/27 03:03:33 ohara Exp $ */ /* This module includes functions for sending/receiveng CMO's. - Some commnets is written in Japanese by the EUC-JP coded - character set. */ +#if defined(_MSC_VER) +#define _CRT_RAND_S +#endif + #include #include #include -#include #include +#include +#include + +#if defined(__sun__) +#include +#include +#include +#endif + +#if defined(__sun__) +#include +#else +#include +#endif + +#if defined(_MSC_VER) +#include +#include +#define X_OK 0x01 +#define R_OK 0x04 +#define MAXHOSTNAMELEN 256 +#define srandom(s) (srand((s))) +static int random() +{ + int r; + rand_s(&r); + return r; +} +#else +#include #include #include -#include +#endif #include "mysocket.h" #include "ox_toolkit.h" +static mathcap *oxf_mathcap(OXFILE *oxfp); + +static int send_int32_lbo(OXFILE *oxfp, int int32); +static int send_int32_nbo(OXFILE *oxfp, int int32); +static int receive_int32_lbo(OXFILE *oxfp); +static int receive_int32_nbo(OXFILE *oxfp); + +static int send_int64_nbo_le(OXFILE *oxfp, double int64); +static int send_int64_lbo(OXFILE *oxfp, double int64); +static double receive_int64_nbo_le(OXFILE *oxfp); +static double receive_int64_lbo(OXFILE *oxfp); + +static void pipe_send_info(int fd, char *hostname, int port, char *password); + +/* translating double of little endian byte order to one of big endian. */ +double htonll_le(double n) +{ + int i; + double r; + char *sp = (char *)&n, *dp = (char *)&r + sizeof(double)-1; + for(i=0; i 0) { + buf = MALLOC(size); + } + if (oxfp->wbuf != NULL) { + oxf_flush(oxfp); + } + oxfp->wbuf = buf; + oxfp->wbuf_size = size; + oxfp->wbuf_count = 0; + return 0; +} + int oxf_read(void *buffer, size_t size, size_t num, OXFILE *oxfp) { - int n = read(oxfp->fd, buffer, size*num); - if (n <= 0) { - oxfp->error = 1; - } + int n = read(oxfp->fd, buffer, size*num); + if (n <= 0) { +#if 0 + oxfp->error = 1; +#else + exit(0); +#endif + } return n; } int oxf_write(void *buffer, size_t size, size_t num, OXFILE *oxfp) { - return write(oxfp->fd, buffer, size*num); + size_t sz = size*num; + if (oxfp->wbuf == NULL) { /* no buffering */ + return write(oxfp->fd, buffer, sz); + } + if ((oxfp->wbuf_count + sz) >= oxfp->wbuf_size) { + oxf_flush(oxfp); + return write(oxfp->fd, buffer, sz); + } + memcpy(oxfp->wbuf + oxfp->wbuf_count, buffer, sz); + oxfp->wbuf_count += sz; + return sz; } +/* sending an object of int64 type with Network Byte Order. */ +static int send_int64_nbo_le(OXFILE *oxfp, double int64) +{ + int64 = htonll_le(int64); + return oxf_write(&int64, sizeof(double), 1, oxfp); +} + +/* sending an object of int64 type with Local Byte Order. */ +static int send_int64_lbo(OXFILE *oxfp, double int64) +{ + return oxf_write(&int64, sizeof(double), 1, oxfp); +} + +/* receiving an object of int64 type with Network Byte Order. */ +static double receive_int64_nbo_le(OXFILE *oxfp) +{ + double tag; + oxf_read(&tag, sizeof(double), 1, oxfp); + return htonll_le(tag); +} + +/* receiving an object of int64 type with Local Byte Order. */ +static double receive_int64_lbo(OXFILE *oxfp) +{ + double tag; + oxf_read(&tag, sizeof(double), 1, oxfp); + return tag; +} + +/* sending an object of int32 type with Network Byte Order. + (not equal to cmo_int32 type) */ +static int send_int32_nbo(OXFILE *oxfp, int int32) +{ + int32 = htonl(int32); + return oxf_write(&int32, sizeof(int), 1, oxfp); +} + +/* sending an object of int32 type with Local Byte Order. + (not equal to cmo_int32 type) */ +static int send_int32_lbo(OXFILE *oxfp, int int32) +{ + return oxf_write(&int32, sizeof(int), 1, oxfp); +} + +/* receiving an object of int32 type with Network Byte Order. + (not equal to cmo_int32 type) */ +static int receive_int32_nbo(OXFILE *oxfp) +{ + int tag; + oxf_read(&tag, sizeof(int), 1, oxfp); + return ntohl(tag); +} + +/* receiving an object of int32 type with Local Byte Order. + (not equal to cmo_int32 type) */ +static int receive_int32_lbo(OXFILE *oxfp) +{ + int tag; + oxf_read(&tag, sizeof(int), 1, oxfp); + return tag; +} + +/* (1) getting the fd by socket(2). + (2) preparing a buffer by fdopen(fd, "a+"). (not "w+") + (3) determing the byte order of the OX connection. + (4) setting function pointers by oxf_setopt(). +*/ OXFILE *oxf_open(int fd) { - OXFILE *oxfp = (OXFILE *)malloc(sizeof(OXFILE)); + OXFILE *oxfp = (OXFILE *)MALLOC(sizeof(OXFILE)); + oxfp = (OXFILE *)MALLOC(sizeof(OXFILE)); oxfp->fd = fd; oxfp->send_int32 = send_int32_nbo; oxfp->receive_int32 = receive_int32_nbo; - oxfp->control = NULL; - oxfp->error = 0; + oxfp->serial_number = 0; + oxfp->control = NULL; + oxfp->error = 0; + oxfp->mathcap = NULL; + oxfp->wbuf = NULL; + oxfp->wbuf_size = 0; + oxfp->wbuf_count = 0; + oxfp->send_double = send_int64_lbo; + oxfp->receive_double = receive_int64_lbo; return oxfp; /* oxfp->fp = fdopen(fd, "a+"); */ /* return (oxfp->fp != NULL)? oxfp: NULL; */ } +int oxf_fileno(OXFILE *oxfp) +{ + return oxfp->fd; +} + OXFILE *oxf_control(OXFILE *oxfp) { - return oxfp->control; + return oxfp->control; } /* The function determines a byte order of integer on the OpenXM @@ -68,8 +234,7 @@ void oxf_determine_byteorder_client(OXFILE *oxfp) oxf_setopt(oxfp, mode); } -/* Server 側ではこちらを用いる */ -/* いまの実装は dup されていることが前提になっている */ +/* If the program is an OX server, then you must use this function. */ void oxf_determine_byteorder_server(OXFILE *oxfp) { int offer = OX_BYTE_LITTLE_ENDIAN; @@ -84,13 +249,16 @@ void oxf_determine_byteorder_server(OXFILE *oxfp) void oxf_flush(OXFILE *oxfp) { - /* fflush(oxfp->fp); */ + if (oxfp->wbuf != NULL) { + write(oxfp->fd, oxfp->wbuf, oxfp->wbuf_count); + oxfp->wbuf_count = 0; + } } void oxf_close(OXFILE *oxfp) { + oxf_flush(oxfp); close(oxfp->fd); - /* fclose(oxfp->fp); */ } #define OXF_SETOPT_NBO 0 @@ -98,25 +266,40 @@ void oxf_close(OXFILE *oxfp) void oxf_setopt(OXFILE *oxfp, int mode) { - if (mode == OXF_SETOPT_LBO) { - oxfp->send_int32 = send_int32_lbo; - oxfp->receive_int32 = receive_int32_lbo; - }else if (mode == OXF_SETOPT_NBO) { - oxfp->send_int32 = send_int32_nbo; - oxfp->receive_int32 = receive_int32_nbo; + int m = 1; + if (mode == OXF_SETOPT_NBO && *(char *)&m) { + /* Little endian architecture. */ + oxfp->send_int32 = send_int32_nbo; + oxfp->receive_int32 = receive_int32_nbo; + oxfp->send_double = send_int64_nbo_le; + oxfp->receive_double = receive_int64_nbo_le; + }else { + oxfp->send_int32 = send_int32_lbo; + oxfp->receive_int32 = receive_int32_lbo; + oxfp->send_double = send_int64_lbo; + oxfp->receive_double = receive_int64_lbo; } } +int oxf_listen(int *portp) +{ + char localhost[MAXHOSTNAMELEN]; + if (gethostname(localhost, MAXHOSTNAMELEN)==0) { + return mysocketListen(localhost, portp); + } + return -1; +} + OXFILE *oxf_connect_active(char *hostname, short port) { int fd = mysocketOpen(hostname, port); - return oxf_open(fd); + return (fd < 0)? NULL: oxf_open(fd); } OXFILE *oxf_connect_passive(int listened) { int fd = mysocketAccept(listened); - return oxf_open(fd); + return (fd < 0)? NULL: oxf_open(fd); } #define LENGTH_OF_ONETIME_PASSWORD 64 @@ -124,7 +307,7 @@ OXFILE *oxf_connect_passive(int listened) /* a password generator. */ char *generate_otp() { - static char crypto[] = "%.,^_+-=/@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + static char crypto[] = "%.,^_+-=/@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static char otp[LENGTH_OF_ONETIME_PASSWORD+1] = {0}; int i; @@ -141,7 +324,7 @@ char *generate_otp() int oxf_confirm_client(OXFILE *oxfp, char *passwd) { int len = strlen(passwd)+1; - char *buf = alloca(len); + char *buf = ALLOCA(len); oxf_read(buf, 1, len, oxfp); return !strcmp(passwd, buf); @@ -152,29 +335,49 @@ int oxf_confirm_server(OXFILE *oxfp, char *passwd) return oxf_write(passwd, 1, strlen(passwd)+1, oxfp); } +__inline__ +static mathcap *oxf_mathcap(OXFILE *oxfp) +{ + if (oxfp->mathcap == NULL) { + oxfp->mathcap = new_mathcap(); + } + return oxfp->mathcap; +} + +cmo_mathcap *oxf_cmo_mathcap(OXFILE *oxfp) +{ + return mathcap_get(oxf_mathcap(oxfp)); +} + +void oxf_mathcap_update(OXFILE *oxfp, cmo_mathcap *ob) +{ + mathcap_update(oxf_mathcap(oxfp), ob); +} + /* example: which("xterm", getenv("PATH")); */ char *which(char *exe, const char *env) { char *tok; char *path; char delim[] = ":"; - char *e = alloca(strlen(env)+1); + char *e = ALLOCA(strlen(env)+1); strcpy(e, env); tok = strtok(e, delim); while (tok != NULL) { - path = malloc(strlen(tok)+strlen(exe)+2); + path = MALLOC(strlen(tok)+strlen(exe)+2); sprintf(path, "%s/%s", tok, exe); if (access(path, X_OK&R_OK) == 0) { return path; } - free(path); + FREE(path); tok = strtok(NULL, delim); } return NULL; } +#if !defined(_MSC_VER) /* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */ -int oxc_start(char *remote_host, short port, char *passwd) +int oxc_start(char *remote_host, int port, char *passwd) { char localhost[MAXHOSTNAMELEN]; char ports[128]; @@ -184,12 +387,90 @@ int oxc_start(char *remote_host, short port, char *pas if (gethostname(localhost, MAXHOSTNAMELEN)==0) { if ((pid = fork()) == 0) { sprintf(ports, "%d", port); -#ifdef DEBUG - fprintf(stderr, "oxf.c:: oxc_start() does %s(ssh) -f %s -h %s -p %s -c %s\n", remote_host, cmd, localhost, ports, passwd); -#endif + ox_printf("oxf.c:: oxc_start() does %s(ssh) -f %s -h %s -p %s -c %s\n", remote_host, cmd, localhost, ports, passwd); execlp("ssh", remote_host, "-f", cmd, "-h", localhost, "-p", ports,"-c", passwd, NULL); } } return pid; +} + +/* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */ +int oxc_start_with_pipe(char *remote_host, int port, char *passwd) +{ + char localhost[MAXHOSTNAMELEN]; + int pid = 0; + char *cmd = "oxc"; + int pipefd[2]; + + if (gethostname(localhost, MAXHOSTNAMELEN)==0) { + if (pipe(pipefd) < 0) { + return -1; + } + if ((pid = fork()) == 0) { + dup2(pipefd[1], 0); + close(pipefd[0]); + close(pipefd[1]); + execlp("ssh", remote_host, cmd, NULL); + exit(1); + } + close(pipefd[1]); + pipe_send_info(pipefd[0], localhost, port, passwd); + } + return pid; +} +#endif + +static void pipe_send_string(int fd, char *s) +{ + int len = strlen(s); + int lenN = htonl(len); + write(fd, &lenN, sizeof(int)); + write(fd, s, len+1); +} + +static char *pipe_read_string() +{ + int len; + char *s; + read(0, &len, sizeof(int)); + len = ntohl(len)+1; + s = MALLOC(len); + read(0, s, len); + return s; +} + +/* The data format used by pipe_send_info() is defined in OX-RFC-101. */ +void pipe_send_info(int fd, char *hostname, int port, char *password) +{ + port = htonl(port); + write(fd, &port, sizeof(int)); + pipe_send_string(fd, hostname); + pipe_send_string(fd, password); +} + +int pipe_read_info(char **hostname, int *port, char **password) +{ + if (read(0, port, sizeof(int)) > 0) { + *port = ntohl(*port); + *hostname = pipe_read_string(); + *password = pipe_read_string(); + return 0; + } + return -1; +} + +/* Example: oxf_execute_cmd(oxfp, "ox_sm1"); */ +OXFILE *oxf_execute_cmd(OXFILE *oxfp, char *cmd) +{ + int port = 0; + int listened; + + if ((listened = oxf_listen(&port)) != -1) { + cmo_list *args = list_appendl(NULL, list_append(new_cmo_list(), (cmo *)new_cmo_int32(port)), new_cmo_string(cmd), NULL); + send_ox_cmo(oxfp, (cmo *)args); + send_ox_command(oxfp, SM_control_spawn_server); + return oxf_connect_passive(listened); + } + return NULL; }