const char * get_property (const char *filename, const char *propname, int mode) { char line[MAXBUFSIZE], *p = NULL; FILE *fh; const char *value_s = NULL; if ((fh = fopen (filename, "r")) != 0) // opening the file in text mode { // avoids trouble on DOS while (fgets (line, sizeof line, fh) != NULL) if ((value_s = get_property_from_string (line, propname, PROPERTY_SEPARATOR, PROPERTY_COMMENT)) != NULL) break; fclose (fh); } p = getenv2 (propname); if (*p != 0) // getenv2() never returns NULL value_s = p; if (value_s) if (mode == PROPERTY_MODE_FILENAME) { static char tmp[FILENAME_MAX]; realpath2 (value_s, tmp); value_s = tmp; } return value_s; }
void SplitPathAndFile(char *fullPath,char *pathPart,char *filePart) // split fullPath into pathPart, and filePart // NOTE: pathPart and filePart must be at least MAXPATHLEN+1 // bytes long // if fullPath is longer than MAXPATHLEN, parts will get truncated when copied // NOTE: if fullPath is not a valid path, return the whole thing as filePart, // and the current directory as the pathPart { struct stat theStat; char tempPath[MAXPATHLEN+1]; if(realpath2(fullPath,pathPart)) { if((stat(pathPart,&theStat)!=-1)&&S_ISDIR(theStat.st_mode)) // point to a file, or a directory? { filePart[0]='\0'; // points to a directory, so no file part, this is done } else { ExtractFileName(pathPart,filePart); // pointed to a file, so separate them } } else { strncpy(tempPath,fullPath,MAXPATHLEN); // copy this to separate it tempPath[MAXPATHLEN]='\0'; ExtractFileName(tempPath,filePart); // separate the pieces if(!realpath2(tempPath,pathPart)) // try to get the path to the unknown file part { if(!realpath2(".",pathPart)) // get the current directory { pathPart[0]='\0'; // just return empty string } strncpy(filePart,fullPath,MAXPATHLEN); filePart[MAXPATHLEN]='\0'; } } }
const char * get_property (const char *filename, const char *propname, int mode) { char line[MAXBUFSIZE], *p = NULL; FILE *fh; const char *value_s = NULL; if ((fh = fopen (filename, "r")) != 0) // opening the file in text mode { // avoids trouble under DOS while (fgets (line, sizeof line, fh) != NULL) if ((value_s = get_property_from_string (line, propname, PROPERTY_SEPARATOR, PROPERTY_COMMENT))) break; fclose (fh); } p = getenv2 (propname); if (*p == 0) // getenv2() never returns NULL { if (!value_s) value_s = NULL; // value_s won't be changed // after this func (=ok) } else value_s = p; if (value_s) if (mode == PROPERTY_MODE_FILENAME) { static char tmp[FILENAME_MAX]; #ifdef __CYGWIN__ fix_character_set (value_s); #endif realpath2 (value_s, tmp); value_s = tmp; } return value_s; }
st_strpath_t * strpath (st_strpath_t *path, const char *path_s) { // TODO: compare this with splitpath() if (path_s == NULL) return NULL; realpath2 (path_s, path->realpath); #if defined DJGPP || defined __CYGWIN__ || defined _WIN32 if (isalpha (path->realpath[0]) && path->realpath[1] == ':' && path->realpath[2] == FILE_SEPARATOR) sprintf (path->drive, "%c:\\", toupper (path->realpath[0])); #else strcpy (path->drive, FILE_SEPARATOR_S); #endif dirname2 (path_s, path->dirname); strcpy (path->basename, basename2 (path_s)); strcpy (path->suffix, get_suffix (path_s)); return path; }
/** * Put in @host_path the full path to the given shell @command. The * @command is searched in @paths if not null, otherwise in $PATH * (relatively to the @tracee's file-system name-space). This * function always returns -1 on error, otherwise 0. */ int which(Tracee *tracee, const char *paths, char host_path[PATH_MAX], char *const command) { char path[PATH_MAX]; const char *cursor; struct stat statr; int status; bool is_explicit; bool found; assert(command != NULL); is_explicit = (strchr(command, '/') != NULL); /* Is the command available without any $PATH look-up? */ status = realpath2(tracee, host_path, command, true); if (status == 0 && stat(host_path, &statr) == 0) { if (!S_ISREG(statr.st_mode)) { notice(tracee, ERROR, USER, "'%s' is not a regular file", command); return -EACCES; } if ((statr.st_mode & S_IXUSR) == 0) { notice(tracee, ERROR, USER, "'%s' is not executable", command); return -EACCES; } found = true; } else found = false; /* Is the the explicit command was found? */ if (is_explicit) { if (found) return 0; else goto not_found; } /* Otherwise search the command in $PATH. */ paths = paths ?: getenv("PATH"); if (paths == NULL || strcmp(paths, "") == 0) goto not_found; cursor = paths; do { size_t length; length = strcspn(cursor, ":"); cursor += length + 1; if (length >= PATH_MAX) continue; else if (length == 0) strcpy(path, "."); else { strncpy(path, cursor - length - 1, length); path[length] = '\0'; } /* Avoid buffer-overflow. */ if (length + strlen(command) + 2 >= PATH_MAX) continue; strcat(path, "/"); strcat(path, command); status = realpath2(tracee, host_path, path, true); if (status == 0 && stat(host_path, &statr) == 0 && S_ISREG(statr.st_mode) && (statr.st_mode & S_IXUSR) != 0) return 0; } while (*(cursor - 1) != '\0'); not_found: status = getcwd2(tracee, path); if (status < 0) strcpy(path, "<unknown>"); notice(tracee, ERROR, USER, "'%s' not found (root = %s, cwd = %s, $PATH=%s)", command, get_root(tracee), path, paths); /* Check if the command was found without any $PATH look-up * but it didn't contain "/". */ if (found && !is_explicit) notice(tracee, ERROR, USER, "to execute a local program, use the './' prefix, for example: ./%s", command); return -1; }
int main (int argc, char **argv) { int x = 0, y = 0, rom_index = 0, c = 0; #if (FILENAME_MAX < MAXBUFSIZE) static char buf[MAXBUFSIZE]; #else static char buf[FILENAME_MAX]; #endif struct stat fstate; struct option long_options[UCON64_MAX_ARGS]; printf ("%s\n" "Uses code from various people. See 'developers.html' for more!\n" "This may be freely redistributed under the terms of the GNU Public License\n\n", ucon64_title); if (atexit (ucon64_exit) == -1) { fputs ("ERROR: Could not register function with atexit()\n", stderr); exit (1); } // flush st_ucon64_t memset (&ucon64, 0, sizeof (st_ucon64_t)); ucon64.rom = ucon64.file = ucon64.mapr = ucon64.comment = ""; ucon64.parport_needed = 0; ucon64.flags = WF_DEFAULT; ucon64.fname_arch[0] = 0; ucon64.argc = argc; ucon64.argv = argv; // must be set prior to calling // ucon64_load_discmage() (for DOS) // convert (st_getopt2_t **) to (st_getopt2_t *) memset (&options, 0, sizeof (st_getopt2_t) * UCON64_MAX_ARGS); for (c = x = 0; option[x]; x++) for (y = 0; option[x][y].name || option[x][y].help; y++) if (c < UCON64_MAX_ARGS) { memcpy (&options[c], &option[x][y], sizeof (st_getopt2_t)); c++; } ucon64.options = options; #ifdef DEBUG ucon64_runtime_debug (); // check (st_getopt2_t *) options consistency #endif #ifdef __unix__ // We need to modify the umask, because the configfile is made while we are // still running in root mode. Maybe 0 is even better (in case root did // `chmod +s'). umask (002); #endif ucon64_configfile (); #ifdef USE_ANSI_COLOR // ANSI colors? ucon64.ansi_color = get_property_int (ucon64.configfile, "ansi_color"); // the conditional call to ansi_init() has to be done *after* the check for // the switch -ncol #endif // parallel port? #ifdef USE_PPDEV get_property (ucon64.configfile, "parport_dev", ucon64.parport_dev, "/dev/parport0"); #elif defined AMIGA get_property (ucon64.configfile, "parport_dev", ucon64.parport_dev, "parallel.device"); #endif // use -1 (UCON64_UNKNOWN) to force probing if the config file doesn't contain // a parport line sscanf (get_property (ucon64.configfile, "parport", buf, "-1"), "%x", &ucon64.parport); // make backups? ucon64.backup = get_property_int (ucon64.configfile, "backups"); // $HOME/.ucon64/ ? get_property_fname (ucon64.configfile, "ucon64_configdir", ucon64.configdir, ""); // DAT file handling ucon64.dat_enabled = 0; get_property_fname (ucon64.configfile, "ucon64_datdir", ucon64.datdir, ""); // we use ucon64.datdir as path to the dats if (!access (ucon64.datdir, // !W_OK doesn't mean that files can't be written to dir for Win32 exe's #if !defined __CYGWIN__ && !defined _WIN32 W_OK | #endif R_OK | X_OK)) if (!stat (ucon64.datdir, &fstate)) if (S_ISDIR (fstate.st_mode)) ucon64.dat_enabled = 1; if (!ucon64.dat_enabled) if (!access (ucon64.configdir, #if !defined __CYGWIN__ && !defined _WIN32 W_OK | #endif R_OK | X_OK)) if (!stat (ucon64.configdir, &fstate)) if (S_ISDIR (fstate.st_mode)) { // fprintf (stderr, "Please move your DAT files from %s to %s\n\n", ucon64.configdir, ucon64.datdir); strcpy (ucon64.datdir, ucon64.configdir); // use .ucon64/ instead of .ucon64/dat/ ucon64.dat_enabled = 1; } if (ucon64.dat_enabled) ucon64_dat_indexer (); // update cache (index) files if necessary #ifdef USE_DISCMAGE // load libdiscmage ucon64.discmage_enabled = ucon64_load_discmage (); #endif if (argc < 2) { ucon64_usage (argc, argv); return 0; } // turn st_getopt2_t into struct option getopt2_long_only (long_options, options, UCON64_MAX_ARGS); // getopt() is utilized to make uCON64 handle/parse cmdlines in a sane // and expected way x = optind = 0; memset (&arg, 0, sizeof (st_args_t) * UCON64_MAX_ARGS); while ((c = getopt_long_only (argc, argv, "", long_options, NULL)) != -1) { if (c == '?') // getopt() returns 0x3f ('?') when an unknown option was given { fprintf (stderr, "Try '%s " OPTION_LONG_S "help' for more information.\n", argv[0]); exit (1); } if (x < UCON64_MAX_ARGS) { const st_ucon64_obj_t *p = (st_ucon64_obj_t *) getopt2_get_index_by_val (options, c)->object; arg[x].console = UCON64_UNKNOWN; // default if (p) { arg[x].flags = p->flags; if (p->console) arg[x].console = p->console; } arg[x].val = c; arg[x++].optarg = (optarg ? optarg : NULL); } else // this shouldn't happen exit (1); } #ifdef DEBUG for (x = 0; arg[x].val; x++) printf ("%d %s %d %d\n\n", arg[x].val, arg[x].optarg ? arg[x].optarg : "(null)", arg[x].flags, arg[x].console); #endif rom_index = optind; // save index of first file if (rom_index == argc) ucon64_execute_options(); else for (; rom_index < argc; rom_index++) { int result = 0; char buf2[FILENAME_MAX]; #ifndef _WIN32 struct dirent *ep; DIR *dp; #else char search_pattern[FILENAME_MAX]; WIN32_FIND_DATA find_data; HANDLE dp; #endif realpath2 (argv[rom_index], buf); if (stat (buf, &fstate) != -1) { if (S_ISREG (fstate.st_mode)) result = ucon64_process_rom (buf); else if (S_ISDIR (fstate.st_mode)) // a dir? { char *p; #if defined __MSDOS__ || defined _WIN32 || defined __CYGWIN__ /* Note that this code doesn't make much sense for Cygwin, because at least the version I use (1.3.6, dbjh) doesn't support current directories for drives. */ c = toupper (buf[0]); if (buf[strlen (buf) - 1] == FILE_SEPARATOR || (c >= 'A' && c <= 'Z' && buf[1] == ':' && buf[2] == 0)) #else if (buf[strlen (buf) - 1] == FILE_SEPARATOR) #endif p = ""; else p = FILE_SEPARATOR_S; #ifndef _WIN32 if ((dp = opendir (buf))) { while ((ep = readdir (dp))) { sprintf (buf2, "%s%s%s", buf, p, ep->d_name); if (stat (buf2, &fstate) != -1) if (S_ISREG (fstate.st_mode)) { result = ucon64_process_rom (buf2); if (result == 1) break; } } closedir (dp); } #else sprintf (search_pattern, "%s%s*", buf, p); if ((dp = FindFirstFile (search_pattern, &find_data)) != INVALID_HANDLE_VALUE) { do { sprintf (buf2, "%s%s%s", buf, p, find_data.cFileName); if (stat (buf2, &fstate) != -1) if (S_ISREG (fstate.st_mode)) { result = ucon64_process_rom (buf2); if (result == 1) break; } } while (FindNextFile (dp, &find_data)); FindClose (dp); } #endif } else result = ucon64_process_rom (buf); } else result = ucon64_process_rom (buf); if (result == 1) break; } return 0; }
int main (int argc, char **argv) { // int i = 0; // char buf[MAXBUFSIZE]; int c = 0, option_index = 0; int x = 0, y = 0; struct option long_only_options[ARGS_MAX]; int result = 0; // const char *p = NULL; const st_property_t props[] = { { "ansi_color", "1", "use ANSI colors in output? (1=yes; 0=no)" }, { "default_cmdline", "", "will be used when quh is started w/o args" }, { "settings", "100", "internal settings like volume, etc." }, #if 0 { "quh_configdir", PROPERTY_MODE_DIR ("quh"), "directory with additional config files" }, #endif {NULL, NULL, NULL} }; memset (&quh, 0, sizeof (st_quh_t)); // defaults quh.pid = 1; tmpnam3 (quh.tmp_file, 0); set_suffix (quh.tmp_file, ".wav"); if(!(quh.o = cache_open (MAXBUFSIZE, CACHE_MEM|CACHE_LIFO))) { fprintf (stderr, "ERROR: Could not malloc %d bytes\n", MAXBUFSIZE); return -1; } realpath2 (PROPERTY_HOME_RC ("quh"), quh.configfile); result = property_check (quh.configfile, QUH_CONFIG_VERSION, 1); if (result == 1) // update needed result = set_property_array (quh.configfile, props); if (result == -1) // property_check() or update failed return -1; signal (SIGINT, quh_signal_handler); signal (SIGTERM, quh_signal_handler); atexit (quh_exit); quh.ansi_color = get_property_int (quh.configfile, "ansi_color"); quh.settings = get_property_int (quh.configfile, "settings"); quh.argc = argc; quh.argv = argv; #if 0 // memorize cmdline if (quh.argc > 2) { for (; quh.argv[i] && i < quh.argc; i++) sprintf (strchr (buf, 0), "%s ", quh.argv[i]); set_property (quh.configfile, "default_cmdline", buf, "will be used when quh is started w/o args"); } else { p = get_property (quh.configfile, "default_cmdline", PROPERTY_MODE_TEXT); if (p) { strncpy (buf, p, MAXBUFSIZE)[MAXBUFSIZE - 1] = 0; quh.argc = strarg (quh.argv, buf, " ", QUH_MAX_ARGS); } } #endif // set default filter chain filters = 0; quh.filter_id[filters++] = QUH_CACHE_PASS; quh.filter_id[filters++] = QUH_CONSOLE_PASS; #ifdef USE_ID3 // quh.filter_id[filters++] = QUH_ID3_IN; #endif // quh.filter_id[filters++] = QUH_CDDB_IN; #ifdef USE_OSS quh.filter_id[filters++] = QUH_OSS_OUT; #elif defined USE_SDL quh.filter_id[filters++] = QUH_SDL_OUT; #endif // convert (st_getopt2_t **) to (st_getopt2_t *) memset (&options, 0, sizeof (st_getopt2_t) * QUH_MAX_ARGS); for (c = x = 0; option[x]; x++) for (y = 0; option[x][y].name || option[x][y].help; y++) if (c < QUH_MAX_ARGS) { memcpy (&options[c], &option[x][y], sizeof (st_getopt2_t)); c++; } #if 0 for (x = 0; quh_decode_usage[x]; x++) if (c < QUH_MAX_ARGS) { memcpy (&options[c], quh_decode_usage[x], sizeof (st_getopt2_t)); c++; } #endif for (x = 0; quh_filter_usage[x]; x++) if (c < QUH_MAX_ARGS) { memcpy (&options[c], quh_filter_usage[x], sizeof (st_getopt2_t)); c++; } for (x = 0; option2[x]; x++) for (y = 0; option2[x][y].name || option2[x][y].help; y++) if (c < QUH_MAX_ARGS) { memcpy (&options[c], &option2[x][y], sizeof (st_getopt2_t)); c++; } getopt2_long_only (long_only_options, options, ARGS_MAX); #if 0 // if no options or filenames were specified we use a default cmdline if (argc < 2) // || !optind) { p = get_property (quh.configfile, "default_cmdline", PROPERTY_MODE_TEXT); if (p) { strncpy (quh.cmdline, p, ARGS_MAX)[ARGS_MAX - 1] = 0; quh.argc = strarg (quh.argv, quh.cmdline, " ", QUH_MAX_ARGS); } } else // store cmdline { strcpy (quh.cmdline, argv[0]); for (x = 1; x < argc; x++) sprintf (strchr (quh.cmdline, 0), " \"%s\"", quh.argv[x]); set_property (quh.configfile, "default_cmdline", quh.cmdline, NULL); } for (x = 0; x < quh.argc; x++) printf ("quh.argv[%d] == %s\n", x, quh.argv[x]); fflush (stdout); #endif while ((c = getopt_long_only (quh.argc, quh.argv, "", long_only_options, &option_index)) != -1) quh_opts (c); // if (quh.verbose) if (!quh.quiet) fputs ("Quh " QUH_VERSION_S " 'Having ears makes sense again' 2005-2006 by NoisyB\n" "This may be freely redistributed under the terms of the GNU Public License\n\n", stdout); if (quh.argc < 2) // || !optind) { getopt2_usage (options); return -1; } #warning files? #if 0 if (!getfile (quh.argc, quh.argv, quh_set_fname, (GETFILE_FILES_ONLY | (quh.flags & QUH_RECURSIVE ? GETFILE_RECURSIVE : 0)))) // recursively? { if (!quh.quiet) getopt2_usage (options); return -1; } #endif if (!quh.filter_id[0]) { fputs ("ERROR: you haven't specified any filters\n", stderr); fflush (stderr); return -1; } if (!quh.files) { fputs ("ERROR: you haven't specified any files to play\n", stderr); fflush (stderr); return -1; } if (!(quh.filter_chain = filter_malloc_chain (quh_filter))) { fputs ("ERROR: filter_malloc_chain() failed\n", stderr); fflush (stderr); return -1; } if (filter_init (quh.filter_chain, NULL, NULL) == -1) { fputs ("ERROR: filter_init() failed\n", stderr); fflush (stderr); return -1; } quh_play (); return 0; }