From c474deaaf63deb633bf9bc951c8cc1cd5d107eda Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 25 Apr 1997 15:38:31 +0000 Subject: [PATCH] Expand one level of symbolic link in sys.argv[0] before inserting its dirname in sys.path. This means that you can create a symbolic link foo in /usr/local/bin pointing to /usr/yourname/src/foo/foo.py, and then invoking foo will insert /usr/yourname/src/foo in sys.path, not /usr/local/bin. This makes it easier to have multifile programs (before, the program would have to do an os.readlink(sys.argv[0]) itself and insert the resulting directory in sys.path -- Grail does this). Note that the expansion is only used for sys.path; sys.argv[0] is still the original, unadorned filename (/usr/local/bin/foo in the example). --- Python/sysmodule.c | 49 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index c1eaeede5e3..69cb7aaccbf 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -54,6 +54,10 @@ Data members: object *sys_trace, *sys_profile; int sys_checkinterval = 10; +#if HAVE_UNISTD_H +#include +#endif + static object *sysdict; #ifdef MS_COREDLL @@ -387,35 +391,64 @@ setpythonargv(argc, argv) if (sysset("argv", av) != 0) fatal("can't assign sys.argv"); if (path != NULL) { + char *argv0 = argv[0]; char *p = NULL; int n = 0; object *a; +#ifdef HAVE_READLINK + char link[MAXPATHLEN+1]; + char argv0copy[2*MAXPATHLEN+1]; + int nr = 0; + if (argc > 0 && argv0 != NULL) + nr = readlink(argv0, link, MAXPATHLEN); + if (nr > 0) { + /* It's a symlink */ + link[nr] = '\0'; + if (link[0] == SEP) + argv0 = link; /* Link to absolute path */ + else if (strchr(link, SEP) == NULL) + ; /* Link without path */ + else { + /* Must join(dirname(argv0), link) */ + char *q = strrchr(argv0, SEP); + if (q == NULL) + argv0 = link; /* argv0 without path */ + else { + /* Must make a copy */ + strcpy(argv0copy, argv0); + q = strrchr(argv0copy, SEP); + strcpy(q+1, link); + argv0 = argv0copy; + } + } + } +#endif /* HAVE_READLINK */ #if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv[0] != NULL) { + if (argc > 0 && argv0 != NULL) { char *q; - p = strrchr(argv[0], SEP); + p = strrchr(argv0, SEP); /* Test for alternate separator */ - q = strrchr(p ? p : argv[0], '/'); + q = strrchr(p ? p : argv0, '/'); if (q != NULL) p = q; if (p != NULL) { - n = p + 1 - argv[0]; + n = p + 1 - argv0; if (n > 1 && p[-1] != ':') n--; /* Drop trailing separator */ } } #else /* All other filename syntaxes */ - if (argc > 0 && argv[0] != NULL) - p = strrchr(argv[0], SEP); + if (argc > 0 && argv0 != NULL) + p = strrchr(argv0, SEP); if (p != NULL) { - n = p + 1 - argv[0]; + n = p + 1 - argv0; #if SEP == '/' /* Special case for Unix filename syntax */ if (n > 1) n--; /* Drop trailing separator */ #endif /* Unix */ } #endif /* All others */ - a = newsizedstringobject(argv[0], n); + a = newsizedstringobject(argv0, n); if (a == NULL) fatal("no mem for sys.path insertion"); if (inslistitem(path, 0, a) < 0)