[BACK]Return to oxf.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_toolkit

Annotation of OpenXM/src/ox_toolkit/oxf.c, Revision 1.24

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>