1 #include <linux/compiler.h>
2 #include <linux/string.h>
9 #include "subcmd-util.h"
11 #include "subcmd-config.h"
16 static const char *argv_exec_path
;
17 static const char *argv0_path
;
19 void exec_cmd_init(const char *exec_name
, const char *prefix
,
20 const char *exec_path
, const char *exec_path_env
)
22 subcmd_config
.exec_name
= exec_name
;
23 subcmd_config
.prefix
= prefix
;
24 subcmd_config
.exec_path
= exec_path
;
25 subcmd_config
.exec_path_env
= exec_path_env
;
28 #define is_dir_sep(c) ((c) == '/')
30 static int is_absolute_path(const char *path
)
32 return path
[0] == '/';
35 static const char *get_pwd_cwd(void)
37 static char cwd
[PATH_MAX
+ 1];
39 struct stat cwd_stat
, pwd_stat
;
40 if (getcwd(cwd
, PATH_MAX
) == NULL
)
43 if (pwd
&& strcmp(pwd
, cwd
)) {
45 if (!stat(pwd
, &pwd_stat
) &&
46 pwd_stat
.st_dev
== cwd_stat
.st_dev
&&
47 pwd_stat
.st_ino
== cwd_stat
.st_ino
) {
48 strlcpy(cwd
, pwd
, PATH_MAX
);
54 static const char *make_nonrelative_path(const char *path
)
56 static char buf
[PATH_MAX
+ 1];
58 if (is_absolute_path(path
)) {
59 if (strlcpy(buf
, path
, PATH_MAX
) >= PATH_MAX
)
60 die("Too long path: %.*s", 60, path
);
62 const char *cwd
= get_pwd_cwd();
64 die("Cannot determine the current working directory");
65 if (snprintf(buf
, PATH_MAX
, "%s/%s", cwd
, path
) >= PATH_MAX
)
66 die("Too long path: %.*s", 60, path
);
71 char *system_path(const char *path
)
75 if (is_absolute_path(path
))
78 astrcatf(&buf
, "%s/%s", subcmd_config
.prefix
, path
);
83 const char *extract_argv0_path(const char *argv0
)
87 if (!argv0
|| !*argv0
)
89 slash
= argv0
+ strlen(argv0
);
91 while (argv0
<= slash
&& !is_dir_sep(*slash
))
95 argv0_path
= strndup(argv0
, slash
- argv0
);
96 return argv0_path
? slash
+ 1 : NULL
;
102 void set_argv_exec_path(const char *exec_path
)
104 argv_exec_path
= exec_path
;
106 * Propagate this setting to external programs.
108 setenv(subcmd_config
.exec_path_env
, exec_path
, 1);
112 /* Returns the highest-priority location to look for subprograms. */
113 char *get_argv_exec_path(void)
118 return strdup(argv_exec_path
);
120 env
= getenv(subcmd_config
.exec_path_env
);
124 return system_path(subcmd_config
.exec_path
);
127 static void add_path(char **out
, const char *path
)
130 if (is_absolute_path(path
))
133 astrcat(out
, make_nonrelative_path(path
));
139 void setup_path(void)
141 const char *old_path
= getenv("PATH");
142 char *new_path
= NULL
;
143 char *tmp
= get_argv_exec_path();
145 add_path(&new_path
, tmp
);
146 add_path(&new_path
, argv0_path
);
150 astrcat(&new_path
, old_path
);
152 astrcat(&new_path
, "/usr/local/bin:/usr/bin:/bin");
154 setenv("PATH", new_path
, 1);
159 static const char **prepare_exec_cmd(const char **argv
)
164 for (argc
= 0; argv
[argc
]; argc
++)
165 ; /* just counting */
166 nargv
= malloc(sizeof(*nargv
) * (argc
+ 2));
168 nargv
[0] = subcmd_config
.exec_name
;
169 for (argc
= 0; argv
[argc
]; argc
++)
170 nargv
[argc
+ 1] = argv
[argc
];
171 nargv
[argc
+ 1] = NULL
;
175 int execv_cmd(const char **argv
) {
176 const char **nargv
= prepare_exec_cmd(argv
);
178 /* execvp() can only ever return if it fails */
179 execvp(subcmd_config
.exec_name
, (char **)nargv
);
186 int execl_cmd(const char *cmd
,...)
189 const char *argv
[MAX_ARGS
+ 1];
193 va_start(param
, cmd
);
196 while (argc
< MAX_ARGS
) {
197 arg
= argv
[argc
++] = va_arg(param
, char *);
202 if (MAX_ARGS
<= argc
) {
203 fprintf(stderr
, " Error: too many args to run %s\n", cmd
);
208 return execv_cmd(argv
);