findbe.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * findbe.c
  4.  *
  5.  * Copyright (c) 1994, Regents of the University of California
  6.  *
  7.  *
  8.  * IDENTIFICATION
  9.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/init/findbe.c,v 1.14.2.1 1999/08/02 05:25:09 scrappy Exp $
  10.  *
  11.  *-------------------------------------------------------------------------
  12.  */
  13. #include <grp.h>
  14. #include <pwd.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <unistd.h>
  18. #include "postgres.h"
  19. #include "miscadmin.h"
  20. #ifndef S_IRUSR /* XXX [TRH] should be in a header */
  21. #define S_IRUSR  S_IREAD
  22. #define S_IWUSR  S_IWRITE
  23. #define S_IXUSR  S_IEXEC
  24. #define S_IRGRP  ((S_IRUSR)>>3)
  25. #define S_IWGRP  ((S_IWUSR)>>3)
  26. #define S_IXGRP  ((S_IXUSR)>>3)
  27. #define S_IROTH  ((S_IRUSR)>>6)
  28. #define S_IWOTH  ((S_IWUSR)>>6)
  29. #define S_IXOTH  ((S_IXUSR)>>6)
  30. #endif
  31. /*
  32.  * ValidateBinary -- validate "path" as a POSTMASTER/POSTGRES executable file
  33.  *
  34.  * returns 0 if the file is found and no error is encountered.
  35.  *   -1 if the regular file "path" does not exist or cannot be executed.
  36.  *   -2 if the file is otherwise valid but cannot be read.
  37.  */
  38. int
  39. ValidateBinary(char *path)
  40. {
  41. struct stat buf;
  42. uid_t euid;
  43. struct group *gp;
  44. struct passwd *pwp;
  45. int i;
  46. int is_r = 0;
  47. int is_x = 0;
  48. int in_grp = 0;
  49. /*
  50.  * Ensure that the file exists and is a regular file.
  51.  *
  52.  * XXX if you have a broken system where stat() looks at the symlink
  53.  * instead of the underlying file, you lose.
  54.  */
  55. if (strlen(path) >= MAXPGPATH)
  56. {
  57. if (DebugLvl > 1)
  58. fprintf(stderr, "ValidateBinary: pathname "%s" is too longn",
  59. path);
  60. return -1;
  61. }
  62. if (stat(path, &buf) < 0)
  63. {
  64. if (DebugLvl > 1)
  65. fprintf(stderr, "ValidateBinary: can't stat "%s"n",
  66. path);
  67. return -1;
  68. }
  69. if (!(buf.st_mode & S_IFREG))
  70. {
  71. if (DebugLvl > 1)
  72. fprintf(stderr, "ValidateBinary: "%s" is not a regular filen",
  73. path);
  74. return -1;
  75. }
  76. /*
  77.  * Ensure that we are using an authorized backend.
  78.  *
  79.  * XXX I'm open to suggestions here.  I would like to enforce ownership
  80.  * of binaries by user "postgres" but people seem to like to run as
  81.  * users other than "postgres"...
  82.  */
  83. /*
  84.  * Ensure that the file is both executable and readable (required for
  85.  * dynamic loading).
  86.  *
  87.  * We use the effective uid here because the backend will not have
  88.  * executed setuid() by the time it calls this routine.
  89.  */
  90. euid = geteuid();
  91. if (euid == buf.st_uid)
  92. {
  93. is_r = buf.st_mode & S_IRUSR;
  94. is_x = buf.st_mode & S_IXUSR;
  95. if (DebugLvl > 1 && !(is_r && is_x))
  96. fprintf(stderr, "ValidateBinary: "%s" is not user read/executen",
  97. path);
  98. return is_x ? (is_r ? 0 : -2) : -1;
  99. }
  100. pwp = getpwuid(euid);
  101. if (pwp)
  102. {
  103. if (pwp->pw_gid == buf.st_gid)
  104. ++in_grp;
  105. else if (pwp->pw_name &&
  106.  (gp = getgrgid(buf.st_gid)))
  107. {
  108. for (i = 0; gp->gr_mem[i]; ++i)
  109. {
  110. if (!strcmp(gp->gr_mem[i], pwp->pw_name))
  111. {
  112. ++in_grp;
  113. break;
  114. }
  115. }
  116. }
  117. if (in_grp)
  118. {
  119. is_r = buf.st_mode & S_IRGRP;
  120. is_x = buf.st_mode & S_IXGRP;
  121. if (DebugLvl > 1 && !(is_r && is_x))
  122. fprintf(stderr, "ValidateBinary: "%s" is not group read/executen",
  123. path);
  124. return is_x ? (is_r ? 0 : -2) : -1;
  125. }
  126. }
  127. is_r = buf.st_mode & S_IROTH;
  128. is_x = buf.st_mode & S_IXOTH;
  129. if (DebugLvl > 1 && !(is_r && is_x))
  130. fprintf(stderr, "ValidateBinary: "%s" is not other read/executen",
  131. path);
  132. return is_x ? (is_r ? 0 : -2) : -1;
  133. }
  134. /*
  135.  * FindExec -- find an absolute path to a valid backend executable
  136.  *
  137.  * The reason we have to work so hard to find an absolute path is that
  138.  * we need to feed the binary the location of its actual executable file,
  139.  * otherwise, we can't do dynamic loading.  It needs a full pathname because
  140.  * we change directories to the /data directory.
  141.  */
  142. int
  143. FindExec(char *full_path, char *argv0, char *binary_name)
  144. {
  145. char buf[MAXPGPATH + 2];
  146. char    *p;
  147. char    *path,
  148.    *startp,
  149.    *endp;
  150. int pathlen;
  151. /*
  152.  * for the postmaster: First try: use the binary that's located in the
  153.  * same directory as the postmaster, if it was invoked with an
  154.  * explicit path. Presumably the user used an explicit path because it
  155.  * wasn't in PATH, and we don't want to use incompatible executables.
  156.  *
  157.  * This has the neat property that it works for installed binaries, old
  158.  * source trees (obj/support/post{master,gres}) and new marc source
  159.  * trees (obj/post{master,gres}) because they all put the two binaries
  160.  * in the same place.
  161.  *
  162.  * for the binary: First try: if we're given some kind of path, use it
  163.  * (making sure that a relative path is made absolute before returning
  164.  * it).
  165.  */
  166. if (argv0 && (p = strrchr(argv0, '/')) && *++p)
  167. {
  168. if (*argv0 == '/' || !getcwd(buf, MAXPGPATH))
  169. buf[0] = '';
  170. else
  171. strcat(buf, "/");
  172. strcat(buf, argv0);
  173. p = strrchr(buf, '/');
  174. strcpy(++p, binary_name);
  175. if (!ValidateBinary(buf))
  176. {
  177. strncpy(full_path, buf, MAXPGPATH);
  178. if (DebugLvl)
  179. fprintf(stderr, "FindExec: found "%s" using argv[0]n",
  180. full_path);
  181. return 0;
  182. }
  183. fprintf(stderr, "FindExec: invalid binary "%s"n",
  184. buf);
  185. return -1;
  186. }
  187. /*
  188.  * Second try: since no explicit path was supplied, the user must have
  189.  * been relying on PATH.  We'll use the same PATH.
  190.  */
  191. if ((p = getenv("PATH")) && *p)
  192. {
  193. if (DebugLvl)
  194. fprintf(stderr, "FindExec: searching PATH ...n");
  195. pathlen = strlen(p);
  196. path = malloc(pathlen + 1);
  197. strcpy(path, p);
  198. for (startp = path, endp = strchr(path, ':');
  199.  startp && *startp;
  200.  startp = endp + 1, endp = strchr(startp, ':'))
  201. {
  202. if (startp == endp) /* it's a "::" */
  203. continue;
  204. if (endp)
  205. *endp = '';
  206. if (*startp == '/' || !getcwd(buf, MAXPGPATH))
  207. buf[0] = '';
  208. strcat(buf, startp);
  209. strcat(buf, "/");
  210. strcat(buf, binary_name);
  211. switch (ValidateBinary(buf))
  212. {
  213. case 0: /* found ok */
  214. strncpy(full_path, buf, MAXPGPATH);
  215. if (DebugLvl)
  216. fprintf(stderr, "FindExec: found "%s" using PATHn",
  217. full_path);
  218. free(path);
  219. return 0;
  220. case -1: /* wasn't even a candidate, keep looking */
  221. break;
  222. case -2: /* found but disqualified */
  223. fprintf(stderr, "FindExec: could not read binary "%s"n",
  224. buf);
  225. free(path);
  226. return -1;
  227. }
  228. if (!endp) /* last one */
  229. break;
  230. }
  231. free(path);
  232. }
  233. fprintf(stderr, "FindExec: could not find a %s to execute...n", binary_name);
  234. return -1;
  235. }