static void *get_log_instance() { if (gLogInstance || gLogInstanceState == 2 || gInFork) return gLogInstance; /* Set a flag that we're going to init a new log instance */ if (!__atomic_cmpxchg32(&gLogInstanceState, 1, 0)) { /* * Another thread was faster in starting instance creation, wait for it * to complete in a simple spin loop (completion should be really quick). */ while (gLogInstanceState == 1) DosSleep(1); return gLogInstance; } void *logInstance = NULL; __LIBC_LOGGROUPS *logGroups = NULL; #if defined(TRACE_ENABLED) logGroups = &gLogGroups; __libc_LogGroupInit(&gLogGroups, "LIBCX_TRACE"); #endif /* Check if we are asked to log to console */ { PSZ dummy; gLogToConsole = DosScanEnv("LIBCX_TRACE_TO_CONSOLE", &dummy) == NO_ERROR; } char buf[CCHMAXPATH + 128]; if (gLogToConsole) { logInstance = __libc_LogInit(0, logGroups, "NUL"); if (logInstance) { /* * This is a dirty hack to write logs to stdout, * LIBC isn't capable of it on its own (@todo fix LIBC). */ typedef struct __libc_logInstance { /** Write Semaphore. */ HMTX hmtx; /** Filehandle. */ HFILE hFile; /** Api groups. */ __LIBC_PLOGGROUPS pGroups; } __LIBC_LOGINST, *__LIBC_PLOGINST; /* Sanity check (note: we use LIBC assert here to avoid recursion) */ assert(((__LIBC_PLOGINST)logInstance)->pGroups == logGroups); /* Duplicate STDOUT */ DosDupHandle(1, &((__LIBC_PLOGINST)logInstance)->hFile); } } else { /* * We don't query QSV_TIME_HIGH as it will remain 0 until 19-Jan-2038 and for * our purposes (generate an unique log name sorted by date) it's fine. */ ULONG time; DosQuerySysInfo(QSV_TIME_LOW, QSV_TIME_LOW, &time, sizeof(time)); // Get log directory (boot drive if no UNIXROOT) const char *path = "/var/log/libcx"; PSZ unixroot; if (DosScanEnv("UNIXROOT", &unixroot) != NO_ERROR) { ULONG drv; DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &drv, sizeof(drv)); unixroot = "C:"; unixroot[0] = '@' + drv; path = ""; } else { /* * Make sure the directory exists (no error checks here as a failure to * do so will pop up later in __libc_LogInit anyway). */ if (strlen(unixroot) >= CCHMAXPATH) return NULL; strcpy(buf, unixroot); strcat(buf, path); DosCreateDir(buf, NULL); } // Get program name char name[CCHMAXPATH]; PPIB ppib = NULL; DosGetInfoBlocks(NULL, &ppib); if (DosQueryModuleName(ppib->pib_hmte, sizeof(name), name) != NO_ERROR) return NULL; _remext(name); logInstance = __libc_LogInit(0, logGroups, "%s%s/%s-%08lx-%04x.log", unixroot, path, _getname(name), time, getpid()); } /* Bail out if we failed to create a log file at all */ if (!logInstance) { gLogInstanceState = 0; return NULL; } if (!gLogToConsole) { // Write out LIBCx info strcpy(buf, "LIBCx version : " VERSION_MAJ_MIN_BLD LIBCX_DEBUG_SUFFIX LIBCX_DEV_SUFFIX "\n"); strcat(buf, "LIBCx module : "); APIRET arc = DosQueryModuleName(ghModule, CCHMAXPATH, buf + strlen(buf)); if (arc == NO_ERROR) sprintf(buf + strlen(buf), " (hmod=%04lx)\n", ghModule); else sprintf(buf + strlen(buf), " <error %ld>\n", arc); __libc_LogRaw(logInstance, __LIBC_LOG_MSGF_FLUSH, buf, strlen(buf)); } /* * Finish initialization by storing the instance and setting the state to 2 * (this will unfreeze other threads that started instance creation, if any). */ gLogInstance = logInstance; gLogInstanceState = 2; return gLogInstance; }
int main(int argc,char **argv) { const char *name; int i; init_privs(); #ifdef __EMX__ _wildcard(&argc,&argv); #endif /*#define PRIV_TEST*/ #ifdef PRIV_TEST { int euid; char command[100]; printf("INIT: %d %d\n", getuid(), geteuid()); drop_privs(); printf("DROP: %d %d\n", getuid(), geteuid()); reclaim_privs(); printf("RECLAIM: %d %d\n", getuid(), geteuid()); euid = geteuid(); if(argc & 1) { drop_privs(); printf("DROP: %d %d\n", getuid(), geteuid()); } if(!((argc-1) & 2)) { destroy_privs(); printf("DESTROY: %d %d\n", getuid(), geteuid()); } sprintf(command, "a.out %d", euid); system(command); return 1; } #endif #ifdef __EMX__ _wildcard(&argc,&argv); #endif /* check whether the compiler lays out structures in a sane way */ if(sizeof(struct partition) != 16 || sizeof(struct directory) != 32 || sizeof(struct vfat_subentry) !=32) { fprintf(stderr,"Mtools has not been correctly compiled\n"); fprintf(stderr,"Recompile it using a more recent compiler\n"); return 137; } #ifdef __EMX__ argv[0] = _getname(argv[0]); _remext(argv[0]); name = argv[0]; #else name = _basename(argv[0]); #endif #if 0 /* this allows the different tools to be called as "mtools -c <command>" ** where <command> is mdir, mdel, mcopy etcetera ** Mainly done for the BeOS, which doesn't support links yet. */ if(argc >= 3 && !strcmp(argv[1], "-c") && !strcmp(name, "mtools")) { argc-=2; argv+=2; name = argv[0]; } #endif /* print the version */ if(argc >= 2 && (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") ==0)) { printf("%c%s version %s, dated %s\n", toupper(name[0]), name+1, mversion, mdate); printf("configured with the following options: "); #ifdef USE_XDF printf("enable-xdf "); #else printf("disable-xdf "); #endif #ifdef USING_VOLD printf("enable-vold "); #else printf("disable-vold "); #endif #ifdef USING_NEW_VOLD printf("enable-new-vold "); #else printf("disable-new-vold "); #endif #ifdef DEBUG printf("enable-debug "); #else printf("disable-debug "); #endif #ifdef USE_RAWTERM printf("enable-raw-term "); #else printf("disable-raw-term "); #endif printf("\n"); return 0; } if (argc >= 2 && strcmp(name, "mtools") == 0) { /* mtools command ... */ argc--; argv++; name = argv[0]; } progname = argv[0]; read_config(); setup_signal(); for (i = 0; i < NDISPATCH; i++) { if (!strcmp(name,dispatch[i].cmd) || (name[0] == 'm' && !strcmp(name+1,dispatch[i].cmd))) dispatch[i].fn(argc, argv, dispatch[i].type); } if (strcmp(name,"mtools")) fprintf(stderr,"Unknown mtools command '%s'\n",name); fprintf(stderr,"Usage: mtools [-V] command [-options] arguments ...\n"); fprintf(stderr,"Supported commands:"); for (i = 0; i < NDISPATCH; i++) { fprintf(stderr, i%8 == 0 ? "\n\t" : ", "); fprintf(stderr, "%s", dispatch[i].cmd); } putc('\n', stderr); fprintf(stderr, "Use 'mtools command -?' for help per command\n"); return 1; }