]> granicus.if.org Git - postgresql/blob - src/backend/utils/init/miscinit.c
Apply Win32 patch from Horak Daniel.
[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.25 1999/01/17 06:18:54 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         proc_exit(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                 proc_exit(FatalExitStatus);
115 }
116
117
118 /* ----------------
119  *              StatusBackendExit
120  * ----------------
121  */
122 void
123 StatusBackendExit(int status)
124 {
125         /* someday, do some real cleanup and then call the LISP exit */
126         /* someday, call StatusPostmasterExit if running without postmaster */
127         proc_exit(status);
128 }
129
130 /* ----------------
131  *              StatusPostmasterExit
132  * ----------------
133  */
134 void
135 StatusPostmasterExit(int status)
136 {
137         /* someday, do some real cleanup and then call the LISP exit */
138         proc_exit(status);
139 }
140 #endif
141
142
143 /* ----------------------------------------------------------------
144  *              processing mode support stuff (used to be in pmod.c)
145  * ----------------------------------------------------------------
146  */
147 static ProcessingMode Mode = NoProcessing;
148
149 #ifdef NOT_USED
150 /*
151  * IsNoProcessingMode --
152  *              True iff processing mode is NoProcessing.
153  */
154 bool
155 IsNoProcessingMode()
156 {
157         return (bool) (Mode == NoProcessing);
158 }
159 #endif
160
161 /*
162  * IsBootstrapProcessingMode --
163  *              True iff processing mode is BootstrapProcessing.
164  */
165 bool
166 IsBootstrapProcessingMode()
167 {
168         return (bool) (Mode == BootstrapProcessing);
169 }
170
171 /*
172  * IsInitProcessingMode --
173  *              True iff processing mode is InitProcessing.
174  */
175 bool
176 IsInitProcessingMode()
177 {
178         return (bool) (Mode == InitProcessing);
179 }
180
181 /*
182  * IsNormalProcessingMode --
183  *              True iff processing mode is NormalProcessing.
184  */
185 bool
186 IsNormalProcessingMode()
187 {
188         return (bool) (Mode == NormalProcessing);
189 }
190
191 /*
192  * SetProcessingMode --
193  *              Sets mode of processing as specified.
194  *
195  * Exceptions:
196  *              BadArg if called with invalid mode.
197  *
198  * Note:
199  *              Mode is NoProcessing before the first time this is called.
200  */
201 void
202 SetProcessingMode(ProcessingMode mode)
203 {
204         AssertArg(mode == NoProcessing || mode == BootstrapProcessing ||
205                           mode == InitProcessing || mode == NormalProcessing);
206
207         Mode = mode;
208 }
209
210 ProcessingMode
211 GetProcessingMode()
212 {
213         return Mode;
214 }
215
216 /* ----------------------------------------------------------------
217  *                              database path / name support stuff
218  * ----------------------------------------------------------------
219  */
220
221 void
222 SetDatabasePath(char *path)
223 {
224         /* use malloc since this is done before memory contexts are set up */
225         if (DatabasePath)
226                 free(DatabasePath);
227         DatabasePath = malloc(strlen(path) + 1);
228         strcpy(DatabasePath, path);
229 }
230
231 void
232 SetDatabaseName(char *name)
233 {
234         if (DatabaseName)
235                 free(DatabaseName);
236         DatabaseName = malloc(strlen(name) + 1);
237         strcpy(DatabaseName, name);
238 }
239
240 #ifndef MULTIBYTE
241 /* even if MULTIBYTE is not enabled, this function is neccesary
242  * since pg_proc.h has an entry for it.
243  */
244 const char *
245 getdatabaseencoding()
246 {
247         elog(ERROR, "MultiByte strings (MB) must be enabled to use this function");
248         return ("");
249 }
250
251 #endif
252
253 #ifdef CYR_RECODE
254 #define MAX_TOKEN       80
255
256 /* Some standard C libraries, including GNU, have an isblank() function.
257    Others, including Solaris, do not.  So we have our own.
258 */
259 static bool
260 isblank(const char c)
261 {
262         return c == ' ' || c == 9 /* tab */ ;
263 }
264
265 static void
266 next_token(FILE *fp, char *buf, const int bufsz)
267 {
268 /*--------------------------------------------------------------------------
269   Grab one token out of fp.  Tokens are strings of non-blank
270   characters bounded by blank characters, beginning of line, and end
271   of line.      Blank means space or tab.  Return the token as *buf.
272   Leave file positioned to character immediately after the token or
273   EOF, whichever comes first.  If no more tokens on line, return null
274   string as *buf and position file to beginning of next line or EOF,
275   whichever comes first.
276 --------------------------------------------------------------------------*/
277         int                     c;
278         char       *eb = buf + (bufsz - 1);
279
280         /* Move over inital token-delimiting blanks */
281         while (isblank(c = getc(fp)));
282
283         if (c != '\n')
284         {
285
286                 /*
287                  * build a token in buf of next characters up to EOF, eol, or
288                  * blank.
289                  */
290                 while (c != EOF && c != '\n' && !isblank(c))
291                 {
292                         if (buf < eb)
293                                 *buf++ = c;
294                         c = getc(fp);
295
296                         /*
297                          * Put back the char right after the token (putting back EOF
298                          * is ok)
299                          */
300                 }
301                 ungetc(c, fp);
302         }
303         *buf = '\0';
304 }
305
306 static void
307 read_through_eol(FILE *file)
308 {
309         int                     c;
310
311         do
312                 c = getc(file);
313         while (c != '\n' && c != EOF);
314 }
315
316 void
317 SetCharSet()
318 {
319         FILE       *file;
320         char       *p,
321                                 c,
322                                 eof = false;
323         char       *map_file;
324         char            buf[MAX_TOKEN];
325         int                     i;
326         unsigned char FromChar,
327                                 ToChar;
328
329         for (i = 0; i < 128; i++)
330         {
331                 RecodeForwTable[i] = i + 128;
332                 RecodeBackTable[i] = i + 128;
333         }
334
335         p = getenv("PG_RECODETABLE");
336         if (p && *p != '\0')
337         {
338                 map_file = (char *) malloc((strlen(DataDir) +
339                                                                         strlen(p) + 2) * sizeof(char));
340                 sprintf(map_file, "%s/%s", DataDir, p);
341 #ifndef __CYGWIN32__
342                 file = fopen(map_file, "r");
343 #else
344                 file = fopen(map_file, "rb");
345 #endif
346                 if (file == NULL)
347                         return;
348                 eof = false;
349                 while (!eof)
350                 {
351                         c = getc(file);
352                         ungetc(c, file);
353                         if (c == EOF)
354                                 eof = true;
355                         else
356                         {
357                                 if (c == '#')
358                                         read_through_eol(file);
359                                 else
360                                 {
361                                         /* Read the FromChar */
362                                         next_token(file, buf, sizeof(buf));
363                                         if (buf[0] != '\0')
364                                         {
365                                                 FromChar = strtoul(buf, 0, 0);
366                                                 /* Read the ToChar */
367                                                 next_token(file, buf, sizeof(buf));
368                                                 if (buf[0] != '\0')
369                                                 {
370                                                         ToChar = strtoul(buf, 0, 0);
371                                                         RecodeForwTable[FromChar - 128] = ToChar;
372                                                         RecodeBackTable[ToChar - 128] = FromChar;
373                                                 }
374                                                 read_through_eol(file);
375                                         }
376                                 }
377                         }
378                 }
379                 fclose(file);
380                 free(map_file);
381         }
382 }
383
384 char *
385 convertstr(unsigned char *buff, int len, int dest)
386 {
387         int                     i;
388         char       *ch = buff;
389
390         for (i = 0; i < len; i++, buff++)
391         {
392                 if (*buff > 127)
393                         if (dest)
394                                 *buff = RecodeForwTable[*buff - 128];
395                         else
396                                 *buff = RecodeBackTable[*buff - 128];
397         }
398         return ch;
399 }
400
401 #endif
402
403 /* ----------------
404  *              GetPgUserName and SetPgUserName
405  *
406  *              SetPgUserName must be called before InitPostgres, since the setuid()
407  *              is done there.
408  *
409  *              Replace GetPgUserName() with a lower-case version
410  *              to allow use in new case-insensitive SQL (referenced
411  *              in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26
412  * ----------------
413  */
414 char *
415 getpgusername()
416 {
417         return UserName;
418 }
419
420 void
421 SetPgUserName()
422 {
423 #ifndef NO_SECURITY
424         char       *p;
425         struct passwd *pw;
426
427         if (IsUnderPostmaster)
428         {
429                 /* use the (possibly) authenticated name that's provided */
430                 if (!(p = getenv("PG_USER")))
431                         elog(FATAL, "SetPgUserName: PG_USER environment variable is unset");
432         }
433         else
434         {
435                 /* setuid() has not yet been done, see above comment */
436                 if (!(pw = getpwuid(geteuid())))
437                         elog(FATAL, "SetPgUserName: no entry in host passwd file");
438                 p = pw->pw_name;
439         }
440         if (UserName)
441                 free(UserName);
442         UserName = malloc(strlen(p) + 1);
443         strcpy(UserName, p);
444 #endif   /* NO_SECURITY */
445 }
446
447 /* ----------------------------------------------------------------
448  *              GetUserId and SetUserId
449  * ----------------------------------------------------------------
450  */
451 static Oid      UserId = InvalidOid;
452
453 int
454 GetUserId()
455 {
456         Assert(OidIsValid(UserId));
457         return UserId;
458 }
459
460 void
461 SetUserId()
462 {
463         HeapTuple       userTup;
464         char       *userName;
465
466         Assert(!OidIsValid(UserId));/* only once */
467
468         /*
469          * Don't do scans if we're bootstrapping, none of the system catalogs
470          * exist yet, and they should be owned by postgres anyway.
471          */
472         if (IsBootstrapProcessingMode())
473         {
474                 UserId = geteuid();
475                 return;
476         }
477
478         userName = GetPgUserName();
479         userTup = SearchSysCacheTuple(USENAME,
480                                                                   PointerGetDatum(userName),
481                                                                   0, 0, 0);
482         if (!HeapTupleIsValid(userTup))
483                 elog(FATAL, "SetUserId: user '%s' is not in '%s'",
484                          userName,
485                          ShadowRelationName);
486         UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
487 }