=================================================================== RCS file: /home/cvs/OpenXM/src/ox_ntl/oxserv.c,v retrieving revision 1.1 retrieving revision 1.6 diff -u -p -r1.1 -r1.6 --- OpenXM/src/ox_ntl/oxserv.c 2003/11/03 03:11:21 1.1 +++ OpenXM/src/ox_ntl/oxserv.c 2004/07/04 11:38:42 1.6 @@ -1,234 +1,149 @@ -/* $OpenXM$ */ +/* $OpenXM: OpenXM/src/ox_ntl/oxserv.c,v 1.5 2003/11/27 14:18:43 iwane Exp $ */ #include #include #include #include +#include +#include #include "oxserv.h" +#include "oxstack.h" +#include "gc/gc.h" #define DPRINTF(x) printf x; fflush(stdout) -#define delete_cmo(m) +#define FP stdout +#define EPRINTF(x) fprintf x; fflush(FP) -#define OXSERV_INIT_STACK_SIZE 2048 -#define OXSERV_EXT_STACK_SIZE 2048 -#if 0 /*===========================================================================* - * for DEBUG + * MACRO *===========================================================================*/ -#include -void -dprintf(const char *fmt, ...) -{ - FILE *fp; - va_list ap; - va_start(ap, fmt); - - fp = fopen("error.txt", "a"); +#define oxserv_get_cmo_tag(m) ((G_getCmoTag == NULL) ? m->tag : G_getCmoTag(m)) - vfprintf(fp, fmt, ap); - fflush(fp); - fclose(fp); +#define oxserv_delete_cmo(c) \ +do { \ + if (c != NULL) { \ + if (G_DeleteCmo != NULL) \ + G_DeleteCmo((cmo *)c); \ + else \ + c = NULL; \ + } \ +} while (0) - va_end(ap); -} -#endif /*===========================================================================* * Global Variables. *===========================================================================*/ -/* cmo stack */ -static int G_ox_stack_size = 0; -static int G_ox_stack_pointer = 0; -static cmo **G_ox_stack = NULL; - /* ox */ +static OXFILE *G_oxfilep = NULL; static cmo_mathcap *G_oxserv_mathcap = NULL; +/* signal */ +int G_oxserv_sigusr1flag = 0; +int G_oxserv_sigusr1cnt = 0; +static jmp_buf G_jmpbuf; + /* User Function */ -static cmo *(*G_userExecuteFunction)(const char *, cmo **, int) = NULL; -static cmo *(*G_userExecuteStringParser)(const char *) = NULL; +static void (*G_userExecuteFunction)(const char *, cmo **, int) = NULL; +static void (*G_userExecuteStringParser)(const char *) = NULL; static cmo *(*G_convertCmo)(cmo *) = NULL; /* convert user object ==> cmo */ +static void (*G_DeleteCmo)(cmo *) = NULL; + +static int (*G_getCmoTag)(cmo *) = NULL; + + /*===========================================================================* - * CMO STACK FUNCTIONs + * CMO_ERROR2 *===========================================================================*/ -/***************************************************************************** - * return the number of cmo in the stack. - * PARAM : NONE - * RETURN : the number of cmo in the stack. - *****************************************************************************/ -#define oxserv_get_stack_pointer() G_ox_stack_pointer +#define new_cmo_error2_string(msg) new_cmo_error2((cmo *)new_cmo_string(msg)) -/***************************************************************************** - * initialize stack. - * PARAM : NONE - * RETURN : if success return OXSERV_SUCCESS, else OXSERV_FAILURE. - *****************************************************************************/ -static int -oxserv_init_stack(void) +static void +oxserv_push_errormes(char *msg) { - free(G_ox_stack); - - G_ox_stack_pointer = 0; - G_ox_stack_size = OXSERV_INIT_STACK_SIZE; - G_ox_stack = (cmo **)malloc(G_ox_stack_size * sizeof(cmo *)); - if (G_ox_stack == NULL) { - DPRINTF(("server: %d: %s\n", errno, strerror(errno))); - return (OXSERV_FAILURE); - } - return (OXSERV_SUCCESS); + EPRINTF((FP, "%s\n", msg)); + oxstack_push((cmo *)new_cmo_error2_string(msg)); } -/***************************************************************************** - * - * PARAM : NONE - * RETURN : if success return OXSERV_SUCCESS, else OXSERV_FAILURE. - *****************************************************************************/ -static int -oxserv_extend_stack(void) +/*===========================================================================* + * synchronized malloc + *===========================================================================*/ +void * +oxserv_malloc(size_t size) { - int size2 = G_ox_stack_size + OXSERV_EXT_STACK_SIZE; - cmo **stack2 = (cmo **)malloc(size2 * sizeof(cmo *)); - if (stack2 == NULL) { - DPRINTF(("server: %d: %s\n", errno, strerror(errno))); - return (OXSERV_FAILURE); - } + void *ptr; - memcpy(stack2, G_ox_stack, G_ox_stack_size * sizeof(cmo *)); - free(G_ox_stack); + BLOCK_INPUT(); + ptr = GC_malloc(size); + UNBLOCK_INPUT(); - G_ox_stack = stack2; - G_ox_stack_size = size2; - - return (OXSERV_SUCCESS); + return (ptr); } -/***************************************************************************** - * push a cmo onto the topof the stack. - * PARAM : m : the cmo to be pushed on the stack. - * RETURN : if success return OXSERV_SUCCESS, else OXSERV_FAILURE. - *****************************************************************************/ -static int -oxserv_push(cmo *m) +void +oxserv_free(void *ptr, size_t size) { - int ret; - - if (G_ox_stack_pointer >= G_ox_stack_size) { - ret = oxserv_extend_stack(); - if (ret != OXSERV_SUCCESS) - return (ret); - } - - G_ox_stack[G_ox_stack_pointer] = m; - G_ox_stack_pointer++; - - return (OXSERV_SUCCESS); + /* nothing */ } -/***************************************************************************** - * remove thd CMO at the top of this stack and - * returns that cmo as the value of this function. - * PARAM : NONE - * RETURN : CMO at the top of the stack. - *****************************************************************************/ -static cmo * -oxserv_pop(void) +void * +oxserv_realloc(void *org, size_t old, size_t size) { - cmo *c; - if (G_ox_stack_pointer > 0) { - G_ox_stack_pointer--; - c = G_ox_stack[G_ox_stack_pointer]; - G_ox_stack[G_ox_stack_pointer] = NULL; - return (c); - } - return (NULL); -} + void *ptr; -/***************************************************************************** - * return the cmo at the specified position in the stack without removing it from the stack. - * PARAM : NONE - * RETURN: thd cmo at the specified position in the stack. - *****************************************************************************/ -static cmo * -oxserv_get(int i) -{ - if (i < G_ox_stack_pointer && i >= 0) { - return (G_ox_stack[i]); - } - return (NULL); + BLOCK_INPUT(); + ptr = GC_realloc(org, size); + UNBLOCK_INPUT(); + + return (ptr); } -/***************************************************************************** - * return the cmo at the top of the stack without removing it from the stack. - * PARAM : NONE - * RETURN: the cmo at the top of the stack. - *****************************************************************************/ -static cmo * -oxserv_peek(void) -{ - return (oxserv_get(G_ox_stack_pointer - 1)); -} -/***************************************************************************** - * - * defined for SM_pops - * - * PARAM : n : remove count - * RETURN: NONE - *****************************************************************************/ -static void -oxserv_remove(int n) -{ - int i; - cmo *m; - - if (n > G_ox_stack_size) - n = G_ox_stack_size; - - for (i = 0; i < n; i++) { - --G_ox_stack_pointer; - m = G_ox_stack[G_ox_stack_pointer]; - G_ox_stack[G_ox_stack_pointer] = NULL; - delete_cmo(m); - } -} - - /*===========================================================================* * OX_SERVER *===========================================================================*/ /***************************************************************************** - * pop n and to discard element from the stack + * -- SM_popCMO -- + * pop an object from the stack, convert it into a serialized from according + * to the standard CMO encoding scheme, and send it to the stream + * * PARAM : fd : OXFILE * RETURN: NONE *****************************************************************************/ static void oxserv_sm_popCMO(OXFILE *fd) { - cmo *m = oxserv_pop(); + cmo *m, *n; + m = oxstack_pop(); if (m == NULL) { + EPRINTF((FP, "stack underflow in popCMO\n")); m = new_cmo_null(); } else if (G_convertCmo) { - m = G_convertCmo(m); + n = G_convertCmo(m); + if (m != n) { + oxserv_delete_cmo(m); + m = n; + } } send_ox_cmo(fd, m); - delete_cmo(m); + oxserv_delete_cmo(m); } /***************************************************************************** + * -- SM_popString -- * pop an cmo from stack, convert it into a string according to the * output format of the local system, and send the string. + * * PARAM : fd : OXFILE * RETURN: NONE *****************************************************************************/ @@ -236,11 +151,13 @@ static void oxserv_sm_popString(OXFILE *fd) { char *str; - cmo *m = oxserv_pop(); + cmo *m = oxstack_pop(); cmo_string *m_str; - if (m == NULL) + if (m == NULL) { + EPRINTF((FP, "stack underflow in popString\n")); m = new_cmo_null(); + } str = new_string_set_cmo(m); @@ -248,31 +165,49 @@ oxserv_sm_popString(OXFILE *fd) send_ox_cmo(fd, (cmo *)m_str); - delete_cmo(m); - delete_cmo(m_str); + oxserv_delete_cmo(m); + oxserv_delete_cmo(m_str); -/* free(str); */ + /* free(str); */ } /***************************************************************************** + * -- SM_pops -- * pop n and to discard element from the stack - * PARAM : fd : OXFILE + * + * PARAM : NONE * RETURN: NONE *****************************************************************************/ static void oxserv_sm_pops() { cmo_int32 *c; + cmo *m; + int n; + int i; - c = (cmo_int32 *)oxserv_pop(); /* suppose */ + c = (cmo_int32 *)oxstack_pop(); /* suppose */ + if (c == NULL) { + EPRINTF((FP, "stack underflow in pops\n")); + return ; + } - oxserv_remove(c->i) + n = oxstack_get_stack_pointer(); + if (c->i < n) + n = c->i; - delete_cmo(c); + for (i = 0; i < n; i++) { + m = oxstack_pop(); + oxserv_delete_cmo(m); + } + + oxserv_delete_cmo(c); + } /***************************************************************************** - * for SM_getsp + * -- SM_getsp -- + * push the current stack pointer onto the stack. * * PARAM : fd : OXFILE * RETURN: NONE @@ -280,8 +215,8 @@ oxserv_sm_pops() static void oxserv_sm_getsp() { - cmo_int32 *m = new_cmo_int32(oxserv_get_stack_pointer()); - oxserv_push((cmo *)m); + cmo_int32 *m = new_cmo_int32(oxstack_get_stack_pointer()); + oxstack_push((cmo *)m); } /***************************************************************************** @@ -367,11 +302,18 @@ oxserv_mathcap_init(int ver, char *vstr, char *sysname mathcap_init(ver, vstr, sysname, cmos, sms); - delete_cmo(G_oxserv_mathcap); + oxserv_delete_cmo(G_oxserv_mathcap); G_oxserv_mathcap = mathcap_get(new_mathcap()); } +/***************************************************************************** + * -- SM_mathcap -- + * push the mathcap of the server. + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_mathcap() { @@ -379,67 +321,122 @@ oxserv_sm_mathcap() oxserv_mathcap_init(0, "", "oxserv", NULL, NULL); } - oxserv_push((cmo *)G_oxserv_mathcap); + oxstack_push((cmo *)G_oxserv_mathcap); } +/***************************************************************************** + * -- SM_executeStringByLocalParserInBatchMode -- + * peek a character string s, parse it by the local parser of the stack machine, + * and interpret by the local interpreter. + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_executeStringByLocalParserInBatchMode(void) { - cmo_string *str = (cmo_string *)oxserv_peek(); - cmo *c; - c = G_userExecuteStringParser(str->s); - oxserv_push(c); + cmo_string *str = (cmo_string *)oxstack_peek(); + if (str == NULL) { + oxserv_push_errormes("stack underflow in executeStringByLocalParserInBatchMode"); + return ; + } + G_userExecuteStringParser(str->s); } +/***************************************************************************** + * -- SM_executeStringByLocalParser -- + * pop a character string s, parse it by the local parser of the stack machine, + * and interpret by the local interpreter. + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_executeStringByLocalParser(void) { - cmo_string *str = (cmo_string *)oxserv_pop(); - cmo *c; - c = G_userExecuteStringParser(str->s); - oxserv_push(c); + cmo_string *str = (cmo_string *)oxstack_pop(); + if (str == NULL) { + oxserv_push_errormes("stack underflow in executeStringByLocalParser"); + return ; + } + G_userExecuteStringParser(str->s); } +/***************************************************************************** + * -- SM_executeFunction -- + * pop s as a function name, pop n as the number of arguments and to execute a + * local function s with n arguments poped from the stack. + * + * suppose G_userExecuteFunction not equal NULL + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_executeFunction(void) { int i; - cmo_string *name = (cmo_string *)oxserv_pop(); - cmo_int32 *cnt = (cmo_int32 *)oxserv_pop(); - cmo **arg = (cmo **)malloc(cnt->i * sizeof(cmo *)); - cmo *ret; + cmo_string *name = (cmo_string *)oxstack_pop(); + cmo_int32 *cnt = (cmo_int32 *)oxstack_pop(); + cmo **arg; + + if (name == NULL || cnt == NULL) { + oxserv_push_errormes("stack underflow in executeFunction"); + return ; + } + + arg = (cmo **)malloc(cnt->i * sizeof(cmo *)); for (i = 0; i < cnt->i; i++) { - arg[i] = oxserv_pop(); + arg[i] = oxstack_pop(); + if (arg[i] == NULL) { + oxserv_push_errormes("stack underflow in executeFunction"); + + for (i--; i >= 0; i--) + oxserv_delete_cmo(arg[i]); + free(arg); + return ; + } } /* user function */ - ret = G_userExecuteFunction(name->s, arg, cnt->i); + G_userExecuteFunction(name->s, arg, cnt->i); - oxserv_push(ret); for (i = 0; i < cnt->i; i++) { - delete_cmo(arg[i]); + oxserv_delete_cmo(arg[i]); } - delete_cmo(name); - delete_cmo(cnt); + oxserv_delete_cmo(name); + oxserv_delete_cmo(cnt); free(arg); } +/***************************************************************************** + * -- SM_pushCMOtag -- + * push the CMO tag of the top object on the stack. + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_pushCMOtag() { - cmo *c = oxserv_peek(); - cmo_int32 *tag = new_cmo_int32(c->tag); - - oxserv_push((cmo *)tag); + cmo *c = oxstack_peek(); + cmo_int32 *tag = new_cmo_int32(oxserv_get_cmo_tag(c)); + oxstack_push((cmo *)tag); } +/***************************************************************************** + * -- SM_dupErrors -- + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static void oxserv_sm_dupErrors() { @@ -449,62 +446,122 @@ oxserv_sm_dupErrors() list = new_cmo_list(); - for (i = 0; i < oxserv_get_stack_pointer(); i++) { - c = oxserv_get(i); + for (i = 0; i < oxstack_get_stack_pointer(); i++) { + c = oxstack_get(i); if (c->tag == CMO_ERROR2) { list_append(list, c); } } - oxserv_push((cmo *)list); + oxstack_push((cmo *)list); } + + +/***************************************************************************** + * -- SM_control_reset_connection -- signal handler for SIGUSR1 -- + * + * PARAM : NONE + * + * : if (sig == 0) called UNBLOCK_INPUT() + * RETURN: NONE + *****************************************************************************/ +void +oxserv_sm_control_reset_connection(int sig) +{ + int tag; + OXFILE *fd = G_oxfilep; + + if (G_oxserv_sigusr1cnt > 0) { + G_oxserv_sigusr1flag = 1; + return ; + } + + + DPRINTF(("reset -- start ==> ")); + G_oxserv_sigusr1flag = 0; + + send_ox_tag(fd, OX_SYNC_BALL); + + oxstack_init_stack(); + + for (;;) { + tag = receive_ox_tag(fd); + DPRINTF(("[OX:%d=0x%x]", tag, tag)); + if (tag == OX_SYNC_BALL) + break; + if (tag == OX_DATA) + receive_cmo(fd); + else + receive_int32(fd); + } + DPRINTF((" <== end.\n")); + + + longjmp(G_jmpbuf, sig); +} + +/***************************************************************************** + * execute sm command + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ static int -oxserv_receive_and_execute_sm_command(OXFILE *fd) +oxserv_execute_sm_command(OXFILE *fd, int code) { - int code = receive_int32(fd); - DPRINTF(("SM_CODE=%d=0x%x\n", code, code)); + DPRINTF(("[SM:%d=0x%x]", code, code)); switch (code) { - case SM_popCMO: + case SM_popCMO: /* 262 */ oxserv_sm_popCMO(fd); break; - case SM_executeStringByLocalParser: + case SM_executeStringByLocalParser: /* 268 */ if (G_userExecuteStringParser) oxserv_sm_executeStringByLocalParser(); break; - case SM_executeStringByLocalParserInBatchMode: + case SM_executeStringByLocalParserInBatchMode: /* 274 */ if (G_userExecuteStringParser) oxserv_sm_executeStringByLocalParserInBatchMode(); break; - case SM_pops: + case SM_pops: /* 265 */ oxserv_sm_pops(); break; - case SM_popString: + case SM_popString: /* 263 */ oxserv_sm_popString(fd); break; - case SM_getsp: + case SM_getsp: /* 275 */ oxserv_sm_getsp(); break; - case SM_mathcap: + case SM_mathcap: /* 264 */ oxserv_sm_mathcap(); break; - case SM_setMathCap: + case SM_setMathCap: /* 273 */ /* dont support */ - oxserv_pop(); + oxstack_pop(); break; - case SM_executeFunction: + case SM_executeFunction: /* 269 */ if (G_userExecuteFunction) oxserv_sm_executeFunction(); break; - case SM_pushCMOtag: + case SM_pushCMOtag: /* 277 */ oxserv_sm_pushCMOtag(); break; - case SM_dupErrors: + case SM_dupErrors: /* 276 */ oxserv_sm_dupErrors(); break; + case SM_popSerializedLocalObject: + case SM_setName: + case SM_evalName: + case SM_beginBlock: + case SM_endBlock: + case SM_shutdown: + case SM_executeFunctionAndPopCMO: + case SM_executeFunctionAndPopSerializedLocalObject: + case SM_control_reset_connection: + case SM_control_reset_connection_server: default: break; } @@ -512,30 +569,35 @@ oxserv_receive_and_execute_sm_command(OXFILE *fd) } + /***************************************************************************** * reveice ox_data + * * PARAM : fd : OXFILE * RETURN: NONE *****************************************************************************/ -int -oxserv_receive(OXFILE *fd) +static int +oxserv_ox_receive(OXFILE *fd) { int tag; cmo *c; int ret = OXSERV_SUCCESS; + int code; tag = receive_ox_tag(fd); - DPRINTF(("oxserv_TAG=%d=0x%x\n", tag, tag)); switch (tag) { case OX_DATA: + BLOCK_INPUT(); c = receive_cmo(fd); - DPRINTF(("CMO_TAG=%d=0x%x\n", c->tag, c->tag)); - oxserv_push(c); + UNBLOCK_INPUT(); + DPRINTF(("[CMO:%d=0x%x]", c->tag, c->tag)); + oxstack_push(c); break; case OX_COMMAND: - ret = oxserv_receive_and_execute_sm_command(fd); + code = receive_int32(fd); + ret = oxserv_execute_sm_command(fd, code); break; default: @@ -546,12 +608,34 @@ oxserv_receive(OXFILE *fd) return (ret); } +int +oxserv_receive(OXFILE *fd) +{ + int i = 0; + int ret; + ret = setjmp(G_jmpbuf); + if (ret == 0) { + DPRINTF(("setjmp first time -- %d\n", ret)); + } else { + DPRINTF(("setjmp return from longjmp() -- %d -- \n", ret)); + } + + for (;; i++) { + ret = oxserv_ox_receive(fd); + if (ret != OXSERV_SUCCESS) + break; + } + return (ret); +} + + /***************************************************************************** * initialize oxserver * * PARAM : see oxserv_mathcap_init() - * RETURN: NONE + * RETURN: success : OXSERV_SUCCESS + * : failure : OXSERV_FAILURE * SEE : oxserv_mathcap_init() * : oxserv_set(); *****************************************************************************/ @@ -560,12 +644,22 @@ oxserv_init(OXFILE *oxfp, int ver, char *vstr, char *s { int ret; - ret = oxserv_init_stack(); + DPRINTF(("init start\n")); + + ret = oxstack_init_stack(); if (ret != OXSERV_SUCCESS) return (ret); + G_oxfilep = oxfp; + oxserv_mathcap_init(ver, vstr, sysname, cmos, sms); + signal(SIGUSR1, oxserv_sm_control_reset_connection); + + /* initialize GMP memory functions. */ + mp_set_memory_functions(oxserv_malloc, oxserv_realloc, oxserv_free); + + /* session start */ oxf_determine_byteorder_server(oxfp); return (OXSERV_SUCCESS); @@ -573,12 +667,14 @@ oxserv_init(OXFILE *oxfp, int ver, char *vstr, char *s /***************************************************************************** - * set oxserver + * set oxserver behavior + * * PARAM : mode : mode * : * : ptr : * : rsv : reserve space. - * RETURN: NONE + * RETURN: success : OXSERV_SUCCESS + * : failure : OXSERV_FAILURE * SEE : *****************************************************************************/ int @@ -586,14 +682,20 @@ oxserv_set(int mode, void *ptr, void *rsv) { switch (mode) { case OXSERV_SET_EXECUTE_FUNCTION: - G_userExecuteFunction = (cmo *(*)(const char *, cmo **, int))ptr; + G_userExecuteFunction = (void (*)(const char *, cmo **, int))ptr; break; case OXSERV_SET_EXECUTE_STRING_PARSER: - G_userExecuteStringParser = (cmo *(*)(const char *))ptr; + G_userExecuteStringParser = (void (*)(const char *))ptr; break; case OXSERV_SET_CONVERT_CMO: G_convertCmo = (cmo *(*)(cmo *))ptr; break; + case OXSERV_SET_DELETE_CMO: + G_DeleteCmo = (void (*)(cmo *))ptr; + break; + case OXSERV_SET_GET_CMOTAG: + G_getCmoTag = (int (*)(cmo *))ptr; + break; default: return (OXSERV_FAILURE); } @@ -605,23 +707,26 @@ oxserv_set(int mode, void *ptr, void *rsv) /***************************************************************************** * destroy - * PARAM : mode : mode - * : - * : ptr : - * : rsv : reserve space. + * + * PARAM : NONE * RETURN: NONE - * SEE : *****************************************************************************/ void oxserv_dest() { - free(G_ox_stack); + oxserv_delete_cmo(G_oxserv_mathcap); + + oxstack_dest(); } -#if 0 +#if __OXSERV_DEBUG +/*===========================================================================* + * DEBUG + *===========================================================================*/ -cmo * + +void oxserv_executeFunction(const char *func, cmo **arg, int argc) { int i; @@ -632,9 +737,15 @@ oxserv_executeFunction(const char *func, cmo **arg, in printf("\t%2d: %s\n", i, new_string_set_cmo(arg[i])); } - return ((cmo *)new_cmo_int32(0)); + return ; } +/***************************************************************************** + * main + * + * PARAM : NONE + * RETURN: NONE + *****************************************************************************/ int main(int argc, char *argv[]) { @@ -646,20 +757,18 @@ main(int argc, char *argv[]) ox_stderr_init(stderr); - oxserv_init(0, "$Date: 2003/11/03 03:11:21 $", "oxserv", NULL, NULL); + oxserv_set(OXSERV_SET_EXECUTE_FUNCTION, oxserv_executeFunction, NULL); - DPRINTF(("main - start\n")); - for (i = 0;; i++) { - DPRINTF(("@")); - ret = oxserv_receive(oxfp); - if (ret != OXSERV_SUCCESS) - break; - } + oxserv_init(oxfp, 0, "$Date: 2004/07/04 11:38:42 $", "oxserv", NULL, NULL); - oxf_close(fd); - delete_cmo(G_oxserv_mathcap); + ret = oxserv_receive(oxfp); + oxserv_dest(); + oxf_close(oxfp); + return (0); } #endif + +