diff options
Diffstat (limited to 'src/backend/utils/init/findbe.c')
-rw-r--r-- | src/backend/utils/init/findbe.c | 377 |
1 files changed, 197 insertions, 180 deletions
diff --git a/src/backend/utils/init/findbe.c b/src/backend/utils/init/findbe.c index 8718e3f91d6..5e6aa7412a6 100644 --- a/src/backend/utils/init/findbe.c +++ b/src/backend/utils/init/findbe.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.5 1997/08/27 03:48:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/Attic/findbe.c,v 1.6 1997/09/07 04:53:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,213 +19,230 @@ #include <unistd.h> #include "postgres.h" -#include "miscadmin.h" /* for DebugLvl */ +#include "miscadmin.h" /* for DebugLvl */ -#ifndef S_IRUSR /* XXX [TRH] should be in a header */ -# define S_IRUSR S_IREAD -# define S_IWUSR S_IWRITE -# define S_IXUSR S_IEXEC -# define S_IRGRP ((S_IRUSR)>>3) -# define S_IWGRP ((S_IWUSR)>>3) -# define S_IXGRP ((S_IXUSR)>>3) -# define S_IROTH ((S_IRUSR)>>6) -# define S_IWOTH ((S_IWUSR)>>6) -# define S_IXOTH ((S_IXUSR)>>6) +#ifndef S_IRUSR /* XXX [TRH] should be in a header */ +#define S_IRUSR S_IREAD +#define S_IWUSR S_IWRITE +#define S_IXUSR S_IEXEC +#define S_IRGRP ((S_IRUSR)>>3) +#define S_IWGRP ((S_IWUSR)>>3) +#define S_IXGRP ((S_IXUSR)>>3) +#define S_IROTH ((S_IRUSR)>>6) +#define S_IWOTH ((S_IWUSR)>>6) +#define S_IXOTH ((S_IXUSR)>>6) #endif /* * ValidateBackend -- validate "path" as a POSTGRES executable file * * returns 0 if the file is found and no error is encountered. - * -1 if the regular file "path" does not exist or cannot be executed. - * -2 if the file is otherwise valid but cannot be read. + * -1 if the regular file "path" does not exist or cannot be executed. + * -2 if the file is otherwise valid but cannot be read. */ int ValidateBackend(char *path) { - struct stat buf; - uid_t euid; - struct group *gp; - struct passwd *pwp; - int i; - int is_r = 0; - int is_x = 0; - int in_grp = 0; - - /* - * Ensure that the file exists and is a regular file. - * - * XXX if you have a broken system where stat() looks at the symlink - * instead of the underlying file, you lose. - */ - if (strlen(path) >= MAXPGPATH) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: pathname \"%s\" is too long\n", - path); - return(-1); - } + struct stat buf; + uid_t euid; + struct group *gp; + struct passwd *pwp; + int i; + int is_r = 0; + int is_x = 0; + int in_grp = 0; - if (stat(path, &buf) < 0) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: can't stat \"%s\"\n", - path); - return(-1); - } - if (!(buf.st_mode & S_IFREG)) { - if (DebugLvl > 1) - fprintf(stderr, "ValidateBackend: \"%s\" is not a regular file\n", - path); - return(-1); - } - - /* - * Ensure that we are using an authorized backend. - * - * XXX I'm open to suggestions here. I would like to enforce ownership - * of backends by user "postgres" but people seem to like to run - * as users other than "postgres"... - */ - - /* - * Ensure that the file is both executable and readable (required for - * dynamic loading). - * - * We use the effective uid here because the backend will not have - * executed setuid() by the time it calls this routine. - */ - euid = geteuid(); - if (euid == buf.st_uid) { - is_r = buf.st_mode & S_IRUSR; - is_x = buf.st_mode & S_IXUSR; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not user read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); - } - pwp = getpwuid(euid); - if (pwp) { - if (pwp->pw_gid == buf.st_gid) { - ++in_grp; - } else if (pwp->pw_name && - (gp = getgrgid(buf.st_gid))) { - for (i = 0; gp->gr_mem[i]; ++i) { - if (!strcmp(gp->gr_mem[i], pwp->pw_name)) { - ++in_grp; - break; - } - } + /* + * Ensure that the file exists and is a regular file. + * + * XXX if you have a broken system where stat() looks at the symlink + * instead of the underlying file, you lose. + */ + if (strlen(path) >= MAXPGPATH) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: pathname \"%s\" is too long\n", + path); + return (-1); } - if (in_grp) { - is_r = buf.st_mode & S_IRGRP; - is_x = buf.st_mode & S_IXGRP; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not group read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); + + if (stat(path, &buf) < 0) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: can't stat \"%s\"\n", + path); + return (-1); } - } - is_r = buf.st_mode & S_IROTH; - is_x = buf.st_mode & S_IXOTH; - if (DebugLvl > 1 && !(is_r && is_x)) - fprintf(stderr, "ValidateBackend: \"%s\" is not other read/execute\n", - path); - return(is_x ? (is_r ? 0 : -2) : -1); + if (!(buf.st_mode & S_IFREG)) + { + if (DebugLvl > 1) + fprintf(stderr, "ValidateBackend: \"%s\" is not a regular file\n", + path); + return (-1); + } + + /* + * Ensure that we are using an authorized backend. + * + * XXX I'm open to suggestions here. I would like to enforce ownership + * of backends by user "postgres" but people seem to like to run as + * users other than "postgres"... + */ + + /* + * Ensure that the file is both executable and readable (required for + * dynamic loading). + * + * We use the effective uid here because the backend will not have + * executed setuid() by the time it calls this routine. + */ + euid = geteuid(); + if (euid == buf.st_uid) + { + is_r = buf.st_mode & S_IRUSR; + is_x = buf.st_mode & S_IXUSR; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not user read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); + } + pwp = getpwuid(euid); + if (pwp) + { + if (pwp->pw_gid == buf.st_gid) + { + ++in_grp; + } + else if (pwp->pw_name && + (gp = getgrgid(buf.st_gid))) + { + for (i = 0; gp->gr_mem[i]; ++i) + { + if (!strcmp(gp->gr_mem[i], pwp->pw_name)) + { + ++in_grp; + break; + } + } + } + if (in_grp) + { + is_r = buf.st_mode & S_IRGRP; + is_x = buf.st_mode & S_IXGRP; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not group read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); + } + } + is_r = buf.st_mode & S_IROTH; + is_x = buf.st_mode & S_IXOTH; + if (DebugLvl > 1 && !(is_r && is_x)) + fprintf(stderr, "ValidateBackend: \"%s\" is not other read/execute\n", + path); + return (is_x ? (is_r ? 0 : -2) : -1); } /* * FindBackend -- find an absolute path to a valid backend executable * * The reason we have to work so hard to find an absolute path is that - * we need to feed the backend server the location of its actual + * we need to feed the backend server the location of its actual * executable file -- otherwise, we can't do dynamic loading. */ int FindBackend(char *backend, char *argv0) { - char buf[MAXPGPATH + 2]; - char *p; - char *path, *startp, *endp; - int pathlen; - - /* - * for the postmaster: - * First try: use the backend that's located in the same directory - * as the postmaster, if it was invoked with an explicit path. - * Presumably the user used an explicit path because it wasn't in - * PATH, and we don't want to use incompatible executables. - * - * This has the neat property that it works for installed binaries, - * old source trees (obj/support/post{master,gres}) and new marc - * source trees (obj/post{master,gres}) because they all put the - * two binaries in the same place. - * - * for the backend server: - * First try: if we're given some kind of path, use it (making sure - * that a relative path is made absolute before returning it). - */ - if (argv0 && (p = strrchr(argv0, '/')) && *++p) { - if (*argv0 == '/' || !getcwd(buf, MAXPGPATH)) - buf[0] = '\0'; - else - strcat(buf, "/"); - strcat(buf, argv0); - p = strrchr(buf, '/'); - strcpy(++p, "postgres"); - if (!ValidateBackend(buf)) { - strncpy(backend, buf, MAXPGPATH); - if (DebugLvl) - fprintf(stderr, "FindBackend: found \"%s\" using argv[0]\n", - backend); - return(0); + char buf[MAXPGPATH + 2]; + char *p; + char *path, + *startp, + *endp; + int pathlen; + + /* + * for the postmaster: First try: use the backend that's located in + * the same directory as the postmaster, if it was invoked with an + * explicit path. Presumably the user used an explicit path because it + * wasn't in PATH, and we don't want to use incompatible executables. + * + * This has the neat property that it works for installed binaries, old + * source trees (obj/support/post{master,gres}) and new marc source + * trees (obj/post{master,gres}) because they all put the two binaries + * in the same place. + * + * for the backend server: First try: if we're given some kind of path, + * use it (making sure that a relative path is made absolute before + * returning it). + */ + if (argv0 && (p = strrchr(argv0, '/')) && *++p) + { + if (*argv0 == '/' || !getcwd(buf, MAXPGPATH)) + buf[0] = '\0'; + else + strcat(buf, "/"); + strcat(buf, argv0); + p = strrchr(buf, '/'); + strcpy(++p, "postgres"); + if (!ValidateBackend(buf)) + { + strncpy(backend, buf, MAXPGPATH); + if (DebugLvl) + fprintf(stderr, "FindBackend: found \"%s\" using argv[0]\n", + backend); + return (0); + } + fprintf(stderr, "FindBackend: invalid backend \"%s\"\n", + buf); + return (-1); } - fprintf(stderr, "FindBackend: invalid backend \"%s\"\n", - buf); - return(-1); - } - - /* - * Second try: since no explicit path was supplied, the user must - * have been relying on PATH. We'll use the same PATH. - */ - if ((p = getenv("PATH")) && *p) { - if (DebugLvl) - fprintf(stderr, "FindBackend: searching PATH ...\n"); - pathlen = strlen(p); - path = malloc(pathlen + 1); - strcpy(path, p); - for (startp = path, endp = strchr(path, ':'); - startp && *startp; - startp = endp + 1, endp = strchr(startp, ':')) { - if (startp == endp) /* it's a "::" */ - continue; - if (endp) - *endp = '\0'; - if (*startp == '/' || !getcwd(buf, MAXPGPATH)) - buf[0] = '\0'; - strcat(buf, startp); - strcat(buf, "/postgres"); - switch (ValidateBackend(buf)) { - case 0: /* found ok */ - strncpy(backend, buf, MAXPGPATH); + + /* + * Second try: since no explicit path was supplied, the user must have + * been relying on PATH. We'll use the same PATH. + */ + if ((p = getenv("PATH")) && *p) + { if (DebugLvl) - fprintf(stderr, "FindBackend: found \"%s\" using PATH\n", - backend); - free(path); - return(0); - case -1: /* wasn't even a candidate, keep looking */ - break; - case -2: /* found but disqualified */ - fprintf(stderr, "FindBackend: could not read backend \"%s\"\n", - buf); + fprintf(stderr, "FindBackend: searching PATH ...\n"); + pathlen = strlen(p); + path = malloc(pathlen + 1); + strcpy(path, p); + for (startp = path, endp = strchr(path, ':'); + startp && *startp; + startp = endp + 1, endp = strchr(startp, ':')) + { + if (startp == endp) /* it's a "::" */ + continue; + if (endp) + *endp = '\0'; + if (*startp == '/' || !getcwd(buf, MAXPGPATH)) + buf[0] = '\0'; + strcat(buf, startp); + strcat(buf, "/postgres"); + switch (ValidateBackend(buf)) + { + case 0: /* found ok */ + strncpy(backend, buf, MAXPGPATH); + if (DebugLvl) + fprintf(stderr, "FindBackend: found \"%s\" using PATH\n", + backend); + free(path); + return (0); + case -1: /* wasn't even a candidate, keep looking */ + break; + case -2: /* found but disqualified */ + fprintf(stderr, "FindBackend: could not read backend \"%s\"\n", + buf); + free(path); + return (-1); + } + if (!endp) /* last one */ + break; + } free(path); - return(-1); - } - if (!endp) /* last one */ - break; } - free(path); - } - fprintf(stderr, "FindBackend: could not find a backend to execute...\n"); - return(-1); + fprintf(stderr, "FindBackend: could not find a backend to execute...\n"); + return (-1); } |