void gvcmz_lkcancel_ast(struct CLB *lnk) { uint4 status; if (CMI_CLB_ERROR(lnk)) { ((link_info *)(lnk->usr))->neterr = TRUE; lkerror = CMMS_L_LKCANCEL; lkerrlnk = lnk; return; } if (*(lnk->mbf) == CMMS_M_LKDELETED || *(lnk->mbf) == CMMS_M_LKABORT || /* per spec */ *(lnk->mbf) == CMMS_L_LKCANCEL) { /* above are end of conversation */ lnk->ast = 0; lkcancel_count++; } else if (*(lnk->mbf) == CMMS_M_LKSUSPENDED || *(lnk->mbf) == CMMS_M_LKGRANTED || *(lnk->mbf) == CMMS_M_LKBLOCKED) { /* above are response from prior message, ours is to come */ status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; lkerror = CMMS_L_LKCANCEL; lkerrlnk = lnk; } else lkresponse_count++; } else { lkerror = CMMS_L_LKCANCEL; lkerrlnk = lnk; } }
bool gtcmtr_lke_showreq(struct CLB *lnk, char rnum, bool all, bool wait, int4 pid, mstr *node) { show_request sreq; show_reply srep; bool locks = FALSE; uint4 status; sreq.code = CMMS_U_LKESHOW; sreq.rnum = rnum; sreq.all = all; sreq.wait = wait; sreq.pid = pid; assert(node && node->addr); sreq.nodelength = node->len; memcpy(sreq.node, node->addr, node->len); lnk->cbl = sizeof(sreq); lnk->mbf = (unsigned char *)&sreq; lnk->ast = NULL; status = cmi_write(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(CMMS_U_LKESHOW, status); return FALSE; } lnk->mbl = sizeof(srep); lnk->mbf = (unsigned char *)&srep; for (;;) { status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(CMMS_V_LKESHOW, status); return FALSE; } if (srep.code != CMMS_V_LKESHOW) return locks; util_out_print(srep.line, FLUSH); locks = TRUE; } }
void gtcm_write_ast(struct CLB *c) { if (CMI_CLB_ERROR(c)) { /* error */ *c->mbf = CMMS_E_TERMINATE; c->ast = 0; gtcm_action_pending(c->usr); return; } if (((connection_struct *)c->usr)->int_cancel.laflag & 1) { /* deal with deferred interrupt cancel message in gtcm_mbxread_ast */ c->ast = 0; gtcm_int_unpack(c->usr); } else if (((connection_struct *)c->usr)->state != CM_NOOP) /* never NOOP I think - smw */ { c->ast = gtcm_read_ast; cmi_read(c); } else c->ast = NULL; }
void gvcmx_susremlk(unsigned char rmv_locks) { uint4 status,count,buffer; unsigned char *ptr; struct CLB *p; error_def(ERR_BADSRVRNETMSG); if (!ntd_root) return; buffer = lksusp_sent = lksusp_rec = 0; for (p = (struct CLB *)RELQUE2PTR(ntd_root->cqh.fl); p != (struct CLB *)ntd_root; p = (struct CLB *)RELQUE2PTR(p->cqe.fl)) { if (((link_info*)(p->usr))->lck_info & REQUEST_PENDING) buffer += p->mbl; } ENSURE_STP_FREE_SPACE(buffer); ptr = stringpool.free; for (p = (struct CLB *)RELQUE2PTR(ntd_root->cqh.fl); p != (struct CLB *)ntd_root; p = (struct CLB *)RELQUE2PTR(p->cqe.fl)) { if (((link_info *)(p->usr))->lck_info & REQUEST_PENDING) { p->mbf = ptr; *ptr++ = CMMS_L_LKSUSPEND; *ptr++ = rmv_locks; p->cbl = 2; p->ast = 0; status = cmi_write(p); if (CMI_ERROR(status)) { ((link_info *)(p->usr))->neterr = TRUE; gvcmz_error(CMMS_M_LKSUSPENDED, status); return; } p->ast = gvcmz_lksuspend_ast; status = cmi_read(p); if (CMI_ERROR(status)) { ((link_info *)(p->usr))->neterr = TRUE; gvcmz_error(CMMS_M_LKSUSPENDED, status); return; } lksusp_sent++; ptr = p->mbf + p->mbl; } } while (lksusp_sent != lksusp_rec && !lkerror) CMI_IDLE(CM_LKSUSPEND_TIME); if (lkerror) { if (CMI_CLB_ERROR(lkerrlnk)) gvcmz_error(lkerror, CMI_CLB_IOSTATUS(lkerrlnk)); else { if (*(lkerrlnk->mbf) != CMMS_E_ERROR) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); else gvcmz_errmsg(lkerrlnk, FALSE); } } }
void gvcmz_doop(unsigned char query_code, unsigned char reply_code, mval *v) { unsigned char *ptr; short len, temp_short; int4 status, max_reply_len; struct CLB *lnk; unsigned char buff[MAX_ZWR_KEY_SZ], *end; error_def(ERR_BADSRVRNETMSG); error_def(ERR_UNIMPLOP); error_def(ERR_TEXT); error_def(ERR_GVIS); lnk = gv_cur_region->dyn.addr->cm_blk; if (!((link_info *)lnk->usr)->server_supports_long_names && (PRE_V5_MAX_MIDENT_LEN < strlen((char *)gv_currkey->base))) { end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE); rts_error(VARLSTCNT(14) ERR_UNIMPLOP, 0, ERR_TEXT, 2, LEN_AND_LIT("GT.CM server does not support global names longer than 8 characters"), ERR_GVIS, 2, end - buff, buff, ERR_TEXT, 2, DB_LEN_STR(gv_cur_region)); } lnk->ast = 0; /* all database queries are sync */ lnk->cbl = 1 + /* HDR */ gv_currkey->end + /* key */ sizeof(unsigned short) + /* gv_key.top */ sizeof(unsigned short) + /* gv_key.end */ sizeof(unsigned short) + /* gv_key.prev */ sizeof(unsigned char) + /* gv_key.base */ sizeof(unsigned char) + /* regnum */ sizeof(unsigned short); /* size for variable len SUBSC */ /* the current GT.CM maximum message buffer length is bounded by the size of a short which is 64K. but the * calculation below of lnk->cbl and max_reply_len takes into account the fact that the value that is sent in as * input or read in from the server side can be at most MAX_DBSTRLEN in size. therefore, there is a dependency * that MAX_DBSTRLEN always be less than the GT.CM maximum message buffer length. to ensure this is always the * case, the following assert is added so that whenever MAX_DBSTRLEN is increased, we will fail this assert * and reexamine the code below. */ assert(sizeof(lnk->cbl) == 2); /* assert it is a short. when it becomes a uint4 the assert can be removed * if the macro CM_MAX_BUF_LEN (used below) is changed appropriately */ assert(MAX_DBSTRLEN == (32 * 1024 - 1)); if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code) { if (CMMS_Q_INCREMENT == query_code) { /* 1-byte boolean value of "undef_inhibit" passed to the server for $INCREMENT although, effective V5.0-000, undef_inhibit is no longer relevant as $INCREMENT() implicitly does a $GET() on the global. We keep this byte to ensure compatibility with V5.0-FT01 */ lnk->cbl++; } assert((uint4)lnk->cbl + sizeof(unsigned short) + (uint4)MAX_DBSTRLEN <= (uint4)CM_MAX_BUF_LEN); lnk->cbl += (sizeof(unsigned short) + v->str.len); /* VALUE + length */ } if ((CMMS_Q_GET == query_code) || (CMMS_Q_INCREMENT == query_code) || (CMMS_Q_QUERY == query_code) && ((link_info *)lnk->usr)->query_is_queryget) max_reply_len = lnk->mbl + SIZEOF(unsigned short) + MAX_DBSTRLEN; /* can't predict the length of data value */ else max_reply_len = lnk->mbl; assert(max_reply_len <= (int4)CM_MAX_BUF_LEN); if (stringpool.top < stringpool.free + max_reply_len) stp_gcol(max_reply_len); lnk->mbf = stringpool.free; ptr = lnk->mbf; *ptr++ = query_code; /* temp_short = gv_currkey->end + sizeof(gv_key) + 1; */ temp_short = gv_currkey->end + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(char) + 1; CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); *ptr++ = gv_cur_region->cmx_regnum; CM_PUT_SHORT(ptr, gv_currkey->top, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->end, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->prev, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr, gv_currkey->base, gv_currkey->end + 1); if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code) { ptr += gv_currkey->end + 1; temp_short = (short)v->str.len; assert((int4)temp_short == v->str.len); /* short <- int4 assignment lossy? */ CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr,v->str.addr, v->str.len); if (CMMS_Q_INCREMENT == query_code) { /* UNDEF flag is no longer relevant, but set the flag to ensure compatibility with V5.0-FT01 */ assert(sizeof(undef_inhibit) == 1); ptr[v->str.len] = (unsigned char)undef_inhibit; } } status = cmi_write(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (CMMS_Q_PUT == query_code || CMMS_Q_ZWITHDRAW == query_code || CMMS_Q_KILL == query_code) { if (reply_code != *ptr) { if (*ptr != CMMS_E_ERROR) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk,FALSE); } return; } if (reply_code != *ptr) { if ((CMMS_R_UNDEF != *ptr) || ((CMMS_Q_GET != query_code) && (CMMS_Q_INCREMENT != query_code))) { if (CMMS_E_ERROR != *ptr) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk, FALSE); } if (CMMS_Q_INCREMENT == query_code) v->mvtype = 0; /* set the result to be undefined */ return; } ptr++; if (CMMS_R_DATA == reply_code) { CM_GET_SHORT(temp_short, ptr, ((link_info *)(lnk->usr))->convert_byteorder); if (1 != temp_short) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); ptr += sizeof(short); status = *ptr; /* Temp assignment to status gets rid of compiler warning in MV_FORCE_MVAL macro */ MV_FORCE_MVAL(v, status); return; } if (reply_code == CMMS_R_PREV || reply_code == CMMS_R_QUERY || reply_code == CMMS_R_ORDER) { CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); if (1 == len) { MV_FORCE_MVAL(v, 0); } else { if (*ptr++ != gv_cur_region->cmx_regnum) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); /* memcpy(gv_altkey, ptr, len - 1); */ CM_GET_USHORT(gv_altkey->top, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->end, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->prev, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); memcpy(gv_altkey->base, ptr, len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); ptr += (len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); MV_FORCE_MVAL(v, 1); } if (CMMS_R_QUERY != reply_code || 1 == len || !((link_info *)lnk->usr)->query_is_queryget) { if (CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget) v->mvtype = 0; /* force undefined to distinguish $Q returning "" from value of QUERYGET being 0 */ return; } } assert(CMMS_R_GET == reply_code || CMMS_R_INCREMENT == reply_code || CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget && 1 < len); CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); assert(ptr >= stringpool.base && ptr + len < stringpool.top); /* incoming message is in stringpool */ v->mvtype = MV_STR; v->str.len = len; v->str.addr = (char *)stringpool.free; /* we don't need the reply msg anymore, can overwrite reply */ memcpy(v->str.addr, ptr, len); /* so that we don't leave a gaping hole in the stringpool */ stringpool.free += len; return; }
gtcm_server() { static readonly int4 reptim[2] = {-100000, -1}; /* 10ms */ static readonly int4 wait[2] = {-1000000, -1}; /* 100ms */ void gtcm_ch(), gtcm_exi_handler(), gtcm_init_ast(), gtcm_int_unpack(), gtcm_mbxread_ast(), gtcm_neterr(), gtcm_read_ast(), gtcm_remove_from_action_queue(), gtcm_shutdown_ast(), gtcm_write_ast(), la_freedb(); bool gtcm_link_accept(); bool alid; char buff[512]; char *h = NULL; char *la_getdb(); char nbuff[256]; char *pak = NULL; char reply; unsigned short outlen; int4 closewait[2] = {0, -1}; int4 inid = 0, mdl = 0, nid = 0, days = 0; int4 lic_status; int4 lic_x; int4 lm_mdl_nid(); uint4 status; int i, receive(), value; mstr name1, name2; struct NTD *cmu_ntdroot(); connection_struct *prev_curr_entry; struct dsc$descriptor_s dprd; struct dsc$descriptor_s dver; $DESCRIPTOR(node_name, nbuff); $DESCRIPTOR(proc_name, "GTCM_SERVER"); $DESCRIPTOR(timout, buff); DCL_THREADGBL_ACCESS; GTM_THREADGBL_INIT; assert(0 == EMPTY_QUEUE); /* check so dont need gdsfhead everywhere */ common_startup_init(GTCM_GNP_SERVER_IMAGE); /* Side-effect: Sets skip_dbtriggers to TRUE for non-trigger platforms */ gtm_env_init(); /* read in all environment variables */ name1.addr = "GTCMSVRNAM"; name1.len = SIZEOF("GTCMSVRNAM") - 1; status = trans_log_name(&name1, &name2, nbuff); if (SS$_NORMAL == status) { proc_name.dsc$a_pointer = nbuff; proc_name.dsc$w_length = node_name.dsc$w_length = name2.len; } else if (SS$_NOLOGNAM == status) { MEMCPY_LIT(nbuff, "GTCMSVR"); node_name.dsc$w_length = SIZEOF("GTCMSVR") - 1; } else rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); sys$setprn(&proc_name); status = lib$get_foreign(&timout, 0, &outlen, 0); if ((status & 1) && (6 > outlen)) { for (i = 0; i < outlen; i++) { value = value * 10; if (buff[i] <= '9' && buff[i] >= '0') value += buff[i] - 48; else break; } if (outlen && (i == outlen)) { cm_timeout = TRUE; closewait[0] = value * -10000000; } } dprd.dsc$w_length = cm_prd_len; dprd.dsc$b_dtype = DSC$K_DTYPE_T; dprd.dsc$b_class = DSC$K_CLASS_S; dprd.dsc$a_pointer= cm_prd_name; dver.dsc$w_length = cm_ver_len; dver.dsc$b_dtype = DSC$K_DTYPE_T; dver.dsc$b_class = DSC$K_CLASS_S; dver.dsc$a_pointer= cm_ver_name; ast_init(); licensed = TRUE; lkid = 2; # ifdef NOLICENSE lid = 1; # else /* this code used to be scattered to discourage reverse engineering, but since it now disabled, that seems pointless */ lic_status = ((NULL == (h = la_getdb(LMDB))) ? LP_NOCNFDB : SS$_NORMAL); lic_status = ((1 == (lic_status & 1)) ? lm_mdl_nid(&mdl, &nid, &inid) : lic_status); lic_status = ((1 == (lic_status & 1)) ? lp_licensed(h, &dprd, &dver, mdl, nid, &lid, &lic_x, &days, pak) : lic_status); if (LP_NOCNFDB != lic_status) la_freedb(h); if (1 == (lic_status & 1)) { licensed = TRUE; if (days < 14) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_WILLEXPIRE); } else { licensed = FALSE; sys$exit(lic_status); } # endif gtcm_ast_avail = astq_dyn_avail - GTCM_AST_OVRHD; stp_init(STP_INITSIZE); rts_stringpool = stringpool; cache_init(); procnum = 0; get_proc_info(0, TADR(login_time), &image_count); memset(proc_to_clb, 0, SIZEOF(proc_to_clb)); status = cmi_init(&node_name, 0, 0, gtcm_init_ast, gtcm_link_accept); if (!(status & 1)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ((status ^ 3) | 4)); sys$exit(status); } ntd_root = cmu_ntdroot(); ntd_root->mbx_ast = gtcm_mbxread_ast; ntd_root->err = gtcm_neterr; gtcm_connection = FALSE; lib$establish(gtcm_ch); gtcm_exi_blk.exit_hand = >cm_exi_handler; gtcm_exi_blk.arg_cnt = 1; gtcm_exi_blk.cond_val = >cm_exi_condition; sys$dclexh(>cm_exi_blk); INVOKE_INIT_SECSHR_ADDRS; initialize_pattern_table(); assert(run_time); /* Should have been set by common_startup_init */ while (!cm_shutdown) { if (blkdlist) gtcml_chkreg(); assert(!lib$ast_in_prog()); status = sys$dclast(>cm_remove_from_action_queue, 0, 0); if (SS$_NORMAL != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) CMERR_CMSYSSRV, 0, status, 0); if (INTERLOCK_FAIL == curr_entry) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) CMERR_CMINTQUE); if (EMPTY_QUEUE != curr_entry) { switch (*curr_entry->clb_ptr->mbf) { case CMMS_L_LKCANALL: reply = gtcmtr_lkcanall(); break; case CMMS_L_LKCANCEL: reply = gtcmtr_lkcancel(); break; case CMMS_L_LKREQIMMED: reply = gtcmtr_lkreqimmed(); break; case CMMS_L_LKREQNODE: reply = gtcmtr_lkreqnode(); break; case CMMS_L_LKREQUEST: reply = gtcmtr_lkrequest(); break; case CMMS_L_LKRESUME: reply = gtcmtr_lkresume(); break; case CMMS_L_LKACQUIRE: reply = gtcmtr_lkacquire(); break; case CMMS_L_LKSUSPEND: reply = gtcmtr_lksuspend(); break; case CMMS_L_LKDELETE: reply = gtcmtr_lkdelete(); break; case CMMS_Q_DATA: reply = gtcmtr_data(); break; case CMMS_Q_GET: reply = gtcmtr_get(); break; case CMMS_Q_KILL: reply = gtcmtr_kill(); break; case CMMS_Q_ORDER: reply = gtcmtr_order(); break; case CMMS_Q_PREV: reply = gtcmtr_zprevious(); break; case CMMS_Q_PUT: reply = gtcmtr_put(); break; case CMMS_Q_QUERY: reply = gtcmtr_query(); break; case CMMS_Q_ZWITHDRAW: reply = gtcmtr_zwithdraw(); break; case CMMS_S_INITPROC: reply = gtcmtr_initproc(); break; case CMMS_S_INITREG: reply = gtcmtr_initreg(); break; case CMMS_S_TERMINATE: reply = gtcmtr_terminate(TRUE); break; case CMMS_E_TERMINATE: reply = gtcmtr_terminate(FALSE); break; case CMMS_U_LKEDELETE: reply = gtcmtr_lke_clearrep(curr_entry->clb_ptr, curr_entry->clb_ptr->mbf); break; case CMMS_U_LKESHOW: reply = gtcmtr_lke_showrep(curr_entry->clb_ptr, curr_entry->clb_ptr->mbf); break; case CMMS_B_BUFRESIZE: reply = CM_WRITE; value = *(unsigned short *)(curr_entry->clb_ptr->mbf + 1); if (value > curr_entry->clb_ptr->mbl) { free(curr_entry->clb_ptr->mbf); curr_entry->clb_ptr->mbf = malloc(value); } *curr_entry->clb_ptr->mbf = CMMS_C_BUFRESIZE; curr_entry->clb_ptr->mbl = value; curr_entry->clb_ptr->cbl = 1; break; case CMMS_B_BUFFLUSH: reply = gtcmtr_bufflush(); break; case CMMS_Q_INCREMENT: reply = gtcmtr_increment(); break; default: reply = FALSE; if (SS$_NORMAL == status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_BADGTMNETMSG, 1, (int)*curr_entry->clb_ptr->mbf); break; } if (curr_entry) /* curr_entry can be NULL if went through gtcmtr_terminate */ { status = sys$gettim(&curr_entry->lastact[0]); if (SS$_NORMAL != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); /* curr_entry is used by gtcm_mbxread_ast to determine if it needs to defer the interrupt message */ prev_curr_entry = curr_entry; if (CM_WRITE == reply) { /* if ast == gtcm_write_ast, let it worry */ curr_entry->clb_ptr->ast = gtcm_write_ast; curr_entry = EMPTY_QUEUE; cmi_write(prev_curr_entry->clb_ptr); } else { curr_entry = EMPTY_QUEUE; if (1 == (prev_curr_entry->int_cancel.laflag & 1)) { /* valid interrupt cancel msg, handle in gtcm_mbxread_ast */ status = sys$dclast(gtcm_int_unpack, prev_curr_entry, 0); if (SS$_NORMAL != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); } else if (CM_READ == reply) { prev_curr_entry->clb_ptr->ast = gtcm_read_ast; cmi_read(prev_curr_entry->clb_ptr); } } } } else if (1 < astq_dyn_avail) { # ifdef GTCM_REPTIM /* if reptim is not needed - and smw doesn't know why it would be - remove this */ status = sys$schdwk(0, 0, &wait[0], &reptim[0]); # else status = sys$schdwk(0, 0, &wait[0], 0); # endif sys$hiber(); sys$canwak(0, 0); } if (cm_timeout && (0 == gtcm_users)) sys$setimr(efn_ignore, closewait, gtcm_shutdown_ast, &cm_shutdown, 0); } }
void gvcmz_doop(unsigned char query_code, unsigned char reply_code, mval *v) { unsigned char *ptr; short len, temp_short; int4 status, max_reply_len; struct CLB *lnk; error_def(ERR_BADSRVRNETMSG); lnk = gv_cur_region->dyn.addr->cm_blk; lnk->ast = 0; /* all database queries are sync */ lnk->cbl = 1 + /* HDR */ gv_currkey->end + /* key */ sizeof(unsigned short) + /* gv_key.top */ sizeof(unsigned short) + /* gv_key.end */ sizeof(unsigned short) + /* gv_key.prev */ sizeof(unsigned char) + /* gv_key.base */ sizeof(unsigned char) + /* regnum */ sizeof(unsigned short); /* size for variable len SUBSC */ if (CMMS_Q_PUT == query_code) lnk->cbl += (sizeof(unsigned short) + v->str.len); /* VALUE + length */ if (CMMS_Q_GET == query_code || CMMS_Q_QUERY == query_code && ((link_info *)lnk->usr)->query_is_queryget) max_reply_len = lnk->mbl + sizeof(unsigned short) + MAX_STRLEN; /* can't predict the length of data value */ else max_reply_len = lnk->mbl; if (stringpool.top < stringpool.free + max_reply_len) stp_gcol(max_reply_len); lnk->mbf = stringpool.free; ptr = lnk->mbf; *ptr++ = query_code; /* temp_short = gv_currkey->end + sizeof(gv_key) + 1; */ temp_short = gv_currkey->end + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(char) + 1; CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); *ptr++ = gv_cur_region->cmx_regnum; CM_PUT_SHORT(ptr, gv_currkey->top, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->end, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); CM_PUT_SHORT(ptr, gv_currkey->prev, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr, gv_currkey->base, gv_currkey->end + 1); if (query_code == CMMS_Q_PUT) { ptr += gv_currkey->end + 1; temp_short = (short)v->str.len; assert((int4)temp_short == v->str.len); /* short <- int4 assignment lossy? */ CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); memcpy(ptr,v->str.addr, v->str.len); } status = cmi_write(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } if (CMMS_Q_PUT == query_code || CMMS_Q_ZWITHDRAW == query_code || CMMS_Q_KILL == query_code) { status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (reply_code != *ptr) { if (*ptr != CMMS_E_ERROR) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk,FALSE); } return; } status = cmi_read(lnk); if (CMI_ERROR(status)) { ((link_info *)(lnk->usr))->neterr = TRUE; gvcmz_error(query_code, status); return; } ptr = lnk->mbf; if (reply_code != *ptr) { if (CMMS_R_UNDEF != *ptr || CMMS_Q_GET != query_code) { if (CMMS_E_ERROR != *ptr) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); gvcmz_errmsg(lnk, FALSE); } return; } ptr++; if (CMMS_R_DATA == reply_code) { CM_GET_SHORT(temp_short, ptr, ((link_info *)(lnk->usr))->convert_byteorder); if (1 != temp_short) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); ptr += sizeof(short); status = *ptr; /* Temp assignment to status gets rid of compiler warning in MV_FORCE_MVAL macro */ MV_FORCE_MVAL(v, status); return; } if (reply_code == CMMS_R_PREV || reply_code == CMMS_R_QUERY || reply_code == CMMS_R_ORDER) { CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(short); if (1 == len) { MV_FORCE_MVAL(v, 0); } else { if (*ptr++ != gv_cur_region->cmx_regnum) rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG); /* memcpy(gv_altkey, ptr, len - 1); */ CM_GET_USHORT(gv_altkey->top, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->end, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); CM_GET_USHORT(gv_altkey->prev, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); memcpy(gv_altkey->base, ptr, len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); ptr += (len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short)); MV_FORCE_MVAL(v, 1); } if (CMMS_R_QUERY != reply_code || 1 == len || !((link_info *)lnk->usr)->query_is_queryget) { if (CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget) v->mvtype = 0; /* force undefined to distinguish $Q returning "" from value of QUERYGET being 0 */ return; } } assert(CMMS_R_GET == reply_code || CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget && 1 < len); CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder); ptr += sizeof(unsigned short); assert(ptr >= stringpool.base && ptr + len < stringpool.top); /* incoming message is in stringpool */ v->mvtype = MV_STR; v->str.len = len; v->str.addr = (char *)stringpool.free; /* we don't need the reply msg anymore, can overwrite reply */ memcpy(v->str.addr, ptr, len); /* so that we don't leave a gaping hole in the stringpool */ stringpool.free += len; return; }