SG_error SG_context__err_to_console(SG_context* pCtx, SG_console_stream cs) { SG_error err; SG_string* pErrStr = NULL; SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); if (pCtx->level > 0) // when in an error-on-error (level > 0), there is NO error string. return SG_ERR_OK; // so we don't need to do anything. // get the full error string about the error at the current level. err = SG_context__err_to_string(pCtx, &pErrStr); if (SG_IS_ERROR(err)) // an allocation/formatting error, just give up. return err; // write the error string/message to the console. we push a new level // so that any problems converting the message to the user's locale or // writing to the console device don't trash the current error context. // // ***DO NOT JUMP OUT OF THIS PUSH..POP BLOCK.*** SG_context__push_level(pCtx); { SG_console(pCtx, cs, SG_string__sz(pErrStr)); err = pCtx->errValues[pCtx->level]; // we return the error value of the conversion/writing. } SG_context__pop_level(pCtx); SG_STRING_NULLFREE(pCtx, pErrStr); return err; }
SG_error SG_context__alloc(SG_context** ppCtx) { // WARNING: We assume that it is possible for the us to create // WARNING: a properly-populated SG_context before the library is initialized. // WARNING: (Before SG_lib__global_initialize() has been called.) // WARNING: // WARNING: That is, that the creation of the SG_context MUST NOT require any // WARNING: character encoding, locale, and/or UTF-8 stuff. // WARNING: // WARNING: Also, there the SG_context creation MUST NOT require us to read // WARNING: any local settings. SG_error err; SG_context* pCtx = NULL; if (!ppCtx) return SG_ERR_INVALIDARG; err = _context__alloc__stacksize(&pCtx); if ( SG_IS_ERROR(err) ) return err; *ppCtx = pCtx; return SG_ERR_OK; }
SG_error SG_context__err_set_description(SG_context* pCtx, const char* szFormat, ...) { SG_error err; va_list ap; SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); if (pCtx->level > 0) // when in an error-on-error (level > 0), return SG_ERR_OK; // we don't alter the description. SG_ASSERT( (SG_IS_ERROR(pCtx->errValues[pCtx->level])) ); // assume __err or __err__generic just set error SG_context__push_level(pCtx); // format extra info on new level so that we don't trash error info in current level { va_start(ap,szFormat); SG_vsprintf_truncate(pCtx, pCtx->szDescription,SG_CONTEXT_LEN_DESCRIPTION + 1,szFormat,ap); va_end(ap); err = pCtx->errValues[pCtx->level]; // the error result of the sprintf } SG_context__pop_level(pCtx); return err; }
SG_error SG_context__err(SG_context* pCtx, SG_error new_err, const char * szFileName, int iLine, const char* szDescription) { SG_error err; // These are checked in SG_context__err__generic(). // SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); err = SG_context__err__generic(pCtx, new_err, szFileName, iLine); if (SG_IS_ERROR(err)) return err; return SG_context__err_set_description(pCtx, szDescription); }
SG_error SG_context__err__generic(SG_context* pCtx, SG_error new_err, const char * szFileName, int iLine) { SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); // asserted in __push SG_ASSERT( (SG_IS_ERROR(new_err)) ); // require an error; formerly asserted in SG_ERR_ macro SG_ASSERT( (SG_IS_OK(pCtx->errValues[pCtx->level])) ); // assume no previous unhandled error pCtx->errValues[pCtx->level] = new_err; return SG_context__err_stackframe_add(pCtx, szFileName, iLine); }
static SG_error _context__alloc__stacksize(SG_context** ppCtx) { SG_error err; SG_context* pCtx = NULL; if (!ppCtx) return SG_ERR_INVALIDARG; err = SG_alloc_err(1, sizeof(SG_context), &pCtx); if ( SG_IS_ERROR(err) ) return err; pCtx->level = 0; pCtx->errValues[pCtx->level] = SG_ERR_OK; pCtx->lenStackTrace = 0; pCtx->szStackTrace[0] = 0; pCtx->numMsgListeners = 0; *ppCtx = pCtx; return SG_ERR_OK; }
int main(int argc, char **argv) { int stackDummy; SG_error err; SG_context * pCtx = NULL; JSRuntime *rt; JSContext *cx; SG_log_console__data cLogStdData; SG_log_text__data cLogFileData; SG_log_text__writer__daily_path__data cLogFileWriterData; JSObject *glob; int result; SG_bool skipModules = SG_FALSE; SG_zero(cLogStdData); SG_zero(cLogFileData); SG_zero(cLogFileWriterData); CheckHelpMessages(); setlocale(LC_ALL, ""); gStackBase = (jsuword)&stackDummy; #ifdef XP_OS2 /* these streams are normally line buffered on OS/2 and need a \n, * * so we need to unbuffer then to get a reasonable prompt */ setbuf(stdout,0); setbuf(stderr,0); #endif gErrFile = stderr; gOutFile = stdout; argc--; argv++; err = SG_context__alloc(&pCtx); if (SG_IS_ERROR(err)) return 1; SG_lib__global_initialize(pCtx); if (SG_context__has_err(pCtx)) { _vscript_context_teardown(&pCtx); return 1; } _checkSkipModules(pCtx, &argc, argv, &skipModules); if (SG_context__has_err(pCtx)) { _vscript_context_teardown(&pCtx); return 1; } SG_jscore__new_runtime(pCtx, ContextCallback, shell_functions, skipModules, &rt); if (SG_context__has_err(pCtx)) { _vscript_context_teardown(&pCtx); return 1; } SG_jscore__new_context(pCtx, &cx, &glob, NULL); if (SG_context__has_err(pCtx)) { _vscript_context_teardown(&pCtx); return 1; } JS_SetGlobalObject(cx, glob); ////////////////////////////////////////////////////////////////// // Allocate and initialize the SG_context. _set_up_logging(pCtx, &cLogStdData, &cLogFileData, &cLogFileWriterData); result = ProcessArgs(cx, glob, argv, argc); _clean_up_logging(pCtx, &cLogStdData, &cLogFileData, &cLogFileWriterData); // TODO 2011/09/30 The following call removes "pCtx" from // TODO the private data in the "cx". This was // TODO done for neatness before we destroy it. // TODO And this has worked fine for years. // TODO // TODO I have commented this out as an experiment // TODO so that the "pCtx" is still available for // TODO use in any GC/Finalize callbacks. // TODO // TODO SG_jsglue__set_sg_context(NULL, cx); JS_EndRequest(cx); JS_DestroyContext(cx); // End of SG_context post-processing. ////////////////////////////////////////////////////////////////// result = result + _vscript_context_teardown(&pCtx); return result; }
void SG_password__get( SG_context *pCtx, const char *szRepoSpec, const char *szUsername, SG_string **ppstrPassword) { SG_string* pstrTarget = NULL; SG_string* pstrPassword = NULL; LPWSTR pwszTarget = NULL; SG_byte* pbPassword = NULL; PCREDENTIAL pCred = NULL; BOOL result = FALSE; SG_NULLARGCHECK_RETURN(szRepoSpec); SG_NULLARGCHECK_RETURN(szUsername); SG_NULLARGCHECK_RETURN(ppstrPassword); _get_key(pCtx, szRepoSpec, szUsername, &pstrTarget); if (SG_CONTEXT__HAS_ERR(pCtx)) { SG_error err, err2; err2 = SG_context__get_err(pCtx, &err); if (SG_IS_ERROR(err2)) { SG_ERR_DISCARD; SG_ERR_THROW(err2); } if (err & __SG_ERR__GETLASTERROR__) SG_ERR_DISCARD; else SG_ERR_RETHROW; } if (pstrTarget) { SG_ERR_CHECK( SG_utf8__extern_to_os_buffer__wchar(pCtx, SG_string__sz(pstrTarget), &pwszTarget, NULL) ); result = CredReadW(pwszTarget, CRED_TYPE_GENERIC, 0, &pCred); if (!result) { DWORD err = GetLastError(); if (err != ERROR_NOT_FOUND && err != ERROR_NO_SUCH_LOGON_SESSION) SG_ERR_THROW2( SG_ERR_GETLASTERROR(GetLastError()), (pCtx, "%s", "unable to retrieve saved credentials") ); } else { SG_uint32 size = pCred->CredentialBlobSize+sizeof(wchar_t); SG_ERR_CHECK( SG_allocN(pCtx, pCred->CredentialBlobSize+sizeof(wchar_t), pbPassword) ); memcpy(pbPassword, pCred->CredentialBlob, size); SG_ERR_CHECK( SG_string__alloc(pCtx, &pstrPassword) ); SG_ERR_CHECK( SG_utf8__intern_from_os_buffer__wchar(pCtx, pstrPassword, (const LPWSTR)pbPassword) ); *ppstrPassword = pstrPassword; pstrPassword = NULL; } } /* fall through */ fail: SG_STRING_NULLFREE(pCtx, pstrTarget); SG_STRING_NULLFREE(pCtx, pstrPassword); SG_NULLFREE(pCtx, pwszTarget); SG_NULLFREE(pCtx, pbPassword); if (pCred) CredFree(pCred); }
SG_error SG_context__err_stackframe_add(SG_context* pCtx, const char* szFilename, SG_uint32 linenum) { SG_error err = SG_ERR_OK; SG_uint32 len_needed; SG_uint32 len_avail; char buf[20]; SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); if (pCtx->level > 0) // when in an error-on-error (level > 0), return SG_ERR_OK; // we don't add to the stack trace. SG_ASSERT( (szFilename && *szFilename) ); SG_ASSERT( (linenum) ); SG_ASSERT( (SG_IS_ERROR(pCtx->errValues[pCtx->level])) ); SG_ASSERT( (!pCtx->bStackTraceAtLimit) ); // do all of the formatting in an error-on-error level so that none of // the string manipulation trashes the current error context. // // ***DO NOT JUMP OUT OF THIS PUSH..POP BLOCK.*** SG_context__push_level(pCtx); { SG_uint32 lenFilename; SG_uint32 lenLineNr; SG_sprintf(pCtx, buf, sizeof(buf), "%d", linenum); lenLineNr = strlen(buf); lenFilename = strlen(szFilename); len_needed = lenFilename + lenLineNr + 3; // 3 == \t, :, and \n. // TODO should 5 be 6 to account for the NULL byte? // 5 == "\t...\n" len_avail = SG_NrElements(pCtx->szStackTrace) - pCtx->lenStackTrace - 5; if (len_needed > len_avail) { pCtx->bStackTraceAtLimit = SG_TRUE; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],"\t...\n",5); pCtx->lenStackTrace += 5; pCtx->szStackTrace[pCtx->lenStackTrace] = 0; } else { pCtx->szStackTrace[pCtx->lenStackTrace] = '\t'; pCtx->lenStackTrace++; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],szFilename,lenFilename); pCtx->lenStackTrace+=lenFilename; pCtx->szStackTrace[pCtx->lenStackTrace] = ':'; pCtx->lenStackTrace++; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],buf,lenLineNr); pCtx->lenStackTrace+=lenLineNr; pCtx->szStackTrace[pCtx->lenStackTrace] = '\n'; pCtx->lenStackTrace++; pCtx->szStackTrace[pCtx->lenStackTrace] = 0; } err = pCtx->errValues[pCtx->level]; // we return the error value from the formatting. } SG_context__pop_level(pCtx); return err; }