# # add_file "tests/t_existsonpath.at" # # patch "ChangeLog" # from [d9a38856d58db1533f87df821bf93af3fa85a631] # to [cf8cf862df378f3fe18bed9aaa87310209f062da] # # patch "tests/t_existsonpath.at" # from [] # to [3bbd717c0872f45e088cd95b692a1fc0c649583f] # # patch "testsuite.at" # from [2e17e62213b9878d08d7c792f244b6e193498618] # to [e4a90072c6563eeaaa85adb066a4e8492447da51] # # patch "unix/process.cc" # from [120cb09130df0f1a2acd085b79ed7edeff5e3b82] # to [cb32d49fc96801972818bd14b8a9badd1d0d3d91] # --- ChangeLog +++ ChangeLog @@ -1,5 +1,14 @@ 2005-06-24 Nathaniel Smith + * unix/process.cc (existsonpath): Reindent. Add logging, and use + 'command -v' instead of 'which' (as per Matt Johnston's discovery + that it is more portable). + (process_spawn): Handle exec failure more properly. + * tests/t_existsonpath.at: New test. + * testsuite.at: Add it. + +2005-06-24 Nathaniel Smith + * unix/process.cc: Remove tabs. 2005-06-24 Nathaniel Smith --- tests/t_existsonpath.at +++ tests/t_existsonpath.at @@ -0,0 +1,22 @@ +AT_SETUP([lua function existsonpath]) +MONOTONE_SETUP + +# Need a way to break into the lua interpreter; our strategy is to +# redefine the use_inodeprints function to run our code, and then +# create a new working copy. + +AT_DATA(test.lua, [function use_inodeprints() + if (existsonpath("ls") == 0) then + io.write("asdfghjkl\n") + end + if (existsonpath("weaohriosfaoisd") ~= 0) then + io.write("qwertyuiop\n") + end + return false +end +]) +AT_CHECK(MONOTONE setup --rcfile=test.lua subdir, [], [stdout], [ignore]) +AT_CHECK(grep -q asdfghjkl stdout, []) +AT_CHECK(grep -q qwertyuiop stdout, []) + +AT_CLEANUP --- testsuite.at +++ testsuite.at @@ -661,3 +661,4 @@ m4_include(tests/t_status.at) m4_include(tests/t_rcfile_dir.at) m4_include(tests/t_lua_includedir.at) +m4_include(tests/t_existsonpath.at) --- unix/process.cc +++ unix/process.cc @@ -16,17 +16,30 @@ int existsonpath(const char *exe) { - const char * const args[3] = {"which", exe, NULL}; - int pid; - int res; - pid = process_spawn(args); - if (pid==-1) - return -1; - if (process_wait(pid, &res)) - return -1; - if (res==0) - return 0; - return -1; + L(F("checking for program '%s'\n") % exe); + // this is horribly ugly, but at least it is rather portable + std::string cmd_str = (F("command -v '%s' >/dev/null 2>&1") % exe).str(); + const char * const args[] = {"sh", "-c", cmd_str.c_str(), NULL}; + int pid; + int res; + pid = process_spawn(args); + if (pid==-1) + { + L(F("error in process_spawn\n")); + return -1; + } + if (process_wait(pid, &res)) + { + L(F("error in process_wait\n")); + return -1; + } + if (res==0) + { + L(F("successful return; %s exists\n") % exe); + return 0; + } + L(F("failure; %s does not exist\n") % exe); + return -1; } bool is_executable(const char *path) @@ -70,7 +83,7 @@ return -1; case 0: /* Child */ execvp(argv[0], (char * const *)argv); - return -1; + raise(SIGKILL); default: /* Parent */ return pid; }