executable.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Utility routines.
  4. *
  5. * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  8. */
  9. #include "libbb.h"
  10. /* check if path points to an executable file;
  11. * return 1 if found;
  12. * return 0 otherwise;
  13. */
  14. int FAST_FUNC file_is_executable(const char *name)
  15. {
  16. struct stat s;
  17. return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode));
  18. }
  19. /* search (*PATHp) for an executable file;
  20. * return allocated string containing full path if found;
  21. * PATHp points to the component after the one where it was found
  22. * (or NULL),
  23. * you may call find_executable again with this PATHp to continue
  24. * (if it's not NULL).
  25. * return NULL otherwise; (PATHp is undefined)
  26. * in all cases (*PATHp) contents are temporarily modified
  27. * but are restored on return (s/:/NUL/ and back).
  28. */
  29. char* FAST_FUNC find_executable(const char *filename, char **PATHp)
  30. {
  31. /* About empty components in $PATH:
  32. * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
  33. * 8.3 Other Environment Variables - PATH
  34. * A zero-length prefix is a legacy feature that indicates the current
  35. * working directory. It appears as two adjacent colons ( "::" ), as an
  36. * initial colon preceding the rest of the list, or as a trailing colon
  37. * following the rest of the list.
  38. */
  39. char *p, *n;
  40. p = *PATHp;
  41. while (p) {
  42. int ex;
  43. n = strchr(p, ':');
  44. if (n) *n = '\0';
  45. p = concat_path_file(
  46. p[0] ? p : ".", /* handle "::" case */
  47. filename
  48. );
  49. ex = file_is_executable(p);
  50. if (n) *n++ = ':';
  51. if (ex) {
  52. *PATHp = n;
  53. return p;
  54. }
  55. free(p);
  56. p = n;
  57. } /* on loop exit p == NULL */
  58. return p;
  59. }
  60. /* search $PATH for an executable file;
  61. * return 1 if found;
  62. * return 0 otherwise;
  63. */
  64. int FAST_FUNC executable_exists(const char *filename)
  65. {
  66. char *path = getenv("PATH");
  67. char *ret = find_executable(filename, &path);
  68. free(ret);
  69. return ret != NULL;
  70. }
  71. #if ENABLE_FEATURE_PREFER_APPLETS
  72. /* just like the real execvp, but try to launch an applet named 'file' first */
  73. int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
  74. {
  75. if (find_applet_by_name(file) >= 0)
  76. execvp(bb_busybox_exec_path, argv);
  77. return execvp(file, argv);
  78. }
  79. #endif
  80. void FAST_FUNC BB_EXECVP_or_die(char **argv)
  81. {
  82. BB_EXECVP(argv[0], argv);
  83. /* SUSv3-mandated exit codes */
  84. xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
  85. bb_perror_msg_and_die("can't execute '%s'", argv[0]);
  86. }
  87. /* Typical idiom for applets which exec *optional* PROG [ARGS] */
  88. void FAST_FUNC exec_prog_or_SHELL(char **argv)
  89. {
  90. if (argv[0]) {
  91. BB_EXECVP_or_die(argv);
  92. }
  93. run_shell(getenv("SHELL"), /*login:*/ 1, NULL);
  94. }