static char * saveloc(char *path) { char *rval = NULL; char ptmp[MAX_PATH_LEN + 2]; if (STlength(path) > MAX_PATH_LEN) { i4 maxl = MAX_PATH_LEN; IIUGmsg(ERget(E_XF0130_Path_Too_Long), FALSE, 2, path, &maxl); /* Truncate and save */ (void) STlcopy(path, ptmp, MAX_PATH_LEN); rval = STalloc(ptmp); } else { rval = STalloc(path); } /* Truncate and save */ (void) STlcopy(path, ptmp, MAX_PATH_LEN); rval = STalloc(ptmp); return (rval); }
/*{ ** Name: CXset_context - Set the CX node "context". ** ** Description: ** ** If configured for clusters, the CX "context" determines ** what node the calling utility is bound to. That is, ** what directory is used when mapping shared segments, how ** file names are "decorated", and It determines the default ** PM hostname, and if running NUMA clusters, the host name ** override. ** ** Inputs: ** host - Node name or host name for the context. ** If NULL, value from PHhost is used. ** rad - If running NUMA clusters, 1st argument must be the host ** name, (or NULL), and a node name is constructed from ** the hostname(PMhost)/rad pair as "R<radid>_<hostname>" ** If not running NUMA clusters, this must be zero. ** ** Outputs: ** none. ** ** Returns: ** OK - Context was set. ** E_CL2C2F_CX_E_BADRAD - Rad value out of range. ** E_CL2C42_CX_E_NOT_CONFIGURED - Node or RAD not configured ** as part of the cluster. ** ** Exceptions: ** none ** ** Side Effects: ** Important & plentyful, see description. ** ** History: ** 16-sep-2002 (devjo01) ** Created. */ STATUS CXset_context( char * host, i4 rad ) { # define HOST_PM_IDX 1 STATUS status = OK; CX_NODE_INFO *pni; char namebuf[ CX_MAX_NODE_NAME_LEN + 1 ]; do { if ( !host ) { host = CXhost_name(); } if ( CXcluster_configured() ) { pni = CXnode_info( host, rad ); if ( NULL == pni ) { status = E_CL2C42_CX_E_NOT_CONFIGURED; break; } namebuf[CX_MAX_NODE_NAME_LEN] = '\0'; STlcopy( pni->cx_node_name, namebuf, CX_MAX_NODE_NAME_LEN ); CVlower( namebuf ); STcopy(namebuf, cx_saved_node_name); if ( pni->cx_host_name_l && ( pni->cx_host_name_l != pni->cx_node_name_l || 0 != STxcompare( pni->cx_node_name, pni->cx_node_name_l, pni->cx_host_name, pni->cx_host_name_l, TRUE, FALSE ) ) ) { STlcopy( pni->cx_host_name, namebuf, CX_MAX_NODE_NAME_LEN ); CVlower( namebuf ); PMsetDefault( HOST_PM_IDX, namebuf ); } else { PMsetDefault( HOST_PM_IDX, namebuf ); } if ( 0 != pni->cx_rad_id ) CX_Proc_CB.cx_numa_user_rad = pni->cx_rad_id; CX_Proc_CB.cx_numa_cluster_rad = pni->cx_rad_id; } else { PMsetDefault( HOST_PM_IDX, host ); if ( 0 != rad ) CX_Proc_CB.cx_numa_user_rad = rad; } } while (0); return status; } /* CXset_context */
void Time2Chars (double dSecond, char* buffer) { char* p; char buff1[16]; char buff2[16]; int m = 0; int h = 0; while (dSecond >= 60.0) { dSecond -= 60.0; m++; } while (m >= 60) { m -= 60; h++; } dSecond = dSecond*100; STprintf(buff1, "%04d", (int)dSecond); STlcopy (buff1, buff2, 2); p = buff1; p += 2; STprintf (buffer, "%02d%:%02d:%s", h, m, buff2); STcat(buffer, "."); STcat(buffer, p); }
/*{ ** Name: II_GetErrorMessage ** ** Description: ** Returns the associated error message for the error status. ** ** Inputs: ** status Error status. ** errmsg Area to be updated with message text. The maximum length, ** in octets, of a returned message is MAX_IIERR_LEN and ** does not include the end-of-string marker. ** The minimum size of this area should be ** (MAX_IIERR_LEN + 1). ** ** Outputs: ** errmsg Error text. If the message text exceeds MAX_IIERR_LEN ** then the message is truncated to MAX_IIERR_LEN. ** ** Returns: ** None. ** ** Example: ** # include "tngapi.h" ** ** II_CHAR errmsg[ MAX_IIERR_LEN + 1] = {'\0'}; ** II_INT status = II_NULL_PARAM; ** ** II_GetErrorMessage( status, errmsg ); ** printf( "Error message =%s\n", errmsg ); ** ** History: ** 24-Jun-2002 (fanra01) ** Created. ** }*/ void II_GetErrorMessage( II_UINT4 status, char* errmsg ) { char errormessage[ MAX_IIERR_LEN + 1 ] = { 0 }; #if defined(NT_GENERIC) char* p = errormessage; int nlen = 0; if (errmsg) { if (hModule == NULL) { hModule = GetModuleHandle( II_MODULENAME ); } if (hModule != NULL) { FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, (LPCVOID)hModule, status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (LPTSTR) errormessage, MAX_IIERR_LEN, NULL ); STlcopy( errormessage, errmsg, MAX_IIERR_LEN ); } } #else /* NT_GENERIC */ /* Here is for Unix platforms , Send back error message to the caller */ if( status != OK ) { STprintf( errormessage, ERget(status) ); SIfprintf( stderr, errormessage ); STlcopy( errormessage, errmsg, STlength(errormessage) ); } #endif return; }
static bool writeMgrFile( char *altPath ) { char *dirPath; char fullPath[OCFG_MAX_STRLEN]; FILE *pfile; LOCATION loc; STATUS status; # ifdef VMS NMgtAt(SYSTEM_LOCATION_VARIABLE,&dirPath); /* usually II_SYSTEM */ if (dirPath != NULL && *dirPath) STlcopy(dirPath,fullPath,sizeof(fullPath)-20-1); else return (FALSE); STcat(fullPath,"["); STcat(fullPath,SYSTEM_LOCATION_SUBDIRECTORY); /* usually "ingres" */ STcat(fullPath,".files]"); STcat(fullPath,MGR_STR_FILE_NAME); # else NMgtAt(SYSTEM_LOCATION_VARIABLE,&dirPath); /* usually II_SYSTEM */ if (dirPath != NULL && *dirPath) STlcopy(dirPath,fullPath,sizeof(fullPath)-20-1); else return (FALSE); STcat(fullPath,"/"); STcat(fullPath,SYSTEM_LOCATION_SUBDIRECTORY); /* usually "ingres" */ STcat(fullPath,"/files/"); STcat(fullPath,MGR_STR_FILE_NAME); # endif /* ifdef VMS */ if ( LOfroms(PATH & FILENAME, fullPath, &loc) != OK ) return FALSE; if (SIfopen(&loc, "w", (i4)SI_TXT, OCFG_MAX_STRLEN, &pfile) != OK) return FALSE; if (altPath && *altPath) SIfprintf(pfile,"%s=%s\n",MGR_STR_PATH,altPath); SIfprintf(pfile,"%s=%s\n",MGR_STR_MANAGER, driverManager == MGR_VALUE_UNIX_ODBC ? MGR_STR_UNIX_ODBC : MGR_STR_CAI_PT); return TRUE; }
/*{ ** Name: CXhost_name - Get host name for current machine. ** ** Description: ** ** This is just a wrapper for PMhost, which assures that ** the name is not more than CX_MAX_NODE_NAME_LEN characters ** long and is entirely lower case. ** ** Inputs: ** none ** ** Outputs: ** none ** ** Returns: ** Address of cached host name. ** ** Exceptions: ** none ** ** Side Effects: ** none. ** ** History: ** 01-oct-2001 (devjo01) ** Created. ** 17-dec-2004 (devjo01) ** Correct 'cx_saved_node_name' ref to intended 'cx_hostname'. */ char * CXhost_name() { static char cx_hostname[CX_MAX_HOST_NAME_LEN] = { '\0', }; if ( '\0' == cx_hostname[0] ) { STlcopy( PMhost(), cx_hostname, CX_MAX_HOST_NAME_LEN ); CVlower(cx_hostname); } return cx_hostname; } /* CXhost_name */
static void yyputline( char *outtext) { char token_buf[MAX_LINE+1]; char token_val[MAX_LINE+1]; char *p = token_buf; static char *symc = ERx( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$"); i4 symc_l = STlength(symc); i4 defidx; static i4 iterate_level = 0; /* Check to make sure we don't have runaway recursion */ if (iterate_level++ > MAX_ITERATION) { SIfprintf( stderr, E_YAPP006 ); yydump(); } /* Break up the string into tokens and try to resolve symbols */ while (*outtext != EOS) { p = token_buf; while (STindex(symc, outtext, symc_l) != NULL) { STlcopy(outtext, p, 1); CMnext(outtext); CMnext(p); } /* Found a token that may be defined as a symbol */ if (p != token_buf) { /* If the token is defined then translate the */ /* value of the substituted text, otherwise just */ /* output the untranslated text. */ STcopy(ERx(""), p); if (OK == is_defined(token_buf, token_val)) yyputline( token_val ); else SIprintf("%s", token_buf); } /* The text being processed at this point is whitespace, */ /* operators, or some other characters that are not */ /* valid for tokens. */ else { SIputc(*outtext, stdout); CMnext(outtext); } } iterate_level--; }
bool ascs_chk_priv( char *user_name, char *priv_name ) { char pmsym[128], userbuf[DB_OWN_MAXNAME+1], *value, *valueptr ; char *strbuf = 0; int priv_len; /* ** privileges entries are of the form ** ii.<host>.*.privilege.<user>: SERVER_CONTROL,NET_ADMIN,... ** ** Currently known privs are: SERVER_CONTROL,NET_ADMIN, ** MONITOR,TRUSTED */ STlcopy( user_name, userbuf, DB_OWN_MAXNAME ); STtrmwhite( userbuf ); STprintf(pmsym, "$.$.privileges.user.%s", userbuf); /* check to see if entry for given user */ /* Assumes PMinit() and PMload() have already been called */ if( PMget(pmsym, &value) != OK ) return FALSE; valueptr = value ; priv_len = STlength(priv_name) ; /* ** STindex the PM value string and compare each individual string ** with priv_name */ while ( *valueptr != EOS && (strbuf=STindex(valueptr, "," , 0))) { if (!STscompare(valueptr, priv_len, priv_name, priv_len)) return TRUE ; /* skip blank characters after the ','*/ valueptr = STskipblank(strbuf+1, 10); } /* we're now at the last or only (or NULL) word in the string */ if ( *valueptr != EOS && !STscompare(valueptr, priv_len, priv_name, priv_len)) return TRUE ; return FALSE; }
/* ** Name: WTSOpenUpLoad() - ** ** Description: ** ** Inputs: ** contentType ** session ** ** Outputs: ** ** Returns: ** GSTATUS : GSTAT_OK ** ** Exceptions: ** None ** ** Side Effects: ** None ** ** History: */ GSTATUS WTSOpenUpLoad( char *contentType, WTS_SESSION *session) { GSTATUS err; i4 length = STlength(MULTIPART); PWTS_UPLOAD load = NULL; char* bound; i4 blen; if (contentType != NULL && STscompare(contentType, length, MULTIPART, length) == 0) { session->status = UPLOAD; if ((err = GAlloc ((char**)&load, sizeof(WTS_UPLOAD), FALSE)) == GSTAT_OK) { session->load = load; bound = STindex (contentType, BOUNDARY, 0) + STlength(BOUNDARY); blen = STlength (bound); /* ** Allocate space for a start boundary and and en boundary ** each having the delimiters and null terminator. */ if (((err = GAlloc (&load->start, blen + 3, FALSE)) == GSTAT_OK) && ((err = GAlloc (&load->end, blen + 5, FALSE)) == GSTAT_OK)) { STcopy ("--",load->start); STlcopy (bound, load->start + 2, blen); STcopy (load->start, load->end); STcat (load->end, "--"); } load->state = US_BEGIN; } } else { session->status = NO_UPLOAD; session->load = NULL; } session->list = NULL; session->variable = NULL; session->vlen = 0; return(GSTAT_OK); }
/* ** Name: scs_gwinfo_subget ** ** Description: ** grab the value part of the gw string of the form ** ** var1=value2,var2='value2',var3='value3',var4=value4 ** ** the input substr is of the form "varN=". We strip out any quotes ** and copy the value to the user buffer. ** ** if there are more than one entry for a var, then take ** the first one. ** ** Inputs: ** substr substring of the variable name ** scb scb with the gw_parm string to scan. ** lbuf length of output buffer ** ** Outputs: ** buf buffer to put extracted value string, less quotes. ** if substr not found, set to empty string. ** ** Returns: ** OK if got string OK, or no string found. ** MO_VALUE_TRUNCATED if value got truncated to lbuf. ** ** History: ** 22-Apr-1994 (daveb) ** documented, changed to "first wins" */ STATUS ascs_gwinfo_subget( char *substr, SCD_SCB *scb, i4 lbuf, char *buf ) { STATUS cl_stat = OK; i4 sublen; i4 outlen; i4 inquote = FALSE; char *str; char *loc; *buf = EOS; if( (str = scb->scb_sscb.sscb_ics.ics_gw_parms) != NULL ) { sublen = STlength( substr ); /* for each potential match, check for full match */ for( ; *str && (loc = STindex( str, substr, 0 )) != NULL ; str++ ) { /* if this is the substring, get the good stuff. */ if( !STbcompare( loc, 0, substr, sublen, FALSE ) ) { loc += sublen; if( *loc == '\'' ) { loc++; inquote = TRUE; } str = loc; while( *loc && (inquote && *loc != '\'') || (!inquote && *loc != ',')) loc++; outlen = loc - str; if( outlen > (lbuf - 1) ) { outlen = lbuf - 1; cl_stat = MO_VALUE_TRUNCATED; } STlcopy( str, buf, outlen ); break; } } } return( cl_stat ); }
/*{ ** Name: CXdecorate_file_name - Append node name to filename. ** ** Description: ** ** Append upper case node name to passed filename, keeping ** total filelength 36 chars or below. ** ** Inputs: ** filename - buffer holding filename. Must be > 36 chars in length. ** nodename - name to append, or if NULL, CXnode_name is used. ** ** Outputs: ** none. ** ** Returns: ** - Pointer to passed filename, so this can be used in-line ** to printf, etc. ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-sep-2002 (devjo01) ** Created. */ char * CXdecorate_file_name( char *filename, char *node ) { i4 len, extlen; len = STlength(filename); if ( NULL == node ) node = CXnode_name(NULL); if (len < DI_FILENAME_MAX) { *(filename + len++) = '_'; if (len < DI_FILENAME_MAX) { extlen = STlcopy(node, filename + len, DI_FILENAME_MAX - len); *(filename + len + extlen) = '\0'; CVupper(filename + len); } } return filename; }
i4 yylex() { bool pattern; bool component; bool keyword; char *keyhead; char yytext[ SI_MAX_TXT_REC + 1 ]; i4 yyleng; /* skip whitespace and comments */ while( CMwhite( yyp ) || *yyp == EOS || *yyp == '-' ) { /* check for comment */ if( *yyp == '-' ) { if( STbcompare( yyp, 2, ERx( "--" ), 2, FALSE ) == 0 ) { while( *yyp != EOS ) CMnext( yyp ); } else break; } if( *yyp == EOS ) { if( SIgetrec( yybuf, sizeof( yybuf ), yyin ) != OK && yywrap() ) { return( 0 ); } else { yyp = yybuf; ++yylineno; } } else CMnext( yyp ); } /* check for a SYMBOL, PATTERN or keyword */ yyleng = 0; pattern = FALSE; keyword = TRUE; keyhead = yyp; while( CMalpha( yyp ) || *yyp == '%' || *yyp == '$' || *yyp == '*' ) { /* check for component of legal SYMBOL or PATTERN */ component = FALSE; /* check for single-character component */ switch( *yyp ) { case '%': pattern = TRUE; case '*': case '$': component = TRUE; ++yyleng; CMnext( yyp ); if( *yyp == '.' ) { ++yyleng; CMnext( yyp ); keyword = FALSE; continue; } else if( CMalpha( yyp ) ) yyerror(); continue; } while( CMalpha( yyp ) || CMdigit( yyp ) || *yyp == '_' || *yyp == '-' ) { ++yyleng; CMnext( yyp ); component = TRUE; } if( component ) { if( *yyp == '.' ) { ++yyleng; CMnext( yyp ); keyword = FALSE; continue; } continue; } } /* check for uneaten '.' */ if( *yyp == '.' ) yyerror(); if( yyleng > 0 ) { /* A keyword, SYMBOL or PATTERN was scanned */ char *p; i4 i; /* put NULL-terminated copy in yytext */ STlcopy( keyhead, yytext, yyleng ); for( p = yytext, i = 0; i <= yyleng; CMnext( p ), i++ ); *p = EOS; /* check for keywords */ if( CMalpha( keyhead) && keyword ) { if( STequal( ERx( "IF" ), yytext ) != 0 ) return( IF ); if( STequal( ERx( "ELSE" ), yytext ) != 0 ) return( ELSE ); if( STequal( ERx( "ELSEIF" ), yytext ) != 0 ) return( ELSEIF ); if( STequal( ERx( "ENDIF" ), yytext ) != 0 ) return( ENDIF ); if( STequal( ERx( "MIN" ), yytext ) != 0 ) return( MIN ); if( STequal( ERx( "MAX" ), yytext ) != 0 ) return( MAX ); if( STequal( ERx( "VALID" ), yytext ) != 0 ) return( VALID ); if( STequal( ERx( "PRIME" ), yytext ) != 0 ) return( PRIME ); if( STequal( ERx( "SIGNED_INT" ), yytext ) != 0 ) return( SIGNED_INT ); if( STequal( ERx( "DECIMAL" ), yytext ) != 0 ) return( DECIMAL ); if( STequal( ERx( "SIZETYPE" ), yytext ) != 0 ) return( SIZETYPE ); if( STequal( ERx( "POWER2" ), yytext ) != 0 ) return( POWER2 ); if( STequal( ERx( "REQUIRES" ), yytext ) != 0 ) return( REQUIRES ); if( STequal( ERx( "UNDEFINED" ), yytext ) != 0 ) return( UNDEFINED ); if( STequal( ERx( "SUM" ), yytext ) != 0 ) { yylval.integer = SUM; return( SUM ); } if( STequal( ERx( "ON" ), yytext ) != 0 ) { yylval.real = 1; return( BOOL_CON ); } if( STequal( ERx( "OFF" ), yytext ) != 0 ) { yylval.real = 0; return( BOOL_CON ); } if( STequal( ERx( "IS" ), yytext ) != 0 ) { yylval.string = STalloc( yytext ); return( COMPARE_OP ); } if( STequal( ERx( "DIRECTORY" ), yytext ) != 0 ) return( DIRECTORY ); if( STequal( ERx( "FILE" ), yytext ) != 0 ) return( FILESPEC ); } /* valid SYMBOL or PATTERN */ yylval.string = STalloc( yytext ); if( pattern ) return( PATTERN ); /* don't accept a single '*' as SYMBOL */ if( yyleng != 1 || *yytext != '*' ) return( SYMBOL ); /* push '*' back onto the input stream */ CMprev( yyp, yybuf ); } /* check for EXEC_TEXT, STR_CON, or EXEC_TEXT_STR */ if( *yyp == '`' || *yyp == '"' ) { int exec_str = 0; char *initstr = yyp; char *p = yyp, *text, *yyprev; if ( *yyp == '"' ) { CMnext( yyp ); if ( *yyp == '`' ) { CMnext( p ); exec_str = 1; } else yyp = p; } for( yyleng = 0, CMnext( yyp ), yyprev = ERx( "" ); *yyp != *p || *yyprev == '\\'; yyprev = ( *yyprev == EOS ) ? yyp : CMnext( yyprev ), CMnext( yyp ), ++yyleng ) { if( *yyp == *p && *yyprev == '\\' ) { /* remove escape character */ char *p1, *p2; for( p1 = p2 = yyprev, CMprev( p1, p ); p1 >= p; CMprev( p1, p ), CMprev( p2, p ) ) { CMcpychar( p1, p2 ); } --yyleng; CMnext( p ); } if( *yyp == EOS ) yyerror(); } CMnext( yyp ); if ( exec_str ) { if ( *yyp == '"' ) CMnext( yyp ); else { /* keep scanning to final '"' */ p = initstr; exec_str = 0; yyleng++; for( ; *yyp != *p || *yyprev == '\\'; yyprev = ( *yyprev == EOS ) ? yyp : CMnext( yyprev ), CMnext( yyp ), ++yyleng ) { if( *yyp == EOS ) yyerror(); } } } text = p; CMnext( text ); STlcopy( text, yytext, yyleng ); yytext[ yyleng ] = EOS; yylval.string = STalloc( yytext ); if( *p == '`' ) { if ( exec_str ) return( EXEC_TEXT_STR ); return( EXEC_TEXT ); } return( STR_CON ); } /* check for NUM_CON */ yyleng = 0; if( *yyp == '-' || CMdigit( yyp ) ) { f8 factor; char *p = yyp; if( *yyp == '-' ) { ++yyleng; factor = -1; CMnext( yyp ); } else factor = 1; if( !CMdigit( yyp ) ) CMprev( yyp, yybuf ); else { if( *yyp == '-' ) { CMnext( yyp ); } else factor = 1; while( CMdigit( yyp ) ) { ++yyleng; CMnext( yyp ); } if( *yyp == '.' ) { ++yyleng; CMnext( yyp ); if( !CMdigit( yyp ) ) yyerror(); while( CMdigit( yyp ) ) { ++yyleng; CMnext( yyp ); } } else if( *yyp == 'K' || *yyp == 'M' ) { ++yyleng; CMnext( yyp ); } STlcopy( p, yytext, yyleng ); yytext[ yyleng ] = EOS; if( yytext[ yyleng - 1 ] == 'K' ) { factor = 1024; yytext[ yyleng - 1 ] = EOS; } else if( yytext[ yyleng - 1 ] == 'M' ) { factor = 1048576; yytext[ yyleng - 1 ] = EOS; } CVaf( yytext, ERx( '.' ), &yylval.real ); yylval.real *= factor; return( NUM_CON ); } } if( STbcompare( yyp, 2, ERx( ">=" ), 2, FALSE ) == 0 ) { yylval.string = STalloc( ERx( ">=" ) ); CMnext( yyp ); CMnext( yyp ); return( COMPARE_OP ); } if( STbcompare( yyp, 2, ERx( "<=" ), 2, FALSE ) == 0 ) { yylval.string = STalloc( ERx( "<=" ) ); CMnext( yyp ); CMnext( yyp ); return( COMPARE_OP ); } /* check for COMPARE_OP */ if( STbcompare( yyp, 1, ERx( "<" ), 1, FALSE ) == 0 ) { yylval.string = STalloc( ERx( "<" ) ); CMnext( yyp ); return( COMPARE_OP ); } if( STbcompare( yyp, 1, ERx( ">" ), 1, FALSE ) == 0 ) { yylval.string = STalloc( ERx( ">" ) ); CMnext( yyp ); return( COMPARE_OP ); } if( STbcompare( yyp, 2, ERx( "==" ), 2, FALSE ) == 0 ) { yylval.string = STalloc( ERx( "==" ) ); CMnext( yyp ); CMnext( yyp ); return( COMPARE_OP ); } /* check for characters which get passed directly */ switch( *yyp ) { char *p; case '(': case ')': case '[': case ']': case '{': case '}': case ':': case ';': case ',': case '=': p = yyp; CMnext( yyp ); return( *p ); case '+': yylval.string = STalloc( ERx( "+" ) ); CMnext( yyp ); return( *yylval.string ); case '-': yylval.string = STalloc( ERx( "-" ) ); CMnext( yyp ); return( *yylval.string ); case '*': yylval.string = STalloc( ERx( "*" ) ); CMnext( yyp ); return( *yylval.string ); case '/': yylval.string = STalloc( ERx( "/" ) ); CMnext( yyp ); return( *yylval.string ); } /* check for LOGIC_OP */ if( STbcompare( yyp, 3, ERx( "&&" ), 3, FALSE ) == 0 ) { yylval.string = STalloc( ERx( "&&" ) ); CMnext( yyp ); CMnext( yyp ); return( LOGIC_OP ); } if( STbcompare( yyp, 3, ERx( "||" ), 3, FALSE ) == 0 ) { yylval.string = STalloc( ERx( "||" ) ); CMnext( yyp ); CMnext( yyp ); return( LOGIC_OP ); } /* anything else is an error */ yyerror(); }
STATUS xfsetdirs(char *dir, char *frompath, char *intopath) { auto i2 dirflag; auto char *s; char *locbuf; STATUS status; locbuf = XF_REQMEM(MAX_LOC + 1, FALSE); if (dir == NULL || *dir == EOS) { /* Default to current directory. */ status = LOgt(locbuf, &Xf_dir); if(status != OK) { #ifdef UNIX status = LOfakepwd(locbuf, &Xf_dir); #endif if(status != OK) { IIUGerr(E_XF0061_Can_Not_Determine_Dir, UG_ERR_ERROR, 0); return(FAIL); } } dir = NULL; } else { STlcopy(dir, locbuf, MAX_LOC); if (LOfroms(PATH, locbuf, &Xf_dir) != OK) { IIUGerr(E_XF0006_Invalid_directory_pat, UG_ERR_ERROR, 1, dir); return (FAIL); } if (!LOisfull(&Xf_dir)) { auto LOCATION xloc; char xbuf[MAX_LOC + 1]; /* ** path spec. is a relative specification -- we must expand it ** to a full pathname. */ LOcopy(&Xf_dir, xbuf, &xloc); status = LOgt(locbuf, &Xf_dir); if(status != OK) { IIUGerr(E_XF0061_Can_Not_Determine_Dir, UG_ERR_ERROR, 0); return(FAIL); } LOaddpath(&Xf_dir, &xloc, &Xf_dir); } /* LOisdir and LOexist are archaic and should be replaced by LOinfo. */ LOisdir(&Xf_dir, &dirflag); if (dirflag != ISDIR || LOexist(&Xf_dir) != OK) { IIUGerr(E_XF0006_Invalid_directory_pat, UG_ERR_ERROR, 1, dir); return (FAIL); } } LOtos(&Xf_dir, &s); /* the COPY FROM path doesn't have to exist. */ if (frompath != NULL && *frompath != EOS) Xf_from_path = saveloc(frompath); /* the COPY INTO path doesn't have to exist. */ if (intopath != NULL && *intopath != EOS) Xf_into_path = saveloc(intopath); IIUGmsg(ERget(S_XF0064_Unload_Directory_is), FALSE, 1, (PTR)(Xf_into_path == NULL ? s : Xf_into_path)); IIUGmsg(ERget(S_XF0065_Reload_Directory_is), FALSE, 1, (PTR)(Xf_from_path == NULL ? s : Xf_from_path)); return (OK); }
bool EXsys_report( register EX_ARGS *exargs, char *buffer ) { /* ** Number of message arguments; we add 2 because the PC and PSL are ** present in exarg_array (which is simply the exception signal vector) ** but aren't counted in exarg_count. */ i4 arg_count = exargs->exarg_count + 2; /* Report Hardware Exceptions ** ** This should report all hardware or system exceptions (including ** those that get mapped into internal Ingres exceptions. All available ** program information should be formatted and printed into the output ** buffer. ** ** We return FALSE for normal INGRES exceptions. These are exceptions ** where: ** 1. The exception number is in the correct range for INGRES ** exceptions. Unfortunately, this will also be true if someone ** signals an RMS failure. So in addition, we check that: ** 2. The signal array's PC is where lib$signal returns to EXsignal, ** meaning that EXsignal signaled this exception. */ /* ** if (CLERROR(exargs->exarg_num) && ** exargs->exarg_array[arg_count-2] == &EXsignal_PC) */ if (CLERROR(exargs->exarg_num)) { return FALSE; } else { char bufs[256]; $DESCRIPTOR(buf, bufs); unsigned short len; unsigned char info[4]; EXdump(EV_SIGVIO_DUMP); if ( !in_sysrep ) { in_sysrep = TRUE; if (Ex_print_stack) { Ex_print_stack(NULL, NULL, NULL, ex_print_error, TRUE); } in_sysrep = FALSE; } lib$sys_getmsg(&exargs->exarg_num, &len, &buf, 0, info); if (info[1] == 0 || arg_count < info[1]) { /* ** No args or insufficient args; don't try to format it. */ STlcopy(bufs, buffer, len); } else { $DESCRIPTOR(obuf, buffer); /* Format it. Use lib$sys_faol, so any number of args works */ obuf.dsc$w_length = buf.dsc$w_length; buf.dsc$w_length = len; lib$sys_faol(&buf, &len, &obuf, exargs->exarg_array); buffer[len] = '\0'; } return TRUE; } }
/* ** Name: gipParseSaveSet() ** ** Description: ** ** Extract save set data from XML DOM nodes and use the to populate ** new_pkgs_info structure. ** ** input: ** doc - Pointer to XML document containing instance info ** cur - Pointer to saveset element in XML doc ** ** History: ** 04-Sep-2007 (hanje04) ** Created. */ static void gipParseSaveSet( xmlDocPtr doc, xmlNodePtr cur ) { xmlChar *ele_text; xmlChar *attrib; attrib = xmlGetProp(cur, "product"); /* ingres or vectorwise */ STlcopy(attrib, new_pkgs_info.product, MAX_REL_LEN); DBG_PRINT("Parsing saveset: product=%s\n",new_pkgs_info.product); cur = cur->xmlChildrenNode; while (cur != NULL) { char tmpbuf[MAX_LOC]; if ( ! xmlStrcmp( cur->name, (const xmlChar *)"basename" ) ) { ele_text = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ( STlen( ele_text ) < MAX_REL_LEN ) { STprintf( tmpbuf, "%s", ele_text ); STcopy( tmpbuf, new_pkgs_info.pkg_basename ); } xmlFree( ele_text ); } else if ( ! xmlStrcmp( cur->name, (const xmlChar *)"version" ) ) { ele_text = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ( STlen( ele_text ) < MAX_VERS_LEN ) { STprintf( tmpbuf, "%s", ele_text ); STcopy( tmpbuf, new_pkgs_info.version ); } xmlFree( ele_text ); } else if ( ! xmlStrcmp( cur->name, (const xmlChar *)"arch" ) ) { ele_text = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ( STlen( ele_text ) < MAX_ARCH_LEN ) { STprintf( tmpbuf, "%s", ele_text ); STcopy( tmpbuf, new_pkgs_info.arch ); } xmlFree( ele_text ); } else if ( ! xmlStrcmp( cur->name, (const xmlChar *)"format" ) ) { ele_text = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ( STlen( ele_text ) < MAX_FORMAT_LEN ) { STprintf( tmpbuf, "%s", ele_text ); STcopy( tmpbuf, new_pkgs_info.format ); } xmlFree( ele_text ); } else if ( ! xmlStrcmp( cur->name, (const xmlChar *)"location" ) ) { /* skip this one, new_pkgs_info.file_loc is set at startup */ } else if ( ! xmlStrcmp( cur->name, (const xmlChar *)"package" ) ) { u_char idxstr[5]; ele_text = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); attrib = xmlGetProp(cur, "idx"); /* get the attribute */ new_pkgs_info.pkgs |= packages[atoi(attrib)]->bit; xmlFree( ele_text ); xmlFree( attrib ); } cur = cur->next; } return; }
i4 main (int argc, char **argv) { STATUS status=OK; PTR drvH=NULL; char **list=NULL; ATTR_ID **attrList=NULL; char **defAttr=NULL; i4 count=0, attrCount = 0, retcount; i4 i; bool badCmdLine = FALSE, rmPkg = FALSE, has_default = FALSE, has_alt = FALSE, isReadOnly = FALSE, mgrSpecified = FALSE, batch = FALSE, def_or_alt=FALSE; i4 pathType = OCFG_SYS_PATH; char altPath[OCFG_MAX_STRLEN] = "\0"; char drvMgr[OCFG_MAX_STRLEN] = "\0"; char line[MAXLINE],prompt[MAXLINE]; char driverPath[OCFG_MAX_STRLEN]; char *dirPath; char driverName[OCFG_MAX_STRLEN]; char *ii_installation; char *p = NULL; char custName[OCFG_MAX_STRLEN]; char etxt[512]; ATTR_ID driverList[6] = { { DRV_ATTR_DRIVER, "\0" }, { DRV_ATTR_DRIVER_ODBC_VER, DRV_STR_VERSION }, { DRV_ATTR_DRIVER_READONLY, DRV_STR_N }, { DRV_ATTR_DRIVER_TYPE, DRV_STR_INGRES }, { DRV_ATTR_VENDOR, DRV_STR_INGRES_CORP }, { DRV_ATTR_DONT_DLCLOSE, DRV_STR_ONE } }; int drvCount = sizeof(driverList) / sizeof(driverList[0]); ATTR_ID **drvList = (ATTR_ID **)MEreqmem( (u_i2) 0, (u_i4)drvCount, TRUE, (STATUS *) NULL); for (i = 0; i < drvCount; i++) { drvList[i] = (ATTR_ID *)MEreqmem( (u_i2) 0, (u_i4)sizeof(ATTR_ID), TRUE, (STATUS *) NULL); drvList[i]->id = driverList[i].id; drvList[i]->value = (char *)MEreqmem( (u_i2) 0, (u_i4)OCFG_MAX_STRLEN, TRUE, (STATUS *) NULL); STcopy(driverList[i].value, drvList[i]->value); } if ( argc > 7 ) badCmdLine = TRUE; /* ** Parse the command line. Reject invalid arguments. */ if ( !badCmdLine && argc > 1 ) { if (checkArgs("-h", argc, argv, NULL, NULL ) ) { display_help(); PCexit(0); } if (checkArgs("-help", argc, argv, NULL, NULL ) ) { display_help(); PCexit(0); } if ( checkArgs("-batch", argc, argv, NULL, NULL ) ) batch = TRUE; if ( checkArgs("-rmpkg", argc, argv, NULL, NULL ) ) rmPkg = TRUE; if (checkArgs("-r", argc, argv, NULL, NULL ) ) isReadOnly = TRUE; if ( checkArgs("-p", argc, argv, altPath, NULL ) ) pathType = OCFG_ALT_PATH; if ( checkArgs("-m", argc, argv, NULL, drvMgr ) ) mgrSpecified = TRUE; } /* ** Set driver manager according to user input. Default is unixODBC. */ if (mgrSpecified && !STbcompare( drvMgr, 0, MGR_STR_CAI_PT, 0, TRUE ) ) driverManager = MGR_VALUE_CAI_PT; else driverManager = MGR_VALUE_UNIX_ODBC; /* ** If none of the arguments are recognized, flag an error. */ if ( !batch && !rmPkg && !isReadOnly && pathType != OCFG_ALT_PATH && !mgrSpecified && argc > 1) badCmdLine = TRUE; if ( badCmdLine ) { display_help(); PCexit(FAIL); } if ( isReadOnly ) STcopy(DRV_STR_Y, drvList[2]->value); else STcopy(DRV_STR_N, drvList[2]->value); if ( !writeMgrFile( altPath ) ) { SIprintf("Aborting due to error writing %s/files/%s\n", SYSTEM_LOCATION_SUBDIRECTORY, MGR_STR_FILE_NAME); PCexit(FAIL); } defAttr = getDefaultInfo(); if (defAttr == NULL) { SIprintf("Aborting due to error reading %s/install/%s\n", SYSTEM_LOCATION_VARIABLE, INFO_STR_FILE_NAME); PCexit(FAIL); } /* ** Get the path of the driver library and create the path/libname string. */ NMgtAt(SYSTEM_LOCATION_VARIABLE,&dirPath); /* usually II_SYSTEM */ if (dirPath != NULL && *dirPath) STlcopy(dirPath,driverPath,sizeof(driverPath)-20-1); else { SIprintf("Error--%s is not defined\n",SYSTEM_LOCATION_VARIABLE); PCexit(FAIL); } # ifdef VMS STcat(driverPath,"["); STcat(driverPath,SYSTEM_LOCATION_SUBDIRECTORY); /* usually "ingres" */ STcat(driverPath,".library]"); if ( isReadOnly ) STcat(driverPath,defAttr[INFO_ATTR_RONLY_DRV_FNAME]); else STcat(driverPath,defAttr[INFO_ATTR_DRIVER_FILE_NAME]); # else STcat(driverPath,"/"); STcat(driverPath,SYSTEM_LOCATION_SUBDIRECTORY); /* usually "ingres" */ STcat(driverPath,"/lib/"); if ( isReadOnly ) STcat(driverPath,defAttr[INFO_ATTR_RONLY_DRV_FNAME]); else STcat(driverPath,defAttr[INFO_ATTR_DRIVER_FILE_NAME]); # endif /* ifdef VMS */ STcopy(driverPath,drvList[0]->value); /* ** Initialize the cache from the odbcinst.ini file. */ openConfig(NULL, pathType, altPath, &drvH, &status); if (status != OK) { STprintf(etxt,"Could not open from path %s.\n", pathType == OCFG_ALT_PATH ? altPath : "/usr/local/etc"); display_err(etxt,status); PCexit(FAIL); } if (rmPkg) { delConfigEntry( drvH, defAttr[INFO_ATTR_DRIVER_NAME], &status ); delConfigEntry( drvH, defAttr[INFO_ATTR_ALT_DRIVER_NAME], &status ); closeConfig(drvH, &status); PCexit(OK); } /* ** Get the driver count. */ retcount = listConfig( drvH, count, list, &status ); if (status != OK) { STprintf(etxt,"Could not list drivers.\n"); display_err(etxt,status); PCexit(FAIL); } count = retcount; if (count) { /* ** Get the list of recognized drivers. */ list = (char **)MEreqmem( (u_i2) 0, (u_i4)(count * sizeof(char *)), TRUE, (STATUS *) NULL); for (i = 0; i < count; i++) list[i] = (char *)MEreqmem( (u_i2) 0, (u_i4)OCFG_MAX_STRLEN, TRUE, (STATUS *) NULL); listConfig( drvH, count, list, &status ); if (status != OK) { STprintf(etxt,"Could not list drivers.\n"); display_err(etxt,status); PCexit(FAIL); } } for (i = 0; i < count; i++) { def_or_alt = FALSE; if (!has_default) { has_default = STbcompare( list[i], 0, defAttr[INFO_ATTR_DRIVER_NAME], 0, TRUE ) == 0 ? TRUE : FALSE; if (has_default) def_or_alt = TRUE; } if (!has_alt) { has_alt = STbcompare( list[i], 0, defAttr[INFO_ATTR_ALT_DRIVER_NAME], 0, TRUE ) == 0 ? TRUE : FALSE; if (has_alt) def_or_alt = TRUE; } if (def_or_alt) { if ( !batch ) { STprintf(prompt, "\tInstallation has pre-defined version of %s.\n\tOverwrite? (Yes/No)", list[i]); if ( line_get( prompt, "", FALSE, line ) == EOF ) { SIprintf("ODBC driver installation safely aborted\n"); PCexit(OK); } STzapblank(line,line); if ( line[0] != 'y' && line [0] != 'Y' ) { SIprintf( "%s left untouched\n", list[i] ); continue; } } /* if (!batch) */ STcopy(list[i],driverName); setConfigEntry( drvH, driverName, drvCount, drvList, &status ); if (status != OK) { STprintf(etxt,"Could not write driver entry.\n"); display_err(etxt,status); PCexit(FAIL); } } /* if (has_default || has_alt) */ else if ( !batch ) { STprintf(prompt, "\tInstallation has custom version of %s.\n\tDelete? (Yes/No)", list[i]); if ( line_get( prompt, "", FALSE, line ) == EOF ) { SIprintf("ODBC driver installation safely aborted\n"); PCexit(OK); } STzapblank(line,line); if ( line[0] != 'y' && line [0] != 'Y' ) { SIprintf( "%s left untouched\n", list[i] ); continue; } STcopy(list[i],driverName); delConfigEntry( drvH, driverName, &status ); if (status != OK) { STprintf(etxt,"Could not write driver entry.\n"); display_err(etxt,status); PCexit(FAIL); } } /* if (!batch) && !has_default */ } /* for (count... */ if (!has_default) { setConfigEntry( drvH, defAttr[INFO_ATTR_DRIVER_NAME], drvCount, drvList, &status ); if (status != OK) { STprintf(etxt,"Could not write driver entry.\n"); display_err(etxt,status); PCexit(FAIL); } } if (!has_alt) { setConfigEntry( drvH, defAttr[INFO_ATTR_ALT_DRIVER_NAME], drvCount, drvList, &status ); if (status != OK) { STprintf(etxt,"Could not write driver entry.\n"); display_err(etxt,status); PCexit(FAIL); } } closeConfig(drvH, &status); if (status != OK) { STprintf(etxt,"Could not close driver info.\n"); display_err(etxt,status); PCexit(FAIL); } if (count) { for (i = 0; i < count; i++) MEfree((PTR)list[i]); MEfree((PTR)list); } for (i = 0; i < drvCount; i++) { MEfree((PTR)drvList[i]->value); MEfree((PTR)drvList[i]); } MEfree((PTR)drvList); PCexit(OK); }
/* Name: adu_getconverter - Obtains the name of converter mapping file ** to use for unicode coercion. ** Description: ** ** To obtain the mapping file to be used for carrying out unicode-local ** character conversion. The following mechanism is followed: ** ** 1. Check symbol table for user defined converter setting ** II_UNICODE_CONVERTER. If set then return this setting ** 2. If the variable is not set then ** 2.a Get the platform character set ** 2.b Read the aliasmaptbl file. ** 2.c Search the alias file for platform charset. ** 3. If still not found then find the II_CHARSETxx value ** for ingres installation and search the alias file for ** this value. ** 4. If none of these attempts succeed then return default ** with a warning to the errorlog if this happens ** ** Input: ** converter - Place holder for the output string, ** It is assumed that the area is at least MAX_LOC ** chars in size. ** Output: ** converter - Pointer to string where the output ** converter name is stored. ** History: ** ** 22-jan-2004 (gupsh01) ** Added. ** 14-Jun-2004 (schka24) ** Safe charset name handling. */ STATUS adu_getconverter( char *converter) { STATUS stat; char *tptr; char *env = 0; char chset[CM_MAXATTRNAME+1]; char pcs[CM_MAXLOCALE+1]; /* platform character set */ char norm_pcs[CM_MAXLOCALE+1]; CL_ERR_DESC syserr; char *alias_buffer = NULL; char *bufptr = NULL; char *buf = NULL; ADU_ALIAS_MAPPING *aliasmapping; ADU_ALIAS_DATA *aliasdata; char *datasize; SIZE_TYPE filesize = 0; SIZE_TYPE sizemap = 0; SIZE_TYPE sizedata = 0; i4 bytes_read; char *abufptr; i4 i = 0; i4 index = 0; /* STEP 1 */ NMgtAt(ERx("II_UNICODE_CONVERTER"), &env); if (env && *env) { STlcopy(env, converter, MAX_LOC-1); return OK; } /* STEP 2 */ stat = CM_getcharset(pcs); if (CMopen_col("aliasmaptbl", &syserr, CM_UCHARMAPS_LOC) != OK) { /* return an ERROR if we are unable to open the file */ return FAIL; } /* initialize buf to help read from the aliasmaptbl file */ buf = MEreqmem(0, COL_BLOCK, TRUE, &stat); if (buf == NULL || stat != OK) { CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } /* First file buffer has size information. */ stat = CMread_col(buf, &syserr); if (stat != OK) { MEfree((char *)buf); CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } tptr = buf; bytes_read = COL_BLOCK; /* filesize is the first entry of the map file */ filesize = *(SIZE_TYPE *) buf; tptr += sizeof(SIZE_TYPE); tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* allocate working space for the data */ alias_buffer = (char *)MEreqmem(0, filesize, TRUE, &stat); if (alias_buffer == NULL || stat != OK) { CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } abufptr = alias_buffer; MEcopy (buf, COL_BLOCK, abufptr); abufptr += COL_BLOCK; /* Read the file till it is read completely */ for ( ;bytes_read < filesize;) { stat = CMread_col(buf, &syserr); if (stat != OK) { MEfree((char *)buf); MEfree((char *)alias_buffer); CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } bytes_read += COL_BLOCK; MEcopy (buf, COL_BLOCK, abufptr); abufptr += COL_BLOCK; } if (bytes_read < filesize) { /* we had to exit for some unknown reason */ MEfree((char *)buf); MEfree((char *)alias_buffer); CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } tptr = alias_buffer; tptr += sizeof(SIZE_TYPE); tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* Read the size of the MappingArray nodes */ sizemap = *(SIZE_TYPE *) tptr; tptr += sizeof(SIZE_TYPE); tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* initialize buffer for ADU_ALIAS_MAPPING buffer */ aliasmapping = (ADU_ALIAS_MAPPING *) MEreqmem(0, sizemap, TRUE, &stat); if (aliasmapping == NULL) { MEfree((char *)buf); MEfree((char *)alias_buffer); CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } /* Copy data for ADU_ALIAS_MAPPING array */ MEcopy(tptr, sizemap, aliasmapping); tptr += sizemap; tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* Get size for the aliasdata */ sizedata = *(SIZE_TYPE *) tptr; tptr += sizeof(SIZE_TYPE); tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* Initialize buffer for ADU_ALIAS_MAPPING buffer */ aliasdata = (ADU_ALIAS_DATA *) MEreqmem(0, sizedata, TRUE, &stat); if (aliasdata == NULL) { MEfree((char *)buf); MEfree((char *)alias_buffer); MEfree((char *)aliasmapping); CMclose_col(&syserr, CM_UCHARMAPS_LOC); return (FAIL); } /* Copy the ADU_ALIAS_DATA array */ MEcopy(tptr, sizedata, aliasdata); tptr += sizedata; tptr = ME_ALIGN_MACRO(tptr, sizeof(PTR)); /* Close the "aliasmaptbl" file */ CMclose_col(&syserr, CM_UCHARMAPS_LOC); /* Normalize pcs */ adu_csnormalize (pcs, STlength(pcs), norm_pcs); /* Retrieve the pcs value */ for (i=0; i < sizedata/sizeof(ADU_ALIAS_DATA); i++) { if ((STcompare (aliasdata[i].aliasNameNorm, norm_pcs)) == 0) { index = aliasdata[i].aliasMapId; /* found */ STcopy (aliasmapping[index].mapping_id, converter); /* cleanup */ MEfree((char *)buf); MEfree((char *)alias_buffer); MEfree((char *)aliasmapping); MEfree((char *)aliasdata); return (OK); } } /* STEP 3 */ /* Obtain Ingres characterset */ STcopy("default", converter); CMget_charset_name(&chset[0]); if (STcasecmp(chset, "UTF8") != 0) { /* search maptable for env */ for (i=0; i < sizedata/sizeof(ADU_ALIAS_DATA); i++) { if ((STcompare (aliasdata[i].aliasNameNorm, norm_pcs)) == 0) { index = aliasdata[i].aliasMapId; /* found */ STcopy (aliasmapping[index].mapping_id, converter); break; } } } /* cleanup */ MEfree((char *)buf); MEfree((char *)alias_buffer); MEfree((char *)aliasmapping); MEfree((char *)aliasdata); /* FIXME warning or error if still "default" ? */ return (OK); }
/*{ ** Name: LGK_initialize() - initialize the lg/lk shared mem segment. ** ** Description: ** This routine is called by the LGinitialize or LKinitialize routine. IT ** assumes that a previous caller has allocated the shared memory segment. ** ** If it discovers that the shared memory segment has not yet been ** initialized, it calls the LG and LK initialize-memory routines to do so. ** ** Inputs: ** flag - bit mask of: ** LOCK_LGK_MEMORY to lock the shared data segment ** LGK_IS_CSP if process is CSP process this node. ** ** Outputs: ** sys_err - place for system-specific error information. ** ** Returns: ** OK - success ** !OK - failure (CS*() routine failure, segment not mapped, ...) ** ** History: ** Summer, 1992 (bryanp) ** Working on the new portable logging and locking system. ** 19-oct-1992 (bryanp) ** Check memory version number when attaching. ** 22-oct-1992 (bryanp) ** Change LGLKDATA.MEM to lglkdata.mem. ** 23-Oct-1992 (daveb) ** name the semaphore too. ** 13-feb-1993 (keving) ** Remove support for II_LGK_MEMORY_SIZE. If II_LG_MEMSIZE ** is not set then calculate memory size from PM values. ** 24-may-1993 (bryanp) ** If the shared memory is the wrong version, don't install the ** at_exit handlers (the rundown routines won't be able to interpret ** the memory properly). ** 26-jul-1993 (jnash) ** Add 'flag' param lock the LGK data segment. ** 20-sep-1993 (bryanp) ** In addition to calling PCatexit, call (on VMS) sys$dclexh, since ** there are some situations (image death and image rundown without ** process rundown) which are caught neither by PCatexit (since ** PCexit isn't run) nor by check-dead threads (since process ** rundown never happened). This fixes a hole where an access- ** violating ckpdb or auditdb command never got cleaned up. ** 31-jan-1994 (bryanp) ** Back out a few "features" which are proving countereffective: ** 1) Don't bother checking mem_creator_pid to see if the previous ** creator of the shared memory has died. This was an attempt to ** gracefully re-use sticky shared memory following a system crash, ** but it is suspected as being the culprit in a series of system ** failures by re-initializing the shared memory at inopportune ** times. ** 2) Don't complain if the shared memory already exists but is of a ** different size than you expected. Just go ahead and try to use ** it anyway. ** 21-feb-1994 (bryanp) ** Reverse item (1) of the above 31-jan-1994 change and re-enable the ** graceful re-use of shared memory. People weren't happy with ** having to run ipcclean and csinstall all the time. ** 23-may-1994 (bryanp) ** On VMS, disable ^Y for LG/LK-aware processes. We don't want to allow ** ^Y because you might interrupt the process right in the middle ** of an LG or LK operation, while holding the shared memory ** semaphore, and this would then wedge the whole installation. ** ** 17-May-1994 (daveb) 59127 ** Attach lgk_mem semaphore if we're attaching to the segment. ** 30-jan-1995 (lawst01) bug 61984 ** Use memory needed calculation from the 'lgk_calculate_size' ** function to determine the size of the shared memory pool for ** locking and locking. If the II_LG_MEMSIZE variable is specified ** with a value larger than needed use the supplied value. If ** lgk_calculate_size is unable to calculate a size then use the ** magic number of 400000. In addition issue a warning message ** and continue executing in the event the number of pages ** allocated is less than the number requested. ** 24-apr-1997 (nanpr01) ** Reinstate Bryanp's change. In the process of fixing bug 61984 ** by Steve Lawrence and subsequent undo of Steve's fix by Nick ** Ireland on 25-jun-96 (nick) caused the if 0 code removed. ** Part of the Steve's change was not reinstated such as not returning ** the status and exit and continue. ** 1. Don't complain if the shared memory already exists but is of a ** different size than you expected. Just go ahead and try to use ** it. ** 18-aug-1998 (hweho01) ** Reclaim the kernel resource if LG/LK shared memory segment is ** reinitialized. If the shared segment is re-used (the previous creator ** of the shared segment has died), the cross-process semaphores get ** initialized more than once at the same locations. That cause the ** kernel resource leaks on DG/UX (OS release 4.11MU04). To fix the ** problem, CS_cp_sem_cleanup() is called to destroy all the ** semaphores before LG/LK shraed segment get recreated. ** CS_cp_sem_cleanup() is made dependent on xCL_NEED_SEM_CLEANUP and ** OS_THREADS_USED, it returns immediately for most platforms. ** 27-Mar-2000 (jenjo02) ** Added test for crossed thread types, refuse connection ** to LGK memory with E_DMA811_LGK_MT_MISMATCH. ** 18-apr-2001 (devjo01) ** s103715 (Portable cluster support) ** - Add CX mem requirement calculations. ** - Add LGK_IS_CSP flag to indicate that LGK memory is being ** initialized for a CSP process. ** - Add basic CX initialization. ** 19-sep-2002 (devjo01) ** If running NUMA clustered allocate memory out of local RAD. ** 30-Apr-2003 (jenjo02) ** Rearchitected to silence long-tolerated race conditions. ** BUG 110121. ** 27-feb-2004 (devjo01) ** Rework allocation of CX shared memory to be compatible ** with race condition fix introduced for bug 110121. ** 29-Dec-2008 (jonj) ** If lgk_calculate_size() returns FAIL, the total memory ** needed exceeds MAX_SIZE_TYPE and we can't continue, but ** tell what we can about the needs of the various bits of ** memory before quitting. ** 06-Aug-2009 (wanfr01) ** Bug 122418 - Return E_DMA812 if LOCK_LGK_MUST_ATTACH is ** is passed in and memory segment does not exist ** 20-Nov-2009 (maspa05) bug 122642 ** In order to synchronize creation of UUIDs across servers added ** a semaphore and a 'last time' variable into LGK memory. ** 14-Dec-2009 (maspa05) bug 122642 ** #ifdef out the above change for Windows. The rest of the change ** does not apply to Windows so the variables aren't defined. */ STATUS LGK_initialize( i4 flag, CL_ERR_DESC *sys_err, char *lgk_info) { PTR ptr; SIZE_TYPE memleft; SIZE_TYPE size; STATUS ret_val; STATUS mem_exists; char mem_name[15]; SIZE_TYPE allocated_pages; i4 me_flags; i4 me_locked_flag; SIZE_TYPE memory_needed; char *nm_string; SIZE_TYPE pages; LGK_MEM *lgk_mem; i4 err_code; SIZE_TYPE min_memory; i4 retries; i4 i; i4 attached; PID *my_pid_slot; i4 clustered; u_i4 nodes; SIZE_TYPE cxmemreq; PTR pcxmem; LGLK_INFO lgkcount; char instid[4]; CL_CLEAR_ERR(sys_err); /* ** if LGK_base is set then this routine has already been called. It is ** set up so that both LGiniitalize and LKinitialize calls it, but only ** the first call does anything. */ if (LGK_base.lgk_mem_ptr) return(OK); PCpid( &LGK_my_pid ); memory_needed = 0; NMgtAt("II_LG_MEMSIZE", &nm_string); if (nm_string && *nm_string) #if defined(LP64) if (CVal8(nm_string, (long*)&memory_needed)) #else if (CVal(nm_string, (i4 *)&memory_needed)) #endif /* LP64 */ memory_needed = 0; /* Always calculate memory needed from PM resource settings */ /* and compare with supplied value, if supplied value is less */ /* than minimum then use minimum */ min_memory = 0; if ( OK == lgk_get_counts(&lgkcount, FALSE)) { if ( lgk_calculate_size(FALSE, &lgkcount, &min_memory) ) { /* ** Memory exceeds MAX_SIZE_TYPE, can't continue. ** ** Do calculation again, this time with "wordy" ** so user can see allocation bits, then quit. */ lgk_calculate_size(TRUE, &lgkcount, &min_memory); return (E_DMA802_LGKINIT_ERROR); } } if (min_memory) memory_needed = (memory_needed < min_memory) ? min_memory : memory_needed; else memory_needed = (memory_needed < 400000 ) ? 400000 : memory_needed; clustered = (i4)CXcluster_enabled(); cxmemreq = 0; if ( clustered ) { if ( OK != CXcluster_nodes( &nodes, NULL ) ) nodes = 0; cxmemreq = CXshm_required( 0, nodes, lgkcount.lgk_max_xacts, lgkcount.lgk_max_locks, lgkcount.lgk_max_resources ); if ( MAX_SIZE_TYPE - memory_needed < cxmemreq ) { /* ** Memory exceeds MAX_SIZE_TYPE, can't continue. ** ** Do calculation again, this time with "wordy" ** so user can see allocation bits, then quit. */ SIprintf("Total LG/LK/CX allocation exceeds max of %lu bytes by %lu\n" "Adjust logging/locking configuration values and try again\n", MAX_SIZE_TYPE, cxmemreq - (MAX_SIZE_TYPE - memory_needed)); lgk_calculate_size(TRUE, &lgkcount, &min_memory); return (E_DMA802_LGKINIT_ERROR); } memory_needed += cxmemreq; } if ( memory_needed < MAX_SIZE_TYPE - ME_MPAGESIZE ) pages = (memory_needed + ME_MPAGESIZE - 1) / ME_MPAGESIZE; else pages = memory_needed / ME_MPAGESIZE; /* ** Lock the LGK segment if requested to do so */ if (flag & LOCK_LGK_MEMORY) me_locked_flag = ME_LOCKED_MASK; else me_locked_flag = 0; me_flags = (me_locked_flag | ME_MSHARED_MASK | ME_IO_MASK | ME_CREATE_MASK | ME_NOTPERM_MASK | ME_MZERO_MASK); if (CXnuma_user_rad()) me_flags |= ME_LOCAL_RAD; STcopy("lglkdata.mem", mem_name); /* ** In general, we just want to attach to the shared memory and detect if ** we are the first process to do so. However, there are ugly race ** conditions to consider, as well as complications because the shared ** memory may be left around following a system crash. ** ** First we attempt to create the shared memory. Usually it already exists, ** so we check for and handle the case of "already exists". */ /* ** (jenjo02) ** ** Restructured to better handle all those ugly race conditions ** which are easily reproduced by running two scripts, one that ** continuously executes "lockstat" while the other is starting ** and stopping Ingres. ** ** For example, ** ** lockstat A acquires and init's the memory ** RCP attaches to "A" memory ** lockstat A terminates normally ** lockstat B attaches to "A" memory, sees that ** "A"s pid is no longer alive, and ** reinitializes the memory, much to ** the RCP's chagrin. ** or (more commonly) ** ** lockstat A acquires and begins to init the mem ** RCP attaches to "A" memory which is ** still being zero-filled by lockstat, ** checks the version number (zero), ** and fails with a E_DMA434 mismatch. ** ** The fix utilizes the mem_ext_sem to synchronize multiple ** processes; if the semaphore hasn't been initialized or ** if mem_version_no is zero, we'll wait one second and retry, ** up to 60 seconds before giving up. This gives the creating ** process time to complete initialization of the memory. ** ** Up to LGK_MAX_PIDS are allowed to attach to the shared ** memory. When a process attaches it sets its PID in the ** first vacant slot in lgk_mem->mem_pid[]; if there are ** no vacant slots, the attach is refused. When the process ** terminates normally by calling LGK_rundown(), it zeroes ** its PID slot. ** ** When attaching to an existing segment, we check if ** there are any live processes still using the memory; ** if so, we can't destroy it (no matter who created it). ** If there are no live processes attached to the memory, ** we destroy and reallocate it (based on current config.dat ** settings). */ for ( retries = 0; ;retries++ ) { LGK_base.lgk_mem_ptr = (PTR)NULL; /* Give up if unable to get memory in one minute */ #if defined(conf_CLUSTER_BUILD) if (retries > 1) #else if ( retries ) #endif { if ( retries < 60 ) PCsleep(1000); else { /* Another process has it blocked way too long */ uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); /* Unable to attach allocated shared memory segment. */ return (E_DMA802_LGKINIT_ERROR); } } ret_val = MEget_pages(me_flags, pages, mem_name, (PTR*)&lgk_mem, &allocated_pages, sys_err); if ( mem_exists = ret_val ) { if (ret_val == ME_ALREADY_EXISTS) { ret_val = MEget_pages((me_locked_flag | ME_MSHARED_MASK | ME_IO_MASK), pages, mem_name, (PTR*)&lgk_mem, &allocated_pages, sys_err); #if defined(conf_CLUSTER_BUILD) if (ret_val && !retries) continue; /* try one more time */ #endif } if (ret_val) { uleFormat(NULL, ret_val, sys_err, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); /* Unable to attach allocated shared memory segment. */ return (E_DMA802_LGKINIT_ERROR); } } else if (flag & LOCK_LGK_MUST_ATTACH) { /* Do not use the shared segment you just allocated */ MEfree_pages((PTR)lgk_mem, allocated_pages, sys_err); return (E_DMA812_LGK_NO_SEGMENT); } size = allocated_pages * ME_MPAGESIZE; /* Expose this process to the memory */ LGK_base.lgk_mem_ptr = (PTR)lgk_mem; if ( mem_exists ) { /* ** Memory exists. ** ** Try to acquire the semaphore. If it's ** uninitialzed, retry from the top. ** ** If the version is zero, then another ** process is initializing the memory; ** keep retrying until the version is ** filled in. ** */ if ( ret_val = CSp_semaphore(1, &lgk_mem->mem_ext_sem) ) { if ( ret_val != E_CS000A_NO_SEMAPHORE ) { uleFormat(NULL, ret_val, sys_err, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); ret_val = E_DMA802_LGKINIT_ERROR; break; } continue; } /* Retry if still being init'd by another process */ if ( !lgk_mem->mem_version_no ) { CSv_semaphore(&lgk_mem->mem_ext_sem); continue; } /* ** Check pids which appear to be attached to ** the memory: ** ** If any process is still alive, then we ** assume the memory is consistent and use it. ** ** If a process is now dead, it terminated ** without going through LGK_rundown ** to zero its PID slot, zero it now. ** ** If there are no live PIDs attached to ** the memory, we destroy and recreate it. */ my_pid_slot = (PID*)NULL; attached = 0; for ( i = 0; i < LGK_MAX_PIDS; i++ ) { if ( lgk_mem->mem_pid[i] && PCis_alive(lgk_mem->mem_pid[i]) ) { attached++; } else { /* Vacate the slot */ if (lgk_mem->mem_pid[i]) { uleFormat(NULL, E_DMA499_DEAD_PROCESS_INFO, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, lgk_mem->mem_pid[i], 0, lgk_mem->mem_info[i].info_txt); } lgk_mem->mem_pid[i] = (PID)0; lgk_mem->mem_info[i].info_txt[0] = EOS; /* Use first vacant slot for this process */ if ( !my_pid_slot ) { my_pid_slot = &lgk_mem->mem_pid[i]; LGK_base.lgk_pid_slot = i; } } /* Quit when both questions answered */ if ( attached && my_pid_slot ) break; } /* If no living pids attached, destroy/reallocate */ if ( !attached ) { CSv_semaphore(&lgk_mem->mem_ext_sem); if ( LGK_destroy(allocated_pages, sys_err) ) { ret_val = E_DMA802_LGKINIT_ERROR; break; } continue; } /* All attached pids alive? */ if ( !my_pid_slot ) { /* ... then there's no room for this process */ uleFormat(NULL, E_DMA80A_LGK_ATTACH_LIMIT, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 1, 0, attached); ret_val = E_DMA802_LGKINIT_ERROR; } else if (lgk_mem->mem_version_no != LGK_MEM_VERSION_CURRENT) { uleFormat(NULL, E_DMA434_LGK_VERSION_MISMATCH, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, lgk_mem->mem_version_no, 0, LGK_MEM_VERSION_CURRENT); ret_val = E_DMA435_WRONG_LGKMEM_VERSION; } /* ** Don't allow mixed connections of MT/non-MT processes. ** Among other things, the mutexing mechanisms are ** incompatible! */ else if ( (CS_is_mt() && (lgk_mem->mem_status & LGK_IS_MT) == 0) || (!CS_is_mt() && lgk_mem->mem_status & LGK_IS_MT) ) { uleFormat(NULL, E_DMA811_LGK_MT_MISMATCH, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2, 0, (lgk_mem->mem_status & LGK_IS_MT) ? "OS" : "INTERNAL", 0, (CS_is_mt()) ? "OS" : "INTERNAL"); ret_val = E_DMA802_LGKINIT_ERROR; } else { /* ** CX memory (if any) will lie immediately past LGK header. */ pcxmem = (PTR)(lgk_mem + 1); pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT)); LGK_base.lgk_lkd_ptr = (char *)LGK_base.lgk_mem_ptr + lgk_mem->mem_lkd; LGK_base.lgk_lgd_ptr = (char *)LGK_base.lgk_mem_ptr + lgk_mem->mem_lgd; /* Stuff our pid in first vacant slot */ *my_pid_slot = LGK_my_pid; STlcopy(lgk_info, lgk_mem->mem_info[i].info_txt, LGK_INFO_SIZE-1); } #if defined(VMS) || defined(UNIX) /* set up pointers to reference the uuid mutex and last time * variable */ if (!ID_uuid_sem_ptr) ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem; if (!ID_uuid_last_time_ptr) ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time; if (!ID_uuid_last_cnt_ptr) ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt; #endif CSv_semaphore(&lgk_mem->mem_ext_sem); } else { /* Memory did not exist */ /* Zero the version to keep other processes out */ lgk_mem->mem_version_no = 0; #if defined(VMS) || defined(UNIX) /* set up the uuid mutex and last time pointers to * reference the objects in shared memory */ { STATUS id_stat; ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem; ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time; ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt; *ID_uuid_last_cnt_ptr=0; ID_UUID_SEM_INIT(ID_uuid_sem_ptr,CS_SEM_MULTI,"uuid sem", &id_stat); } #endif /* ... then initialize the mutex */ CSw_semaphore(&lgk_mem->mem_ext_sem, CS_SEM_MULTI, "LGK mem ext sem" ); /* Record if memory created for MT or not */ if ( CS_is_mt() ) lgk_mem->mem_status = LGK_IS_MT; /* ** memory is as follows: ** ** -----------------------------------------------------------| ** | LGK_MEM struct (keep track of this mem) | ** | | ** -----------------------------------------------------------| ** | If a clustered installation memory reserved for CX | ** | | ** ------------------------------------------------------------ ** | LKD - database of info for lk system | ** | | ** ------------------------------------------------------------ ** | LGD - database of info for lg system | ** | | ** ------------------------------------------------------------ ** | memory manipulated by LGKm_* routines for structures used | ** | by both the lk and lg systems. | ** | | ** ------------------------------------------------------------ */ /* put the LGK_MEM struct at head of segment leaving ptr pointing ** at next aligned piece of memory */ /* ** CX memory (if any) will lie immediately past LGK header. */ pcxmem = (PTR)(lgk_mem + 1); pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT)); LGK_base.lgk_lkd_ptr = pcxmem + cxmemreq; LGK_base.lgk_lkd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lkd_ptr, sizeof(ALIGN_RESTRICT)); lgk_mem->mem_lkd = (i4)((char *)LGK_base.lgk_lkd_ptr - (char *)LGK_base.lgk_mem_ptr); LGK_base.lgk_lgd_ptr = (PTR) ((char *) LGK_base.lgk_lkd_ptr + sizeof(LKD)); LGK_base.lgk_lgd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lgd_ptr, sizeof(ALIGN_RESTRICT)); lgk_mem->mem_lgd = (i4)((char *)LGK_base.lgk_lgd_ptr - (char *)LGK_base.lgk_mem_ptr); /* now initialize the rest of memory for allocation */ /* how much memory is left? */ ptr = ((char *)LGK_base.lgk_lgd_ptr + sizeof(LGD)); memleft = size - (((char *) ptr) - ((char *) LGK_base.lgk_mem_ptr)); if ( (ret_val = lgkm_initialize_mem(memleft, ptr)) == OK && (ret_val = LG_meminit(sys_err)) == OK && (ret_val = LK_meminit(sys_err)) == OK ) { /* Clear array of attached pids and pid info */ for ( i = 0; i < LGK_MAX_PIDS; i++ ) { lgk_mem->mem_pid[i] = (PID)0; lgk_mem->mem_info[i].info_txt[0] = EOS; } /* Set the creator pid */ LGK_base.lgk_pid_slot = 0; lgk_mem->mem_creator_pid = LGK_my_pid; /* Set the version, releasing other processes */ lgk_mem->mem_version_no = LGK_MEM_VERSION_CURRENT; } else { uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0); ret_val = E_DMA802_LGKINIT_ERROR; /* Destroy the shared memory */ LGK_destroy(allocated_pages, sys_err); } } if ( ret_val == OK ) { PCatexit(LGK_rundown); if ( clustered ) { /* ** Perform preliminary cluster connection and CX memory init. */ /* Get installation code */ NMgtAt("II_INSTALLATION", &nm_string); if ( nm_string ) { instid[0] = *(nm_string); instid[1] = *(nm_string+1); } else { instid[0] = 'A'; instid[1] = 'A'; } instid[2] = '\0'; ret_val = CXinitialize( instid, pcxmem, flag & LGK_IS_CSP ); if ( ret_val ) { /* Report error returned from CX */ uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0 ); break; } } #ifdef VMS { static $EXHDEF exit_block; i4 ctrl_y_mask = 0x02000000; /* ** On VMS, programs like the dmfjsp and logstat run as images in ** the shell process. That is, the system doesn't start and stop ** a process for each invocation of the program, it just starts ** and stops an image in the same process. This means that if ** the program should die, the image may be rundown but the process ** will remain, which means that the check-dead threads of other ** processes in the installation will not feel that they need to ** rundown this process, since it's still alive. ** ** By declaring an exit handler, which will get a chance to run ** even if PCexit isn't called, we improve our chances of getting ** to perform rundown processing if we should die unexpectedly. ** ** Furthermore, we ask DCL to disable its ^Y processing, which ** lessens the chance that the user will interrupt us while we ** are holding the semaphore. */ exit_block.exh$g_func = LGK_rundown; exit_block.exh$l_argcount = 1; exit_block.exh$gl_value = &exit_block.exh$l_status; if (sys$dclexh(&exit_block) != SS$_NORMAL) ret_val = FAIL; lib$disable_ctrl(&ctrl_y_mask, 0); } #endif } break; } if ( ret_val ) LGK_base.lgk_mem_ptr = NULL; return(ret_val); }
/*{ ** Name: CXget_context - Parse command arguments for NUMA args. ** ** Description: ** ** One particularly ugly requirement of NUMA clusters, is the need ** to specify the target context of certain commands that ** normally could easily determine a default context by themselves. ** ** E.g. 'lockstat' run on any node of a non-NUMA cluster "knows" ** implicitly that the current node corresponds to the current host. ** ** However, in a NUMA cluster, this happy state, no longer applies. ** If our sysadm logs onto a node which is configured into two or ** more virtual NUMA nodes, there is no way for 'lockstat', etc., ** to guess which of the virtual nodes is the target for the Ingres ** tool. ** ** We try to make a virtue of this neccesity by centralizing the ** parsing needed for these commands and in passing pick up a ** generalized way of setting processor affinity for Ingres tools. ** ** Two types of arguments are checked here: ** '-rad' is a RAD spec, in which the host machine is implicitly ** the local machine. ** ** '-node' may refer to either a local RAD by its node name or ** node alias, or to a node anywhere in thr cluster if CX_NSC_NODE_GLOBAL ** is set. ** ** Both arguments can be in the form -arg=value, or -arg value. ** ** The users input is checked against the following rules: ** ** R1: If NOT running clusters, '-node' parameter will always ** cause an error. ** ** R2: Only one of either "-node" or "-rad" is allowed. ** ** R3: If "-rad" is present, value must correspond to a valid RAD. ** ** R4: If "-node" is present, it must be a valid node, or node alias. ** ** R4a: If CX_NSC_NODE_GLOBAL is not set, node must match local host ** name or be hosted (virtual nodes only) by local host. ** ** R5: If not otherwise specified, and running NUMA clusters, ** RAD value is taken from environment variable II_DEFAULT_RAD. ** ** R6: If running NUMA clusters, and CX_NSC_RAD_OPTIONAL is not ** set, an error will be reported if context is not set by a ** valid -rad, or -node, or II_DEFAULT_RAD value. ** ** R7: If rules R2-R6 are not violated, and CX_NSC_CONSUME is set, ** and an matching parameter or parameter pair was provided, ** the parameters are removed from the argument vector, and ** the argument count is adjusted. ** ** R8: If CX_NSC_SET_CONTEXT is set, and not running NUMA clusters, ** and a valid RAD value was provided with an explicit '-rad' ** argument, CXnuma_bind_to_rad is called to set process affinity ** to the specified RAD. ** ** R9: If CX_NSC_SET_CONTEXT is set, running NUMA clusters, or ** if a valid '-node' parameter was supplied, CXset_cluster ** is called for the specified node. ** ** R10: If CX_NSC_REPORT_ERRS is set, and an error occurred, ** message is sent to stdout. ** ** If all appropriate rules are met, then OK is returned. ** Caller should be set up to catch and complain about any ** extra invalid parameters. ** ** If outbuf is not NULL, node name if copied out if status = ** OK, else error message text is copies out. In both cases ** only a max of outlen chars are returned, including an EOS. ** ** Inputs: ** ** pargc - Address of integer holding # of arg strings. ** ** argv - Array of string pointers to argument values. ** ** flags - Flag bits OR'ed together. Valid flags are: ** ** CX_NSC_REPORT_ERRS - Emit any error message to stdout. ** ** CX_NSC_NODE_GLOBAL - Allow node argument to refer to ** Nodes outside the current host. ** ** CX_NSC_CONSUME - Eat any -rad/-node args & values if OK. ** ** CX_NSC_IGNORE_NODE - Ignore '-node' params in scan. ** ** CX_NSC_SET_CONTEXT - Set CX context based on good params. ** ** CX_NSC_RAD_OPTIONAL - Don't fail if NUMA & RAD not set. ** If running NUMA clusters, only ** set this in combination with ** CX_NSC_SET_CONTEXT if you are sure ** that shared memory won't be accessed, ** and all you need is to retreive the ** context later (e.g. iirun). ** ** outbuf - buffer to receive nodename, or error message text. ** ** outlen - limit to # bytes copied to outbuf. ** ** Outputs: ** ** *pargc - decremented by if argument(s) are consumed. ** ** argv - Adjused to remove consumed argument(s). ** ** outbuf - Holds '\0' terminated string with either nodename ** or error message depending on status. ** ** Returns: ** OK - All is well. ** E_CL2C40_CX_E_BAD_PARAMETER - Bad params values, ** or bad combination ** of parameters. ** E_CL2C43_CX_E_REMOTE_NODE - Node specified was not on ** current host machine. ** E_CL2C2F_CX_E_BADRAD - Rad value out of range. ** E_CL2C42_CX_E_NOT_CONFIGURED - Node or RAD not configured ** as part of a cluster. ** E_CL2C41_CX_E_MUST_SET_RAD - Running NUMA clusters, ** and no argument, or ** environment variable, set ** the RAD context. ** ** Exceptions: ** none ** ** Side Effects: ** See CXnuma_bind_to_rad(), if called with a '-rad' ** argument outside a NUMA cluster, else see ** CXset_context(). ** ** Notes: ** Typically in a NUMA cluster configuration, the target RAD ** information is needed very early in the applications logic, ** since it cannot implicitly determine the virtual node it ** is intended to be running on. ** ** History: ** 18-sep-2002 (devjo01) ** Created. */ STATUS CXget_context( i4 *pargc, char *argv[], i4 flags, char *outbuf, i4 outlen ) { STATUS status = OK; CX_NODE_INFO *pni = NULL; bool numa; i4 arg, radarg = 0, nodearg = 0, badarg = 0; i4 target_rad; i4 argstokill = 1; char *pvalue = NULL, *argp, *host; char lclbuf[256]; i4 erargc; ER_ARGUMENT erargs[2]; host = CXhost_name(); do { /* Scan passed arguments for "-rad" & "-node" */ for ( arg = 1; arg < *pargc; arg++ ) { argp = argv[arg]; if ( '-' != *argp ) continue; if ( 0 == STxcompare(argp, 4, ERx( "-rad" ), 4, FALSE, FALSE) ) { if ( radarg || nodearg ) { /* R2 */ badarg = arg; break; } radarg = arg; if ( *(argp + 4) == '=' ) { pvalue = argp + 5; } else if ( '\0' != *(argp + 4) || (arg >= (*pargc - 1)) ) { /* R3 */ badarg = arg; break; } else { /* Next argument must be a valid RAD ID */ pvalue = argv[++arg]; argstokill = 2; } if ( '\0' == *pvalue ) { /* R3 */ badarg = radarg; break; } if ( OK != CVan( pvalue, &target_rad ) || target_rad <= 0 ) { /* R3 */ badarg = arg; break; } } else if ( !(CX_NSC_IGNORE_NODE & flags) && 0 == STxcompare(argp, 5, ERx( "-node" ), 5, FALSE, FALSE ) ) { if ( radarg || nodearg ) { /* R2 */ badarg = arg; break; } nodearg = arg; if ( *(argp + 5) == '=' ) { pvalue = argp + 6; } else if ( ('\0' != *(argp + 5)) || (arg >= (*pargc - 1)) ) { /* R4 */ badarg = arg; break; } else { /* Next argument must be a node ID */ pvalue = argv[++arg]; argstokill = 2; } if ( '\0' == *pvalue ) { /* R4 */ badarg = nodearg; break; } } } /* end for */ /* If bad syntax seen, scram & fail */ if ( badarg ) { status = E_CL2C40_CX_E_BAD_PARAMETER; erargc = 1; erargs[0].er_size = 0; erargs[0].er_value = (PTR)argv[badarg]; break; } numa = CXnuma_cluster_configured(); /* If no explicit parameters seen, try default */ if ( numa && !pvalue && !(flags & CX_NSC_RAD_OPTIONAL) ) { /* R5 */ argp = ERx( "II_DEFAULT_RAD" ); pvalue = getenv( argp ); if ( pvalue && ( ( '\0' == *pvalue ) || OK != CVan(pvalue, &target_rad) ) ) pvalue = NULL; } /* Got a value either from command line or environment */ if ( pvalue ) { if ( nodearg ) { if ( CXcluster_configured() ) { pni = CXnode_info(pvalue, 0); if ( pni ) { /* If can't be global, make sure its local */ if ( !(flags & CX_NSC_NODE_GLOBAL) && !( ( 0 == STxcompare( host, 0, pni->cx_node_name, pni->cx_node_name_l, TRUE, FALSE ) ) || ( ( 0 != pni->cx_host_name_l ) && ( 0 == STxcompare( host, 0, pni->cx_host_name, pni->cx_host_name_l, TRUE, FALSE ) ) ) ) ) { /* Node must be local and was not. (R4a) */ status = E_CL2C43_CX_E_REMOTE_NODE; erargc = 2; erargs[0].er_size = 0; erargs[0].er_value = (PTR)argv[0]; erargs[1].er_size = pni->cx_host_name_l; erargs[1].er_value = (PTR)(pni->cx_host_name); break; } } } } else if ( numa ) { pni = CXnode_info(host, target_rad); } else if ( target_rad > CXnuma_rad_count() ) { if ( !(flags & CX_NSC_RAD_OPTIONAL) ) { /* R3 */ status = E_CL2C2F_CX_E_BADRAD; erargc = 0; break; } target_rad = 0; } if ( ( numa || nodearg ) && ( NULL == pni ) ) { /* Requested node/rad not configured */ /* R3, R4 */ if ( !argp ) argp = argv[radarg+nodearg]; status = E_CL2C42_CX_E_NOT_CONFIGURED; erargc = 1; erargs[0].er_size = 0; erargs[0].er_value = (PTR)argp; break; } } else { if ( numa && !(flags & CX_NSC_RAD_OPTIONAL) ) { /* If required argument missing, scram & fail */ status = E_CL2C41_CX_E_MUST_SET_RAD; erargc = 1; erargs[0].er_size = 0; erargs[0].er_value = (PTR)argv[0]; break; } } if ( (flags & CX_NSC_CONSUME) && (radarg || nodearg) ) { for ( arg = radarg + nodearg + argstokill; arg < *pargc; arg++ ) { argv[arg-argstokill] = argv[arg]; } *pargc = *pargc - argstokill; argv[*pargc] = NULL; } } while (0); if ( OK == status ) { lclbuf[CX_MAX_NODE_NAME_LEN] = '\0'; if ( NULL == pni ) { (void)STlcopy(host, lclbuf, CX_MAX_NODE_NAME_LEN); } else { (void)STlcopy(pni->cx_node_name, lclbuf, CX_MAX_NODE_NAME_LEN); } CVlower( lclbuf ); if ( flags & CX_NSC_SET_CONTEXT ) { if ( !numa && 0 != target_rad ) { (void)CXnuma_bind_to_rad( target_rad ); } (void)CXset_context(lclbuf, 0); } } if ( OK != status ) { cx_fmt_msg( status, lclbuf, sizeof(lclbuf), erargc, erargs ); if ( flags & CX_NSC_REPORT_ERRS ) (void)SIprintf( "\n%s\n", lclbuf ); } if ( outbuf ) { STlcopy( lclbuf, outbuf, outlen - 1 ); *(outbuf + outlen - 1) = '\0'; } return status; } /*CXget_context*/
/* ** Name: makeutable - make unicode collation element table ** ** Descrription: ** Reads input collation element text file and compiles a table. ** also reads the Unicode character database and adds attributes for ** each character found. Currently we only take note of canonical ** decomposition for normalization. ** ** Inputs: ** desfile - collation element description file ** ** Outputs: ** None ** ** Returns: ** utbl - collation element table ** ** History: ** 14-mar-2001 (stephenb) ** Created ** 5-apr-2001 (stephenb) ** Add code to read unciode character database. ** 17-may-2001 (stephenb) ** Read in combining class from character database. ** 24-dec-2001 (somsa01) ** Modified such that the varsize which is placed in the Unicode ** table is now a SIZE_TYPE rather than an i4. ** 12-dec-2001 (devjo01) ** Make sure 1st overflow entry is properly aligned. ** Add messages to report if files cannot be opened. ** 17-jul-2001 (gupsh01) ** Modified the placing of the decomposition enty to ** decomp structure in the file, to be the first entry. ** 04-Mar-2005 (hanje04) ** Add support for reverse hybrid builds, i.e. 64bit exe needs to ** call 32bit version. ** 17-May-2007 (gupsh01) ** Added support for reverse sorting of the accented characters. ** This is done to support @backwards tag in custom collation file. ** 08-Aug-2007 (kiria01) b118917 ** Detect lines relating to conditional special caseing and ignore them. ** 08-Aug-2007 (gupsh01) ** Fixed the typo for CASE_IGNORABLE setting. Also fixed the ** handling of Final_Sigma in the special_casing.txt. ** 08-Aug-2007 (gupsh01) ** Fixed the decomposition mapping which were not being set for ** composite characters. ** 24-Nov-2008 (gupsh01) ** When alloating the memory for recombination table make sure ** we initialize the buffer. */ static ADUUCETAB * makeutable( char *desfile) { char buf[MAX_UCOL_REC]; FILE *fp; FILE *dfp; LOCATION loc; char table_vers[MAX_UVERS] = ""; i4 lno = 0; char *recptr; char *separator; ADUUCETAB *tab = &w.utab; i4 num_rvals = 0; ADUUCETAB *epointer = (ADUUCETAB *)w.buff; /* entries first */ /* then instructions */ char *ipointer; SIZE_TYPE *varsize; char *tptr; ADU_UCEFILE *rrec = NULL; ADU_UCEFILE *cerec = NULL; char csval[7]; char svalue[21]; char *ceptr; char *comment; u_i4 cval; i4 numce; bool combent; i4 i; /* Stuff to track the size of the recomb_tbl entries */ u_i2 **recomb_def2d; u_i2 *recomb_def1d; char *recombtbl; char *tracker; SIZE_TYPE *recomb_tbl_size; i4 tr = 0; i4 j = 0; STATUS stat; i4 rcbufsz; char *tempbuf; i4 current_bytes; char *upperval; char *lowerval; char *titleval; char *endval; i4 bts = 0; i4 lcnt = 0; i4 tcnt = 0; i4 ucnt = 0; i4 row = 0; i4 col = 0; bool backward_set = FALSE; /* open file */ STcopy(desfile, buf); LOfroms(FILENAME, buf, &loc); if (SIopen(&loc, "r", &fp) != OK) { SIprintf("aducompile: Unable to open input file \"%s\".\n", loc.string ); return NULL; } varsize = (SIZE_TYPE *)(w.buff + ENTRY_SIZE); recomb_tbl_size = (SIZE_TYPE *)(varsize + 1); ipointer = (char*)(recomb_tbl_size + 1); ipointer = ME_ALIGN_MACRO(ipointer, sizeof(PTR)); /* this is a sparse table, make sure we initialize it */ MEfill(INSTRUCTION_SIZE + ENTRY_SIZE, 0, w.buff); *varsize = 0; /* read data */ while (SIgetrec(buf, sizeof(buf), fp) != ENDFILE) { lno++; if (buf[0] == '#') /* comment line */ continue; (VOID)STtrmwhite(buf); if (STcompare(buf, "") == 0) /* blank line */ continue; /* should first find version */ if (table_vers[0] == EOS) { if (STbcompare(buf, 8, "@version", 8, TRUE) == 0) { /* we don't parse the version string, maybe we should */ STlcopy(buf+9, table_vers, MAX_UVERS); continue; } else { SIprintf("Syntax error on line %d, version line must be first \ non-comment line in the file, ignored\n", lno); continue; } } /* then alternate weights (optional), currently un-supported */ if (STbcompare(buf, 10, "@alternate", 10, TRUE) == 0) { SIprintf("Syntax error on line %d, alternate weights are not \ currently supported, ignored\n", lno); continue; } /* now backwards lines (also not currently supported) */ if (STbcompare(buf, 10, "@backwards", 10, TRUE) == 0) { backward_set = TRUE; continue; } /* and rearrange lines */ if (STbcompare(buf, 10, "@rearrange", 10, TRUE) == 0) { bool strend = FALSE; u_i4 rval; for (recptr = buf + 10;;) { /* skip blanks */ if ((recptr = STskipblank(recptr, STlength(recptr))) == NULL) { /* blank string, ignore */ SIprintf("Syntax error on line %d, no characters in \ rearrange list, ignoring\n", lno); strend = TRUE; break; } /* find next comma separator */ if ((separator = STindex(recptr, ",", 0)) == NULL) { strend = TRUE; separator = recptr + 4; } if (separator - recptr != 4) { SIprintf("Syntax error on line %d, characters in a rearrange\ line must be a comma separated list of 4 digit hex values, ABORTING\n", lno); tab = NULL; break; }