executable.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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 will be trashed (s/:/NUL/).
  27. */
  28. char* FAST_FUNC find_executable(const char *filename, char **PATHp)
  29. {
  30. /* About empty components in $PATH:
  31. * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
  32. * 8.3 Other Environment Variables - PATH
  33. * A zero-length prefix is a legacy feature that indicates the current
  34. * working directory. It appears as two adjacent colons ( "::" ), as an
  35. * initial colon preceding the rest of the list, or as a trailing colon
  36. * following the rest of the list.
  37. */
  38. char *p, *n;
  39. p = *PATHp;
  40. while (p) {
  41. n = strchr(p, ':');
  42. if (n)
  43. *n++ = '\0';
  44. p = concat_path_file(
  45. p[0] ? p : ".", /* handle "::" case */
  46. filename
  47. );
  48. if (file_is_executable(p)) {
  49. *PATHp = n;
  50. return p;
  51. }
  52. free(p);
  53. p = n;
  54. } /* on loop exit p == NULL */
  55. return p;
  56. }
  57. /* search $PATH for an executable file;
  58. * return 1 if found;
  59. * return 0 otherwise;
  60. */
  61. int FAST_FUNC executable_exists(const char *filename)
  62. {
  63. char *path = xstrdup(getenv("PATH"));
  64. char *tmp = path;
  65. char *ret = find_executable(filename, &tmp);
  66. free(path);
  67. free(ret);
  68. return ret != NULL;
  69. }
  70. #if ENABLE_FEATURE_PREFER_APPLETS
  71. /* just like the real execvp, but try to launch an applet named 'file' first */
  72. int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
  73. {
  74. if (find_applet_by_name(file) >= 0)
  75. execvp(bb_busybox_exec_path, argv);
  76. return execvp(file, argv);
  77. }
  78. #endif
  79. void FAST_FUNC BB_EXECVP_or_die(char **argv)
  80. {
  81. BB_EXECVP(argv[0], argv);
  82. /* SUSv3-mandated exit codes */
  83. xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
  84. bb_perror_msg_and_die("can't execute '%s'", argv[0]);
  85. }
  86. /* Typical idiom for applets which exec *optional* PROG [ARGS] */
  87. void FAST_FUNC exec_prog_or_SHELL(char **argv)
  88. {
  89. if (argv[0]) {
  90. BB_EXECVP_or_die(argv);
  91. }
  92. run_shell(getenv("SHELL"), /*login:*/ 1, NULL);
  93. }