version 1.5, 2000/11/24 05:49:27 |
version 1.25, 2016/07/14 08:16:19 |
|
|
/* -*- mode: C; coding: euc-japan -*- */ |
/* -*- mode: C; coding: euc-japan -*- */ |
/* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.4 2000/10/12 15:53:25 ohara Exp $ */ |
/* $OpenXM: OpenXM/src/ox_toolkit/oxf.c,v 1.24 2016/06/30 01:14:00 ohara Exp $ */ |
|
|
/* |
/* |
This module includes functions for sending/receiveng CMO's. |
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 <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
|
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <time.h> |
|
#include <limits.h> |
|
|
|
#if defined(__sun__) || defined(__FreeBSD__) |
|
#include <netdb.h> |
|
#include <sys/types.h> |
|
#include <netinet/in.h> |
|
#elif defined(__linux__) |
|
#include <arpa/inet.h> |
|
#endif |
|
|
|
#if defined(__sun__) |
|
#include <synch.h> |
|
#else |
|
#include <inttypes.h> |
|
#endif |
|
|
|
#if defined(_MSC_VER) |
|
#include <io.h> |
|
#include <winsock2.h> |
|
#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; |
|
} |
|
#define READ(fd,buf,n) (recv((fd),(buf),(n),0)) |
|
#define WRITE(fd,buf,n) (send((fd),(buf),(n),0)) |
|
#else |
|
#include <unistd.h> |
#include <sys/file.h> |
#include <sys/file.h> |
#include <sys/param.h> |
#include <sys/param.h> |
#include <time.h> |
#define READ(fd,buf,n) (read((fd),(buf),(n))) |
|
#define WRITE(fd,buf,n) (write((fd),(buf),(n))) |
|
#endif |
|
|
#include "mysocket.h" |
#include "mysocket.h" |
#include "ox_toolkit.h" |
#include "ox_toolkit.h" |
|
|
|
static mathcap *oxf_mathcap(OXFILE *oxfp); |
|
|
static int send_int32_lbo(OXFILE *oxfp, int int32); |
static int send_int32_lbo(OXFILE *oxfp, int int32); |
static int send_int32_nbo(OXFILE *oxfp, int int32); |
static int send_int32_nbo(OXFILE *oxfp, int int32); |
static int receive_int32_lbo(OXFILE *oxfp); |
static int receive_int32_lbo(OXFILE *oxfp); |
static int receive_int32_nbo(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<sizeof(double); i++) { |
|
*dp-- = *sp++; |
|
} |
|
return r; |
|
} |
|
|
|
/* enable write buffering */ |
|
int oxf_setbuffer(OXFILE *oxfp, char *buf, int size) |
|
{ |
|
if (buf == NULL && size > 0) { |
|
buf = MALLOC(size); |
|
} |
|
if (oxfp->wbuf != NULL) { |
|
oxf_flush(oxfp); |
|
} |
|
oxfp->wbuf = buf; |
|
oxfp->wbuf_size = size; |
|
oxfp->wbuf_count = 0; |
|
return 0; |
|
} |
|
|
|
void OX_FD_ZERO(OXFILE_set *s) |
|
{ |
|
memset(s,0,sizeof(OXFILE_set)); |
|
} |
|
|
|
void OX_FD_SET(OXFILE *oxfp,OXFILE_set *s) |
|
{ |
|
if (oxfp != NULL && oxfp->fd >=0 && oxfp->fd < OX_FD_SETSIZE && !FD_ISSET(oxfp->fd,&(s->fdset))) { |
|
FD_SET(oxfp->fd,&(s->fdset)); |
|
s->p[oxfp->fd] = oxfp; |
|
s->count++; |
|
} |
|
} |
|
|
|
void OX_FD_CLR(OXFILE *oxfp,OXFILE_set *s) |
|
{ |
|
if (oxfp != NULL && oxfp->fd >=0 && oxfp->fd < OX_FD_SETSIZE && FD_ISSET(oxfp->fd,&(s->fdset))) { |
|
FD_CLR(oxfp->fd,&(s->fdset)); |
|
s->p[oxfp->fd] = NULL; |
|
s->count--; |
|
} |
|
} |
|
|
|
int OX_FD_ISSET(OXFILE *oxfp,OXFILE_set *s) |
|
{ |
|
if (oxfp != NULL && oxfp->fd >=0 && oxfp->fd < OX_FD_SETSIZE) { |
|
return FD_ISSET(oxfp->fd,&(s->fdset)); |
|
} |
|
return 0; |
|
} |
|
|
|
/* The argument `s' is a set of file descripters for reading */ |
|
OXFILE *oxf_select(OXFILE_set *s, struct timeval *tv) |
|
{ |
|
int r; |
|
r = select(OX_FD_SETSIZE,&(s->fdset),NULL,NULL,tv); |
|
return (r<0)? NULL: s->p[r]; |
|
} |
|
|
int oxf_read(void *buffer, size_t size, size_t num, OXFILE *oxfp) |
int oxf_read(void *buffer, size_t size, size_t num, OXFILE *oxfp) |
{ |
{ |
int n = read(oxfp->fd, buffer, size*num); |
int n = READ(oxfp->fd, buffer, size*num); |
if (n <= 0) { |
if (n <= 0) { |
|
#if 0 |
oxfp->error = 1; |
oxfp->error = 1; |
|
#else |
|
exit(0); |
|
#endif |
} |
} |
return n; |
return n; |
} |
} |
|
|
int oxf_write(void *buffer, size_t size, size_t num, OXFILE *oxfp) |
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. |
/* sending an object of int32 type with Network Byte Order. |
(not equal to cmo_int32 type) */ |
(not equal to cmo_int32 type) */ |
static int send_int32_nbo(OXFILE *oxfp, int int32) |
static int send_int32_nbo(OXFILE *oxfp, int int32) |
Line 71 static int receive_int32_lbo(OXFILE *oxfp) |
|
Line 226 static int receive_int32_lbo(OXFILE *oxfp) |
|
return tag; |
return tag; |
} |
} |
|
|
/* socket システムコールなどで socket を開いたのち、 |
/* (1) getting the fd by socket(2). |
fdopen(sd, "a+") でバッファリングする(予定)。("w+" ではない) |
(2) preparing a buffer by fdopen(fd, "a+"). (not "w+") |
バッファリングの後、バイトオーダを決定し、 |
(3) determing the byte order of the OX connection. |
oxf_setopt() で関数ポインタを設定し直す。*/ |
(4) setting function pointers by oxf_setopt(). |
|
*/ |
OXFILE *oxf_open(int fd) |
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->fd = fd; |
oxfp->send_int32 = send_int32_nbo; |
oxfp->send_int32 = send_int32_nbo; |
oxfp->receive_int32 = receive_int32_nbo; |
oxfp->receive_int32 = receive_int32_nbo; |
|
oxfp->serial_number = 0; |
oxfp->control = NULL; |
oxfp->control = NULL; |
oxfp->error = 0; |
oxfp->error = 0; |
oxfp->mathcap = NULL; |
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; |
return oxfp; |
/* oxfp->fp = fdopen(fd, "a+"); */ |
/* oxfp->fp = fdopen(fd, "a+"); */ |
/* return (oxfp->fp != NULL)? oxfp: NULL; */ |
/* return (oxfp->fp != NULL)? oxfp: NULL; */ |
} |
} |
|
|
|
int oxf_fileno(OXFILE *oxfp) |
|
{ |
|
return oxfp->fd; |
|
} |
|
|
OXFILE *oxf_control(OXFILE *oxfp) |
OXFILE *oxf_control(OXFILE *oxfp) |
{ |
{ |
return oxfp->control; |
return oxfp->control; |
Line 112 void oxf_determine_byteorder_client(OXFILE *oxfp) |
|
Line 279 void oxf_determine_byteorder_client(OXFILE *oxfp) |
|
oxf_setopt(oxfp, mode); |
oxf_setopt(oxfp, mode); |
} |
} |
|
|
/* Server 側ではこちらを用いる */ |
/* If the program is an OX server, then you must use this function. */ |
/* いまの実装は dup されていることが前提になっている */ |
|
void oxf_determine_byteorder_server(OXFILE *oxfp) |
void oxf_determine_byteorder_server(OXFILE *oxfp) |
{ |
{ |
int offer = OX_BYTE_LITTLE_ENDIAN; |
int offer = OX_BYTE_LITTLE_ENDIAN; |
Line 128 void oxf_determine_byteorder_server(OXFILE *oxfp) |
|
Line 294 void oxf_determine_byteorder_server(OXFILE *oxfp) |
|
|
|
void oxf_flush(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) |
void oxf_close(OXFILE *oxfp) |
{ |
{ |
|
oxf_flush(oxfp); |
close(oxfp->fd); |
close(oxfp->fd); |
/* fclose(oxfp->fp); */ |
|
} |
} |
|
|
#define OXF_SETOPT_NBO 0 |
#define OXF_SETOPT_NBO 0 |
Line 142 void oxf_close(OXFILE *oxfp) |
|
Line 311 void oxf_close(OXFILE *oxfp) |
|
|
|
void oxf_setopt(OXFILE *oxfp, int mode) |
void oxf_setopt(OXFILE *oxfp, int mode) |
{ |
{ |
if (mode == OXF_SETOPT_LBO) { |
int m = 1; |
oxfp->send_int32 = send_int32_lbo; |
if (mode == OXF_SETOPT_NBO && *(char *)&m) { |
oxfp->receive_int32 = receive_int32_lbo; |
/* Little endian architecture. */ |
}else if (mode == OXF_SETOPT_NBO) { |
oxfp->send_int32 = send_int32_nbo; |
oxfp->send_int32 = send_int32_nbo; |
oxfp->receive_int32 = receive_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(short *portp) |
int oxf_listen(int *portp) |
{ |
{ |
char localhost[MAXHOSTNAMELEN]; |
char localhost[MAXHOSTNAMELEN]; |
if (gethostname(localhost, MAXHOSTNAMELEN)==0) { |
if (gethostname(localhost, MAXHOSTNAMELEN)==0) { |
Line 163 int oxf_listen(short *portp) |
|
Line 338 int oxf_listen(short *portp) |
|
OXFILE *oxf_connect_active(char *hostname, short port) |
OXFILE *oxf_connect_active(char *hostname, short port) |
{ |
{ |
int fd = mysocketOpen(hostname, port); |
int fd = mysocketOpen(hostname, port); |
return oxf_open(fd); |
return (fd < 0)? NULL: oxf_open(fd); |
} |
} |
|
|
OXFILE *oxf_connect_passive(int listened) |
OXFILE *oxf_connect_passive(int listened) |
{ |
{ |
int fd = mysocketAccept(listened); |
int fd = mysocketAccept(listened); |
return oxf_open(fd); |
return (fd < 0)? NULL: oxf_open(fd); |
} |
} |
|
|
#define LENGTH_OF_ONETIME_PASSWORD 64 |
#define LENGTH_OF_ONETIME_PASSWORD 64 |
Line 194 char *generate_otp() |
|
Line 369 char *generate_otp() |
|
int oxf_confirm_client(OXFILE *oxfp, char *passwd) |
int oxf_confirm_client(OXFILE *oxfp, char *passwd) |
{ |
{ |
int len = strlen(passwd)+1; |
int len = strlen(passwd)+1; |
char *buf = alloca(len); |
char *buf = ALLOCA(len); |
|
|
oxf_read(buf, 1, len, oxfp); |
oxf_read(buf, 1, len, oxfp); |
return !strcmp(passwd, buf); |
return !strcmp(passwd, buf); |
Line 205 int oxf_confirm_server(OXFILE *oxfp, char *passwd) |
|
Line 380 int oxf_confirm_server(OXFILE *oxfp, char *passwd) |
|
return oxf_write(passwd, 1, strlen(passwd)+1, oxfp); |
return oxf_write(passwd, 1, strlen(passwd)+1, oxfp); |
} |
} |
|
|
void oxf_mathcap_update(OXFILE *oxfp, cmo_mathcap *ob) |
__inline__ |
|
static mathcap *oxf_mathcap(OXFILE *oxfp) |
{ |
{ |
if (oxfp->mathcap == NULL) { |
if (oxfp->mathcap == NULL) { |
oxfp->mathcap = new_mathcap(); |
oxfp->mathcap = new_mathcap(); |
} |
} |
mathcap_update(oxfp->mathcap, ob); |
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")); */ |
/* example: which("xterm", getenv("PATH")); */ |
char *which(char *exe, const char *env) |
char *which(char *exe, const char *env) |
{ |
{ |
char *tok; |
char *tok; |
char *path; |
char *path; |
char delim[] = ":"; |
char delim[] = ":"; |
char *e = alloca(strlen(env)+1); |
char *e = ALLOCA(strlen(env)+1); |
strcpy(e, env); |
strcpy(e, env); |
tok = strtok(e, delim); |
tok = strtok(e, delim); |
while (tok != NULL) { |
while (tok != NULL) { |
path = malloc(strlen(tok)+strlen(exe)+2); |
path = MALLOC(strlen(tok)+strlen(exe)+2); |
sprintf(path, "%s/%s", tok, exe); |
sprintf(path, "%s/%s", tok, exe); |
if (access(path, X_OK&R_OK) == 0) { |
if (access(path, X_OK&R_OK) == 0) { |
return path; |
return path; |
} |
} |
free(path); |
FREE(path); |
tok = strtok(NULL, delim); |
tok = strtok(NULL, delim); |
} |
} |
return NULL; |
return NULL; |
} |
} |
|
|
|
#if !defined(_MSC_VER) |
/* Remarks: ssh determines remote host by his name, i.e. by arg[0]. */ |
/* 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 localhost[MAXHOSTNAMELEN]; |
char ports[128]; |
char ports[128]; |
Line 245 int oxc_start(char *remote_host, short port, char *pas |
|
Line 432 int oxc_start(char *remote_host, short port, char *pas |
|
if (gethostname(localhost, MAXHOSTNAMELEN)==0) { |
if (gethostname(localhost, MAXHOSTNAMELEN)==0) { |
if ((pid = fork()) == 0) { |
if ((pid = fork()) == 0) { |
sprintf(ports, "%d", port); |
sprintf(ports, "%d", port); |
#ifdef DEBUG |
ox_printf("oxf.c:: oxc_start() does %s(ssh) -f %s -h %s -p %s -c %s\n", remote_host, cmd, localhost, ports, passwd); |
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 |
|
execlp("ssh", remote_host, "-f", cmd, |
execlp("ssh", remote_host, "-f", cmd, |
"-h", localhost, "-p", ports,"-c", passwd, NULL); |
"-h", localhost, "-p", ports,"-c", passwd, NULL); |
} |
} |
Line 255 int oxc_start(char *remote_host, short port, char *pas |
|
Line 440 int oxc_start(char *remote_host, short port, char *pas |
|
return pid; |
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"); */ |
/* Example: oxf_execute_cmd(oxfp, "ox_sm1"); */ |
OXFILE *oxf_execute_cmd(OXFILE *oxfp, char *cmd) |
OXFILE *oxf_execute_cmd(OXFILE *oxfp, char *cmd) |
{ |
{ |
short port = 0; |
int port = 0; |
int listened; |
int listened; |
|
|
if ((listened = oxf_listen(&port)) != -1) { |
if ((listened = oxf_listen(&port)) != -1) { |
send_ox_cmo(oxfp, (cmo *)new_cmo_int32(port)); |
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 *)new_cmo_string(cmd)); |
send_ox_cmo(oxfp, (cmo *)args); |
send_ox_cmo(oxfp, (cmo *)new_cmo_int32(2)); /* number of arguments */ |
send_ox_command(oxfp, SM_control_spawn_server); |
send_ox_cmo(oxfp, (cmo *)new_cmo_string("oxc_open")); |
|
send_ox_command(oxfp, SM_executeFunction); |
|
return oxf_connect_passive(listened); |
return oxf_connect_passive(listened); |
} |
} |
return NULL; |
return NULL; |