1 /*-------------------------------------------------------------------------
4 * miscellanious initialization support stuff
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.45 2000/04/12 17:16:02 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include <sys/param.h>
18 #include <sys/types.h>
28 #include "catalog/catname.h"
29 #include "catalog/pg_shadow.h"
30 #include "miscadmin.h"
31 #include "utils/syscache.h"
35 unsigned char RecodeForwTable[128];
36 unsigned char RecodeBackTable[128];
40 ProcessingMode Mode = InitProcessing;
42 /* ----------------------------------------------------------------
43 * ignoring system indexes support stuff
44 * ----------------------------------------------------------------
47 static bool isIgnoringSystemIndexes = false;
50 * IsIgnoringSystemIndexes
51 * True if ignoring system indexes.
54 IsIgnoringSystemIndexes()
56 return isIgnoringSystemIndexes;
61 * Set true or false whether PostgreSQL ignores system indexes.
65 IgnoreSystemIndexes(bool mode)
67 isIgnoringSystemIndexes = mode;
70 /* ----------------------------------------------------------------
71 * database path / name support stuff
72 * ----------------------------------------------------------------
76 SetDatabasePath(const char *path)
79 /* use strdup since this is done before memory contexts are set up */
82 DatabasePath = strdup(path);
83 AssertState(DatabasePath);
88 SetDatabaseName(const char *name)
93 DatabaseName = strdup(name);
94 AssertState(DatabaseName);
99 /* even if MULTIBYTE is not enabled, this function is neccesary
100 * since pg_proc.h has entries for them.
103 getdatabaseencoding()
105 elog(ERROR, "MultiByte support must be enabled to use this function");
110 pg_encoding_to_char(int encoding)
112 elog(ERROR, "MultiByte support must be enabled to use this function");
117 pg_char_to_encoding(const char *encoding_string)
119 elog(ERROR, "MultiByte support must be enabled to use this function");
128 /* Some standard C libraries, including GNU, have an isblank() function.
129 Others, including Solaris, do not. So we have our own.
132 isblank(const char c)
134 return c == ' ' || c == 9 /* tab */ ;
138 next_token(FILE *fp, char *buf, const int bufsz)
140 /*--------------------------------------------------------------------------
141 Grab one token out of fp. Tokens are strings of non-blank
142 characters bounded by blank characters, beginning of line, and end
143 of line. Blank means space or tab. Return the token as *buf.
144 Leave file positioned to character immediately after the token or
145 EOF, whichever comes first. If no more tokens on line, return null
146 string as *buf and position file to beginning of next line or EOF,
147 whichever comes first.
148 --------------------------------------------------------------------------*/
150 char *eb = buf + (bufsz - 1);
152 /* Move over inital token-delimiting blanks */
153 while (isblank(c = getc(fp)));
159 * build a token in buf of next characters up to EOF, eol, or
162 while (c != EOF && c != '\n' && !isblank(c))
169 * Put back the char right after the token (putting back EOF
179 read_through_eol(FILE *file)
185 while (c != '\n' && c != EOF);
198 unsigned char FromChar,
201 for (i = 0; i < 128; i++)
203 RecodeForwTable[i] = i + 128;
204 RecodeBackTable[i] = i + 128;
207 p = getenv("PG_RECODETABLE");
210 map_file = (char *) malloc((strlen(DataDir) +
211 strlen(p) + 2) * sizeof(char));
212 sprintf(map_file, "%s/%s", DataDir, p);
214 file = AllocateFile(map_file, "r");
216 file = AllocateFile(map_file, "rb");
230 read_through_eol(file);
233 /* Read the FromChar */
234 next_token(file, buf, sizeof(buf));
237 FromChar = strtoul(buf, 0, 0);
238 /* Read the ToChar */
239 next_token(file, buf, sizeof(buf));
242 ToChar = strtoul(buf, 0, 0);
243 RecodeForwTable[FromChar - 128] = ToChar;
244 RecodeBackTable[ToChar - 128] = FromChar;
246 read_through_eol(file);
257 convertstr(unsigned char *buff, int len, int dest)
262 for (i = 0; i < len; i++, buff++)
266 *buff = RecodeForwTable[*buff - 128];
268 *buff = RecodeBackTable[*buff - 128];
276 * GetPgUserName and SetPgUserName
278 * SetPgUserName must be called before InitPostgres, since the setuid()
281 * Replace GetPgUserName() with a lower-case version
282 * to allow use in new case-insensitive SQL (referenced
283 * in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26
299 if (IsUnderPostmaster)
301 /* use the (possibly) authenticated name that's provided */
302 if (!(p = getenv("PG_USER")))
303 elog(FATAL, "SetPgUserName: PG_USER environment variable is unset");
307 /* setuid() has not yet been done, see above comment */
308 if (!(pw = getpwuid(geteuid())))
309 elog(FATAL, "SetPgUserName: no entry in host passwd file");
314 UserName = malloc(strlen(p) + 1);
316 #endif /* NO_SECURITY */
319 /* ----------------------------------------------------------------
320 * GetUserId and SetUserId
321 * ----------------------------------------------------------------
323 static Oid UserId = InvalidOid;
328 AssertState(OidIsValid(UserId));
338 AssertState(!OidIsValid(UserId)); /* only once */
341 * Don't do scans if we're bootstrapping, none of the system catalogs
342 * exist yet, and they should be owned by postgres anyway.
344 if (IsBootstrapProcessingMode())
350 userName = GetPgUserName();
351 userTup = SearchSysCacheTuple(SHADOWNAME,
352 PointerGetDatum(userName),
354 if (!HeapTupleIsValid(userTup))
355 elog(FATAL, "SetUserId: user '%s' is not in '%s'",
358 UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
361 /*-------------------------------------------------------------------------
363 * posmaster pid file stuffs. $DATADIR/postmaster.pid is created when:
365 * (1) postmaster starts. In this case pid > 0.
366 * (2) postgres starts in standalone mode. In this case
369 * to gain an interlock.
371 * SetPidFname(datadir)
372 * Remember the the pid file name. This is neccesary
373 * UnlinkPidFile() is called from proc_exit().
375 * GetPidFname(datadir)
376 * Get the pid file name. SetPidFname() should be called
377 * before GetPidFname() gets called.
380 * This is called from proc_exit() and unlink the pid file.
382 * SetPidFile(pid_t pid)
383 * Create the pid file. On failure, it checks if the process
384 * actually exists or not. SetPidFname() should be called
385 * in prior to calling SetPidFile().
387 *-------------------------------------------------------------------------
391 * Path to pid file. proc_exit() remember it to unlink the file.
393 static char PidFile[MAXPGPATH];
396 * Remove the pid file. This function is called from proc_exit.
405 * Set path to the pid file
408 SetPidFname(char *datadir)
410 snprintf(PidFile, sizeof(PidFile), "%s/%s", datadir, PIDFNAME);
414 * Get path to the pid file
423 * Create the pid file
426 SetPidFile(pid_t pid)
438 pidfile = GetPidFname();
439 fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600);
444 * Couldn't create the pid file. Probably it already exists. Read
445 * the file to see if the process actually exists
447 fd = open(pidfile, O_RDONLY, 0600);
450 fprintf(stderr, "Can't open pid file: %s\n", pidfile);
451 fprintf(stderr, "Please check the permission and try again.\n");
454 if ((len = read(fd, pidstr, sizeof(pidstr) - 1)) < 0)
456 fprintf(stderr, "Can't read pid file: %s\n", pidfile);
457 fprintf(stderr, "Please check the permission and try again.\n");
464 * Check to see if the process actually exists
467 post_pid = (pid_t) atoi(pidstr);
469 /* if pid < 0, the pid is for postgres, not postmatser */
473 post_pid = -post_pid;
476 if (post_pid == 0 || (post_pid > 0 && kill(post_pid, 0) < 0))
480 * No, the process did not exist. Unlink the file and try to
483 if (unlink(pidfile) < 0)
485 fprintf(stderr, "Can't remove pid file: %s\n", pidfile);
486 fprintf(stderr, "The file seems accidently left, but I couldn't remove it.\n");
487 fprintf(stderr, "Please remove the file by hand and try again.\n");
490 fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600);
493 fprintf(stderr, "Can't create pid file: %s\n", pidfile);
494 fprintf(stderr, "Please check the permission and try again.\n");
502 * Another postmaster is running
504 fprintf(stderr, "Can't create pid file: %s\n", pidfile);
506 fprintf(stderr, "Is another postgres (pid: %d) running?\n", post_pid);
508 fprintf(stderr, "Is another postmaster (pid: %s) running?\n", pidstr);
513 sprintf(pidstr, "%d", pid);
514 if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr))
516 fprintf(stderr, "Write to pid file failed\n");
517 fprintf(stderr, "Please check the permission and try again.\n");