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