Skip to content

Instantly share code, notes, and snippets.

@phlummox
Forked from rusek/delegate.c
Created July 26, 2023 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phlummox/80c79c679400d2f2076f7b72280a7dca to your computer and use it in GitHub Desktop.
Save phlummox/80c79c679400d2f2076f7b72280a7dca to your computer and use it in GitHub Desktop.
Interpreter path relative to script location in shebang
/*
Helper program for resolving the path to the interpreter executable
relative to the script location in shebangs.
Sample usage:
#!/usr/bin/delegate ../my-virtualenv/bin/python
import sys
def main():
print sys.executable
if __name__ == '__main__':
main()
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#define MAX_PATH_SIZE 4096
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "usage: %s <interpreter> <file>\n", argv[0]);
return -1;
}
char *interp_path = argv[1];
char *script_path = argv[2];
int ret;
if (strchr(interp_path, '/') == NULL) {
ret = execvp(interp_path, argv + 1);
} else if (interp_path[0] == '/') {
ret = execv(interp_path, argv + 1);
} else {
char *base_high = strrchr(script_path, '/');
size_t base_len = base_high != NULL ? base_high - script_path + 1 : 0;
size_t interp_len = strlen(interp_path);
if (base_len + interp_len < MAX_PATH_SIZE) {
char buf[MAX_PATH_SIZE];
memcpy(buf, script_path, base_len);
memcpy(buf + base_len, interp_path, interp_len + 1); // with '\0'
argv[1] = buf;
ret = execv(buf, argv + 1);
} else {
errno = ENAMETOOLONG;
ret = -1;
}
}
perror(argv[0]);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment