std::string search_executable(tstring const& filename, tstring const& path) { const bool filename_has_extension = has_extension(filename); const bool filename_is_absolute_path = is_absolute(filename); const std::vector<std::string> extensions = get_executable_extensions(); if( ! filename_is_absolute_path ) { const std::vector<std::string> dirs = split(path, PATH_SEPARATOR); for(std::vector<std::string>::const_iterator ipath = dirs.begin(); ipath != dirs.end(); ++ipath ) { const std::string path1 = tinfra::path::join(*ipath, filename); if( filename_has_extension ) { if( is_executable(path1 ,extensions) ) return path1; continue; } std::string maybe_with_ext = find_variant(path1, extensions); if( ! maybe_with_ext.empty() ) return maybe_with_ext; } } else if( ! filename_has_extension ) { return find_variant(filename.str(), extensions); } else { if( is_executable(filename, extensions) ) { return filename.str(); } } return ""; }
std::string which(const char *name) { #ifdef _WIN32 // TODO not yet implemented // static_assert(false, "subprocess::which is not yet implemented for WIN32"); return std::string(name); #else std::vector<char> path; util::copy_string(getenv("PATH"), path); if (is_executable(name)) { return name; } for (char *dir = strtok(path.data(), ":"); dir; dir = strtok(NULL, ":")) { std::string filename; filename.append(dir); filename.push_back('/'); filename.append(name); if (is_executable(filename.c_str())) { return filename; } } return ""; #endif }
/* * Search $PATH for a command. This emulates the path search that * execvp would perform, without actually executing the command so it * can be used before fork() to prepare to run a command using * execve() or after execvp() to diagnose why it failed. * * The caller should ensure that file contains no directory * separators. * * Returns the path to the command, as found in $PATH or NULL if the * command could not be found. The caller inherits ownership of the memory * used to store the resultant path. * * This should not be used on Windows, where the $PATH search rules * are more complicated (e.g., a search for "foo" should find * "foo.exe"). */ static char *locate_in_PATH(const char *file) { const char *p = getenv("PATH"); struct strbuf buf = STRBUF_INIT; if (!p || !*p) return NULL; while (1) { const char *end = strchrnul(p, ':'); strbuf_reset(&buf); /* POSIX specifies an empty entry as the current directory. */ if (end != p) { strbuf_add(&buf, p, end - p); strbuf_addch(&buf, '/'); } strbuf_addstr(&buf, file); if (is_executable(buf.buf)) return strbuf_detach(&buf, NULL); if (!*end) break; p = end + 1; } strbuf_release(&buf); return NULL; }
/* return phase path */ char * get_phase_dir (phases_t index) { #if defined(__linux__) || defined(__APPLE__) char *name = phase_info[index].name; if (external_gcc != TRUE) { /* Construct the path to the internal gcc binaries. */ if (strcmp(name, "gcc") == 0 || strcmp(name, "g++") == 0) { char *root_dir = directory_path(get_executable_dir()); char *bin_dir = concat_path(root_dir, INTERNAL_GCC_BIN); char *gcc_path = concat_path(bin_dir, name); if (is_executable(gcc_path)) { free(gcc_path); return bin_dir; } free(gcc_path); free(bin_dir); } } if (phase_info[index].find_dir_by_path) { char cmd[PATH_BUF_LEN]; char result[PATH_BUF_LEN]; sprintf(cmd, "dirname \"`which %s`\"", phase_info[index].name); if(read_cmd_out(cmd, result) == NULL) return phase_info[index].dir; return string_copy(result); } #endif return phase_info[index].dir; }
// TODO: move it to posix_common.sh std::string search_executable(tstring const& filename, tstring const& path) { if( is_absolute(filename) ) if( is_executable(filename) ) return filename.str(); std::vector<std::string> dirs = split(path, PATH_SEPARATOR); for(std::vector<std::string>::const_iterator ipath = dirs.begin(); ipath != dirs.end(); ++ipath ) { std::string result_name = tinfra::path::join(*ipath, filename); if( is_executable(result_name) ) { return result_name; } } return ""; }
void scan_directory(const char *dir) { DIR *pd; struct dirent *pe; char canonical_path[PATH_MAX+1] = { 0 }; char *end; struct stat sb; if (!(pd = opendir(dir))) { perror_str("[!] Unable to open dir \"%s\"", dir); return; } while ((pe = readdir(pd))) { if (pe->d_name[0] == '.') { if (pe->d_name[1] == '\0') continue; if (pe->d_name[1] == '.' && pe->d_name[2] == '\0') continue; } end = my_stpcpy(canonical_path, dir); if (end - canonical_path >= PATH_MAX - 1 - strlen(pe->d_name)) { fprintf(stderr, "[!] name too long \"%s/%s\"\n", dir, pe->d_name); continue; } if (end > canonical_path && *(end - 1) != '/') *end++ = '/'; strcpy(end, pe->d_name); #ifdef DEBUG printf("[*] checking: 0x%x 0x%x 0x%x 0x%x %s ...\n", (unsigned int)pe->d_ino, (unsigned int)pe->d_off, pe->d_reclen, pe->d_type, canonical_path); #endif /* decide where to put this one */ if (lstat(canonical_path, &sb) == -1) { perror_str("[!] Unable to lstat \"%s\"", canonical_path); continue; } /* skip symlinks.. */ if (S_ISLNK(sb.st_mode)) continue; record_access_level(canonical_path, &sb); /* can the child directory too */ if (S_ISDIR(sb.st_mode) && is_executable(&sb)) scan_directory(canonical_path); } closedir(pd); }
int os_can_exe(const char_u *name) { // If it's an absolute or relative path don't need to use $PATH. if (os_is_absolute_path(name) || (name[0] == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { return is_executable(name); } return is_executable_in_path(name); }
static int check_extensions(char *pathname) { int n; char *p; static char *exts[] = {".com", ".exe", ".bat"}; /* fix path */ for (p = pathname; *p; p++) { if (*p == '/') *p = '\\'; } if (is_executable(pathname)) return (1); for (n = 0; n < 3; n++) { strcpy(p, exts[n]); if (is_executable(pathname)) return (1); } *p = 0; return (0); }
char* parse_rules(char *filename) { FILE *fp; struct stat sb; char *fb; char line[BUFFERSIZE]; /* Open the rules file for reading */ fp = fopen (filename, "r"); if (fp == NULL) { fprintf (stderr, "Could not open rules file!\n"); goto file_error; } /* Use stat to get the size of the file */ if (stat(filename, &sb) != 0) goto malloc_error; /* Allocate a buffer of that size */ fb = calloc(sb.st_size, 1); if (fb == NULL) goto malloc_error; /* Read it line-by-line */ while (fgets(line, BUFFERSIZE, fp) != NULL) { int port; char program[BUFFERSIZE]; /* Scan each line for the correct format */ if (sscanf(line, "%i %512s\n", &port, program) != 2){ printf("ERROR: Ill-formed file\n"); goto error; } if(!is_executable(program)) { printf("ERROR: Cannot execute file\n"); goto error; } /* We don't need strncat because line must be shorter than fb */ /* fb is the whole size of the file */ strcat(fb, line); } fclose(fp); return fb; error: free(fb); malloc_error: fclose(fp); file_error: return NULL; }
/* * Return TRUE if "name" can be found in $PATH and executed, FALSE if not or an * error occurs. */ static int is_executable_in_path(const char_u *name) { const char *path = getenv("PATH"); /* PATH environment variable does not exist or is empty. */ if (path == NULL || *path == NUL) { return FALSE; } int buf_len = STRLEN(name) + STRLEN(path) + 2; char_u *buf = alloc((unsigned)(buf_len)); if (buf == NULL) { return FALSE; } /* * Walk through all entries in $PATH to check if "name" exists there and * is an executable file. */ for (;; ) { const char *e = strchr(path, ':'); if (e == NULL) { e = path + STRLEN(path); } /* Glue together the given directory from $PATH with name and save into * buf. */ vim_strncpy(buf, (char_u *) path, e - path); append_path((char *) buf, (const char *) name, buf_len); if (is_executable(buf)) { /* Found our executable. Free buf and return. */ vim_free(buf); return OK; } if (*e != ':') { /* End of $PATH without finding any executable called name. */ vim_free(buf); return FALSE; } path = e + 1; } /* We should never get to this point. */ assert(false); return FALSE; }
/// Checks if a file is inside the `$PATH` and is executable. /// /// @param[in] name The name of the executable. /// @param[out] abspath Path of the executable, if found and not `NULL`. /// /// @return `true` if `name` is an executable inside `$PATH`. static bool is_executable_in_path(const char_u *name, char_u **abspath) { const char *path = getenv("PATH"); // PATH environment variable does not exist or is empty. if (path == NULL || *path == NUL) { return false; } size_t buf_len = STRLEN(name) + STRLEN(path) + 2; char_u *buf = xmalloc(buf_len); // Walk through all entries in $PATH to check if "name" exists there and // is an executable file. for (;; ) { const char *e = strchr(path, ':'); if (e == NULL) { e = path + STRLEN(path); } // Glue together the given directory from $PATH with name and save into // buf. STRLCPY(buf, path, e - path + 1); append_path((char *) buf, (const char *) name, (int)buf_len); if (is_executable(buf)) { // Check if the caller asked for a copy of the path. if (abspath != NULL) { *abspath = save_absolute_path(buf); } free(buf); return true; } if (*e != ':') { // End of $PATH without finding any executable called name. free(buf); return false; } path = e + 1; } // We should never get to this point. assert(false); return false; }
bool is_executable(tstring const& name) { #ifdef _WIN32 // check PATHEXT or ".exe .com .bat .cmd" std::vector<std::string> extensions = get_executable_extensions(); return is_executable(name, extensions); #else string_pool temporary_context; struct stat st; if( ::stat(name.c_str(temporary_context), &st) != 0 ) return false; const bool regular_file = (st.st_mode & S_IFREG) == S_IFREG; const bool executable = (st.st_mode & 0111) != 0; return regular_file && executable; #endif }
/* * filter the permissions we have on the entry into buckets */ void record_access_level(const char *path, struct stat *sb) { if (is_setuid(sb)) record_access(&g_suid, path, sb); else if (is_setgid(sb)) record_access(&g_sgid, path, sb); else if (is_writable(sb)) record_access(&g_writable, path, sb); #ifdef RECORD_LESS_INTERESTING else if (is_readable(sb)) record_access(&g_readable, path, sb); else if (is_executable(sb)) record_access(&g_executable, path, sb); #endif }
/// Checks if the given path represents an executable file. /// /// @param[in] name The name of the executable. /// @param[out] abspath Path of the executable, if found and not `NULL`. /// /// @return `true` if `name` is executable and /// - can be found in $PATH, /// - is relative to current dir or /// - is absolute. /// /// @return `false` otherwise. bool os_can_exe(const char_u *name, char_u **abspath) { // If it's an absolute or relative path don't need to use $PATH. if (path_is_absolute_path(name) || (name[0] == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { if (is_executable(name)) { if (abspath != NULL) { *abspath = save_absolute_path(name); } return true; } return false; } return is_executable_in_path(name, abspath); }
static void handle_file(FileView *view, FileHandleExec exec, FileHandleLink follow) { char full_path[PATH_MAX]; int executable; int runnable; const dir_entry_t *const curr = &view->dir_entry[view->list_pos]; get_full_path_of(curr, sizeof(full_path), full_path); if(is_dir(full_path) || is_unc_root(view->curr_dir)) { if(!curr->selected && (curr->type != FT_LINK || follow == FHL_NO_FOLLOW)) { open_dir(view); return; } } runnable = is_runnable(view, full_path, curr->type, follow == FHL_FOLLOW); executable = is_executable(full_path, curr, exec == FHE_NO_RUN, runnable); if(stats_file_choose_action_set() && (executable || runnable)) { /* The call below does not return. */ vifm_choose_files(view, 0, NULL); } if(executable && !is_dir_entry(full_path, curr->type)) { execute_file(full_path, exec == FHE_ELEVATE_AND_RUN); } else if(runnable) { run_selection(view, exec == FHE_NO_RUN); } else if(curr->type == FT_LINK) { follow_link(view, follow == FHL_FOLLOW); } }
/* Opens specified file. Returns its file descriptor. Same file opened multiple times returns different file descriptors. A process has an independent set of file descriptors (files open in that process). fd = 0 is STDIN_FILENO, fd = 1 is STDOUT_FILENO - These are never returned here. If file could not be opened, -1 is returned. */ static int sys_open(const char *file) { check_mem_ptr(file); if (file == NULL) sys_exit(ERROR); lock_acquire(&secure_file); struct file *fl = filesys_open(file); if (fl == NULL) { lock_release(&secure_file); return FD_ERROR; } struct thread *t = thread_current(); /* Freed in sys_close(). */ struct proc_file *f = malloc(sizeof(struct proc_file)); if (f == NULL) sys_exit(FD_ERROR); list_push_front(&t->files, &f->file_elem); f->file = fl; /* If file is currently being run as an executable in this process, we must not be able to write to it. */ if (is_executable(file)) file_deny_write(f->file); int file_descriptor = t->next_file_descriptor; f->fd = file_descriptor; /* Increment next_file_descriptor so that the next file to be opened has a different file descriptor. */ t->next_file_descriptor++; lock_release(&secure_file); return file_descriptor; }
bool run() { flower("run"); //process profile profile; string message; if(is_executable()) { //executable _make.run(); //command message=_make.run_command().literal(); } else if(is_ast()) { //ast shell("tail",_make.output_path()); } else stop(); //report string buffer; buffer.space(profile.string_()); buffer.space(execute("du","-h",_make.output_path()).inline_().literal()); buffer.space(message); flower(buffer,"*"); return true; }
static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) { int prefix_len; DIR *dir = opendir(path); struct dirent *de; struct strbuf buf = STRBUF_INIT; int len; if (!dir) return; if (!prefix) prefix = "git-"; prefix_len = strlen(prefix); strbuf_addf(&buf, "%s/", path); len = buf.len; while ((de = readdir(dir)) != NULL) { int entlen; if (prefixcmp(de->d_name, prefix)) continue; strbuf_setlen(&buf, len); strbuf_addstr(&buf, de->d_name); if (!is_executable(buf.buf)) continue; entlen = strlen(de->d_name) - prefix_len; if (has_extension(de->d_name, ".exe")) entlen -= 4; add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); strbuf_release(&buf); }
// Get program path from PATH variable. static char * get_executable_dir_from_path(char *name) { if (name[0] != '/') { char *path = getenv("PATH"); if (path != NULL) { char *p = string_copy(path); char *tmp; char *dir; while ((dir = strtok_r(p, ":", &tmp)) != NULL) { if (is_directory(dir)) { char filename[MAXPATHLEN]; snprintf(filename, MAXPATHLEN, "%s/%s", dir, name); if (is_executable(filename)) { return string_copy(filename); } } p = NULL; } } } return name; }
static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) { DIR *dir = opendir(path); struct dirent *de; struct strbuf buf = STRBUF_INIT; int len; if (!dir) return; if (!prefix) prefix = "git-"; strbuf_addf(&buf, "%s/", path); len = buf.len; while ((de = readdir(dir)) != NULL) { const char *ent; size_t entlen; if (!skip_prefix(de->d_name, prefix, &ent)) continue; strbuf_setlen(&buf, len); strbuf_addstr(&buf, de->d_name); if (!is_executable(buf.buf)) continue; entlen = strlen(ent); strip_suffix(ent, ".exe", &entlen); add_cmdname(cmds, ent, entlen); } closedir(dir); strbuf_release(&buf); }
static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) { int prefix_len; DIR *dir = opendir(path); struct dirent *de; char *buf = NULL; if (!dir) return; if (!prefix) prefix = "perf-"; prefix_len = strlen(prefix); astrcatf(&buf, "%s/", path); while ((de = readdir(dir)) != NULL) { int entlen; if (!strstarts(de->d_name, prefix)) continue; astrcat(&buf, de->d_name); if (!is_executable(buf)) continue; entlen = strlen(de->d_name) - prefix_len; if (has_extension(de->d_name, ".exe")) entlen -= 4; add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); free(buf); }
int is_setgid(struct stat *sb) { return (is_executable(sb) && (sb->st_mode & S_ISGID)); }
/** * Main program. Returns 1 if all programs run successfully, 0 if * something failed and -1 if there was an error running programs. */ int main(int argc, char *argv[]) { int retcode; struct sigaction zig; pid_t pid; char *c; /* Check parameters */ if (argc < 2) { fprintf(stderr, "Usage: %s test_prog\n", argv[0]); return 1; } if (argc > 2 && strcmp(argv[2], "--leader") == 0) { pounder_fprintf(stdout, "Logging this test output to %s/POUNDERLOG.\n", getenv("POUNDER_LOGDIR")); is_leader = 1; record_pid(); } progname = argv[0]; /* Set up signals */ memset(&zig, 0x00, sizeof(zig)); zig.sa_handler = jump_out; sigaction(SIGHUP, &zig, NULL); sigaction(SIGINT, &zig, NULL); sigaction(SIGTERM, &zig, NULL); if (is_directory(argv[1])) { retcode = process_dir(argv[1]); } else { if (is_executable(argv[1])) { c = rindex(argv[1], '/'); c++; // Start the test pid = spawn_test(argv[1]); if (pid < 0) { perror("fork"); retcode = -1; goto out; } // Track the test note_process(pid, argv[1]); if (wait_for_pids() == 0) { retcode = 1; } else { retcode = 0; } } else { pounder_fprintf(stderr, "%s: Not a directory or a test.\n", argv[1]); retcode = -1; } } out: kill_daemons(); wait_for_daemons(); if (is_leader) { if (retcode == 0) { pounder_fprintf(stdout, "%s: %s.\n", argv[1], pass_msg); } else if (retcode < 0 || retcode == 255) { pounder_fprintf(stdout, "%s: %s with code %d.\n", argv[1], abort_msg, retcode); } else { pounder_fprintf(stdout, "%s: %s with code %d.\n", argv[1], fail_msg, retcode); } unlink(pidfile); } exit(retcode); }
static char * locate_next_exec(const char *path, const char *first_dir, const char *name, const char* ignore_prefix) { struct buffer buf[1]; size_t first_dir_len, ignore_prefix_len; const char *dir_start; bool more, found; enum { BEFORE_FIRST_DIR, SEARCH_SECOND_DIR } state; first_dir_len = strlen(first_dir); if (ignore_prefix != NULL) { ignore_prefix_len = strlen(ignore_prefix); } else { ignore_prefix_len = 0; } buffer_init(buf); dir_start = path; more = true; found = false; state = BEFORE_FIRST_DIR; for (;;) { const char *dir_end = strchr(dir_start, ':'); size_t dir_len; if (dir_end == NULL) { more = false; dir_end = strchr(path, '\0'); } dir_len = dir_end - dir_start; if (dir_start[0] != '/' && !(dir_len == 1 && *dir_start == '.')) { build_location(dir_start, dir_len, NULL, buf); warning("PATH component is not absolute path: %s", buf->ptr); } else if (state == BEFORE_FIRST_DIR) { bool found = false; if (first_dir_len == dir_len) { if (0 == memcmp(dir_start, first_dir, first_dir_len)) { found = true; } } if (found) { build_location(dir_start, dir_len, name, buf); if (!is_executable(buf->ptr)) { fatal_error("Failed to locate executable regular file '%s' in %s", name, first_dir); } state = SEARCH_SECOND_DIR; } } else if (state == SEARCH_SECOND_DIR) { bool skip = false; if (ignore_prefix != NULL && dir_len >= ignore_prefix_len) { if (0 == memcmp(dir_start, ignore_prefix, ignore_prefix_len)) { skip = (dir_len == ignore_prefix_len) || (dir_start[ignore_prefix_len] == '/'); } } if (!skip) { build_location(dir_start, dir_len, name, buf); if (is_executable(buf->ptr)) { found = true; break; } } } else { assert(false); } if (more) { dir_start = dir_end + 1; continue; } break; } if (!found) { fatal_error("Failed to locate real executable '%s' in %s", name, path); } return buffer_forget(buf, strlen(buf->ptr) + 1); }
/** * External interface to ifs_createfile */ int onefs_sys_create_file(connection_struct *conn, int base_fd, const char *path, uint32_t access_mask, uint32_t open_access_mask, uint32_t share_access, uint32_t create_options, int flags, mode_t mode, int oplock_request, uint64_t id, struct security_descriptor *sd, uint32_t dos_flags, int *granted_oplock) { struct sm_lock sml, *psml = NULL; enum oplock_type onefs_oplock; enum oplock_type onefs_granted_oplock = OPLOCK_NONE; struct ifs_security_descriptor ifs_sd = {}, *pifs_sd = NULL; uint32_t sec_info_effective = 0; int ret_fd = -1; uint32_t onefs_dos_attributes; struct ifs_createfile_flags cf_flags = CF_FLAGS_NONE; START_PROFILE(syscall_createfile); /* Setup security descriptor and get secinfo. */ if (sd != NULL) { NTSTATUS status; uint32_t sec_info_sent = 0; sec_info_sent = (get_sec_info(sd) & IFS_SEC_INFO_KNOWN_MASK); status = onefs_samba_sd_to_sd(sec_info_sent, sd, &ifs_sd, SNUM(conn), &sec_info_effective); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("SD initialization failure: %s\n", nt_errstr(status))); errno = EINVAL; goto out; } pifs_sd = &ifs_sd; } /* Stripping off private bits will be done for us. */ onefs_oplock = onefs_samba_oplock_to_oplock(oplock_request); if (!lp_oplocks(SNUM(conn))) { SMB_ASSERT(onefs_oplock == OPLOCK_NONE); } /* Convert samba dos flags to UF_DOS_* attributes. */ onefs_dos_attributes = dos_attributes_to_stat_dos_flags(dos_flags); /** * Deal with kernel creating Default ACLs. (Isilon bug 47447.) * * 1) "nt acl support = no", default_acl = no * 2) "inherit permissions = yes", default_acl = no */ if (lp_nt_acl_support(SNUM(conn)) && !lp_inherit_perms(SNUM(conn))) cf_flags = cf_flags_or(cf_flags, CF_FLAGS_DEFAULT_ACL); /* * Some customer workflows require the execute bit to be ignored. */ if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE, PARM_ALLOW_EXECUTE_ALWAYS, PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT) && (open_access_mask & FILE_EXECUTE)) { DEBUG(3, ("Stripping execute bit from %s: (0x%x)\n", path, open_access_mask)); /* Strip execute. */ open_access_mask &= ~FILE_EXECUTE; /* * Add READ_DATA, so we're not left with desired_access=0. An * execute call should imply the client will read the data. */ open_access_mask |= FILE_READ_DATA; DEBUGADD(3, ("New stripped access mask: 0x%x\n", open_access_mask)); } DEBUG(10,("onefs_sys_create_file: base_fd = %d, fname = %s" "open_access_mask = 0x%x, flags = 0x%x, mode = 0%o, " "desired_oplock = %s, id = 0x%x, secinfo = 0x%x, sd = %p, " "dos_attributes = 0x%x, path = %s, " "default_acl=%s\n", base_fd, path, (unsigned int)open_access_mask, (unsigned int)flags, (unsigned int)mode, onefs_oplock_str(onefs_oplock), (unsigned int)id, sec_info_effective, sd, (unsigned int)onefs_dos_attributes, path, cf_flags_and_bool(cf_flags, CF_FLAGS_DEFAULT_ACL) ? "true" : "false")); /* Initialize smlock struct for files/dirs but not internal opens */ if (!(oplock_request & INTERNAL_OPEN_ONLY)) { smlock_init(conn, &sml, is_executable(path), access_mask, share_access, create_options); psml = &sml; } smlock_dump(10, psml); ret_fd = ifs_createfile(base_fd, path, (enum ifs_ace_rights)open_access_mask, flags & ~O_ACCMODE, mode, onefs_oplock, id, psml, sec_info_effective, pifs_sd, onefs_dos_attributes, cf_flags, &onefs_granted_oplock); DEBUG(10,("onefs_sys_create_file(%s): ret_fd = %d, " "onefs_granted_oplock = %s\n", ret_fd < 0 ? strerror(errno) : "success", ret_fd, onefs_oplock_str(onefs_granted_oplock))); if (granted_oplock) { *granted_oplock = onefs_oplock_to_samba_oplock(onefs_granted_oplock); } out: END_PROFILE(syscall_createfile); aclu_free_sd(pifs_sd, false); return ret_fd; }
static void parachute_start(const char *myname, const char *panic_script) { time_t last_start = 0, last_panic = 0; long respawn_count = 0; int status; if (panic_script && !is_executable(panic_script)) panic(0, "Panic script `%s' is not executable for us.", panic_script); /* setup sighandler */ parachute_init_signals(0); for (;;) { if (respawn_count > 0 && difftime(time(NULL), last_start) < 10) { error(0, "Child process died too fast, disabling for 30 sec."); gwthread_sleep(30.0); } if (!(child_pid = fork())) { /* child process */ parachute_init_signals(1); /* reset sighandlers */ return; } else if (child_pid < 0) { error(errno, "Could not start child process! Will retry in 5 sec."); gwthread_sleep(5.0); continue; } else { /* father process */ time(&last_start); info(0, "Child process with PID (%ld) started.", (long) child_pid); do { if (waitpid(child_pid, &status, 0) == child_pid) { /* check here why child terminated */ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { info(0, "Child process exited gracefully, exit..."); gwlib_shutdown(); exit(0); } else if (WIFEXITED(status)) { error(0, "Caught child PID (%ld) which died with return code %d", (long) child_pid, WEXITSTATUS(status)); child_pid = -1; } else if (WIFSIGNALED(status)) { error(0, "Caught child PID (%ld) which died due to signal %d", (long) child_pid, WTERMSIG(status)); child_pid = -1; } } else if (errno != EINTR) { error(errno, "Error while waiting of child process."); } } while(child_pid > 0); if (parachute_shutdown) { /* may only happens if child process crashed while shutdown */ info(0, "Child process crashed while shutdown. Exiting due to signal..."); info(0, "Going into gwlib_shutdown..."); gwlib_shutdown(); info(0, "gwlib_shutdown done... Bye bye..."); exit(WIFEXITED(status) ? WEXITSTATUS(status) : 0); } /* check whether it's panic while start */ if (respawn_count == 0 && difftime(time(NULL), last_start) < 2) { info(0, "Child process crashed while starting. Exiting..."); info(0, "Going into gwlib_shutdown..."); gwlib_shutdown(); info(0, "gwlib_shutdown done... Bye bye..."); exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1); } respawn_count++; if (panic_script && myname && difftime(time(NULL), last_panic) > 300) { time(&last_panic); debug("kannel", 0, "Executing panic script: %s %s %ld", panic_script, myname, respawn_count); execute_panic_script(panic_script, "%s %ld", myname, respawn_count); } /* sleep a while to get e.g. sockets released */ gwthread_sleep(5.0); } } }
/* ---- program entry --------------------------- */ int main( int argc, cstr argv[] ) { double start = now(); // options: uint verbose = 1; // 0=off, 1=default, 2=verbose uint outputstyle = 'b'; // 0=none, 'b'=binary, 'x'=intel hex, 's'=motorola s-records uint liststyle = 1; // 0=none, 1=plain, 2=with objcode, 4=with label listing, 6=both, 8=clock cycles bool clean = no; bool ixcbr2 = no; bool ixcbxh = no; bool targetZ80 = no; bool target8080 = no; bool targetZ180 = no; bool asm8080 = no; bool dotnames = no; bool reqcolon = no; bool casefold = no; bool flatops = no; bool compare = no; bool selftest = no; bool cgi_mode = no; uint maxerrors = 30; // filepaths: cstr inputfile = NULL; cstr outputfile = NULL; // or dir cstr listfile = NULL; // or dir cstr tempdir = NULL; cstr c_compiler = NULL; cstr c_includes = NULL; cstr libraries = NULL; // eval arguments: for(int i=1; i<argc; ) { cptr s = argv[i++]; if(s[0] != '-') { if(!inputfile) { inputfile = s; continue; } // if outfile is not prefixed with -o then it must be the last argument: if(!outputfile && i==argc) { outputfile = s; continue; } if(!listfile) { listfile = s; continue; } goto h; } if(s[1]=='-') { if(eq(s,"--clean")) { clean = yes; continue; } if(eq(s,"--bin")) { outputstyle='b'; continue; } if(eq(s,"--hex")) { outputstyle='x'; continue; } if(eq(s,"--s19")) { outputstyle='s'; continue; } if(eq(s,"--opcodes")) { liststyle |= 2; continue; } if(eq(s,"--labels")) { liststyle |= 4; continue; } if(eq(s,"--cycles")) { liststyle |= 8; continue; } if(eq(s,"--ixcbr2")) { ixcbr2 = 1; continue; } if(eq(s,"--ixcbxh")) { ixcbxh = 1; continue; } if(eq(s,"--z80")) { targetZ80 = 1; continue; } if(eq(s,"--8080")) { target8080 = 1; continue; } if(eq(s,"--asm8080")) { asm8080 = 1; continue; } if(eq(s,"--z180")) { targetZ180 = 1; continue; } if(eq(s,"--dotnames")) { dotnames = 1; continue; } if(eq(s,"--reqcolon")) { reqcolon = 1; continue; } if(eq(s,"--casefold")) { casefold = 1; continue; } if(eq(s,"--flatops")) { flatops = 1; continue; } if(eq(s,"--compare")) { compare = 1; continue; } if(eq(s,"--test")) { selftest = 1; continue; } if(eq(s,"--cgi")) { cgi_mode = 1; continue; } if(startswith(s,"--maxerrors=")) { char* ep; ulong n = strtoul(s+12,&ep,10); if(*ep||n==0||n>999) goto h; maxerrors = (uint)n; continue; } goto h; } while(char c = *++s) { switch(c) { case 'e': compare = 1; continue; case 'T': selftest = 1; continue; case 'u': liststyle |= 2; continue; case 'w': liststyle |= 4; continue; case 'y': liststyle |= 8; continue; case 's': outputstyle=c; continue; case 'x': outputstyle=c; continue; case 'b': outputstyle=c; continue; case 'z': clean=yes; continue; case 'g': cgi_mode=yes; continue; case 'v': if(*(s+1)>='0' && *(s+1)<='3') verbose = *++s - '0'; else ++verbose; continue; case 'i': if(inputfile || i==argc) goto h; else inputfile = argv[i++]; continue; case 'o': if(*(s+1)=='0') { outputstyle = 0; ++s; continue; } if(outputfile || i==argc) goto h; else outputfile = argv[i++]; continue; case 'l': if(*(s+1)=='0') { liststyle = 0; ++s; continue; } if(listfile || i==argc) goto h; else listfile = argv[i++]; continue; case 'I': if(c_includes || i==argc) goto h; else c_includes = argv[i++]; continue; case 'L': if(libraries|| i==argc) goto h; else libraries= argv[i++]; continue; case 'c': if(c_compiler || i==argc) goto h; else c_compiler = argv[i++]; continue; case 't': if(tempdir || i==argc) goto h; else tempdir = argv[i++]; continue; default: goto h; } } } if(selftest) { // assemble a bunch of sources from the $PROJECT/Test/ directory // and compare them to old versions found in the original/ subdirectories. // if no path to the $PROJECT directory is given, then the current working directory is used. // all expected sources and original output files must be in place and match. cstr zasm = argv[0]; cstr testdir = fullpath( inputfile ? inputfile : outputfile ? outputfile : "./" ); if(errno==ok && lastchar(testdir)!='/') errno = ENOTDIR; if(errno) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", testdir, strerror(errno)); return 1; } // if compiler was given, then it will be checked by the recursively called main() // else: no c compiler given: try to use scdd from $PROJECT/sdcc/bin/ if(!c_compiler) { #ifdef _BSD c_compiler = catstr(testdir,"sdcc/bin/sdcc"); #endif #ifdef _LINUX c_compiler = catstr(testdir,"sdcc/bin-Linux32/sdcc"); #endif if(!is_file(c_compiler) || !is_executable(c_compiler)) c_compiler = NULL; // passing "-c" + NULL should not crash main() } uint errors = 0; char opt[] = "-v0e"; opt[2] += verbose; change_working_dir(catstr(testdir,"Test/ZXSP/")); { cstr a[] = { zasm, opt, "template_o.asm", "original/" }; errors += main(NELEM(a),a); a[2] = "template_p.asm"; errors += main(NELEM(a),a); a[2] = "template_ace.asm"; errors += main(NELEM(a),a); a[2] = "template_tap.asm"; errors += main(NELEM(a),a); a[2] = "template_z80.asm"; errors += main(NELEM(a),a); a[2] = "template_sna.asm"; errors += main(NELEM(a),a); a[2] = "mouse.asm"; errors += main(NELEM(a),a); cstr b[] = { zasm, opt, "-c", c_compiler, "template_rom_with_c_code.asm", "original/" }; errors += main(NELEM(b),b); } change_working_dir(catstr(testdir,"Test/Z80/")); { cstr a[] = { zasm, opt, "ZX Spectrum Rom/zx82.asm", "original/" }; errors += main(NELEM(a),a); cstr c[] = { zasm, opt, "--casefold", "CAMEL80-12/camel80.asm", "original/" }; errors += main(NELEM(c),c); cstr d[] = { zasm, opt, "monitor_32k.asm", "original/" }; errors += main(NELEM(d),d); cstr e[] = { zasm, opt, "allsrc.asm", "original/" }; errors += main(NELEM(e),e); cstr f[] = { zasm, opt, "basic.asm", "original/" }; errors += main(NELEM(f),f); cstr g[] = { zasm, opt, "MS-Basic.asm", "original/" }; errors += main(NELEM(g),g); cstr h[] = { zasm, opt, "--reqcolon", "5bsort018.asm", "original/" }; errors += main(NELEM(h),h); cstr i[] = { zasm, opt, "64#4+016.asm", "original/" }; errors += main(NELEM(i),i); cstr j[] = { zasm, opt, "--8080", "CPM22.asm", "original/" }; errors += main(NELEM(j),j); cstr k[] = { zasm, opt, "EMUF/EMUF.asm", "original/" }; errors += main(NELEM(k),k); cstr l[] = { zasm, opt, "G007_MON_source_recreation.asm", "original/" }; errors += main(NELEM(l),l); cstr n[] = { zasm, opt, "--reqcolon", "Hello World.asm", "original/" }; errors += main(NELEM(n),n); cstr o[] = { zasm, opt, "--8080", "m80b.asm", "original/" }; errors += main(NELEM(o),o); cstr p[] = { zasm, opt, "monitor_32k.asm", "original/" }; errors += main(NELEM(p),p); cstr q[] = { zasm, opt, "MS-Basic.asm", "original/" }; errors += main(NELEM(q),q); cstr r[] = { zasm, opt, "mybios4_mod.asm", "original/" }; errors += main(NELEM(r),r); cstr s[] = { zasm, opt, "--dotnames", "--reqcolon", "OpenSE Basic/opense.asm", "original/" }; errors += main(NELEM(s),s); cstr b[] = { zasm, opt, "ZX Spectrum Rom/sc178.asm", "original/" }; errors += main(NELEM(b),b); cstr m[] = { zasm, opt, "test z80 cpu - prelim.asm", "original/" }; errors += main(NELEM(m),m); cstr t[] = { zasm, opt, "--reqcolon", "VZ200 RS232 Terminal/VZ RS232.asm", "original/" }; errors += main(NELEM(t),t); cstr u[] = { zasm, opt, "wmfw/wmfw2_5_orig.asm", "original/" }; errors += main(NELEM(u),u); cstr v[] = { zasm, opt, "z80mon.asm", "original/" }; errors += main(NELEM(v),v); cstr w[] = { zasm, opt, "z80sourc.asm", "original/" }; errors += main(NELEM(w),w); cstr x[] = { zasm, opt, "--reqcolon", "zx81v2.asm", "original/" }; errors += main(NELEM(x),x); cstr y[] = { zasm, opt, "--ixcbr2", "zasm-test-opcodes.asm", "original/" }; errors += main(NELEM(y),y); } change_working_dir(catstr(testdir,"Test/8080/")); { cstr a[] = { zasm, opt, "--asm8080", "--reqcolon", "Altair8800_Monitor.asm", "original/" }; errors += main(NELEM(a),a); cstr b[] = { zasm, opt, "8080PRE.asm", "original/" }; errors += main(NELEM(b),b); cstr y[] = { zasm, opt, "zasm-test-opcodes.asm", "original/" }; errors += main(NELEM(y),y); } change_working_dir(catstr(testdir,"Test/Z180/")); { cstr a[] = { zasm, opt, "--z180", "first.asm", "original/" }; errors += main(NELEM(a),a); cstr b[] = { zasm, opt, "--z180", "counter master.asm", "original/" }; errors += main(NELEM(b),b); cstr y[] = { zasm, opt, "zasm-test-opcodes.asm", "original/" }; errors += main(NELEM(y),y); } if(verbose) { fprintf(stderr, "\ntotal time: %3.4f sec.\n", now()-start); if(errors>1) fprintf(stderr, "\nzasm: %u errors\n\n", errors); else fprintf(stderr, errors ? "\nzasm: 1 error\n\n" : "zasm: no errors\n"); } return errors>0; } // check options: if(targetZ180) targetZ80 = yes; // implied if(asm8080 && !targetZ80) target8080 = yes; // only implied if not --Z80 set if(!target8080) targetZ80 = yes; // default to Z80 if not --8080 or --asm8080 set if(asm8080 && targetZ180) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "the 8080 assembler does not support Z180 opcodes."); return 1; } if(target8080 && targetZ80) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "--8080 and --z80|--z180 are mutually exclusive."); return 1; } if(ixcbr2 || ixcbxh) { if(target8080) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "i8080 has no index registers and no prefix 0xCB instructions."); return 1; } if(targetZ180) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "no --ixcb… allowed: the Z180 traps illegal instructions"); return 1; } if(asm8080) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "the 8080 assembler does not support illegal opcodes."); return 1; } if(ixcbr2 && ixcbxh) { fprintf(stderr,"--> %s\nzasm: 1 error\n", "--ixcbr2 and --ixcbxh are mutually exclusive."); return 1; } } // check source file: if(!inputfile) { h: fprintf(stderr, help, version, compiledatestr(), _PLATFORM); return 1; } inputfile = fullpath(inputfile,no); if(errno) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", inputfile, strerror(errno)); return 1; } if(!is_file(inputfile)) { if(verbose) fprintf(stderr, "--> %s: not a regular file\nzasm: 1 error\n", inputfile); return 1; } // check output file or dir: if(!outputfile) outputfile = directory_from_path(inputfile); outputfile = fullpath(outputfile); if(errno && errno!=ENOENT) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", outputfile, strerror(errno)); return 1; } // check list file or dir: if(!listfile) listfile = directory_from_path(outputfile); listfile = fullpath(listfile); if(errno && errno!=ENOENT) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", listfile, strerror(errno)); return 1; } // check temp dir: if(!tempdir) tempdir = directory_from_path(outputfile); tempdir = fullpath(tempdir); if(errno && errno!=ENOENT) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", tempdir, strerror(errno)); return 1; } if(lastchar(tempdir)!='/') { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", tempdir, strerror(ENOTDIR)); return 1; } // check c_includes path: if(c_includes) { c_includes = fullpath(c_includes); if(errno==ok && lastchar(c_includes)!='/') errno = ENOTDIR; if(errno) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", c_includes, strerror(errno)); return 1; } } // check c_libraries path: if(libraries) { libraries = fullpath(libraries); if(errno==ok && lastchar(libraries)!='/') errno = ENOTDIR; if(errno) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", libraries, strerror(errno)); return 1; } } // check cc_path: if(c_compiler) { if(c_compiler[0]!='/') { cstr s = quick_fullpath(c_compiler); if(is_file(s)) c_compiler = s; else { Array<str> ss; split(ss, getenv("PATH"), ':'); for(uint i=0; i<ss.count(); i++) { s = catstr(ss[i],"/",c_compiler); if(is_file(s)) { c_compiler = s; break; } } } } c_compiler = fullpath(c_compiler); if(errno) { if(verbose) fprintf(stderr, "--> %s: %s\nzasm: 1 error\n", c_compiler, strerror(errno)); return 1; } if(!is_file(c_compiler)) { if(verbose) fprintf(stderr, "--> %s: not a regular file\nzasm: 1 error\n", c_compiler); return 1; } if(!is_executable(c_compiler)) { if(verbose) fprintf(stderr, "--> %s: not executable\nzasm: 1 error\n", c_compiler); return 1; } } // DO IT! Z80Assembler ass; ass.verbose = verbose; ass.ixcbr2_enabled = ixcbr2; ass.ixcbxh_enabled = ixcbxh; ass.target_8080 = target8080; ass.target_z80 = targetZ80; ass.target_z180 = targetZ180; ass.asm8080 = asm8080; ass.require_colon = reqcolon; ass.allow_dotnames = dotnames; ass.casefold= casefold; ass.flat_operators = flatops; ass.max_errors = maxerrors; ass.compare_to_old = compare; ass.cgi_mode = cgi_mode; if(c_includes) ass.c_includes = c_includes; if(libraries) ass.stdlib_dir = libraries; if(c_compiler) ass.c_compiler = c_compiler; ass.assembleFile( inputfile, outputfile, listfile, tempdir, liststyle, outputstyle, clean ); uint errors = ass.errors.count(); if(verbose) // show errors on stderr: { cstr current_file = NULL; for(uint i=0; i<errors; i++) { Error const& e = ass.errors[i]; SourceLine* sourceline = e.sourceline; if(!sourceline) { if(current_file) fprintf(stderr,"\n"); current_file=NULL; fprintf(stderr,"--> %s\n",e.text); continue; } cstr filename = sourceline->sourcefile; if(filename!=current_file) // note: compare pointers! { current_file = filename; fprintf(stderr, "\nin file %s:\n", filename_from_path(filename)); } cstr linenumber = numstr(sourceline->sourcelinenumber+1); fprintf(stderr, "%s: %s\n", linenumber, sourceline->text); fprintf(stderr, "%s%s^ %s\n", spacestr(strlen(linenumber)+2), sourceline->whitestr(), e.text); } fprintf(stderr, "assemble: %u lines\n", ass.source.count()); fprintf(stderr, "time: %3.4f sec.\n", now()-start); if(errors>1) fprintf(stderr, "\nzasm: %u errors\n\n", errors); else fprintf(stderr, errors ? "\nzasm: 1 error\n\n" : "zasm: no errors\n"); } return errors>0; // 0=ok, 1=errors }
static gboolean is_accessible_directory(mode_t mode) { if(!S_ISDIR(mode)) return FALSE; return is_readable(mode) && is_executable(mode); }
int main(int argc, char *argv[]) { char *fmt1, *fmt2; int rval, c, aflag, vflag; aflag = vflag = 0; fmt1 = fmt2 = NULL; while ((c = getopt(argc, argv, "af:v")) != -1) { switch (c) { case 'a': aflag++; break; case 'f': if (fmt1 != NULL) { if (fmt2 != NULL) errx(1, "too many formats"); fmt2 = optarg; } else fmt1 = optarg; break; case 'v': vflag++; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (vflag && fmt1 != NULL) errx(1, "-v may not be used with -f"); if (argc <= 0) { usage(); /* NOTREACHED */ } #ifdef __i386__ if (vflag) { for (c = 0; c < argc; c++) dump_file(argv[c]); exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } #endif rval = 0; for (; argc > 0; argc--, argv++) { int fd, status, is_shlib, rv, type; if ((fd = open(*argv, O_RDONLY, 0)) < 0) { warn("%s", *argv); rval |= 1; continue; } rv = is_executable(*argv, fd, &is_shlib, &type); close(fd); if (rv == 0) { rval |= 1; continue; } switch (type) { case TYPE_ELF: case TYPE_AOUT: break; #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) case TYPE_ELF32: rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag); continue; #endif case TYPE_UNKNOWN: default: /* * This shouldn't happen unless is_executable() * is broken. */ errx(EDOOFUS, "unknown executable type"); } /* ld.so magic */ LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); if (fmt1 != NULL) LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); if (fmt2 != NULL) LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); if (aflag) LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1); else if (fmt1 == NULL && fmt2 == NULL) /* Default formats */ printf("%s:\n", *argv); fflush(stdout); switch (fork()) { case -1: err(1, "fork"); break; default: if (wait(&status) < 0) { warn("wait"); rval |= 1; } else if (WIFSIGNALED(status)) { fprintf(stderr, "%s: signal %d\n", *argv, WTERMSIG(status)); rval |= 1; } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { fprintf(stderr, "%s: exit status %d\n", *argv, WEXITSTATUS(status)); rval |= 1; } break; case 0: if (is_shlib == 0) { execl(*argv, *argv, (char *)NULL); warn("%s", *argv); } else { dlopen(*argv, RTLD_TRACE); warnx("%s: %s", *argv, dlerror()); } _exit(1); } } return rval; }
char *find_executable(char *exename) { int n; char *p, *s; static char exepath[MAX_FILENAME_LEN + 1]; if (exename == NULL || !*exename) return (NULL); #ifdef _WIN32 /* full path */ if (*exename == '/' || *exename == '\\' || *(exename + 1) == ':') { strcpy(exepath, exename); return (check_extensions(exepath) ? exepath : NULL); } /* get current directory */ if (NULL == _getcwd(exepath, MAX_FILENAME_LEN)) error("find_executable", "couldn't get working directory"); p = exepath + strlen(exepath); if (*(p - 1) == '\\') *--p = 0; /* relative path */ if (0 == strncmp(exename, ".\\", 2) || 0 == strncmp(exename, "..\\", 3) || 0 == strncmp(exename, "./", 2) || 0 == strncmp(exename, "../", 3)) { if (exename[1] != '.') strcpy(p, &exename[1]); else { if (NULL == (p = strrchr(exepath, '\\'))) p = exepath; strcpy(p, &exename[2]); } return (check_extensions(exepath) ? exepath : NULL); } /* current directory */ *p++ = '\\'; strcpy(p, exename); if (check_extensions(exepath)) return (exepath); #else /* full path */ if (*exename == '/') { if (is_executable(exename)) return (strcpy(exepath, exename)); return (NULL); } /* relative path */ if (0 == strncmp(exename, "./", 2) || 0 == strncmp(exename, "../", 3)) { if (NULL == getcwd(exepath, MAX_FILENAME_LEN)) error("find_executable", "couldn't get working directory\n"); p = exepath + strlen(exepath); if (*(p - 1) == '/') *--p = 0; if (exename[1] != '.') strcpy(p, &exename[1]); else { if (NULL == (p = strrchr(exepath, '/'))) p = exepath; strcpy(p, &exename[2]); } return (is_executable(exepath) ? exepath : NULL); } #endif /* scan $PATH environment variable */ if (NULL == (p = getenv("PATH"))) return (NULL); while (*p) { if (NULL == (s = strchr(p, PATH_DELIM))) { strcpy(exepath, p); n = strlen(exepath); } else { n = (int) (s++ - p); strncpy(exepath, p, n); exepath[n] = 0; } if (n) { p = exepath + n; #ifdef _WIN32 if (*(p - 1) != '\\') *p++ = '\\'; strcpy(p, exename); if (check_extensions(exepath)) return (exepath); #else if (*(p - 1) != '/') *p++ = '/'; strcpy(p, exename); if (is_executable(exepath)) return (exepath); #endif } if (NULL == (p = s)) break; } return (NULL); }