1 /*-------------------------------------------------------------------------
4 * miscellanious initialization support stuff
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.42 2000/01/19 14:01:25 momjian Exp $
12 *-------------------------------------------------------------------------
16 #include <sys/param.h>
17 #include <sys/types.h>
27 #include "catalog/catname.h"
28 #include "catalog/pg_shadow.h"
29 #include "miscadmin.h"
30 #include "utils/syscache.h"
34 unsigned char RecodeForwTable[128];
35 unsigned char RecodeBackTable[128];
38 ProcessingMode Mode = InitProcessing;
41 /* ----------------------------------------------------------------
42 * database path / name support stuff
43 * ----------------------------------------------------------------
47 SetDatabasePath(const char *path)
50 /* use strdup since this is done before memory contexts are set up */
53 DatabasePath = strdup(path);
54 AssertState(DatabasePath);
59 SetDatabaseName(const char *name)
64 DatabaseName = strdup(name);
65 AssertState(DatabaseName);
70 /* even if MULTIBYTE is not enabled, this function is neccesary
71 * since pg_proc.h has entries for them.
76 elog(ERROR, "MultiByte support must be enabled to use this function");
80 const char *pg_encoding_to_char(int encoding)
82 elog(ERROR, "MultiByte support must be enabled to use this function");
86 int pg_char_to_encoding(const char *encoding_string)
88 elog(ERROR, "MultiByte support must be enabled to use this function");
97 /* Some standard C libraries, including GNU, have an isblank() function.
98 Others, including Solaris, do not. So we have our own.
101 isblank(const char c)
103 return c == ' ' || c == 9 /* tab */ ;
107 next_token(FILE *fp, char *buf, const int bufsz)
109 /*--------------------------------------------------------------------------
110 Grab one token out of fp. Tokens are strings of non-blank
111 characters bounded by blank characters, beginning of line, and end
112 of line. Blank means space or tab. Return the token as *buf.
113 Leave file positioned to character immediately after the token or
114 EOF, whichever comes first. If no more tokens on line, return null
115 string as *buf and position file to beginning of next line or EOF,
116 whichever comes first.
117 --------------------------------------------------------------------------*/
119 char *eb = buf + (bufsz - 1);
121 /* Move over inital token-delimiting blanks */
122 while (isblank(c = getc(fp)));
128 * build a token in buf of next characters up to EOF, eol, or
131 while (c != EOF && c != '\n' && !isblank(c))
138 * Put back the char right after the token (putting back EOF
148 read_through_eol(FILE *file)
154 while (c != '\n' && c != EOF);
167 unsigned char FromChar,
170 for (i = 0; i < 128; i++)
172 RecodeForwTable[i] = i + 128;
173 RecodeBackTable[i] = i + 128;
176 p = getenv("PG_RECODETABLE");
179 map_file = (char *) malloc((strlen(DataDir) +
180 strlen(p) + 2) * sizeof(char));
181 sprintf(map_file, "%s/%s", DataDir, p);
183 file = AllocateFile(map_file, "r");
185 file = AllocateFile(map_file, "rb");
199 read_through_eol(file);
202 /* Read the FromChar */
203 next_token(file, buf, sizeof(buf));
206 FromChar = strtoul(buf, 0, 0);
207 /* Read the ToChar */
208 next_token(file, buf, sizeof(buf));
211 ToChar = strtoul(buf, 0, 0);
212 RecodeForwTable[FromChar - 128] = ToChar;
213 RecodeBackTable[ToChar - 128] = FromChar;
215 read_through_eol(file);
226 convertstr(unsigned char *buff, int len, int dest)
231 for (i = 0; i < len; i++, buff++)
235 *buff = RecodeForwTable[*buff - 128];
237 *buff = RecodeBackTable[*buff - 128];
245 * GetPgUserName and SetPgUserName
247 * SetPgUserName must be called before InitPostgres, since the setuid()
250 * Replace GetPgUserName() with a lower-case version
251 * to allow use in new case-insensitive SQL (referenced
252 * in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26
268 if (IsUnderPostmaster)
270 /* use the (possibly) authenticated name that's provided */
271 if (!(p = getenv("PG_USER")))
272 elog(FATAL, "SetPgUserName: PG_USER environment variable is unset");
276 /* setuid() has not yet been done, see above comment */
277 if (!(pw = getpwuid(geteuid())))
278 elog(FATAL, "SetPgUserName: no entry in host passwd file");
283 UserName = malloc(strlen(p) + 1);
285 #endif /* NO_SECURITY */
288 /* ----------------------------------------------------------------
289 * GetUserId and SetUserId
290 * ----------------------------------------------------------------
292 static Oid UserId = InvalidOid;
297 AssertState(OidIsValid(UserId));
307 AssertState(!OidIsValid(UserId));/* only once */
310 * Don't do scans if we're bootstrapping, none of the system catalogs
311 * exist yet, and they should be owned by postgres anyway.
313 if (IsBootstrapProcessingMode())
319 userName = GetPgUserName();
320 userTup = SearchSysCacheTuple(SHADOWNAME,
321 PointerGetDatum(userName),
323 if (!HeapTupleIsValid(userTup))
324 elog(FATAL, "SetUserId: user '%s' is not in '%s'",
327 UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
330 /*-------------------------------------------------------------------------
332 * posmaster pid file stuffs. $DATADIR/postmaster.pid is created when:
334 * (1) postmaster starts. In this case pid > 0.
335 * (2) postgres starts in standalone mode. In this case
338 * to gain an interlock.
340 * SetPidFname(datadir)
341 * Remember the the pid file name. This is neccesary
342 * UnlinkPidFile() is called from proc_exit().
344 * GetPidFname(datadir)
345 * Get the pid file name. SetPidFname() should be called
346 * before GetPidFname() gets called.
349 * This is called from proc_exit() and unlink the pid file.
351 * SetPidFile(pid_t pid)
352 * Create the pid file. On failure, it checks if the process
353 * actually exists or not. SetPidFname() should be called
354 * in prior to calling SetPidFile().
356 *-------------------------------------------------------------------------
360 * Path to pid file. proc_exit() remember it to unlink the file.
362 static char PidFile[MAXPGPATH];
365 * Remove the pid file. This function is called from proc_exit.
367 void UnlinkPidFile(void)
373 * Set path to the pid file
375 void SetPidFname(char * datadir)
377 snprintf(PidFile, sizeof(PidFile), "%s/%s", datadir, PIDFNAME);
381 * Get path to the pid file
383 char *GetPidFname(void)
389 * Create the pid file
391 int SetPidFile(pid_t pid)
403 pidfile = GetPidFname();
404 fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600);
407 * Couldn't create the pid file. Probably
408 * it already exists. Read the file to see if the process
411 fd = open(pidfile, O_RDONLY, 0600);
413 fprintf(stderr, "Can't open pid file: %s\n", pidfile);
414 fprintf(stderr, "Please check the permission and try again.\n");
417 if ((len = read(fd, pidstr, sizeof(pidstr)-1)) < 0) {
418 fprintf(stderr, "Can't read pid file: %s\n", pidfile);
419 fprintf(stderr, "Please check the permission and try again.\n");
426 * Check to see if the process actually exists
429 post_pid = (pid_t)atoi(pidstr);
431 /* if pid < 0, the pid is for postgres, not postmatser */
434 post_pid = -post_pid;
437 if (post_pid == 0 || (post_pid > 0 && kill(post_pid, 0) < 0)) {
439 * No, the process did not exist. Unlink
440 * the file and try to create it
442 if (unlink(pidfile) < 0) {
443 fprintf(stderr, "Can't remove pid file: %s\n", pidfile);
444 fprintf(stderr, "The file seems accidently left, but I couldn't remove it.\n");
445 fprintf(stderr, "Please remove the file by hand and try again.\n");
448 fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600);
450 fprintf(stderr, "Can't create pid file: %s\n", pidfile);
451 fprintf(stderr, "Please check the permission and try again.\n");
456 * Another postmaster is running
458 fprintf(stderr, "Can't create pid file: %s\n", pidfile);
460 fprintf(stderr, "Is another postgres (pid: %d) running?\n", post_pid);
464 fprintf(stderr, "Is another postmaster (pid: %s) running?\n", pidstr);
470 sprintf(pidstr, "%d", pid);
471 if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
472 fprintf(stderr,"Write to pid file failed\n");
473 fprintf(stderr, "Please check the permission and try again.\n");