#include "alloc-util.h"
#include "chase.h"
+#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
return read_full_stream_full(f, filename, offset, size, flags, ret_contents, ret_size);
}
-int executable_is_script(const char *path, char **interpreter) {
- _cleanup_free_ char *line = NULL;
- size_t len;
- char *ans;
+int script_get_shebang_interpreter(const char *path, char **ret) {
+ _cleanup_fclose_ FILE *f = NULL;
int r;
assert(path);
- r = read_one_line_file(path, &line);
- if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */
- return 0;
+ f = fopen(path, "re");
+ if (!f)
+ return -errno;
+
+ char c;
+ r = safe_fgetc(f, &c);
if (r < 0)
return r;
+ if (r == 0)
+ return -EBADMSG;
+ if (c != '#')
+ return -EMEDIUMTYPE;
+ r = safe_fgetc(f, &c);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EBADMSG;
+ if (c != '!')
+ return -EMEDIUMTYPE;
- if (!startswith(line, "#!"))
- return 0;
-
- ans = strstrip(line + 2);
- len = strcspn(ans, " \t");
+ _cleanup_free_ char *line = NULL;
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
- if (len == 0)
- return 0;
+ _cleanup_free_ char *p = NULL;
+ const char *s = line;
- ans = strndup(ans, len);
- if (!ans)
- return -ENOMEM;
+ r = extract_first_word(&s, &p, /* separators = */ NULL, /* flags = */ 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOEXEC;
- *interpreter = ans;
- return 1;
+ if (ret)
+ *ret = TAKE_PTR(p);
+ return 0;
}
/**
return verify_file_at(AT_FDCWD, fn, blob, accept_extra_nl);
}
-int executable_is_script(const char *path, char **interpreter);
+int script_get_shebang_interpreter(const char *path, char **ret);
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field);
assert(j);
assert(path);
- if (executable_is_script(path, &interpreter) > 0) {
+ if (script_get_shebang_interpreter(path, &interpreter) >= 0) {
_cleanup_free_ char *comm = NULL;
r = path_extract_filename(path, &comm);
return log_error_errno(r, "Failed to add match: %m");
/* Append _EXE only if the interpreter is not a link. Otherwise, it might be outdated often. */
- path = is_symlink(interpreter) > 0 ? interpreter : NULL;
- }
+ if (is_symlink(interpreter) > 0)
+ return 0;
- if (path) {
- r = journal_add_match_pair(j, "_EXE", path);
- if (r < 0)
- return log_error_errno(r, "Failed to add match: %m");
+ path = interpreter;
}
+ r = journal_add_match_pair(j, "_EXE", path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add match: %m");
+
return 0;
}
assert_se(strv_isempty(a));
}
-TEST(executable_is_script) {
+TEST(script_get_shebang_interpreter) {
_cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
_cleanup_fclose_ FILE *f = NULL;
char *command;
- int r;
assert_se(fmkostemp_safe(t, "w", &f) == 0);
fputs("#! /bin/script -a -b \ngoo goo", f);
fflush(f);
- r = executable_is_script(t, &command);
- assert_se(r > 0);
+ ASSERT_OK(script_get_shebang_interpreter(t, &command));
ASSERT_STREQ(command, "/bin/script");
free(command);
- r = executable_is_script("/bin/sh", &command);
- assert_se(r == 0);
+ ASSERT_ERROR(script_get_shebang_interpreter("/bin/sh", NULL), EMEDIUMTYPE);
- r = executable_is_script("/usr/bin/yum", &command);
- if (r > 0) {
+ if (script_get_shebang_interpreter("/usr/bin/yum", &command) >= 0) {
assert_se(startswith(command, "/"));
free(command);
}