]> granicus.if.org Git - postgresql/blob - src/backend/utils/init/miscinit.c
XLOG (also known as WAL -:)) Bootstrap/Startup/Shutdown.
[postgresql] / src / backend / utils / init / miscinit.c
1 /*-------------------------------------------------------------------------
2  *
3  * miscinit.c
4  *        miscellanious initialization support stuff
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.35 1999/10/06 21:58:10 vadim Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <sys/param.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/file.h>
18 #include <unistd.h>
19 #include <grp.h>
20 #include <pwd.h>
21
22 #include "postgres.h"
23 #include "catalog/catname.h"
24 #include "catalog/pg_shadow.h"
25 #include "miscadmin.h"
26 #include "utils/syscache.h"
27
28
29 /*
30  * EnableAbortEnvVarName
31  *              Enables system abort iff set to a non-empty string in environment.
32  */
33 #define EnableAbortEnvVarName   "POSTGRESABORT"
34
35 extern char *getenv(const char *name);  /* XXX STDLIB */
36
37 /*      from globals.c */
38 extern char *UserName;
39
40 #ifdef CYR_RECODE
41 unsigned char RecodeForwTable[128];
42 unsigned char RecodeBackTable[128];
43
44 #endif
45
46
47 /*
48  * Define USE_ENVIRONMENT to get PGDATA, etc. from environment variables.
49  * This is the default on UNIX platforms.
50  */
51 #define USE_ENVIRONMENT
52
53 /* ----------------------------------------------------------------
54  *                              some of the 19 ways to leave postgres
55  * ----------------------------------------------------------------
56  */
57
58 /*
59  * ExitPostgres
60  *              Exit POSTGRES with a status code.
61  *
62  * Note:
63  *              This function never returns.
64  *              ...
65  *
66  * Side effects:
67  *              ...
68  *
69  * Exceptions:
70  *              none
71  */
72 void
73 ExitPostgres(ExitStatus status)
74 {
75         proc_exit(status);
76 }
77
78 /*
79  * AbortPostgres
80  *              Abort POSTGRES dumping core.
81  *
82  * Note:
83  *              This function never returns.
84  *              ...
85  *
86  * Side effects:
87  *              Core is dumped iff EnableAbortEnvVarName is set to a non-empty string.
88  *              ...
89  *
90  * Exceptions:
91  *              none
92  */
93 #ifdef NOT_USED
94 void
95 AbortPostgres()
96 {
97         char       *abortValue = getenv(EnableAbortEnvVarName);
98
99         if (PointerIsValid(abortValue) && abortValue[0] != '\0')
100                 abort();
101         else
102                 proc_exit(FatalExitStatus);
103 }
104
105
106 /* ----------------
107  *              StatusBackendExit
108  * ----------------
109  */
110 void
111 StatusBackendExit(int status)
112 {
113         /* someday, do some real cleanup and then call the LISP exit */
114         /* someday, call StatusPostmasterExit if running without postmaster */
115         proc_exit(status);
116 }
117
118 /* ----------------
119  *              StatusPostmasterExit
120  * ----------------
121  */
122 void
123 StatusPostmasterExit(int status)
124 {
125         /* someday, do some real cleanup and then call the LISP exit */
126         proc_exit(status);
127 }
128
129 #endif
130
131
132 /* ----------------------------------------------------------------
133  *              processing mode support stuff (used to be in pmod.c)
134  * ----------------------------------------------------------------
135  */
136 static ProcessingMode Mode = InitProcessing;
137
138 /*
139  * IsBootstrapProcessingMode
140  *              True iff processing mode is BootstrapProcessing.
141  */
142 bool
143 IsBootstrapProcessingMode()
144 {
145         return (bool) (Mode == BootstrapProcessing);
146 }
147
148 /*
149  * IsInitProcessingMode
150  *              True iff processing mode is InitProcessing.
151  */
152 bool
153 IsInitProcessingMode()
154 {
155         return (bool) (Mode == InitProcessing);
156 }
157
158 /*
159  * IsNormalProcessingMode
160  *              True iff processing mode is NormalProcessing.
161  */
162 bool
163 IsNormalProcessingMode()
164 {
165         return (bool) (Mode == NormalProcessing);
166 }
167
168 /*
169  * SetProcessingMode
170  *              Sets mode of processing as specified.
171  *
172  * Exceptions:
173  *              BadArg if called with invalid mode.
174  *
175  * Note:
176  *              Mode is InitProcessing before the first time this is called.
177  */
178 void
179 SetProcessingMode(ProcessingMode mode)
180 {
181         AssertArg(mode == BootstrapProcessing || mode == InitProcessing || 
182                                 mode == NormalProcessing);
183
184         Mode = mode;
185 }
186
187 ProcessingMode
188 GetProcessingMode()
189 {
190         return Mode;
191 }
192
193 /* ----------------------------------------------------------------
194  *                              database path / name support stuff
195  * ----------------------------------------------------------------
196  */
197
198 void
199 SetDatabasePath(char *path)
200 {
201         /* use malloc since this is done before memory contexts are set up */
202         if (DatabasePath)
203                 free(DatabasePath);
204         DatabasePath = malloc(strlen(path) + 1);
205         strcpy(DatabasePath, path);
206 }
207
208 void
209 SetDatabaseName(char *name)
210 {
211         if (DatabaseName)
212                 free(DatabaseName);
213         DatabaseName = malloc(strlen(name) + 1);
214         strcpy(DatabaseName, name);
215 }
216
217 #ifndef MULTIBYTE
218 /* even if MULTIBYTE is not enabled, this function is neccesary
219  * since pg_proc.h has an entry for it.
220  */
221 const char *
222 getdatabaseencoding()
223 {
224         elog(ERROR, "MultiByte strings (MB) must be enabled to use this function");
225         return ("");
226 }
227
228 #endif
229
230 #ifdef CYR_RECODE
231 #define MAX_TOKEN       80
232
233 /* Some standard C libraries, including GNU, have an isblank() function.
234    Others, including Solaris, do not.  So we have our own.
235 */
236 static bool
237 isblank(const char c)
238 {
239         return c == ' ' || c == 9 /* tab */ ;
240 }
241
242 static void
243 next_token(FILE *fp, char *buf, const int bufsz)
244 {
245 /*--------------------------------------------------------------------------
246   Grab one token out of fp.  Tokens are strings of non-blank
247   characters bounded by blank characters, beginning of line, and end
248   of line.      Blank means space or tab.  Return the token as *buf.
249   Leave file positioned to character immediately after the token or
250   EOF, whichever comes first.  If no more tokens on line, return null
251   string as *buf and position file to beginning of next line or EOF,
252   whichever comes first.
253 --------------------------------------------------------------------------*/
254         int                     c;
255         char       *eb = buf + (bufsz - 1);
256
257         /* Move over inital token-delimiting blanks */
258         while (isblank(c = getc(fp)));
259
260         if (c != '\n')
261         {
262
263                 /*
264                  * build a token in buf of next characters up to EOF, eol, or
265                  * blank.
266                  */
267                 while (c != EOF && c != '\n' && !isblank(c))
268                 {
269                         if (buf < eb)
270                                 *buf++ = c;
271                         c = getc(fp);
272
273                         /*
274                          * Put back the char right after the token (putting back EOF
275                          * is ok)
276                          */
277                 }
278                 ungetc(c, fp);
279         }
280         *buf = '\0';
281 }
282
283 static void
284 read_through_eol(FILE *file)
285 {
286         int                     c;
287
288         do
289                 c = getc(file);
290         while (c != '\n' && c != EOF);
291 }
292
293 void
294 SetCharSet()
295 {
296         FILE       *file;
297         char       *p,
298                                 c,
299                                 eof = false;
300         char       *map_file;
301         char            buf[MAX_TOKEN];
302         int                     i;
303         unsigned char FromChar,
304                                 ToChar;
305
306         for (i = 0; i < 128; i++)
307         {
308                 RecodeForwTable[i] = i + 128;
309                 RecodeBackTable[i] = i + 128;
310         }
311
312         p = getenv("PG_RECODETABLE");
313         if (p && *p != '\0')
314         {
315                 map_file = (char *) malloc((strlen(DataDir) +
316                                                                         strlen(p) + 2) * sizeof(char));
317                 sprintf(map_file, "%s/%s", DataDir, p);
318 #ifndef __CYGWIN32__
319                 file = AllocateFile(map_file, "r");
320 #else
321                 file = AllocateFile(map_file, "rb");
322 #endif
323                 if (file == NULL)
324                         return;
325                 eof = false;
326                 while (!eof)
327                 {
328                         c = getc(file);
329                         ungetc(c, file);
330                         if (c == EOF)
331                                 eof = true;
332                         else
333                         {
334                                 if (c == '#')
335                                         read_through_eol(file);
336                                 else
337                                 {
338                                         /* Read the FromChar */
339                                         next_token(file, buf, sizeof(buf));
340                                         if (buf[0] != '\0')
341                                         {
342                                                 FromChar = strtoul(buf, 0, 0);
343                                                 /* Read the ToChar */
344                                                 next_token(file, buf, sizeof(buf));
345                                                 if (buf[0] != '\0')
346                                                 {
347                                                         ToChar = strtoul(buf, 0, 0);
348                                                         RecodeForwTable[FromChar - 128] = ToChar;
349                                                         RecodeBackTable[ToChar - 128] = FromChar;
350                                                 }
351                                                 read_through_eol(file);
352                                         }
353                                 }
354                         }
355                 }
356                 FreeFile(file);
357                 free(map_file);
358         }
359 }
360
361 char *
362 convertstr(unsigned char *buff, int len, int dest)
363 {
364         int                     i;
365         char       *ch = buff;
366
367         for (i = 0; i < len; i++, buff++)
368         {
369                 if (*buff > 127)
370                         if (dest)
371                                 *buff = RecodeForwTable[*buff - 128];
372                         else
373                                 *buff = RecodeBackTable[*buff - 128];
374         }
375         return ch;
376 }
377
378 #endif
379
380 /* ----------------
381  *              GetPgUserName and SetPgUserName
382  *
383  *              SetPgUserName must be called before InitPostgres, since the setuid()
384  *              is done there.
385  *
386  *              Replace GetPgUserName() with a lower-case version
387  *              to allow use in new case-insensitive SQL (referenced
388  *              in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26
389  * ----------------
390  */
391 char *
392 getpgusername()
393 {
394         return UserName;
395 }
396
397 void
398 SetPgUserName()
399 {
400 #ifndef NO_SECURITY
401         char       *p;
402         struct passwd *pw;
403
404         if (IsUnderPostmaster)
405         {
406                 /* use the (possibly) authenticated name that's provided */
407                 if (!(p = getenv("PG_USER")))
408                         elog(FATAL, "SetPgUserName: PG_USER environment variable is unset");
409         }
410         else
411         {
412                 /* setuid() has not yet been done, see above comment */
413                 if (!(pw = getpwuid(geteuid())))
414                         elog(FATAL, "SetPgUserName: no entry in host passwd file");
415                 p = pw->pw_name;
416         }
417         if (UserName)
418                 free(UserName);
419         UserName = malloc(strlen(p) + 1);
420         strcpy(UserName, p);
421 #endif   /* NO_SECURITY */
422 }
423
424 /* ----------------------------------------------------------------
425  *              GetUserId and SetUserId
426  * ----------------------------------------------------------------
427  */
428 static Oid      UserId = InvalidOid;
429
430 int
431 GetUserId()
432 {
433         Assert(OidIsValid(UserId));
434         return UserId;
435 }
436
437 void
438 SetUserId()
439 {
440         HeapTuple       userTup;
441         char       *userName;
442
443         Assert(!OidIsValid(UserId));/* only once */
444
445         /*
446          * Don't do scans if we're bootstrapping, none of the system catalogs
447          * exist yet, and they should be owned by postgres anyway.
448          */
449         if (IsBootstrapProcessingMode())
450         {
451                 UserId = geteuid();
452                 return;
453         }
454
455         userName = GetPgUserName();
456         userTup = SearchSysCacheTuple(USENAME,
457                                                                   PointerGetDatum(userName),
458                                                                   0, 0, 0);
459         if (!HeapTupleIsValid(userTup))
460                 elog(FATAL, "SetUserId: user '%s' is not in '%s'",
461                          userName,
462                          ShadowRelationName);
463         UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
464 }