]> granicus.if.org Git - postgresql/blob - src/backend/utils/init/miscinit.c
From: t-ishii@sra.co.jp
[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.18 1998/07/26 04:31:01 scrappy 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 #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         proc_exit(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         proc_exit(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 #ifndef MULTIBYTE
238 /* even if MULTIBYTE is not enabled, this function is neccesary
239  * since pg_proc.h does have.
240  */
241 const char *
242 getdatabaseencoding()
243 {
244   elog(ERROR, "you need to enable MB to use this function");
245   return("");
246 }
247 #endif
248
249 #ifdef CYR_RECODE
250 #define MAX_TOKEN       80
251
252 /* Some standard C libraries, including GNU, have an isblank() function.
253    Others, including Solaris, do not.  So we have our own.
254 */
255 static bool
256 isblank(const char c)
257 {
258         return (c == ' ' || c == 9 /* tab */ );
259 }
260
261 static void
262 next_token(FILE *fp, char *buf, const int bufsz)
263 {
264 /*--------------------------------------------------------------------------
265   Grab one token out of fp.  Tokens are strings of non-blank
266   characters bounded by blank characters, beginning of line, and end
267   of line.      Blank means space or tab.  Return the token as *buf.
268   Leave file positioned to character immediately after the token or
269   EOF, whichever comes first.  If no more tokens on line, return null
270   string as *buf and position file to beginning of next line or EOF,
271   whichever comes first.
272 --------------------------------------------------------------------------*/
273         int                     c;
274         char       *eb = buf + (bufsz - 1);
275
276         /* Move over inital token-delimiting blanks */
277         while (isblank(c = getc(fp)));
278
279         if (c != '\n')
280         {
281
282                 /*
283                  * build a token in buf of next characters up to EOF, eol, or
284                  * blank.
285                  */
286                 while (c != EOF && c != '\n' && !isblank(c))
287                 {
288                         if (buf < eb)
289                                 *buf++ = c;
290                         c = getc(fp);
291
292                         /*
293                          * Put back the char right after the token (putting back EOF
294                          * is ok)
295                          */
296                 }
297                 ungetc(c, fp);
298         }
299         *buf = '\0';
300 }
301
302 static void
303 read_through_eol(FILE *file)
304 {
305         int                     c;
306
307         do
308                 c = getc(file);
309         while (c != '\n' && c != EOF);
310 }
311
312 void
313 SetCharSet()
314 {
315         FILE       *file;
316         char       *p,
317                                 c,
318                                 eof = false;
319         char       *map_file;
320         char            buf[MAX_TOKEN];
321         int                     i;
322         unsigned char FromChar,
323                                 ToChar;
324
325         for (i = 0; i < 128; i++)
326         {
327                 RecodeForwTable[i] = i + 128;
328                 RecodeBackTable[i] = i + 128;
329         }
330
331         p = getenv("PG_RECODETABLE");
332         if (p && *p != '\0')
333         {
334                 map_file = (char *) malloc((strlen(DataDir) +
335                                                                         strlen(p) + 2) * sizeof(char));
336                 sprintf(map_file, "%s/%s", DataDir, p);
337                 file = fopen(map_file, "r");
338                 if (file == NULL)
339                         return;
340                 eof = false;
341                 while (!eof)
342                 {
343                         c = getc(file);
344                         ungetc(c, file);
345                         if (c == EOF)
346                                 eof = true;
347                         else
348                         {
349                                 if (c == '#')
350                                         read_through_eol(file);
351                                 else
352                                 {
353                                         /* Read the FromChar */
354                                         next_token(file, buf, sizeof(buf));
355                                         if (buf[0] != '\0')
356                                         {
357                                                 FromChar = strtoul(buf, 0, 0);
358                                                 /* Read the ToChar */
359                                                 next_token(file, buf, sizeof(buf));
360                                                 if (buf[0] != '\0')
361                                                 {
362                                                         ToChar = strtoul(buf, 0, 0);
363                                                         RecodeForwTable[FromChar - 128] = ToChar;
364                                                         RecodeBackTable[ToChar - 128] = FromChar;
365                                                 }
366                                                 read_through_eol(file);
367                                         }
368                                 }
369                         }
370                 }
371                 fclose(file);
372                 free(map_file);
373         }
374 }
375
376 char *
377 convertstr(unsigned char *buff, int len, int dest)
378 {
379         int                     i;
380         char       *ch = buff;
381
382         for (i = 0; i < len; i++, buff++)
383         {
384                 if (*buff > 127)
385                         if (dest)
386                                 *buff = RecodeForwTable[*buff - 128];
387                         else
388                                 *buff = RecodeBackTable[*buff - 128];
389         }
390         return ch;
391 }
392
393 #endif
394
395 /* ----------------
396  *              GetPgUserName and SetPgUserName
397  *
398  *              SetPgUserName must be called before InitPostgres, since the setuid()
399  *              is done there.
400  *
401  *              Replace GetPgUserName() with a lower-case version
402  *              to allow use in new case-insensitive SQL (referenced
403  *              in pg_proc.h). Define GetPgUserName() as a macro - tgl 97/04/26
404  * ----------------
405  */
406 char *
407 getpgusername()
408 {
409         return UserName;
410 }
411
412 void
413 SetPgUserName()
414 {
415 #ifndef NO_SECURITY
416         char       *p;
417         struct passwd *pw;
418
419         if (IsUnderPostmaster)
420         {
421                 /* use the (possibly) authenticated name that's provided */
422                 if (!(p = getenv("PG_USER")))
423                         elog(FATAL, "SetPgUserName: PG_USER environment variable unset");
424         }
425         else
426         {
427                 /* setuid() has not yet been done, see above comment */
428                 if (!(pw = getpwuid(geteuid())))
429                         elog(FATAL, "SetPgUserName: no entry in passwd file");
430                 p = pw->pw_name;
431         }
432         if (UserName)
433                 free(UserName);
434         UserName = malloc(strlen(p) + 1);
435         strcpy(UserName, p);
436 #endif                                                  /* NO_SECURITY */
437 }
438
439 /* ----------------------------------------------------------------
440  *              GetUserId and SetUserId
441  * ----------------------------------------------------------------
442  */
443 static Oid      UserId = InvalidOid;
444
445 Oid
446 GetUserId()
447 {
448         Assert(OidIsValid(UserId));
449         return (UserId);
450 }
451
452 void
453 SetUserId()
454 {
455         HeapTuple       userTup;
456         char       *userName;
457
458         Assert(!OidIsValid(UserId));/* only once */
459
460         /*
461          * Don't do scans if we're bootstrapping, none of the system catalogs
462          * exist yet, and they should be owned by postgres anyway.
463          */
464         if (IsBootstrapProcessingMode())
465         {
466                 UserId = geteuid();
467                 return;
468         }
469
470         userName = GetPgUserName();
471         userTup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName),
472                                                                   0, 0, 0);
473         if (!HeapTupleIsValid(userTup))
474                 elog(FATAL, "SetUserId: user \"%s\" is not in \"%s\"",
475                          userName,
476                          ShadowRelationName);
477         UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
478 }