/*{ ** Name: psy_qrymod - Process views, permits, and integrities ** ** Description: ** This function applies the qrymod algorithm to user queries. ** This algorithm is well-described in the specific functions ** psyview.c, psyinteg.c, and psypermit.c. It MUST be applied ** in the order: views, integrities, permits. This is because ** permits are on base tables, not on views, and we don't want ** the extra qualifications stuck on by the permit process to ** affect the integrities. ** ** Rules modifications are applied after all other query mods. ** Rules processing (in psyrules.c) may add statement trees to rule lists ** maintained in sess_cb. ** ** Inputs: ** qtree The query tree to modify ** sess_cb Current session control block ** psq_cb Calling control block ** num_joins ptr to a var containing number of joins ** in the query tree ** ** Outputs: ** qtree Can be modified by views, permits, ** and integrities ** sess_cb All kinds of miscellaneous stuff ** that is too detailed to describe here ** psq_cb ** .err_blk Filled in if an error happens ** ** *num_joins Will be incremented if any of the views ** involved in the query or any permits ** applied use joins. ** ** *resp_mask if the qmode==PSQ_VIEW will contain ** indicators of whether the view appears ** to be updateable and/or grantable view ** ** Returns: ** E_DB_OK Success ** E_DB_FATAL Failure ** Exceptions: ** none ** ** Side Effects: ** Can allocate memory ** Catalog I/O ** ** History: ** 09-jul-86 (jeff) ** Adapted from 4.0 qrymod() function ** 02-sep-86 (seputis) ** used result relation from auxiliary table since RDF ptrs are NULLed ** 18-sep-86 (daved) ** the result relation in the session cb is not always the ** same as the one found in the user range table. this is because ** the one in the range table is accurate only in an append statement. ** thus, we will now change the session cb to point to the correct ** result relation. ** 2-apr-87 (daved) ** set a pss_permit flag in the range table for each used entry. ** psy_permit will clear this flag. Psy_view will set this flag ** in all range entries that a derived from a table that still has ** this flag set, else it will clear this flag for new entries. ** We will then call psy_permit again, to catch all the new entries. ** 24-sep-87 (stec) ** Change error handling - call psf_error. ** 25-oct-87 (stec) ** Remove transaction creation, this is now done by SCF. ** 26-jan-89 (neil) ** Now also calls psy_rules to fill in rule tree. ** 08-mar-89 (neil) ** Calls psy_rules with more arguments. ** 22-jun-89 (andre) ** remove call to psy_protect() before call to psy_view() since ** psy_view() was modified to call psy_protect() before performing ** query modification on SQL views not belonging to the user. ** Additionally, &qtree will not be passed to psy_view(), since there ** is no apparent reason to do so (we no longer attempt to assign to ** the corresponding argument inside of psy_view() ) ** 24-jul-89 (jennifer) ** For each statement, indicate that audit information is NULL. ** 08-sep-89 (andre) ** recieve and pass to psy_view() and psy_permit() ptr to a var ** containing number of joins in the query tree. ** 19-sep-90 (andre) ** as a result of changes in psy_view(), we no longer need to call ** psy_permit() from psy_qrymod(). ** 13-dec-90 (ralph) ** Move reset of pss_audit to before psy_view invocation (b34903) ** 11-mar-91 (andre) ** if qmode is PSQ_VIEW, pass PSQ_RETRIEVE to psy_view(), psy_integ(), ** and psy_rules() + do not try to copy pss_usrrange to pss_auxrng ** since psy_dview() already placed the range table entries into ** pss_auxrng. ** (this is a part of fix for bug 33038) ** 07-aug-91 (andre) ** if qmode is PSQ_VIEW do NOT translate it to PSQ_RETRIEVE + ** if qmode is PSQ_VIEW do not bother calling psy_integ() and ** psy_rules() ** ** Added resp_mask to the argument list. This mask will be used to ** communicate info to the caller of psy_qrymod(). psy_qrymod() itself ** will not contribute anything to the information, instead, it will ** pass it to other functions (initially only to psy_view()) which will ** be responsible for providing the actual information. ** 30-dec-92 (andre) ** when processing a view tree in the course of processing CREATE RULE ** on a view we do NOT want to do any permit, rule, or integrity ** checking ** 04-jan-93 (andre) ** if we are processing DELETE, INSERT, or UPDATE, and a table or a ** view being updated has rules defined on it, set PSS_CHECK_RULES in ** sess_cb->pss_resrng->pss_var_mask to remind psy_view() to call ** psy_rules() ** ** since psy_dview() is going away, and psl_cview() calls psy_qrymod() ** with range variables as they were entered in the grammar, we must ** copy the range table from pss_usrrange to pss_auxrng for define VIEW ** just as we do for all other QUEL statements ** ** In most cases psy_rules() will NO LONGER be called from ** psy_qrymod(). It will be called from psy_view() when processing ** INSERT, DELETE, or UPDATE. This change was necessary because now ** rules can be defined on views, and it seemed reasonable that rule ** checking (just like privilege checking) can be driven from ** psy_view(). The once exception occurs when we are processing UPDATE ** WHERE CURRENT OF - psy_view() will simply return when presented with ** this query mode, but there may be rules that apply to this ** statement. Consequently, psy_rules() will be called from ** psy_qrymod() only when psq_qmode == PSQ_REPCURS ** 08-jan-93 (rblumer) ** set flag to bypass permission checking for dummy set-input ** range variables. ** 30-mar-93 (rblumer) ** set check_perms to false for system-generated procedures ** and for (internal) queries with PSS_NO_CHECKPERMS set. ** 01-apr-93 (andre) ** (fix for bugs 50823, 50825, and 50899) ** do not copy QUEL range table to aux. range table when processing ** REPLACE CURSOR - the entry describing the table/view over ** which the cursor has been defined has already been placed into ** pss_auxrng ** 08-apr-93 (andre) ** do not call psy_rules() explicitly for PSQ_REPCURS. psy_view() will ** now handle PSQ_REPCURS and call psy_rules() when necessary. ** 09-apr-93 (andre) ** set PSS_CHECK_RULES in the pss_var_mask corresponding to the ** table/view being updated via a cursor ** 26-apr-93 (markg) ** If the server is running C2 then initialize each range ** entry to show that it needs to be audited. ** 5-jul-93 (robf) ** If server is C2 then initialize any result range table to show ** it needs to be audited. ** 14-sep-93 (robf) ** Add QUERY_SYSCAT check, disallowing direct querying of ** base catalogs without privilege. This is done here rather than ** lower down in view/permit processing since we want to allow ** access to views on base catalogs (e.g. standard catalogs) ** to go ahead. ** 13-oct-93 (robf) ** Add <st.h> ** 25-oct-93 (stephenb) ** If the server is running C2 then also initialize the result range ** entry to show that it needs to be audited. ** 13-dec-93 (robf) ** When checking for query_syscat privilege, allow for extended ** catalogs. Some catalogs (like iistar_cdbs) have both the ** DMT_CATALOG and DMT_EXTENDED_CAT bits set. In this case we allow ** access since this priv restricts base catalogs only. ** 09-feb-94 (andre) ** fix for bug 59595: ** we also need to forego checking permits if we are parsing a ** system-generated query ** 11-jul-94 (robf) ** Restrict direct queries to table extensions the same way ** as system catalogs, i.e. to those with SELECT_SYSCAT privilege. ** The rationale for this is that info in extensions is really ** part of the base table, and to present an appropriately ** protected view of the data access should be through the base ** table, not directly at the extension. */ DB_STATUS psy_qrymod( PST_QNODE *qtree, PSS_SESBLK *sess_cb, PSQ_CB *psq_cb, PST_J_ID *num_joins, i4 *resp_mask) { PSS_RNGTAB *resrng; PSS_USRRANGE *rngtab = &sess_cb->pss_auxrng; PSF_MSTREAM *mstream = &sess_cb->pss_ostream; DB_ERROR *err_blk = &psq_cb->psq_error; i4 qmode = psq_cb->psq_mode; DB_STATUS status; i4 i; i4 check_perms = TRUE; GLOBALREF PSF_SERVBLK *Psf_srvblk; i4 err_code; bool can_query_syscat=FALSE; *resp_mask = 0L; /* init the response mask */ /* ** avoid permit checking when processing RULE trees, ** or when parsing/reparsing a system-generated procedure, ** or when parsing a system-generated query (e.g. a query to check whether ** constraints hold on existing data) */ if ((psq_cb->psq_mode == PSQ_RULE) || ( (sess_cb->pss_dbp_flags & PSS_DBPROC) && (sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED)) || (psq_cb->psq_flag & PSQ_NO_CHECK_PERMS) || ( (psq_cb->psq_info != (PST_INFO *) NULL) && (psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED)) ) { check_perms = FALSE; } /* ** Can user directly query system catalogs ? ** Users with databse privilege QUERY_SYSCAT, or users with ** SECURITY subject privilege may directly query system cats */ if(psy_ckdbpr(psq_cb, DBPR_QUERY_SYSCAT)==E_DB_OK) can_query_syscat=TRUE; else if(sess_cb->pss_ustat&DU_USECURITY) can_query_syscat=TRUE; else can_query_syscat=FALSE; /* ** Reset pss_audit prior to calling psy_view. */ sess_cb->pss_audit = NULL; /* ** We don't want to clobber the user's view of the range table in ** the process of doing qrymod. Therefore, we will copy the user's ** range table to the auxiliary range table, and use that instead. */ /* don't need to copy range table for SQL because there are no range ** table entries that live longer than one statement ** ** REPLACE CURSOR places description of the table/view over which it is ** defined into pss_auxrng */ if ( sess_cb->pss_lang == DB_QUEL && qmode != PSQ_REPCURS) { status = pst_rgcopy(&sess_cb->pss_usrrange, rngtab, &sess_cb->pss_resrng, err_blk); if (DB_FAILURE_MACRO(status)) return (status); } for (i = 0; i < PST_NUMVARS; i++) { rngtab->pss_rngtab[i].pss_rgparent = -1; /* don't want to check permissions on ** set-input temporary tables */ if (rngtab->pss_rngtab[i].pss_rgtype == PST_SETINPUT) rngtab->pss_rngtab[i].pss_permit = FALSE; else rngtab->pss_rngtab[i].pss_permit = check_perms; /* ** See if this is a real base catalog. ** We special case iidbcapabilities since its marked as a base ** catalog, but gets directly queried (and needs to be ** accessed by frontends) */ if(rngtab->pss_rngtab[i].pss_used && rngtab->pss_rngtab[i].pss_rgno != -1 && rngtab->pss_rngtab[i].pss_tabdesc && (( (rngtab->pss_rngtab[i].pss_tabdesc->tbl_2_status_mask&DMT_TEXTENSION) ) || ( (rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_CATALOG) && !(rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_VIEW) && !(rngtab->pss_rngtab[i].pss_tabdesc->tbl_status_mask&DMT_EXTENDED_CAT) && STncasecmp((char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name, "iidbcapabilities", GL_MAXNAME)!=0 )) ) { /* ** This is a base catalog. */ if(!can_query_syscat) { /* ** Error, user can't query base catalogs. */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) (VOID)psy_secaudit( FALSE, sess_cb, (char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name, &rngtab->pss_rngtab[i].pss_tabdesc->tbl_owner, DB_MAXNAME, SXF_E_SECURITY, I_SX273B_QUERY_SYSCAT, (SXF_A_SELECT|SXF_A_FAIL), err_blk); (VOID) psf_error(E_PS035A_CANT_QUERY_SYSCAT, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(DB_NAME), (char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name), (char*)&rngtab->pss_rngtab[i].pss_tabdesc->tbl_name); return E_DB_ERROR; } } /* ** If this is a C2 server set the PSS_DOAUDIT flag ** for this entry. */ if (Psf_srvblk->psf_capabilities & PSF_C_C2SECURE) rngtab->pss_rngtab[i].pss_var_mask |= PSS_DOAUDIT; } if (resrng = sess_cb->pss_resrng) { /* don't want to check permissions ** on set-input temporary tables */ if (rngtab->pss_rngtab[i].pss_rgtype == PST_SETINPUT) rngtab->pss_rngtab[i].pss_permit = FALSE; else rngtab->pss_rngtab[i].pss_permit = check_perms; /* ** if processing DELETE, UPDATE, INSERT, or UPDATE/REPLACE cursor, and ** there are rules defined on the view/table being updated, set ** PSS_CHECK_RULES in pss_var_mask */ if ( ( qmode == PSQ_APPEND || qmode == PSQ_DELETE || qmode == PSQ_REPLACE || qmode == PSQ_REPCURS ) && resrng->pss_tabdesc->tbl_status_mask & DMT_RULE ) { resrng->pss_var_mask |= PSS_CHECK_RULES; } /* ** If this is a C2 server set the PSS_DOAUDIT flag ** for the result table. */ if (Psf_srvblk->psf_capabilities & PSF_C_C2SECURE) rngtab->pss_rsrng.pss_var_mask |= PSS_DOAUDIT; } /* Apply view processing */ status = psy_view(mstream, qtree, rngtab, qmode, sess_cb, err_blk, num_joins, resp_mask); if (DB_FAILURE_MACRO(status)) { return (status); } /* ** do not check for existing INTEGRITIES when processing trees as a ** part of CREATE/DEFINE VIEW or CREATE RULE processing */ if (qmode != PSQ_VIEW && qmode != PSQ_RULE) { /* Apply integrity processing */ status = psy_integ(mstream, qtree, rngtab, resrng, qmode, sess_cb, &qtree, err_blk); if (DB_FAILURE_MACRO(status)) { return (status); } } return (status); }
/*{ ** Name: scs_monitor - Implement the SCS part of the monitor task ** ** Description: ** This routine is called ala the regular thread processing routine. ** It parses its input, decides what to do, and returns the output. ** ** The commmands completely interpreted here are: ** ** set server shut (CS_CLOSE) ** Disallow new connections, shutdown when ** last current session exits. ** ** remove SESSION ** New improved "safe" version, acts the same ** as front-end exiting and dropping GCA connection. ** ** kill SESSION ** Signal CS_KILL_EVENT to a user session actively ** running a query. ** ** NEW: ** set server closed ** Disallow new regular user sessions. ** ** set server open ** Reallow new regular user sessions. Cancel ** any pending 'set server shut' shutdown. ** ** show server listen ** ** crash session SESSIONID ** ** Commands partially handled here and partially in CSmonitor are: ** ** stop server (CS_KILL) ** Kill user sessions, shutdown when they're gone. ** ** stop server conditional (CS_COND_CLOSE) ** Shutdown if no sessions, which never works because ** this session always exists. ** ** crash server (CS_CRASH) ** Take the server down immediately. ** ** All other commands are passed to CSmonitor for handling. ** ** Inputs: ** mode Mode of operation ** CS_INPUT, _OUPUT, ... ** scb Sessions control block to monitor ** *command Text of the command ** powerful Is this user powerful ** output_fcn Function to call to perform the output. ** This routine will be called as ** (*output_fcn)(newline_present, ** length, ** buffer) ** where buffer is the length character ** output string, and newline_present ** indicates whether a newline needs to ** be added to the end of the string. ** ** Outputs: ** next_mode As above. ** Returns: ** OK ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-Jul-1993 (daveb) ** created. ** 15-Sep-1993 (daveb) ** ifdef out all but drop connection for now. ** 1-Nov-1993 (daveb) ** Match LRC proposal. Drop becomes remove, remove becomes kill. ** 10-Nov-1993 (daveb) ** Match approved proposal. Kill becomes "crash session SESSIONID" ** 15-dec-93 (robf) ** Add prototype "broadcast" message request. ** 4-mar-94 (robf) ** Add initial security auditing to iimonitor events. ** 12-dec-1996 (canor01) ** Add support for sampler thread. ** 24-Apr-2003 (jenjo02) ** Added "kill" command to abort eligible queries ** while leaving the session intact, SIR 110141. ** 17-Sep-2004 (schka24) ** Manual fix to remove command so that it fires. ** 05-may-2005 (horda03) Bug 114453/INGSRV 3290 ** For server/session changes log the command. ** 22-may-2007 (horda03) Bug 117966 ** Log the command before calling CSmonitor, as ** the CS could be crashing the server. ** 23-Sep-2009 (hanal04) Bug 115316 ** Added "SHOW SERVER CAPABILITIES". */ static STATUS scs_monitor( i4 mode, CS_SCB *scb, i4 *nmode, char *command, i4 powerful, i4 (*output_fcn)(PTR, i4, char *) ) { STATUS ret_stat; char buf[81]; bool completely_done; PTR ptr_scb; SCD_SCB *an_scb; i4 log_cmd = 0; i4 local_error; SCD_SCB *my_scb = (SCD_SCB*)scb; *nmode = CS_EXCHANGE; completely_done = FALSE; ret_stat = OK; switch (mode) { case CS_INITIATE: *nmode = CS_INPUT; break; case CS_TERMINATE: break; case CS_INPUT: CVlower(command); if (STscompare("setservershut", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to stop servers"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274D_SET_SERVER_SHUT ); } else /* disallow regular listens, exit when last conn exits */ { Sc_main_cb->sc_listen_mask = (SC_LSN_TERM_IDLE |SC_LSN_SPECIAL_OK) ; TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Server will stop. %d. sessions remaining", Sc_main_cb->sc_current_conns ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274D_SET_SERVER_SHUT ); log_cmd = 1; } completely_done = TRUE; } else if (STscompare("setserverclosed", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to disable connections"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2748_SET_SERVER_CLOSED ); } else /* Disallow regular listens */ { if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2748_SET_SERVER_CLOSED ); Sc_main_cb->sc_listen_mask &= (~SC_LSN_REGULAR_OK); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "User connections now disabled" ); log_cmd = 1; } completely_done = TRUE; } else if (STscompare("setserveropen", 0, command, 0) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to enable connections"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2749_SET_SERVER_OPEN ); } else /* allow all listens, cancel any impending shutdown */ { Sc_main_cb->sc_listen_mask = (SC_LSN_REGULAR_OK | SC_LSN_SPECIAL_OK); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "User connections now allowed" ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2749_SET_SERVER_OPEN ); log_cmd = 1; } completely_done = TRUE; } else if (STncasecmp("broadcast", command, 9) == 0) { /* Audit log the attempt here? */ if (!powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser status required to broadcast messages"); } else { /* ** Broadcast the message to any connected sessions */ scs_scan_scbs(scs_broadcast_mesg, (PTR)(command+10)); } completely_done = TRUE; } else if (STscompare("stopserverconditional", 0, command, 0) == 0 || STscompare("stopserver", 0, command, 0) == 0 || STscompare("crashserver", 0, command, 0) == 0 ) { /* Audit log the attempt here? */ if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, powerful? SXF_A_CONTROL|SXF_A_SUCCESS: SXF_A_CONTROL|SXF_A_FAIL, /* Action */ I_SX274A_STOP_SERVER ); log_cmd = powerful; } else if (STscompare("showservercapabilities", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%v", SC_CAPABILITIES_FLAGS, Sc_main_cb->sc_capabilities ); completely_done = TRUE; } else if (STscompare("showserverlisten", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", Sc_main_cb->sc_listen_mask & SC_LSN_REGULAR_OK ? "OPEN" : "CLOSED" ); completely_done = TRUE; } else if (STscompare("showservershutdown", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "%s", Sc_main_cb->sc_listen_mask & SC_LSN_TERM_IDLE ? "PENDING" : "OPEN" ); completely_done = TRUE; } # ifdef NOT_SUPPORTED else if (STscompare("showconnections", 0, command, 0) == 0 ) { scs_scan_scbs( scs_show_func, (PTR)&powerful ); completely_done = TRUE; } else if (STscompare("show connection", 15, command, 15) == 0 ) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 14, &ptr_scb) || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid connection id"); break; } scs_show_func( an_scb, &powerful ); } # endif else if (STscompare("remove", 6, command, 6) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 6, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); break; } if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to remove session"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274B_REMOVE_SESSION ); break; } if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274B_REMOVE_SESSION ); scs_remove_sess( an_scb ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p removed", an_scb); log_cmd = 1; } else if (STscompare("crash session", 13, command, 13) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 12, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); break; } if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to crash session"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX274C_CRASH_SESSION ); break; } if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX274C_CRASH_SESSION ); scs_crash_sess( an_scb ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p crashed", an_scb); log_cmd = 1; } else if (STscompare("kill", 4, command, 4) == 0) { completely_done = TRUE; STzapblank(command, command); if (CVaxptr(command + 4, &ptr_scb) || scb == NULL || !scs_is_user_scb( (an_scb = (SCD_SCB *)ptr_scb) ) || an_scb == my_scb ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Invalid session id"); } else if ((MEcmp(an_scb->cs_scb.cs_username, scb->cs_username, sizeof(scb->cs_username))) && !powerful) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Superuser or owner status required to kill query"); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_FAIL, I_SX2755_KILL_QUERY ); } else switch ( an_scb->scb_sscb.sscb_qmode ) { case 0: TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p is not executing a query", an_scb); break; /* Honor only "meaningful" types of queries: */ case PSQ_RETRIEVE: case PSQ_RETINTO: case PSQ_APPEND: case PSQ_REPLACE: case PSQ_DELETE: case PSQ_COPY: case PSQ_MODIFY: case PSQ_EXECQRY: case PSQ_EXCURS: case PSQ_CALLPROC: case PSQ_REPCURS: case PSQ_RETCURS: case PSQ_EXEDBP: case PSQ_REGPROC: case PSQ_DDEXECPROC: case PSQ_CREATE: if ( an_scb->scb_sscb.sscb_force_abort || an_scb->scb_sscb.sscb_interrupt ) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query already aborting", an_scb); } else { scs_kill_query( an_scb ); if ( Sc_main_cb->sc_capabilities & SC_C_C2SECURE ) scs_mon_audit((SCD_SCB*)scb, SXF_A_CONTROL|SXF_A_SUCCESS, I_SX2755_KILL_QUERY ); TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query killed", an_scb); } break; default: TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "Session %p query cannot be killed", an_scb); break; } } # ifdef NOT_SUPPORTED else if (STscompare("help", 0, command, 0) == 0) { TRformat(output_fcn, 1, buf, sizeof(buf) - 1, "SCS monitor commands:\nset server shut\nset server closed\nset server open\nshow server listen\nshow server shutdown\nremove SESSION\ncrash session SESSION\n\nCS monitor commands:\n"); } # endif else if (! CS_is_mt()) /* OS Thread version will start an OS thread in the CS */ if ((STscompare("start sampling", 14, command, 14) == 0)) { if (!powerful) { TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1, "Superuser status required to start sampling.", 0L); } else { GCA_LS_PARMS local_crb; CL_ERR_DESC errdesc; local_crb.gca_status = 0; local_crb.gca_assoc_id = 0; local_crb.gca_size_advise = 0; local_crb.gca_user_name = "<Sampler Thread>"; local_crb.gca_account_name = 0; local_crb.gca_access_point_identifier = "NONE"; local_crb.gca_application_id = 0; /* set up all the CS control blocks for the sampler */ ret_stat = CSmonitor( mode, scb, nmode, command, powerful, output_fcn ); if ( ret_stat == OK ) ret_stat = CSadd_thread(CS_LIM_PRIORITY-1, (PTR) &local_crb, SCS_SSAMPLER, (CS_SID*)NULL, &errdesc); if (ret_stat) { TRformat(output_fcn, (i4 *) 1, buf, sizeof(buf)-1, "Sampling failed to start."); } } } /* log the command before calling CSmonitor(), as the server could be left in an ** unknown state if the command CRASH SERVER or STOP SERVER are used */ if (log_cmd) { ule_format( I_SC051E_IIMONITOR_CMD, 0, ULE_LOG, NULL, 0, 0, 0, &local_error, 3, STlength(command), command, DB_OWN_MAXNAME, &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_rusername, sizeof(DB_TERM_NAME), &((SCD_SCB *)scb)->scb_sscb.sscb_ics.ics_terminal, 0, 0); } if( !completely_done ) ret_stat = CSmonitor( mode, scb, nmode, command, powerful, output_fcn ); break; case CS_OUTPUT: break; } return( ret_stat ); }
STATUS gcn_recrypt( bool clustered, u_i1 *local_mask, char *gcn_val, bool *v1DecryptErr, bool *writeOutput) { i2 pc; char *pv[ 3 ]; STATUS status = OK; char *p; char pwd[GC_L_PASSWORD]; i2 j; bool printable; *v1DecryptErr = FALSE; pc = gcu_words( gcn_val, NULL, pv, ',', 3 ); if (pc < 2 ) pv[1] = ""; if (pc < 3 ) pv[2] = ""; if (!STcasecmp(pv[2],"V0") || (pc < 3)) status = gcn_decrypt( pv[0], pv[1], pwd ); else status = gcn_decode( pv[0],(u_i1*)local_mask, pv[1], pwd ); if (status != OK) { if (!STcasecmp(pv[2],"V1")) *v1DecryptErr = TRUE; goto end_routine; } if (!STlength(pwd)) { if (!STcasecmp(pv[2],"V1")) *v1DecryptErr = TRUE; status = FAIL; goto end_routine; } p = &pwd[0]; printable = TRUE; for (j = 0; j < STlength(pwd); j++) { if (!CMprint(p)) { printable = FALSE; break; } CMnext(p); } if (!printable) { if (!STcasecmp(pv[2],"V1")) *v1DecryptErr = TRUE; status = FAIL; goto end_routine; } if (clustered) { if (!STncasecmp("V1", pv[2], STlength(pv[2]))) *writeOutput = TRUE; status = gcu_encode( pv[0], pwd, pv[1] ); STpolycat( 5, pv[0], ",", pv[1], ",", "V0", gcn_val ); } else { status = gcn_encode( pv[0],(u_i1*)local_mask, pwd, pv[1] ); STpolycat( 5, pv[0], ",", pv[1], ",", "V1", gcn_val ); } end_routine: return status; }
main(int argc, char **argv) { STATUS status = OK; VMS_STATUS vStatus; char srcbuf[NAME_FILE_SIZE]; char dstbuf[NAME_FILE_SIZE]; char delFile[NAME_FILE_SIZE]; struct dsc$descriptor_s filename_d = { sizeof (delFile) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, delFile }; FILE *srcFile = NULL; FILE *dstFile = NULL; FILE *nameFile = NULL; LOCATION loc; bool clusterArg = FALSE; bool unclusterArg = FALSE; bool writeOutput = FALSE; bool validSyntax; bool clustered = FALSE; bool v1DecryptErr = FALSE; bool rewrite = FALSE; bool isLogin = FALSE; i4 total_recs = 0; char local_host[MAX_LOC+CM_MAXATTRNAME]; char config_host[MAX_LOC+CM_MAXATTRNAME]; i2 i,j; i4 active_rec; i4 offset; char *onOff = NULL; bool srcOpened=FALSE; bool dstOpened=FALSE; bool printable = TRUE; GCN_QUEUE *gcn_q; GCN_QUEUE *merge_q; i4 rec_len = 0; QUEUE *q; u_i1 local_mask[ 8 ]; /* Must be 8 bytes */ char name[MAX_LOC+CM_MAXATTRNAME]; i4 count; char *p = NULL; i4 dcryptFail = 0; i2 pc; char *pv[ 3 ]; GCN_DB_REC0 tmp_rec; SYSTIME timestamp; MEadvise(ME_INGRES_ALLOC); SIeqinit(); GChostname( local_host, sizeof(local_host)); STcopy (PMhost(), config_host); if (argc == 1) validSyntax = TRUE; /* ** Parse input arguments. */ for (i = 1; i < argc; i++) { validSyntax = FALSE; for (j = 0; j < argLen; j++) { if (!STncasecmp(arg[j],argv[i], STlength(argv[i]))) { switch(j) { case HELP1: case HELP2: case HELP3: case HELP4: usage(); break; case VERBOSE: validSyntax = TRUE; verboseArg = TRUE; break; case CLUSTER: validSyntax = TRUE; clusterArg = TRUE; writeOutput = TRUE; break; case UNCLUSTER: validSyntax = TRUE; unclusterArg = TRUE; writeOutput = TRUE; break; } } /* if (!STncasecmp(arg[j],argv[i], STlength(argv[i]))) */ if (validSyntax) break; } /* for (j = 0; j < argLen; j++) */ if (!validSyntax) break; } /* for (i = 1; i < argc; i++) */ if (!validSyntax) { usage(); PCexit(1); } if (clusterArg && unclusterArg) { SIprintf("Cannot specify both -c and -u\n\n"); usage(); PCexit(1); } if (verboseArg) SIprintf("Local host is %s\n", local_host); /* ** Generate key seeds for encoding and decoding. */ STpolycat( 2, GCN_LOGIN_PREFIX, local_host, name ); gcn_init_mask( name, sizeof( local_mask ), local_mask ); QUinit(&gcn_qhead); QUinit(&merge_qhead); PMinit(); /* ** See if this is a clustered installation. If it is, ** the node, login, and attribute files have no file extension. */ if ( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) != OK ) { SIprintf("Error reading config.dat, exiting\n"); goto cvt_exit; } PMsetDefault( 0, SystemCfgPrefix ); PMsetDefault( 1, config_host ); PMsetDefault( 2, ERx("gcn") ); status = PMget( ERx("!.cluster_mode"), &onOff); if (onOff && *onOff) ; else onOff = "OFF"; if (verboseArg) SIprintf("Cluster mode is %s\n", onOff); if (!clusterArg && !unclusterArg) clustered = !STncasecmp(onOff, "ON", STlength(onOff)); /* ** Rewrite the named GCN files. For clustered installations, the ** node, login and attribute files have no hostname extension. */ for ( i = 0; i < NBR_NAMED_FILES; i++ ) { /* ** Ticket files are simply deleted. */ if (i == IILTICKET || i == IIRTICKET) { STprintf(delFile, "II_SYSTEM:[INGRES.FILES.NAME]II%s*;*", named_file[i].file); if (verboseArg) SIprintf("Deleting %s\n", delFile); filename_d.dsc$w_length = STlength(delFile); vStatus = lib$delete_file(&filename_d,0,0,0,0,0,0,0,0,0); if (!vStatus & STS$M_SUCCESS) SIprintf("delete of %s failed, status is 0x%d\n", delFile, vStatus); continue; } rewrite = FALSE; if (!clusterArg && !unclusterArg) writeOutput = FALSE; if ( ( status = NMloc( FILES, PATH & FILENAME, (char *)NULL, &loc ) ) != OK ) { SIprintf("iicvtgcn: Could not find II_SYSTEM:[ingres.files]\n"); goto cvt_exit; } LOfaddpath( &loc, "name", &loc ); if (clustered || unclusterArg) { if (named_file[i].add_cluster_node) STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host); else STprintf(srcbuf, "II%s", named_file[i].file); } else STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host); if (verboseArg) SIprintf("Opening %s for input\n", srcbuf); LOfstfile( srcbuf, &loc ); /* ** Ignore non-existent files. */ if ( LOexist( &loc ) != OK ) { if (verboseArg) SIprintf("%s does not exist\n", srcbuf); continue; } /* ** Open the existing file as "regular" RACC. */ status = SIfopen( &loc, "r", (i4)SI_RACC, sizeof( GCN_DB_REC0 ), &srcFile ); /* ** If the file exists but can't be opened, it's already optimized. */ if (status == E_CL1904_SI_CANT_OPEN && ( LOexist( &loc ) == OK ) ) { /* ** Open the existing file as "optimized" RACC. */ status = SIfopen( &loc, "r", (i4)GCN_RACC_FILE, sizeof( GCN_DB_REC0 ), &srcFile ); if (status != OK) { SIprintf( "iicvtgcn: Error opening %s, status is %x\n", srcbuf, status ); continue; } if (verboseArg) SIprintf("%s is already optimized\n", srcbuf); } else if (status != OK) { SIprintf( "iicvtgcn: Error opening %s, status is %x\n", srcbuf, status ); continue; } /* ** A successful open as SI_RACC means the file is not optimized. ** This file needs a rewrite. */ else { if (verboseArg) SIprintf("Rewriting %s as optimized\n", srcbuf); writeOutput = TRUE; } srcOpened = TRUE; while ( status == OK ) { /* ** Read the source data and store in a queue for analysis. */ status = SIread( srcFile, sizeof( GCN_DB_REC0 ), &count, (PTR)&tmp_rec ); if ( status == ENDFILE ) break; if ( status != OK ) { SIprintf("iicvtgcn: Error reading %s, status is %x\n", srcbuf, status); goto cvt_exit; } else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1) continue; else { gcn_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL); if (!gcn_q) { SIprintf("iicvtgcn: Cannot allocate memory, exiting\n"); goto cvt_exit; } MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf); QUinsert(&gcn_q->q, &gcn_qhead); /* ** EOF record found. */ if (gcn_q->buf.gcn_tup_id == -1) { gcn_q->buf.gcn_l_uid = 0; gcn_q->buf.gcn_uid[0] = '\0'; gcn_q->buf.gcn_l_obj = 0; gcn_q->buf.gcn_obj[0] = '\0'; gcn_q->buf.gcn_l_val = 0; gcn_q->buf.gcn_val[0] = '\0'; gcn_q->buf.gcn_invalid = TRUE; break; } } } /* while ( status == OK ) */ /* ** Decrypt passwords for IILOGIN files. If any V1 records are found, ** the IILOGIN file will need to be rewritten. */ isLogin = FALSE; for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) { gcn_q = (GCN_QUEUE *)q; /* ** EOF record found. */ if (gcn_q->buf.gcn_tup_id == -1) { gcn_q->buf.gcn_invalid = TRUE; break; } if (i == IILOGIN) { isLogin = TRUE; MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), (PTR)&tmp_rec); if (verboseArg) SIprintf("\tEncoding vnode %s\n", gcn_q->buf.gcn_obj); if (unclusterArg) status = gcn_recrypt( FALSE, local_mask, gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput); else if (clusterArg) status = gcn_recrypt( TRUE, local_mask, gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput); else status = gcn_recrypt( clustered, local_mask, gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput); if (status != OK) { if (verboseArg) SIprintf("Cannot decrypt password from " \ "vnode %s status %x\n", gcn_q->buf.gcn_obj, status); dcryptFail++; MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf); continue; } if (v1DecryptErr) { if (verboseArg) SIprintf("Cannot decrypt password from " \ "vnode %s\n", gcn_q->buf.gcn_obj); dcryptFail++; MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf); continue; } } /* if (LOGIN) */ } /* for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) */ if (dcryptFail && verboseArg && isLogin) { if (clustered || unclusterArg ) SIprintf("\n%d vnode(s) could not be decrypted.\n" \ "Probably some login entries were created on " \ "another node.\nTry executing iicvtgcn on another " \ "node to merge the other node's entries.\n\n", dcryptFail); else SIprintf("\n%d vnode(s) could not be decrypted.\n" \ "Probably the login file was created on " \ "another host.\nTry executing iicvtgcn on " \ "a different host.\n\n", dcryptFail); } if (!writeOutput) { if (srcOpened) SIclose(srcFile); srcOpened = FALSE; cleanup_queues(); continue; } /* ** Open the destination file with special GCN_RACC_FILE flag, for ** optimized writes. */ if (clustered || clusterArg) { if (named_file[i].add_cluster_node) STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host); else STprintf(dstbuf, "II%s", named_file[i].file); } else STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host); if (clusterArg && !named_file[i].add_cluster_node) rewrite = TRUE; LOfstfile( dstbuf, &loc ); if (rewrite) { status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, sizeof( GCN_DB_REC0 ), &dstFile ); if ( status != OK ) { status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, sizeof( GCN_DB_REC0 ), &dstFile ); if (status == OK) { SIclose( dstFile); status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, sizeof( GCN_DB_REC0 ), &dstFile ); } } } else status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, sizeof( GCN_DB_REC0 ), &dstFile ); if ( status != OK ) { SIprintf( "iicvtgcn: Error opening %s, status is %x\n",dstbuf, status ); goto cvt_exit; } dstOpened = TRUE; if (verboseArg) SIprintf("%s %s\n", rewrite ? "Rewriting " : "Writing ", dstbuf); /* ** If this is a merge operation (-c), login, attribute or ** node files may change the location of EOF, since the ** file to be merged may have different records than ** the destination file. ** Before merging, the output file is read and fed into a queue. ** Then each merge record is compared to each output record. ** If the entire records match, nothing is done. ** If a global login record matches only the vnode name ** global or private records will be added if not present; ** otherwise, nothing is done. ** Node or attribute records may be added if only one field ** fails to match. */ status = SIfseek(dstFile, (i4)0, SI_P_START); if (rewrite) { while ( status == OK ) { /* ** Read the source data and store in a queue for analysis. */ status = SIread( dstFile, sizeof( GCN_DB_REC0 ), &count, (PTR)&tmp_rec ); if ( status == ENDFILE ) break; if ( status != OK ) { SIprintf("iicvtgcn: Error reading %s, status is %x\n", dstbuf, status); goto cvt_exit; } else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1) continue; else { merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL); if (!merge_q) { SIprintf("iicvtgcn: Cannot allocate memory, exiting\n"); goto cvt_exit; } MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&merge_q->buf); QUinsert(&merge_q->q, &merge_qhead); /* ** EOF record found. */ if (merge_q->buf.gcn_tup_id == -1) break; } if ( status == ENDFILE ) break; } /* while ( status == OK ) */ /* ** Go through the input queue. Compare each record with ** the output (merge) queue. If the record is invalid ** or doesn't match, it's ignored. */ dcryptFail = 0; total_recs = 0; for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) { SYSTIME timestamp; gcn_q = (GCN_QUEUE *)q; if (gcn_q->buf.gcn_tup_id == -1) break; if ( !gcn_merge_rec( gcn_q, isLogin ) ) continue; if (isLogin) { /* ** Login passwords get encrypted as V0 in a cluster ** environment. */ MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), (PTR)&tmp_rec); status = gcn_recrypt( TRUE, local_mask, gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput); if (status != OK) { if (verboseArg) SIprintf("Cannot decrypt password from " \ "vnode %s status %x\n", gcn_q->buf.gcn_obj, status); dcryptFail++; MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf); continue; } if (v1DecryptErr) { if (verboseArg) SIprintf("Cannot decrypt password from " \ "vnode %s\n", gcn_q->buf.gcn_obj); dcryptFail++; MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf); continue; } } merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL); if (!merge_q) { SIprintf("iicvtgcn: Cannot allocate memory, exiting\n"); goto cvt_exit; } MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), (PTR)&merge_q->buf); total_recs++; QUinsert(&merge_q->q, &merge_qhead); } if (dcryptFail && verboseArg && isLogin) { if (clustered || unclusterArg ) SIprintf("\n%d vnode(s) could not be decrypted.\n" \ "Probably some login entries were created on " \ "another node.\nTry executing iicvtgcn on another " \ "node to merge the other node's entries.\n\n", dcryptFail); else SIprintf("\n%d vnode(s) could not be decrypted.\n" \ "Probably the login file was created on " \ "another host.\nTry executing iicvtgcn on " \ "a different host.\n\n", dcryptFail); } if (verboseArg) SIprintf("Total records merged: %d\n", total_recs); /* ** If no records to merge, clean up and continue. */ if (!total_recs) { cleanup_queues(); continue; } status = SIfseek(dstFile, (i4)0, SI_P_START); active_rec = 0; for (q = merge_qhead.q_prev; q != &merge_qhead; q = q->q_prev) { merge_q = (GCN_QUEUE *)q; if (verboseArg) SIprintf("Rewriting %s record vnode %s val %s\n", !STcasecmp("*", merge_q->buf.gcn_uid) ? "global" : "private", merge_q->buf.gcn_obj, merge_q->buf.gcn_val); if (merge_q->buf.gcn_tup_id == -1) continue; status = SIwrite(sizeof( GCN_DB_REC0 ), (char *)&merge_q->buf, &count, dstFile ); if ( status != OK) { SIprintf( "iicvtgcn: Failed to write file %s, " \ "status is %x\n", srcbuf, status ); goto cvt_exit; } active_rec++; } /* ** Write new EOF record. */ tmp_rec.gcn_tup_id = -1; tmp_rec.gcn_l_uid = 0; tmp_rec.gcn_uid[0] = '\0'; tmp_rec.gcn_l_obj = 0; tmp_rec.gcn_obj[0] = '\0'; tmp_rec.gcn_l_val = 0; tmp_rec.gcn_val[0] = '\0'; tmp_rec.gcn_invalid = TRUE; offset = active_rec * sizeof(GCN_DB_REC0); status = SIfseek(dstFile, (i4)offset, SI_P_START); status = SIwrite(sizeof( GCN_DB_REC0 ), (PTR)&tmp_rec, &count, dstFile ); } else { for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) { gcn_q = (GCN_QUEUE *)q; gcn_q->buf.gcn_l_val = STlength(gcn_q->buf.gcn_val); if (verboseArg) SIprintf("Writing %s record vnode %s val %s\n", !STcasecmp("*", gcn_q->buf.gcn_uid) ? "global" : "private", gcn_q->buf.gcn_obj, gcn_q->buf.gcn_val); status = SIwrite(sizeof( GCN_DB_REC0 ), (char *)&gcn_q->buf, &count, dstFile ); if ( status != OK) { SIprintf( "iicvtgcn: Failed to write file %s, " \ "status is %x\n", srcbuf, status ); goto cvt_exit; } } } /* if (rewrite) */ cleanup_queues(); SIclose( srcFile ); srcOpened = FALSE; SIclose( dstFile ); dstOpened = FALSE; } /* for (i = 0; i < NBR_NAMED_FILES; i++ ) */ cvt_exit: cleanup_queues(); if (srcOpened) SIclose(srcFile); if (dstOpened) SIclose(dstFile); PCexit( OK ); }
static VOID gcn_nq_filename( char *type, char *host, char *filename ) { i4 len, plen, slen; char *onOff = NULL; bool clustered = FALSE; STATUS status; /* ** Filename template: II<type>[_<host>] */ plen = 2; len = STlength( type ); slen = (host && *host) ? STlength( host ) + 1 : 0; /* ** Adjust filename for platform limitations: ** drop prefix if type and suffix OK; ** drop suffix if prefix and type OK; ** otherwise, drop both prefix and suffix. */ if ( plen + len + slen > LO_NM_LEN ) if ( len + slen <= LO_NM_LEN ) plen = 0; else if ( plen + len <= LO_NM_LEN ) slen = 0; else plen = slen = 0; /* ** See if this is a clustered installation. If it is, ** the node, login, and attribute files have no file extension. */ if ( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) != OK ) { SIprintf("Error reading config.dat\n"); return; } PMsetDefault( 0, "ii" ); PMsetDefault( 1, host ); PMsetDefault( 2, ERx("gcn") ); status = PMget( ERx("!.cluster_mode"), &onOff); if (onOff && *onOff) clustered = !STncasecmp(onOff, "ON", STlength(onOff)); if (clustered && (!STncasecmp("LOGIN", type, STlength(type)) || !STncasecmp("NODE", type, STlength(type)) || !STncasecmp("ATTR", type, STlength(type)))) slen = 0; CVupper(type); STprintf( filename, "%s%s%s%s", plen ? "II" : "", type, slen ? "_" : "", slen ? host : "" ); /* ** Finally, truncate the filename if it is too long ** (hopefully this will never happen). */ if ( STlength( filename ) > LO_NM_LEN ) filename[ LO_NM_LEN ] = '\0'; return; }