/* ** Name: qeu_evraise ** ** Description: ** This routine raises an event, it processes the external request ** QEU_RAISE_EVENT, typically when raising the event associated with ** a security alarm. ** ** Note this *does* do event tracing (SET PRINTEVENTS/LOGEVENTS) ** but does *not* do security checks/auditing on the operation, this ** is assumed to be handled at a higher level. ** ** Inputs: ** qef_rcb.evname - Event name ** qef_rcb.evowner - Event owner ** qef_rcb.evtext - Event text ** qef_rcb.ev_l_text- Length of text ** ** History: ** 26-nov-93 (robf) ** Created for secure 2.0 ** 12-Jan-1998 (kinpa04/merja01) ** Remove (i4) casting of session id. This caused the ** session ID to get truncated on axp_osf while raising events. ** 10-Jan-2001 (jenjo02) ** We know this session's id; pass it to SCF. ** 30-Dec-2005 (kschendel) ** Update call to qef-adf-error. ** */ DB_STATUS qeu_evraise( QEF_CB *qef_cb, QEF_RCB *qef_rcb ) { DB_DATA_VALUE tm; /* Timestamp */ DB_DATE tm_date; SCF_ALERT scfa; SCF_CB scf_cb; SCF_SCI sci_list[1]; DB_ALERT_NAME alert; i4 err; char *errstr; DB_STATUS status=E_DB_OK; i4 tr1 = 0, tr2 = 0; /* Dummy trace values */ /* ** Build alert name */ STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evname, alert.dba_alert); STRUCT_ASSIGN_MACRO(*qef_rcb->qef_evowner, alert.dba_owner); scf_cb.scf_length = sizeof(SCF_CB); scf_cb.scf_type = SCF_CB_TYPE; scf_cb.scf_facility = DB_QEF_ID; scf_cb.scf_session = qef_cb->qef_ses_id; /* Get the database name */ scf_cb.scf_ptr_union.scf_sci = (SCI_LIST *) sci_list; scf_cb.scf_len_union.scf_ilength = 1; sci_list[0].sci_length = sizeof(DB_DB_NAME); sci_list[0].sci_code = SCI_DBNAME; sci_list[0].sci_aresult = (char *) &alert.dba_dbname; sci_list[0].sci_rlength = NULL; status = scf_call(SCU_INFORMATION, &scf_cb); if (status != E_DB_OK) { _VOID_ qef_error(E_QE022F_SCU_INFO_ERROR, 0L, status, &err, &qef_rcb->error, 0); return E_DB_ERROR; } /* Format SCF event request block */ scf_cb.scf_ptr_union.scf_alert_parms = &scfa; scfa.scfa_name = &alert; scfa.scfa_text_length = 0; scfa.scfa_user_text = NULL; scfa.scfa_flags = 0; if (qef_rcb->qef_ev_l_text > 0) /* No need for empty strings */ { if (qef_rcb->qef_ev_l_text > DB_EVDATA_MAX) qef_rcb->qef_ev_l_text = DB_EVDATA_MAX; scfa.scfa_text_length = qef_rcb->qef_ev_l_text; scfa.scfa_user_text = qef_rcb->qef_evtext; } tm.db_datatype = DB_DTE_TYPE; /* Get time stamp for the event */ tm.db_prec = 0; tm.db_length = sizeof(tm_date); tm.db_data = (PTR)&tm_date; tm.db_collID = -1; status = adu_datenow(qef_cb->qef_adf_cb, &tm); if (status != E_DB_OK) { if ((status = qef_adf_error(&qef_cb->qef_adf_cb->adf_errcb, status, qef_cb, &qef_rcb->error)) != E_DB_OK) return (status); } scfa.scfa_when = &tm_date; /* If tracing and/or logging events then display event information */ if (ult_check_macro(&qef_cb->qef_trace, QEF_T_EVENTS, &tr1, &tr2)) qea_evtrace(qef_rcb, QEF_T_EVENTS, &alert, &tm, (i4)qef_rcb->qef_ev_l_text, (char*)qef_rcb->qef_evtext); if (ult_check_macro(&qef_cb->qef_trace, QEF_T_LGEVENTS, &tr1, &tr2)) qea_evtrace(qef_rcb, QEF_T_LGEVENTS, &alert, &tm, 0, (char *)NULL); /* ** Raise the event in SCF */ status = scf_call(SCE_RAISE, &scf_cb); if (status != E_DB_OK) { char *enm, *onm; /* Event and owner names */ enm = (char *)&alert.dba_alert; onm = (char *)&alert.dba_owner; errstr="RAISE"; switch (scf_cb.scf_error.err_code) { case E_SC0270_NO_EVENT_MESSAGE: _VOID_ qef_error(E_QE019A_EVENT_MESSAGE, 0L, status, &err, &qef_rcb->error, 1, (i4)STlength(errstr), errstr); break; case E_SC0280_NO_ALERT_INIT: _VOID_ qef_error(E_QE0200_NO_EVENTS, 0L, status, &err, &qef_rcb->error, 1, (i4)STlength(errstr), errstr); break; default: _VOID_ qef_error(E_QE020F_EVENT_SCF_FAIL, 0L, status, &err, &qef_rcb->error, 4, (i4)STlength(errstr), errstr, (i4)sizeof(i4), (PTR)&scf_cb.scf_error.err_code, qec_trimwhite(DB_OWN_MAXNAME, onm), onm, qec_trimwhite(DB_EVENT_MAXNAME, enm), enm); break; } qef_rcb->error.err_code = E_QE0025_USER_ERROR; status = E_DB_ERROR; } /* If SCF not ok */ return status; }
/*{ ** Name: qeu_devent - Drop an event definition. ** ** External QEF call: status = qef_call(QEU_DEVENT, &qeuq_cb); ** ** Description: ** Drop the event tuple and the event text from the appropriate ** tables (iievent and iiqrytext). An event may only be dropped ** by name as a result of the DROP EVENT statement. ** ** The single event tuple is deleted based on its name and owner (since ** the iievent table is hashed on name and owner this is a singleton ** keyed retrieval). If the event tuple wasn't fetched, then an error ** is returned to the user. ** ** If the event was found then all permits applied to this event ** are dropped (using qeu_dprot with the dummy event/table ids and ** without a permit number to indicate ALL protection tuples). In ** this case qeu_dprot need not recheck that the event does exist. ** Note that the qeu_dprot routine will open and close iiqrytext ** to remove the text associated with the event permit. ** ** Following permit removal all query text tuples associated with the ** CREATE EVENT statement are removed from iiqrytext based on the ** query text ids in the fetched event tuple. ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_culd Number of event tuples. Must be 1. ** .qeuq_uld_tup Event tuple: ** .dbe_name Event name. ** .dbe_owner Event owner. ** .dbe_type Event type - ignored until there are more. ** Remaining fields are assigned and used here. ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** E_QE020B_EVENT_ABSENT (ret E_QE0025_USER_ERROR) ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 28-aug-89 (neil) ** Written for Terminator II/alerters. ** 09-feb-90 (neil) ** Added auditing functionality. ** 03-mar-90 (neil) ** Modify interface to que_dprot to indicate from DROP EVENT. ** 24-jun-92 (andre) ** after deleting IIEVENT tuple, call qeu_d_cascade to handle ** destruction of IIPROTECT, IIQRYTEXT tuples and marking dependent ** dbprocs dormant ** 08-sep-92 (andre) ** before calling qeu_d_cascade(), reset QEU_DROP_TEMP_TABLE in ** qeuq_flag_mask ** 24-jun-93 (robf) ** Perform MAC access check prior to drop of event. If no access is ** allowed then treat as non-existent event. ** 10-sep-93 (andre) ** before calling qeu_d_cascade(), set QEU_FORCE_QP_INVALIDATION in ** qeuq_flag_mask ** 21-sep-93 (stephenb) ** Replace generic I_SX2032_EVENT_ACCESS with I_SX203C_EVENT_DROP. ** 08-oct-93 (andre) ** qeu_d_cascade() expects one more parameter - an address of a ** DMT_TBL_ENTRY describing table/view/index being dropped; for all ** other types of objects, NULL must be passed ** 14-oct-93 (robf) ** Make sure access check is on tuple being deleted, not input tuple. ** 7-dec-93 (robf) ** Check if event is in used by an alarm, if so reject the operation. ** 7-jun-94 (robf) ** audit the security label for the event correctly on B1, this ** ensures level auditing picks up the change. (Previously we were ** auditing the input tuple security label, which was empty, ** not the delete tuple security label). Also don't try to ** but this makes the case clearer) ** 12-oct-94 (ramra01) ** Initialize variable local_status before use - 65258 ** 13-jun-96 (nick) ** Above change didn't actually work. ** */ DB_STATUS qeu_devent( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { QEU_CB tranqeu; /* For transaction request */ bool transtarted = FALSE; QEU_CB evqeu; /* For iievent table */ QEF_DATA evqef_data; DB_IIEVENT *evtuple; /* Input tuple with name and owner */ DB_IIEVENT evtuple_del; /* Tuple currently being deleted */ bool event_opened = FALSE; DMR_ATTR_ENTRY evkey_array[2]; /* Key values from iievent */ DMR_ATTR_ENTRY *evkey_ptr_array[2]; DB_STATUS status; DB_STATUS local_status = E_DB_OK; i4 error; DB_ERROR err; for (;;) /* Dummy for loop for error breaks */ { /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; evtuple = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data; /* Open iievent tables */ evqeu.qeu_type = QEUCB_CB; evqeu.qeu_length = sizeof(QEUCB_CB); evqeu.qeu_db_id = qeuq_cb->qeuq_db_id; evqeu.qeu_lk_mode = DMT_IX; evqeu.qeu_flag = DMT_U_DIRECT; evqeu.qeu_access_mode = DMT_A_WRITE; evqeu.qeu_mask = 0; evqeu.qeu_tab_id.db_tab_base = DM_B_EVENT_TAB_ID; /* Open iievent */ evqeu.qeu_tab_id.db_tab_index = DM_I_EVENT_TAB_ID; status = qeu_open(qef_cb, &evqeu); if (status != E_DB_OK) { error = evqeu.error.err_code; break; } event_opened = TRUE; evqeu.qeu_count = 1; /* Initialize event-specific qeu */ evqeu.qeu_tup_length = sizeof(DB_IIEVENT); evqeu.qeu_output = &evqef_data; evqef_data.dt_next = NULL; evqef_data.dt_size = sizeof(DB_IIEVENT); evqef_data.dt_data = (PTR)&evtuple_del; /* ** Position iievent table based on name & owner and drop specific ** event. If we can't find it issue an error. */ evqeu.qeu_getnext = QEU_REPO; /* Get event that matches (keyed on) event name and owner */ evqeu.qeu_klen = 2; evqeu.qeu_key = evkey_ptr_array; evkey_ptr_array[0] = &evkey_array[0]; evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY; evkey_ptr_array[0]->attr_operator = DMR_OP_EQ; evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name; evkey_ptr_array[1] = &evkey_array[1]; evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY; evkey_ptr_array[1]->attr_operator = DMR_OP_EQ; evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner; evqeu.qeu_qual = NULL; evqeu.qeu_qarg = NULL; status = qeu_get(qef_cb, &evqeu); if (status != E_DB_OK) { if (evqeu.error.err_code == E_QE0015_NO_MORE_ROWS) { (VOID)qef_error(E_QE020B_EVENT_ABSENT, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(evtuple->dbe_name), (char *)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; } else /* Other error */ { error = evqeu.error.err_code; } break; } /* If no event found */ break; } /* End dummy for loop */ /* Handle any error messages */ if (status != E_DB_OK) { (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); } else { QEUQ_CB dqeuq; STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq); dqeuq.qeuq_flag_mask &= ~QEU_DROP_TEMP_TABLE; dqeuq.qeuq_flag_mask |= QEU_FORCE_QP_INVALIDATION; dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid; STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid); dqeuq.qeuq_uld_tup = &evqef_data; /* ** Check if dbevent used by alarm, if so we can't drop it */ if(qeu_ev_used_with_alarm(qef_cb, qeuq_cb, &evtuple_del.dbe_uniqueid) !=E_DB_OK) { (VOID) qef_error(E_US2479_9337_ALARM_USES_EVENT, 0L, local_status, &error, &qeuq_cb->error, 2, qec_trimwhite(sizeof(evtuple->dbe_owner), (char*)&evtuple->dbe_owner), (PTR)&evtuple->dbe_owner, qec_trimwhite(sizeof(evtuple->dbe_name), (char*)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; status=E_DB_ERROR; } if(status==E_DB_OK) { /* ** perform cascading destruction - qeu_d_cascade() handles its ** own error reporting */ STRUCT_ASSIGN_MACRO(*qeuq_cb, dqeuq); dqeuq.qeuq_flag_mask &= ~((i4) QEU_DROP_TEMP_TABLE); dqeuq.qeuq_rtbl = &evtuple_del.dbe_uniqueid; STRUCT_ASSIGN_MACRO(evtuple_del.dbe_txtid, dqeuq.qeuq_qid); dqeuq.qeuq_uld_tup = &evqef_data; /* perform cascading destruction of the dbevent */ status = qeu_d_cascade(qef_cb, &dqeuq, (DB_QMODE) DB_EVENT, (DMT_TBL_ENTRY *) NULL); if (status != E_DB_OK) { STRUCT_ASSIGN_MACRO(dqeuq.error, qeuq_cb->error); } } } /* Audit DROP EVENT if so far so good */ if ( status == E_DB_OK && Qef_s_cb->qef_state & QEF_S_C2SECURE ) { DB_ERROR e_error; status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME, SXF_E_EVENT, I_SX203C_EVENT_DROP, SXF_A_SUCCESS | SXF_A_DROP, &e_error); } /* Close off all the tables and transaction */ if (event_opened) { local_status = qeu_close(qef_cb, &evqeu); if (local_status != E_DB_OK) { (VOID) qef_error(evqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) { if (status == E_DB_OK) local_status = qeu_etran(qef_cb, &tranqeu); else local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } return (status); } /* qeu_devent */
/*{ ** Name: qeu_cevent - Store event information for one event. ** ** External QEF call: status = qef_call(QEU_CEVENT, &qeuq_cb); ** ** Description: ** Add the event tuple and the event query text to the appropriate ** tables (iievent and iiqrytext). ** ** Most of the event tuple was filled by the parser from the CREATE EVENT ** statement, except that since this is the first access to iievent, ** the uniqueness of the event name (within the current user scope) is ** validated here. First, all events that have the same name and ** owner are fetched (the iievent table is hashed on name and owner ** so this is a singleton keyed retrieval). If there are any then ** the event is a duplicate and an error is returned. If this is ** unique then the event is entered into iievent. ** ** To allow permissions to apply to events, an event tuple includes ** a "dummy table id" (much like database procedures). This id is ** retrieved from DMU_GET_TABID. ** ** An internal qrytext id (time-stamp) is created and all the qrytext ** tuples associated with the event are entered into iiqrytext. ** Note that the size of CREATE EVENT query text is never likely to ** be more than one iiqrytext tuple, but the code allows more than ** one tuple in case a WITH clause is added in the future (extending ** the length of the statement). ** ** The current "create date" is retrieved from ADF (using date("now")). ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_cq Number of query text tuples. ** .qeuq_qry_tup Query text tuples. ** .qeuq_culd Number of event tuples. Must be 1. ** .qeuq_uld_tup Event tuple: ** .dbe_name Event name. ** .dbe_owner Event owner. ** .dbe_type Event type. ** The remaining fields are filled here. ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** E_QE020A_EVENT_EXISTS (ret E_QE0025_USER_ERROR) ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 28-aug-89 (neil) ** Written for Terminator II/alerters. ** 09-feb-90 (neil) ** Added auditing functionality. ** 03-mar-90 (neil) ** Clear adf_constants before calling ADF. The problem was that the ** session CB may have been pointing at "old" data which had been ** reused for other things. ** 19-may-93 (anitap) ** Added support to create implicit schema for dbevent. ** 07-jul-93 (anitap) ** Added two arguments qef_rcb & qeuq_cb to qea_schema() instead of ** PTR. ** Changed assignment of flag to IMPLICIT_SCHEMA. ** 21-sep-93 (stephenb) ** Replace generic I_SX2032_EVENT_ACCESS with I_SX2032_EVENT_CREATE. ** 27-oct-93 (andre) ** As a part of fix for bug 51852 (which was reported in 6.4 but can ** and will manifest itself in 6.5 as soon as someone places some ** stress on the DBMS), we want to use the dbevent id (really ** guaranteed to be unique) instead of timestamps (allegedly unique, ** but in fact may be non-unique if several objects get created in ** rapid succession on a reasonably fast box) to identify IIQRYTEXT ** tuples associated with a given dbevent. This id (pumped through ** randomizing function) will be used to key into IIQRYTEXT */ DB_STATUS qeu_cevent( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { DB_IIEVENT *evtuple; /* New event tuple */ DB_IIEVENT evtuple_temp; /* Tuple and */ DMR_ATTR_ENTRY evkey_array[2]; /* keys for uniqueness check */ DMR_ATTR_ENTRY *evkey_ptr_array[2]; DMU_CB dmu_cb; /* For unique table-id request */ DB_DATA_VALUE evcreate_dv; /* For create date */ DB_IIQRYTEXT *qtuple; /* Event text */ DB_TAB_ID randomized_id; i4 i; /* Querytext counter */ QEF_DATA *next; /* and data pointer */ DB_STATUS status, local_status; DB_ERROR e_error; i4 error; bool tbl_opened = FALSE; QEU_CB tranqeu; /* May need a transaction */ bool transtarted = FALSE; QEU_CB qeu; QEF_DATA qef_data; i4 flag = IMPLICIT_SCHEMA; QEF_RCB *qef_rcb = (QEF_RCB *)NULL; for (;;) /* Dummy for loop for error breaks */ { /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL) || (qeuq_cb->qeuq_culd != 1 || qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; evtuple = (DB_IIEVENT *)qeuq_cb->qeuq_uld_tup->dt_data; /* Validate that the event name/owner is unique */ qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_EVENT_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_EVENT_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IX; qeu.qeu_flag = DMT_U_DIRECT; qeu.qeu_access_mode = DMT_A_WRITE; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; /* Retrieve the same named/owned event - if not there then ok */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_IIEVENT); qeu.qeu_output = &qef_data; qef_data.dt_next = NULL; qef_data.dt_size = sizeof(DB_IIEVENT); qef_data.dt_data = (PTR)&evtuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 2; /* Keyed on name and owner */ qeu.qeu_key = evkey_ptr_array; evkey_ptr_array[0] = &evkey_array[0]; evkey_ptr_array[0]->attr_number = DM_1_EVENT_KEY; evkey_ptr_array[0]->attr_operator = DMR_OP_EQ; evkey_ptr_array[0]->attr_value = (char *)&evtuple->dbe_name; evkey_ptr_array[1] = &evkey_array[1]; evkey_ptr_array[1]->attr_number = DM_2_EVENT_KEY; evkey_ptr_array[1]->attr_operator = DMR_OP_EQ; evkey_ptr_array[1]->attr_value = (char *)&evtuple->dbe_owner; qeu.qeu_qual = NULL; qeu.qeu_qarg = NULL; status = qeu_get(qef_cb, &qeu); if (status == E_DB_OK) /* Found the same event! */ { (VOID)qef_error(E_QE020A_EVENT_EXISTS, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(evtuple->dbe_name), (char *)&evtuple->dbe_name), (PTR)&evtuple->dbe_name); error = E_QE0025_USER_ERROR; break; } if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS) { error = qeu.error.err_code; /* Some other error */ break; } /* The event is unique - append it */ status = E_DB_OK; /* ** Get unique event id (a table id) from DMF. This id enables ** permissions to be associated with the event. */ dmu_cb.type = DMU_UTILITY_CB; dmu_cb.length = sizeof(DMU_CB); dmu_cb.dmu_flags_mask = 0; dmu_cb.dmu_tran_id = qef_cb->qef_dmt_id; dmu_cb.dmu_db_id = qeuq_cb->qeuq_db_id; status = dmf_call(DMU_GET_TABID, &dmu_cb); if (status != E_DB_OK) { error = dmu_cb.error.err_code; break; } evtuple->dbe_uniqueid.db_tab_base = dmu_cb.dmu_tbl_id.db_tab_base; evtuple->dbe_uniqueid.db_tab_index = dmu_cb.dmu_tbl_id.db_tab_index; /* ** use dbevent id to generate randomized id which will be used to ** identify IIQRYTEXT tuples associated with this dbevent */ randomized_id.db_tab_base = ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_base); randomized_id.db_tab_index = ulb_rev_bits(evtuple->dbe_uniqueid.db_tab_index); /* set text id to "randomized" id */ evtuple->dbe_txtid.db_qry_high_time = randomized_id.db_tab_base; evtuple->dbe_txtid.db_qry_low_time = randomized_id.db_tab_index; /* Get the create date of the event */ evcreate_dv.db_datatype = DB_DTE_TYPE; evcreate_dv.db_prec = 0; evcreate_dv.db_length = sizeof(DB_DATE); evcreate_dv.db_data = (PTR)&evtuple->dbe_create; evcreate_dv.db_collID = -1; qef_cb->qef_adf_cb->adf_constants = NULL; status = adu_datenow(qef_cb->qef_adf_cb, &evcreate_dv); if (status != E_DB_OK) { error = qeu.error.err_code; break; } /* Insert single event tuple */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_IIEVENT); qeu.qeu_input = qeuq_cb->qeuq_uld_tup; /* Which points at evtuple */ status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; /* ** Update all query text tuples with query id - validate list. Even ** though we will probably have just one text tuple this is set up ** for syntactic extensions to the CREATE EVENT statement. */ next = qeuq_cb->qeuq_qry_tup; for (i = 0; i < qeuq_cb->qeuq_cq; i++) { qtuple = (DB_IIQRYTEXT *)next->dt_data; next = next->dt_next; qtuple->dbq_txtid.db_qry_high_time = randomized_id.db_tab_base; qtuple->dbq_txtid.db_qry_low_time = randomized_id.db_tab_index; if (i < (qeuq_cb->qeuq_cq -1) && next == NULL) { error = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; break; } } /* for all query text tuples */ if (status != E_DB_OK) break; /* Insert all query text tuples */ qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; qeu.qeu_tab_id.db_tab_index = 0L; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = qeuq_cb->qeuq_cq; qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qeu.qeu_input = qeuq_cb->qeuq_qry_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; status = qea_schema(qef_rcb, qeuq_cb, qef_cb, (DB_SCHEMA_NAME *)&evtuple->dbe_owner, flag); if (status != E_DB_OK) { error = qeuq_cb->error.err_code; break; } if (transtarted) /* If we started a transaction */ { status = qeu_etran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } } /* Audit CREATE EVENT */ if ( Qef_s_cb->qef_state & QEF_S_C2SECURE ) { status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, evtuple->dbe_name.db_ev_name, &evtuple->dbe_owner, DB_EVENT_MAXNAME, SXF_E_EVENT, I_SX2032_EVENT_CREATE, SXF_A_SUCCESS | SXF_A_CREATE, &e_error); if (status != E_DB_OK) break; } qeuq_cb->error.err_code = E_QE0000_OK; return (E_DB_OK); } /* End dummy for */ /* call qef_error to handle error messages */ (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables. */ local_status = E_DB_OK; if (tbl_opened) /* If system table opened, close it */ { local_status = qeu_close(qef_cb, &qeu); if (local_status != E_DB_OK) { (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) /* If we started a transaction */ { local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } return (status); } /* qeu_cevent */
/*{ ** Name: QEA_CALLPROC - call the named procedure ** ** Description: ** The current execution environment is saved and an ** environment is created in which to execute the ** named procedure. ** ** This procedure is only called when a nested procedure is invoked. ** This can occur the first time through, or if the procedure is not ** found (LOAD_QP) or the plan was deemed invalid (INVALID_QUERY) then ** the procedure is re-entered in this routine. ** ** If rules are turned off (QEF_T_NORULES) then this procedure returns ** immediately. ** ** Inputs: ** action Callproc action header ** qef_rcb ** call_dsh DSH doing the callproc ** function unused ** state unused ** ** Outputs: ** call_dsh ** .error.err_code one of the following ** E_QE0119_LOAD_QP - Load a procedure QP ** E_QE0125_RULES_INHIBIT - Rules are turned off. ** E_QE0000_OK ** Returns: ** E_DB_{OK,WARN,ERROR,FATAL} ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 20-apr-89 (paul) ** Moved from qeq.c ** 09-may-89 (neil) ** Added rule name tracing. ** 26-may-89 (paul) ** Increase statement #, cleanup DSH on error recovery. ** 31-may-89 (neil) ** Cleanup tracing; modify when context count is set; reset "saved ** resource" bit if procedure is loaded. ** 23-jun-89 (neil) ** Extended trace for nested procedures: Indicate procedure nesting ** level and rule depth. ** 26-sep-89 (neil) ** Support for SET NORULES. ** 02-jan-90 (neil) ** DSH initialization error handling improved to indicate problem ** specifics. ** 03-jan-90 (ralph) ** Change interface to QSO_JUST_TRANS ** 10-jan-90 (neil) ** Improved DSH cleanup on DSH initialization errors. Made sure ** to confirm allocation error, and to pass a FALSE "release" flag ** to qeq_cleanup. ** 09-feb-90 (neil) ** Auditing cleanup: only audit the firing of rules and only if ** auditing is on (for performance). ** 09-nov-92 (jhahn) ** Added handling for byrefs. ** 14-dec-92 (jhahn) ** Cleaned up handling of byrefs. ** 12-feb-93 (jhahn) ** Added support for statement level rules. (FIPS) ** 24-mar-93 (jhahn) ** Various fixes for support of statement level rules. (FIPS) ** 02-apr-93 (jhahn) ** Made set input procedures called from rules bump qef_rule_depth. ** 01-may-93 (jhahn) ** Undid above change. Instead added new action QEA_INVOKE_RULE. ** 06-jul-93 (robf) ** Pass security label to qeu_secaudit ** 01-sep-93 (jhahn) ** Added support for multiple query plans for set input procedures. ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 18-may-94 (anitap) ** Bug #63465 ** If error in nested procedure, the whole transaction was being ** rolled back. ** 7-nov-95 (inkdo01) ** Changes to replace QEN_ADF structure instances by pointers in ** QEF_AHD structures. ** 24-jul-96 (inkdo01) ** Added support of global temp table proc parms. ** 4-mar-97 (inkdo01) ** Added display of error QE030B (row rule calls SET OF proc). ** 23-may-97 (inkdo01) ** Change QE030B to only pass procname, since it is mapped to a ** US error in qeferror, anyway. ** 17-aug-99 (thaju02) ** initialize dmt_show.db_tab_id.db_tab_base to 0 prior to calling ** dmt_show, to avoid falsely reporting E_QE0018. (b98431) ** 27-apr-01 (inkdo01) ** Add code to detect nested/dynamic calls to row procs. ** 15-mar-04 (inkdo01) ** dsh_tempTables is now an array of ptrs. ** 17-mar-04 (inkdo01) ** We be fixin' a bug in error handlin' when qeq_dsh() doesn't ** return a dsh. ** 13-may-04 (inkdo01) ** Preserve status across qeq_cleanup calls. ** 18-may-04 (inkdo01) ** Quick fix to eliminate QE0018 when QE030D (US09AF) happens. ** 13-Jul-2004 (schka24) ** Straighten out which dsh is used where, fix loss of error ** code when finding called qp leading to QE0018. ** 13-Dec-2005 (kschendel) ** Inlined QEN_ADF changed to pointer, fix here. ** 29-May-2008 (gefei01) ** Prototype change for qeq_dsh(). ** 22-Apr-2009 (hanal04) Bug 121970 ** In printrule tracing print the ahd_pcount not qef_pcount ** which is set to zero if we are in a sub-procedure. ** 21-Jun-2010 (kschendel) b123775 ** Combine is-tproc and in-progress args to qeq-dsh. ** Make dbp alias a real QSO_NAME. */ DB_STATUS qea_callproc( QEF_AHD *act, QEF_RCB *qef_rcb, QEE_DSH *call_dsh, i4 function, /* Unused */ i4 state ) /* Unused */ { i4 err; DB_STATUS status = E_DB_OK, savestat; QEF_CB *qef_cb = call_dsh->dsh_qefcb; PTR *cbs = call_dsh->dsh_cbs; QEE_DSH *proc_dsh; /* DSH for called dbp */ QEN_ADF *qen_adf; ADE_EXCB *ade_excb; QSF_RCB qsf_rcb; i4 tr1 = 0, tr2 = 0; /* Dummy trace values */ DB_ERROR e_error; /* To pass to qeu_secaudit */ i4 page_count; bool is_deferred = act->qhd_obj.qhd_callproc.ahd_proc_temptable != NULL; bool gttparm = act->qhd_obj.qhd_callproc.ahd_gttid.db_tab_base != 0; bool need_cleanup = FALSE; bool need_release; bool from_rule = act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS; QEE_TEMP_TABLE *proc_temptable; char *cbuf = qef_cb->qef_trfmt; i4 cbufsize = qef_cb->qef_trsize; i4 open_count; do { /* ** This action is called back if a request to CREATE a QP for a ** CALLPROC fails. In this case we just continue with error processing. ** No need for another error as CLEAN_RSRC is only set if a client on ** the outside issued an error knowing we have a stacked environment. ** (Note: as of the 123775 fixes, we shouldn't ever get here with ** CLEAN_RSRC set, since qeq-query no longer attempts to execute ** the action from the sequencer callback. I'm leaving the code ** here for now, though.) */ if ((qef_rcb->qef_intstate & QEF_CLEAN_RSRC) != 0) { call_dsh->dsh_error.err_code = E_QE0025_USER_ERROR; qef_rcb->qef_intstate &= ~QEF_CLEAN_RSRC; status = E_DB_ERROR; break; } if (is_deferred) { proc_temptable = call_dsh->dsh_tempTables[act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex]; if (proc_temptable->tt_statusFlags & TT_EMPTY) if (from_rule) break; /* empty ttab in statement rule - ** nothing to do at all */ else status = openTempTable(qef_rcb, call_dsh, act->qhd_obj.qhd_callproc .ahd_proc_temptable->ttb_tempTableIndex, gttparm); else status = qen_rewindTempTable(call_dsh, act->qhd_obj. qhd_callproc.ahd_proc_temptable->ttb_tempTableIndex); if (status != E_DB_OK) break; } /* If called from a rule & SET NORULES is on, then inhibit execution */ if ( from_rule && ult_check_macro(&qef_cb->qef_trace, QEF_T_NORULES, &tr1, &tr2) ) { /* Trace inhibited rule if required */ if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; STprintf(cbuf, "PRINTRULES: Rule '%.*s' suppressed\n", qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); } call_dsh->dsh_error.err_code = E_QE0125_RULES_INHIBIT; status = E_DB_ERROR; break; } /* If rules off */ /* ** Security audit rule firing - check that is first time (not ** recreation), is a rule and, for performance, that we really ** need to audit. */ if ( (qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0 && (act->qhd_obj.qhd_callproc.ahd_rulename.db_name[0] != EOS) && (Qef_s_cb->qef_state & QEF_S_C2SECURE) ) { status = qeu_secaudit(FALSE, qef_cb->qef_ses_id, act->qhd_obj.qhd_callproc.ahd_rulename.db_name, (DB_OWN_NAME *)&act->qhd_obj.qhd_callproc.ahd_ruleowner, sizeof(act->qhd_obj.qhd_callproc.ahd_rulename), SXF_E_RULE, I_SX202F_RULE_ACCESS, SXF_A_SUCCESS | SXF_A_EXECUTE, &e_error); if (status != E_DB_OK) { call_dsh->dsh_error.err_code = e_error.err_code; break; } } /* Actually execute a CALLPROC. */ /* We generate an actual parameter list, save the current */ /* execution context, stack the DSH and setup the new */ /* execution context. Processing then continues with the */ /* new QP. */ /* Save the current execution context as represented by */ /* QEF_RCB and the current DSH. */ STRUCT_ASSIGN_MACRO(*qef_rcb, *call_dsh->dsh_saved_rcb); call_dsh->dsh_act_ptr = act; qen_adf = act->qhd_obj.qhd_callproc.ahd_procparams; if (qen_adf != NULL) { /* Compute the actual parameters for this procedure */ /* call. */ qef_rcb->qef_pcount = act->qhd_obj.qhd_callproc.ahd_pcount; ade_excb = (ADE_EXCB *)cbs[qen_adf->qen_pos]; ade_excb->excb_seg = ADE_SMAIN; status = ade_execute_cx(call_dsh->dsh_adf_cb, ade_excb); if (status != E_DB_OK) { status = qef_adf_error(&call_dsh->dsh_adf_cb->adf_errcb, status, qef_cb, &call_dsh->dsh_error); if (status != E_DB_OK) break; } } else { /* No actual parameters */ qef_rcb->qef_pcount = 0; } /* ** If tracing rules and first time through then display ** rule/procedure information. */ if ((qef_rcb->qef_intstate & QEF_DBPROC_QP) == 0) { if (ult_check_macro(&qef_cb->qef_trace, QEF_T_RULES, &tr1, &tr2)) { char *rn, *pn; /* Rule/procedure names */ rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; /* Tailor trace for rules vs nested procedures */ STprintf(cbuf, *rn == EOS ? "PRINTRULES 1: Executing procedure '%.*s'\n" : "PRINTRULES 1: Executing procedure '%.*s' from rule '%.*s'\n", qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn); qec_tprintf(qef_rcb, cbufsize, cbuf); STprintf(cbuf, "PRINTRULES 2: Rule/procedure depth = %d/%d, parameters passed = %d\n", qef_rcb->qef_rule_depth, qef_rcb->qef_context_cnt + 1, act->qhd_obj.qhd_callproc.ahd_pcount); qec_tprintf(qef_rcb, cbufsize, cbuf); } /* If tracing rules */ } /* ** Indicate that we have nested one more level, generate an error if ** we are nested too deeply. Context count is actually set later. */ if (qef_cb->qef_max_stack < qef_rcb->qef_context_cnt + 1) { status = E_DB_ERROR; qef_error(E_QE0208_EXCEED_MAX_CALL_DEPTH, 0L, status, &err, &call_dsh->dsh_error, 1, sizeof(qef_cb->qef_max_stack), &qef_cb->qef_max_stack); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; break; } if (gttparm) { STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_gttid, qef_rcb->qef_setInputId); /* copy temptab ID */ page_count = 1; is_deferred = TRUE; } else if (is_deferred) { DMT_CB *dmt_cb = proc_temptable->tt_dmtcb; DMT_SHW_CB dmt_show; DMT_TBL_ENTRY dmt_tbl_entry; dmt_show.type = DMT_SH_CB; dmt_show.length = sizeof(DMT_SHW_CB); dmt_show.dmt_session_id = qef_cb->qef_ses_id; dmt_show.dmt_db_id = qef_rcb->qef_db_id; dmt_show.dmt_tab_id.db_tab_base = 0; dmt_show.dmt_flags_mask = DMT_M_TABLE | DMT_M_ACCESS_ID; dmt_show.dmt_char_array.data_address = NULL; dmt_show.dmt_table.data_address = (PTR) &dmt_tbl_entry; dmt_show.dmt_table.data_in_size = sizeof(DMT_TBL_ENTRY); dmt_show.dmt_record_access_id = dmt_cb->dmt_record_access_id; status = dmf_call(DMT_SHOW, &dmt_show); if (status != E_DB_OK) { STRUCT_ASSIGN_MACRO(dmt_show.error, call_dsh->dsh_error); break; } page_count = dmt_tbl_entry.tbl_page_count; STRUCT_ASSIGN_MACRO(dmt_cb->dmt_id, qef_rcb->qef_setInputId); } else { page_count = -1; MEfill(sizeof(DB_TAB_ID), (u_char)0, (PTR)&qef_rcb->qef_setInputId); } STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_procedureID, qef_rcb->qef_dbpId); /* Get the id of the procedure to call */ STRUCT_ASSIGN_MACRO(act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id, qef_rcb->qef_qp); qef_rcb->qef_qso_handle = NULL; /* Set the full name of the procedure into the RCB in case */ /* we have to call PSF to define the procedure. */ qef_rcb->qef_dbpname = act->qhd_obj.qhd_callproc.ahd_dbpalias; /* Lookup this procedure name as a QSF alias. At this time */ /* we do not have a valid DB_CURSOR_ID because we do not */ /* have the timestamp for the QP object. Ask QSF to look */ /* this up for us. If found, we continue executing, if not */ /* return to SCF to define this procedure. */ qsf_rcb.qsf_type = QSFRB_CB; qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rcb.qsf_length = sizeof(QSF_RCB); qsf_rcb.qsf_owner = (PTR)DB_QEF_ID; qsf_rcb.qsf_sid = qef_rcb->qef_cb->qef_ses_id; qsf_rcb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ; qsf_rcb.qsf_feobj_id.qso_lname = sizeof(qsf_rcb.qsf_feobj_id.qso_name); MEcopy((PTR)&act->qhd_obj.qhd_callproc.ahd_dbpalias, sizeof(qsf_rcb.qsf_feobj_id.qso_name), (PTR)qsf_rcb.qsf_feobj_id.qso_name); qsf_rcb.qsf_lk_state = QSO_FREE; status = qsf_call(QSO_JUST_TRANS, &qsf_rcb); if (DB_FAILURE_MACRO(status)) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; break; } else { /* ** The procedure was found - make sure "saved" bit isn't on for ** the scope of this execution. It may get turned back on if ** the QP or DSH is found to be invalid but then we'll re-enter ** here (to try again) and turn it off. */ qef_rcb->qef_intstate &= ~QEF_DBPROC_QP; } /* Increase context count now that we've loaded the QP */ qef_rcb->qef_context_cnt++; /* Procedure in QSF, load the timestamp into the QEF_RCB */ /* to allow normal QEF processing to continue. */ MEcopy((PTR)qsf_rcb.qsf_obj_id.qso_name, sizeof(DB_CURSOR_ID), (PTR)&qef_rcb->qef_qp); status = qeq_dsh(qef_rcb, 0 , &proc_dsh, QEQDSH_IN_PROGRESS, page_count); if (DB_FAILURE_MACRO(status)) { char *rn, *pn; /* Rule/procedure names */ STRUCT_ASSIGN_MACRO(qef_rcb->error, call_dsh->dsh_error); if (call_dsh->dsh_error.err_code == E_QE0023_INVALID_QUERY) { /* No such procedure in QSF, ask SCF to define it */ /* Tell SCF to call us back even if the porcedure */ /* cannot be loaded. We will need to clean up */ qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_intstate |= QEF_DBPROC_QP; call_dsh->dsh_error.err_code = E_QE0119_LOAD_QP; qef_rcb->qef_context_cnt--; break; } /* ** The QP DSH is invalid for some reason. Generate error and return. ** If any allocation error then change to useful error message. */ if ( call_dsh->dsh_error.err_code == E_UL0005_NOMEM || call_dsh->dsh_error.err_code == E_QS0001_NOMEM || call_dsh->dsh_error.err_code == E_QE001E_NO_MEM || call_dsh->dsh_error.err_code == E_QE000D_NO_MEMORY_LEFT || call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) { pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; rn = act->qhd_obj.qhd_callproc.ahd_rulename.db_name; if (*rn == EOS) rn = "NULL "; if (call_dsh->dsh_error.err_code == E_QE030B_RULE_PROC_MISMATCH) qef_error(E_QE030B_RULE_PROC_MISMATCH, 0L, status, &err, &call_dsh->dsh_error, 1, /* qec_trimwhite(DB_RULE_MAXNAME, rn), rn, */ qec_trimwhite(DB_DBP_MAXNAME, pn), pn); else qef_error(E_QE0199_CALL_ALLOC, 0L, status, &err, &call_dsh->dsh_error, 3, qec_trimwhite(DB_DBP_MAXNAME, pn), pn, qec_trimwhite(DB_RULE_MAXNAME, rn), rn, sizeof(qef_rcb->qef_context_cnt),&qef_rcb->qef_context_cnt); call_dsh->dsh_error.err_code = E_QE0122_ALREADY_REPORTED; } /* ** Now clean up and restore to state before routine entry. ** Pass in FALSE for release as if the DSH is NULL we do NOT want ** to cause cleanup to release all DSH's for this session ** (qee_cleanup). If the DSH is not NULL it will be cleaned up at ** the end of the query. */ need_cleanup = TRUE; need_release = FALSE; break; } if (proc_dsh->dsh_qp_ptr->qp_status & QEQP_ROWPROC) { char *pn; /* Row producing procs cannot be invoked by QEA_CALLPROC (which ** implies either nested proc call or dynamic SQL proc call). */ pn = act->qhd_obj.qhd_callproc.ahd_dbpalias.qso_n_id.db_cur_name; qef_error(E_QE030D_NESTED_ROWPROCS, 0L, E_DB_ERROR, &err, &call_dsh->dsh_error, 1, qec_trimwhite(DB_DBP_MAXNAME, pn), pn); status = E_DB_ERROR; break; } /* Found QP and DSH, stack old context */ proc_dsh->dsh_stack = call_dsh; proc_dsh->dsh_stmt_no = qef_cb->qef_stmt++; qef_cb->qef_dsh = (PTR) proc_dsh; qef_cb->qef_open_count++; /* Initialize procedure parameters (& user params - even if wrong) */ if (proc_dsh->dsh_qp_ptr->qp_ndbp_params != 0 || qef_rcb->qef_pcount > 0) { status = qee_dbparam(qef_rcb, proc_dsh, call_dsh, act->qhd_obj.qhd_callproc.ahd_params, act->qhd_obj.qhd_callproc.ahd_pcount, TRUE); if (DB_FAILURE_MACRO(status)) { /* If we fail after acquiring the DSH, we need to */ /* deallocate the DSH and recover back to the original */ /* calling state. */ STRUCT_ASSIGN_MACRO(proc_dsh->dsh_error, call_dsh->dsh_error); qef_cb->qef_open_count--; need_cleanup = TRUE; need_release = TRUE; break; } } if (is_deferred) { /* FIXME should error if it's null */ if (proc_dsh->dsh_qp_ptr->qp_setInput != NULL) STRUCT_ASSIGN_MACRO(qef_rcb->qef_setInputId, * (DB_TAB_ID *)(proc_dsh->dsh_row[proc_dsh->dsh_qp_ptr-> qp_setInput->vl_tab_id_index])); } } while (FALSE); if (need_cleanup) { /* error in a nested DB procedure, abort up to the beginning of the ** procedure if there are no other cursors opened. We ** guarantee that by decrementing the qef_open_count. If the ** count becomes zero, qeq_cleanup will abort to the last internal ** savepoint. Fix for bug 63465. */ savestat = status; open_count = qef_cb->qef_open_count; while (qef_cb->qef_open_count > 0) qef_cb->qef_open_count--; status = qeq_cleanup(qef_rcb, status, need_release); status = savestat; qef_cb->qef_open_count = open_count; qef_cb->qef_dsh = (PTR) call_dsh; qef_rcb->qef_context_cnt--; qef_rcb->qef_pcount = call_dsh->dsh_saved_rcb->qef_pcount; qef_rcb->qef_usr_param = call_dsh->dsh_saved_rcb->qef_usr_param; qef_rcb->qef_qp = call_dsh->dsh_saved_rcb->qef_qp; qef_rcb->qef_qso_handle = call_dsh->dsh_saved_rcb->qef_qso_handle; call_dsh->dsh_qef_rowcount = call_dsh->dsh_saved_rcb->qef_rowcount; call_dsh->dsh_qef_targcount = call_dsh->dsh_saved_rcb->qef_targcount; call_dsh->dsh_qef_output = call_dsh->dsh_saved_rcb->qef_output; call_dsh->dsh_qef_count = call_dsh->dsh_saved_rcb->qef_count; } return (status); }
/*{ ** Name: qeu_dsecalarm - Drop single or all alarm definition. ** ** External QEF call: status = qef_call(QEU_DSECALM, &qeuq_cb); ** ** Description: ** Drop the alarm tuple, the alarm text from the appropriate tables ** (iisecalarm, iiqrytext and update the table "relstat" field. An ** alarm can be dropped either by name (when the DROP SECURITY_ALARM ** statement is issued) or by object id (when its associated object ** is dropped). ** ** When originating from the DROP SECURITY_ALARM statement the single ** alarm tuple is deleted based on its name - provided in the ** qeuq_uld_tup parameter. In this case the single alarm is fetched ** (to collect the text, table id) and deleted. If it wasn't ** found then an error is returned. ** ** When originating from a DROP TABLE statement (this is similar to ** the DROP INTEGRITY ON table ALL), all tuples that satisfy the ** table-id are fetched (to collect their text ids) and dropped. ** If none are found no error is returned. ** ** For each alarm that is dropped the text tuples are ** also dropped based on the ids collected from the fetched alarm. ** ** The way this routine works is the following: ** ** set up QEU CB's for iisecalarm, iiqrytext and open tables; ** if (DROP SECURITY_ALARM) then ** set up iisecalarm "qualified" name and owner; ** else ** set up iisecalarm "keyed" on DROP object id; ** endif; ** for (all alarm tuples found) loop ** get alarm tuple; ** if (not found) then ** if (DROP SECURITY_ALARM) then ** error - alarm does not exist; ** break; ** else ** clear error; ** break; ** endif; ** endif; ** set up iiqrytext keys based on alarm text id; ** for (all text tuples found) loop ** get text tuple; ** delete text tuple; ** endloop; ** delete current alarm tuple; ** if (DROP SECURITY_ALARM) then ** endloop; ** endif; ** endloop; ** close tables; ** ** Inputs: ** qef_cb QEF session control block ** qeuq_cb ** .qeuq_eflag Designate error handling for user errors. ** QEF_INTERNAL Return error code. ** QEF_EXTERNAL Send message to user. ** .qeuq_rtbl Table id of alarm - if DROP TABLE. If DROP ** SECURITY_ALARM then this is ignored. ** .qeuq_cr Must be 1 if DROP SECURITY_ALARM, 0 ** if DROP TABLE. ** .qeuq_uld_tup Alarm tuple to be deleted - if DROP ** SECURITY_ALARM, otherwise this is ignored: ** .dba_alarmname alarm name *or* ** .dba_alarmno Alarm number ** .qeuq_db_id Database id. ** .qeuq_d_id DMF session id. ** from_drop_alarm TRUE if called from DROP SECURITY_ALARM ** ** Outputs: ** qeuq_cb ** .error.err_code E_QE0002_INTERNAL_ERROR ** E_QE0017_BAD_CB ** E_QE0018_BAD_PARAM_IN_CB ** E_QE0022_ABORTED ** Returns: ** E_DB_{OK, WARN, ERROR, FATAL} ** Exceptions: ** none ** ** History: ** 26-nov-93 (robf) ** Written for Secure 2.0 ** 30-dec-93 (robf) ** Don't write audit records if called implicitly during drop ** of a table. ** 16-feb-94 (robf) ** Check DROP ALL flag from qeuq_cb.qeuq_permit_mask & QEU_DROP_ALL, ** so we loop appropriately when there are several alarms on ** the object to be dropped. */ DB_STATUS qeu_dsecalarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb, bool from_drop_alarm) { QEU_CB tranqeu; /* For transaction request */ bool transtarted = FALSE; QEU_CB aqeu; /* For iisecalarm table */ QEF_DATA aqef_data; DB_SECALARM *atuple_name; /* Input tuple with name or id */ DB_SECALARM atuple; /* Tuple currently being deleted */ bool alarm_opened = FALSE; DMR_ATTR_ENTRY akey_array[3]; DMR_ATTR_ENTRY *akey_ptr_array[3]; QEU_CB qqeu; /* For iiqrytext table */ QEU_QUAL_PARAMS qparams; DB_IIQRYTEXT qtuple; QEF_DATA qqef_data; bool qtext_opened = FALSE; DMR_ATTR_ENTRY qkey_array[2]; DMR_ATTR_ENTRY *qkey_ptr_array[2]; bool drop_specific_alarm; /* TRUE if dropping a specific ** alarm */ char obj_type; char *alarm_name; DB_STATUS status, local_status; i4 error; DB_ERROR e_error; SXF_ACCESS access; SXF_EVENT evtype; DB_OWN_NAME objowner; for (;;) /* Dummy for loop for error breaks */ { MEfill(sizeof(objowner),' ',(PTR)&objowner); /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( (qeuq_cb->qeuq_rtbl == NULL && qeuq_cb->qeuq_cr == 0) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } drop_specific_alarm = from_drop_alarm; /* ** If passed DROP ALL then not dropping specific alarm */ if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL) drop_specific_alarm=FALSE; /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; tranqeu.qeu_mask = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; /* Open iisecalarm, iiqrytext tables */ aqeu.qeu_type = QEUCB_CB; aqeu.qeu_length = sizeof(QEUCB_CB); aqeu.qeu_db_id = qeuq_cb->qeuq_db_id; aqeu.qeu_lk_mode = DMT_IX; aqeu.qeu_flag = DMT_U_DIRECT; aqeu.qeu_access_mode = DMT_A_WRITE; aqeu.qeu_mask = 0; STRUCT_ASSIGN_MACRO(aqeu, qqeu); /* Quick initialization */ /* Open iisecalarm */ aqeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; aqeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; status = qeu_open(qef_cb, &aqeu); if (status != E_DB_OK) { error = aqeu.error.err_code; break; } alarm_opened = TRUE; qqeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; /* Open iiqrytext */ qqeu.qeu_tab_id.db_tab_index = DM_I_QRYTEXT_TAB_ID; status = qeu_open(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } qtext_opened = TRUE; aqeu.qeu_count = 1; /* Initialize alarm-specific qeu */ aqeu.qeu_tup_length = sizeof(DB_SECALARM); aqeu.qeu_output = &aqef_data; aqef_data.dt_next = NULL; aqef_data.dt_size = sizeof(DB_SECALARM); aqef_data.dt_data = (PTR)&atuple; qqeu.qeu_count = 1; /* Initialize qtext-specific qeu */ qqeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qqeu.qeu_output = &qqef_data; qqef_data.dt_next = NULL; qqef_data.dt_size = sizeof(DB_IIQRYTEXT); qqef_data.dt_data = (PTR)&qtuple; /* ** If DROP SECURITY_ALARM then position iisecalarm table based on ** alarm name or numbr ** and drop the specific alarm (if we can't find it issue an error). ** Positioning is done via qeu_qalarm_by_name/id. ** If DROP TABLE then fetch and drop ALL alarms applied to the table. */ aqeu.qeu_getnext = QEU_REPO; if (from_drop_alarm) { /* ** Might be scanning for database/installation alarms ** or special DROP ALL processing. */ atuple_name = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data; alarm_name=(char*)&atuple_name->dba_alarmname; /* ** alarmno -1 indicates all alarms when qualifying */ if(qeuq_cb->qeuq_permit_mask & QEU_DROP_ALL) atuple_name->dba_alarmno= -1; /* Get alarm that matches alarm name (qualified) */ qparams.qeu_qparms[0] = (PTR) atuple_name; aqeu.qeu_klen = 0; /* Not keyed */ aqeu.qeu_qual = qeu_qalarm_by_name; aqeu.qeu_qarg = &qparams; } else /* DROP TABLE */ { /* Get alarm that applies to specific table id (keyed) */ obj_type=DBOB_TABLE; alarm_name="unknown"; aqeu.qeu_klen = 3; aqeu.qeu_key = akey_ptr_array; akey_ptr_array[0] = &akey_array[0]; akey_ptr_array[1] = &akey_array[1]; akey_ptr_array[2] = &akey_array[2]; akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY; akey_ptr_array[0]->attr_operator = DMR_OP_EQ; akey_ptr_array[0]->attr_value = (char*)&obj_type; akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY; akey_ptr_array[1]->attr_operator = DMR_OP_EQ; akey_ptr_array[1]->attr_value = (char *)&qeuq_cb->qeuq_rtbl->db_tab_base; akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY; akey_ptr_array[2]->attr_operator = DMR_OP_EQ; akey_ptr_array[2]->attr_value = (char *)&qeuq_cb->qeuq_rtbl->db_tab_index; aqeu.qeu_qual = NULL; aqeu.qeu_qarg = NULL; } for (;;) /* For all alarm tuples found */ { status = qeu_get(qef_cb, &aqeu); if (status != E_DB_OK) { if (aqeu.error.err_code == E_QE0015_NO_MORE_ROWS) { if (drop_specific_alarm) { (VOID)qef_error(E_US2473_9331_ALARM_ABSENT, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple_name->dba_alarmname), alarm_name), (PTR)alarm_name); error = E_QE0000_OK; status=E_DB_OK; } else /* No [more] alarms for table */ { error = E_QE0000_OK; status = E_DB_OK; } } else /* Other error */ { error = aqeu.error.err_code; } break; } /* If no alarms found */ aqeu.qeu_getnext = QEU_NOREPO; aqeu.qeu_klen = 0; status = E_DB_OK; /* Postion iiqrytxt table for query id associated with this alarm */ qkey_ptr_array[0] = &qkey_array[0]; qkey_ptr_array[1] = &qkey_array[1]; qqeu.qeu_getnext = QEU_REPO; qqeu.qeu_klen = 2; qqeu.qeu_key = qkey_ptr_array; qkey_ptr_array[0]->attr_number = DM_1_QRYTEXT_KEY; qkey_ptr_array[0]->attr_operator = DMR_OP_EQ; qkey_ptr_array[0]->attr_value = (char *)&atuple.dba_txtid.db_qry_high_time; qkey_ptr_array[1]->attr_number = DM_2_QRYTEXT_KEY; qkey_ptr_array[1]->attr_operator = DMR_OP_EQ; qkey_ptr_array[1]->attr_value = (char *)&atuple.dba_txtid.db_qry_low_time; qqeu.qeu_qual = NULL; qqeu.qeu_qarg = NULL; for (;;) /* For all query text tuples */ { status = qeu_get(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } qqeu.qeu_klen = 0; qqeu.qeu_getnext = QEU_NOREPO; status = qeu_delete(qef_cb, &qqeu); if (status != E_DB_OK) { error = qqeu.error.err_code; break; } } /* For all query text tuples */ if (error != E_QE0015_NO_MORE_ROWS) break; if(atuple.dba_objtype==DBOB_TABLE) { DMT_CHAR_ENTRY char_spec; DMT_CB dmt_cb; /* ** Alter the table relstat to flag alarms. This ** validates that the table exists and ensures that we ** get an exclusive lock on it. */ char_spec.char_id = DMT_C_ALARM; char_spec.char_value = DMT_C_ON; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id; dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY); dmt_cb.dmt_char_array.data_address = (PTR)&char_spec; dmt_cb.length = sizeof(DMT_CB); dmt_cb.type = DMT_TABLE_CB; dmt_cb.dmt_id.db_tab_base = atuple.dba_objid.db_tab_base; dmt_cb.dmt_id.db_tab_index = atuple.dba_objid.db_tab_index; dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_ALTER, &dmt_cb); if (status != E_DB_OK) { error = dmt_cb.error.err_code; if (error == E_DM0054_NONEXISTENT_TABLE) { error = E_QE0025_USER_ERROR; status = E_DB_OK; /* Still remove the alarm */ } else { /* ** Some other error */ break; } } } else if(!(atuple.dba_flags&DBA_ALL_DBS)) { /* ** Check access to the database, also get the security label ** for later use */ status=qeu_db_exists(qef_cb, qeuq_cb, (DB_DB_NAME *)&atuple.dba_objname, SXF_A_CONTROL, &objowner); if(status==E_DB_ERROR) { /* Error, no access to database */ break; } else if (status==E_DB_WARN) { /* Database not found */ status=E_DB_ERROR; /* E_US2474_9332_ALARM_NO_DB */ (VOID)qef_error(9332, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple.dba_objname), (char *)&atuple.dba_objname), (PTR)&atuple.dba_objname); break; } } /* Now delete the current alarm tuple */ status = qeu_delete(qef_cb, &aqeu); if (status != E_DB_OK) { error = aqeu.error.err_code; break; } /* ** If doing a specific DROP SECURITY_ALARM we're done with this ** loop. ** Otherwise continue with next alarm applied to table. */ if (drop_specific_alarm) break; } /* For all alarm found */ if (status != E_DB_OK) break; break; } /* End dummy for loop */ /* Handle any error messages */ if (status != E_DB_OK) (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables and transaction */ if (alarm_opened) { local_status = qeu_close(qef_cb, &aqeu); if (local_status != E_DB_OK) { (VOID) qef_error(aqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (qtext_opened) { local_status = qeu_close(qef_cb, &qqeu); if (local_status != E_DB_OK) { (VOID) qef_error(qqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) { if (status == E_DB_OK) local_status = qeu_etran(qef_cb, &tranqeu); else local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } /* ** Dropping an alarm is a control operation on the base object ** (database/table). */ if( from_drop_alarm==TRUE && Qef_s_cb->qef_state & QEF_S_C2SECURE ) { if(atuple.dba_objtype==DBOB_DATABASE) { evtype=SXF_E_DATABASE; /* ** Database label/owner should be set in db_exists request above */ } else { evtype=SXF_E_TABLE; } if(status==E_DB_OK) access=(SXF_A_CONTROL|SXF_A_SUCCESS); else access=(SXF_A_CONTROL|SXF_A_FAIL); if(qeu_secaudit(FALSE, qef_cb->qef_ses_id, (char *)&atuple.dba_objname, &objowner, sizeof(atuple.dba_objname), evtype, I_SX202E_ALARM_DROP, access, &e_error)!=E_DB_OK) { error = e_error.err_code; status=E_DB_ERROR; } } if(status!=E_DB_OK) { (VOID) qef_error(E_QE028C_DROP_ALARM_ERR, 0L, local_status, &error, &qeuq_cb->error, 0); qeuq_cb->error.err_code= E_QE0025_USER_ERROR; } return (status); } /* qeu_dsecalarm */
DB_STATUS qeu_csecalarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { DB_IIQRYTEXT *qtuple; /* Alarm text */ DB_SECALARM *atuple; /* New alarm tuple */ DB_SECALARM atuple_temp; /* Tuple to check for uniqueness */ DB_STATUS status, local_status; i4 error=0; bool transtarted = FALSE; bool tbl_opened = FALSE; i4 i; /* Querytext tuple counter */ QEF_DATA *next; /* and data pointer */ QEU_CB tranqeu; QEU_CB qeu; QEU_QUAL_PARAMS qparams; DB_QRY_ID qryid; /* Ids for query text */ QEF_DATA qef_data; bool loop=FALSE; QEF_RCB qef_rcb; i4 number; DMR_ATTR_ENTRY akey_array[3]; DMR_ATTR_ENTRY *akey_ptr_array[3]; DMT_CHAR_ENTRY char_spec; /* DMT_ALTER specification */ DMT_CB dmt_cb; DB_ERROR e_error; SXF_ACCESS access; SXF_EVENT evtype; DB_OWN_NAME objowner; do { MEfill(sizeof(objowner),' ',(PTR)&objowner); /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL || ( qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } qef_rcb.qef_cb = qef_cb; qef_rcb.qef_db_id = qeuq_cb->qeuq_db_id; qef_cb->qef_dbid = qeuq_cb->qeuq_db_id; /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; tranqeu.qeu_mask = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; atuple = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data; /* For database alarms, make sure the database exists */ if(atuple->dba_objtype==DBOB_DATABASE && !(atuple->dba_flags&DBA_ALL_DBS)) { status=qeu_db_exists(qef_cb, qeuq_cb, (DB_DB_NAME *)&atuple->dba_objname, SXF_A_CONTROL, &objowner); if(status==E_DB_ERROR) { /* Error checking database name */ break; } else if (status==E_DB_WARN) { /* Database not found */ status=E_DB_ERROR; /* E_US2474_9332_ALARM_NO_DB */ (VOID)qef_error(9332, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_objname), (char *)&atuple->dba_objname), (PTR)&atuple->dba_objname); break; } } else if(atuple->dba_objtype==DBOB_TABLE) { /* ** Alter the table relstat to flag alarms exist. This validates that ** the table exists and ensures that we get an exclusive lock on it. */ char_spec.char_id = DMT_C_ALARM; /* create alarm code */ char_spec.char_value = DMT_C_ON; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id; dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY); dmt_cb.dmt_char_array.data_address = (PTR)&char_spec; dmt_cb.length = sizeof(DMT_CB); dmt_cb.type = DMT_TABLE_CB; dmt_cb.dmt_id.db_tab_base = atuple->dba_objid.db_tab_base; dmt_cb.dmt_id.db_tab_index = atuple->dba_objid.db_tab_index; dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_ALTER, &dmt_cb); if (status != E_DB_OK) { error = dmt_cb.error.err_code; break; } } /* Get a unique query id */ TMnow((SYSTIME *)&qryid); atuple->dba_txtid.db_qry_high_time = qryid.db_qry_high_time; atuple->dba_txtid.db_qry_low_time = qryid.db_qry_low_time; /* Get a unique alarm id */ status = qea_reserveID(&atuple->dba_alarmid, qef_cb, &qef_rcb.error); if (status != E_DB_OK) { error = qef_rcb.error.err_code; break; } /* ** Generate an alarm name if needed, all blanks indicates no ** name specified. This is required for uniqueness check below. */ if(!STskipblank( (char*)&atuple->dba_alarmname, sizeof(atuple->dba_alarmname))) { status=qeu_gen_alarm_name( atuple->dba_objtype, (char*)&atuple->dba_objname, &qef_rcb, &atuple->dba_alarmid, (char*)&atuple->dba_alarmname, &error); if(status!=E_DB_OK) break; } /* Validate that the alarm name is unique */ qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IX; qeu.qeu_flag = DMT_U_DIRECT; qeu.qeu_access_mode = DMT_A_WRITE; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; atuple->dba_alarmno=0; /* Retrieve the same named alarm - if not there then ok */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_output = &qef_data; qef_data.dt_next = NULL; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR)&atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 0; /* Not keyed */ qparams.qeu_qparms[0] = (PTR) atuple; /* What we're looking for */ qeu.qeu_qual = qeu_qalarm_by_name; qeu.qeu_qarg = &qparams; status = qeu_get(qef_cb, &qeu); if (status == E_DB_OK) /* Found the same alarm! */ { (VOID)qef_error(E_US2472_9330_ALARM_EXISTS, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_alarmname), (char *)&atuple->dba_alarmname), (PTR)&atuple->dba_alarmname); error = E_QE0025_USER_ERROR; break; } if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS) { /* Some other error */ error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened=FALSE; /* ** Generate a unique alarm number. This is primarily for ** backwards compatibility with "anonymous" alarms which had ** to be dropped by number, not name. */ status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = &qef_data; qeu.qeu_output = &qef_data; qef_data.dt_next = 0; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR) &atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 3; qeu.qeu_key = akey_ptr_array; akey_ptr_array[0] = &akey_array[0]; akey_ptr_array[1] = &akey_array[1]; akey_ptr_array[2] = &akey_array[2]; akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY; akey_ptr_array[0]->attr_operator = DMR_OP_EQ; akey_ptr_array[0]->attr_value = (char*) &atuple->dba_objtype; akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY; akey_ptr_array[1]->attr_operator = DMR_OP_EQ; akey_ptr_array[1]->attr_value = (char*) &atuple->dba_objid.db_tab_base; akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY; akey_ptr_array[2]->attr_operator = DMR_OP_EQ; akey_ptr_array[2]->attr_value = (char*) &atuple->dba_objid.db_tab_index; qeu.qeu_qual = 0; qeu.qeu_qarg = 0; /* ** Get all alarm tuples for this object ** and determine the next alarm number. */ status = E_DB_OK; number = 0; while (status == E_DB_OK) { status = qeu_get(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } qeu.qeu_getnext = QEU_NOREPO; qeu.qeu_klen = 0; if (atuple_temp.dba_alarmno > number) number = atuple_temp.dba_alarmno; } if (error != E_QE0015_NO_MORE_ROWS) break; /* ** We have to add 1 to derive the next alarm number. */ atuple->dba_alarmno=number+1; /* Save the alarm tuple */ status = E_DB_OK; /* Insert single alarm tuple */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = qeuq_cb->qeuq_uld_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; /* Update all query text tuples with query id - validate list */ next = qeuq_cb->qeuq_qry_tup; for (i = 0; i < qeuq_cb->qeuq_cq; i++) { qtuple = (DB_IIQRYTEXT *)next->dt_data; next = next->dt_next; qtuple->dbq_txtid.db_qry_high_time = qryid.db_qry_high_time; qtuple->dbq_txtid.db_qry_low_time = qryid.db_qry_low_time; if (i < (qeuq_cb->qeuq_cq -1) && next == NULL) { error = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; break; } } /* for all query text tuples */ if (status != E_DB_OK) break; /* Insert all query text tuples */ qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; qeu.qeu_tab_id.db_tab_index = 0L; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = qeuq_cb->qeuq_cq; qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qeu.qeu_input = qeuq_cb->qeuq_qry_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; if (transtarted) /* If we started a transaction */ { status = qeu_etran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } } } while(loop); /* call qef_error to handle error messages */ if(error) (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables. */ local_status = E_DB_OK; if (tbl_opened) /* If system table opened, close it */ { local_status = qeu_close(qef_cb, &qeu); if (local_status != E_DB_OK) { (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) /* If we started a transaction */ { local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if ( Qef_s_cb->qef_state & QEF_S_C2SECURE ) { if(atuple->dba_objtype==DBOB_DATABASE) { evtype=SXF_E_DATABASE; } else { evtype=SXF_E_TABLE; } /* ** Creating an alarm is a control operation on the base object ** (database/table) */ if(status==E_DB_OK) access=(SXF_A_CONTROL|SXF_A_SUCCESS); else access=(SXF_A_CONTROL|SXF_A_FAIL); if(qeu_secaudit(FALSE, qef_cb->qef_ses_id, (char *)&atuple->dba_objname, &objowner, sizeof(atuple->dba_objname), evtype, I_SX202D_ALARM_CREATE, access, &e_error)!=E_DB_OK) { error = e_error.err_code; status=E_DB_ERROR; } } /* ** Log QEF create error */ if(status!=E_DB_OK) { (VOID) qef_error(E_QE028B_CREATE_ALARM_ERR, 0L, local_status, &error, &qeuq_cb->error, 0); qeuq_cb->error.err_code= E_QE0025_USER_ERROR; } return (status); } /* qeu_csecalarm */