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