/** * b u _ i p w d * * set/return the path to the initial working directory. * bu_setprogname() must be called on app startup for the correct pwd to * be acquired/set. */ static const char * bu_ipwd() { /* private stash */ static const char *ipwd = NULL; static char buffer[MAXPATHLEN] = {0}; if (ipwd) { return ipwd; } ipwd = getenv("PWD"); /* not our memory to free */ if (!ipwd && (ipwd = bu_which("pwd"))) { FILE *fp; fp = popen(ipwd, "r"); if (fp) { if (bu_fgets(buffer, MAXPATHLEN, fp)) { ipwd = buffer; } else { ipwd = "."; } } else { ipwd = "."; } } else { ipwd = "."; } return ipwd; }
/** * b u _ a r g v 0 _ f u l l _ p a t h * * returns the full path to argv0, regardless of how the application * was invoked. */ const char * bu_argv0_full_path(void) { static char buffer[MAXPATHLEN] = {0}; const char *argv0 = bu_argv0(); const char *ipwd = bu_ipwd(); const char *which = bu_which(argv0); if (argv0[0] == BU_DIR_SEPARATOR) { /* seems to be a full path */ snprintf(buffer, MAXPATHLEN, "%s", argv0); return buffer; } if (argv0[0] == '.' && argv0[1] == BU_DIR_SEPARATOR) { /* remove a ./ if present */ argv0 += 2; } /* running from installed */ if (which) { snprintf(buffer, MAXPATHLEN, "%s", which); return buffer; } /* running from source dir */ snprintf(buffer, MAXPATHLEN, "%s%c%s", ipwd, BU_DIR_SEPARATOR, argv0); if (bu_file_exists(buffer)) { return buffer; } /* give up */ snprintf(buffer, MAXPATHLEN, "%s", argv0); return buffer; }
int bu_crashreport(const char *filename) { if (UNLIKELY(!filename || strlen(filename) == 0)) { return 0; } /* vat time ist? */ (void)time(&now); path = bu_argv0_full_path(); /* do our own expansion to avoid heap allocation */ snprintf(buffer, CR_BUFSIZE, "******************************************\n\n" "%s\n" /* version info */ "Command: %s\n" /* program name */ "Process: %d\n" /* pid */ "Path: %s\n" /* which binary */ "Date: %s\n", /* date/time */ brlcad_ident("Crash Report"), bu_getprogname(), bu_process_id(), path ? path : "Unknown", ctime(&now)); fp = fopen(filename, "ab"); if (UNLIKELY(!fp || ferror(fp))) { perror("unable to open crash report file"); bu_log("ERROR: Unable to open crash report file [%s]\n", filename); return 0; } /* make the file stream unbuffered */ if (setvbuf(fp, (char *)NULL, _IONBF, 0) != 0) { perror("unable to make stream unbuffered"); } /* print the report header */ if (fwrite(buffer, 1, strlen(buffer), fp) != strlen(buffer)) { /* cannot bomb */ bu_log("ERROR: Unable to write to crash report file [%s]\n", filename); (void)fclose(fp); fp = NULL; return 0; } /* write out the backtrace */ fprintf(fp, "Call stack backtrace (thread %d):\n", bu_parallel_id()); fflush(fp); if (bu_backtrace(fp) == 0) { bu_log("WARNING: Unable to obtain a call stack backtrace\n"); } /* write out operating system information */ path = bu_which("uname"); if (path) { snprintf(buffer, CR_BUFSIZE, "%s -a 2>&1", path); #if defined(HAVE_POPEN) && !defined(STRICT_FLAGS) popenfp = popen(buffer, "r"); if (!popenfp) { perror("unable to popen uname"); bu_log("WARNING: Unable to obtain uname information\n"); } #endif if (popenfp) { fprintf(fp, "\nSystem characteristics:\n"); fflush(fp); while (bu_fgets(buffer, CR_BUFSIZE, popenfp)) { size_t ret; size_t len; len = strlen(buffer); ret = fwrite(buffer, 1, len, fp); if (ret != len) perror("fwrite failed"); } } #if defined(HAVE_POPEN) && !defined(STRICT_FLAGS) (void)pclose(popenfp); #endif popenfp = NULL; path = NULL; } /* write out kernel and hardware information */ path = bu_which("sysctl"); if (path) { /* need 2>&1 to capture stderr junk from sysctl on Mac OS X for kern.exec */ snprintf(buffer, CR_BUFSIZE, "%s -a 2>&1", path); #if defined(HAVE_POPEN) && !defined(STRICT_FLAGS) popenfp = popen(buffer, "r"); if (popenfp == (FILE *)NULL) { perror("unable to popen sysctl"); bu_log("WARNING: Unable to obtain sysctl information\n"); } #endif if (popenfp != (FILE *)NULL) { fprintf(fp, "\nSystem information:\n"); fflush(fp); while (bu_fgets(buffer, CR_BUFSIZE, popenfp)) { size_t ret; size_t len; len = strlen(buffer); if ((len == 0) || ((len == 1) && (buffer[0] == '\n'))) { continue; } ret = fwrite(buffer, 1, len, fp); if (ret != len) perror("fwrite failed"); } } #if defined(HAVE_POPEN) && !defined(STRICT_FLAGS) (void)pclose(popenfp); #endif popenfp = NULL; path = NULL; } memset(buffer, 0, CR_BUFSIZE); fprintf(fp, "\n"); fflush(fp); (void)fclose(fp); fp = NULL; /* success */ return 1; }