]> granicus.if.org Git - postgresql/blob - src/backend/utils/error/elog.c
ef05d9180c9d68f0b48e4a7520e6ea131f2e9011
[postgresql] / src / backend / utils / error / elog.c
1 /*-------------------------------------------------------------------------
2  *
3  * elog.c
4  *        error logger
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.95 2002/04/04 04:43:44 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <time.h>
18 #include <fcntl.h>
19 #include <sys/types.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #include <sys/time.h>
24 #include <ctype.h>
25 #ifdef ENABLE_SYSLOG
26 #include <syslog.h>
27 #endif
28
29 #include "commands/copy.h"
30 #include "libpq/libpq.h"
31 #include "libpq/pqformat.h"
32 #include "miscadmin.h"
33 #include "storage/proc.h"
34 #include "tcop/tcopprot.h"
35 #include "utils/memutils.h"
36
37 #ifdef MULTIBYTE
38 #include "mb/pg_wchar.h"
39 #endif
40
41 int                     server_min_messages;
42 char       *server_min_messages_str = NULL;
43 const char      server_min_messages_str_default[] = "notice";
44
45 int                     client_min_messages;
46 char       *client_min_messages_str = NULL;
47 const char      client_min_messages_str_default[] = "notice";
48
49 #ifdef ENABLE_SYSLOG
50 /*
51  * 0 = only stdout/stderr
52  * 1 = stdout+stderr and syslog
53  * 2 = syslog only
54  * ... in theory anyway
55  */
56 int                     Use_syslog = 0;
57 char       *Syslog_facility;
58 char       *Syslog_ident;
59
60 static void write_syslog(int level, const char *line);
61
62 #else
63 #define Use_syslog 0
64 #endif
65
66 bool            Log_timestamp;
67 bool            Log_pid;
68
69 #define TIMESTAMP_SIZE 20               /* format `YYYY-MM-DD HH:MM:SS ' */
70 #define PID_SIZE 9                              /* format `[123456] ' */
71
72 static const char *print_timestamp(void);
73 static const char *print_pid(void);
74 static void send_message_to_frontend(int type, const char *msg);
75 static const char *useful_strerror(int errnum);
76 static const char *elog_message_prefix(int lev);
77
78 static int      Debugfile = -1;
79
80
81 /*--------------------
82  * elog
83  *              Primary error logging function.
84  *
85  * 'lev': error level; indicates recovery action to take, if any.
86  * 'fmt': a printf-style string.
87  * Additional arguments, if any, are formatted per %-escapes in 'fmt'.
88  *
89  * In addition to the usual %-escapes recognized by printf, "%m" in
90  * fmt is replaced by the error message for the current value of errno.
91  *
92  * Note: no newline is needed at the end of the fmt string, since
93  * elog will provide one for the output methods that need it.
94  *
95  * If 'lev' is ERROR or worse, control does not return to the caller.
96  * See elog.h for the error level definitions.
97  *--------------------
98  */
99 void
100 elog(int lev, const char *fmt,...)
101 {
102         va_list         ap;
103         /*
104          * The expanded format and final output message are dynamically
105          * allocated if necessary, but not if they fit in the "reasonable
106          * size" buffers shown here.  In extremis, we'd rather depend on
107          * having a few hundred bytes of stack space than on malloc() still
108          * working (since memory-clobber errors often take out malloc first).
109          * Don't make these buffers unreasonably large though, on pain of
110          * having to chase a bug with no error message.
111          *
112          * Note that we use malloc() not palloc() because we want to retain
113          * control if we run out of memory.  palloc() would recursively call
114          * elog(ERROR), which would be all right except if we are working on a
115          * FATAL or PANIC error.        We'd lose track of the fatal condition
116          * and report a mere ERROR to outer loop, which would be a Bad Thing.
117          * So, we substitute an appropriate message in-place, without
118          * downgrading the level if it's above ERROR.
119          */
120         char            fmt_fixedbuf[128];
121         char            msg_fixedbuf[256];
122         char       *fmt_buf = fmt_fixedbuf;
123         char       *msg_buf = msg_fixedbuf;
124         char            copylineno_buf[32];     /* for COPY line numbers */
125         const char *errorstr;
126         const char *prefix;
127         const char *cp;
128         char       *bp;
129         size_t          space_needed;
130         size_t          timestamp_size; /* prefix len for timestamp+pid */
131         bool            output_to_server = false;
132         bool            output_to_client = false;
133
134         /* Check for old elog calls.  Codes were renumbered in 7.3. 2002-02-24 */
135         if (lev < DEBUG5)
136                 elog(FATAL, "Pre-7.3 object file made an elog() call.  Recompile.");
137
138         /*
139          * Convert initialization errors into fatal errors. This is probably
140          * redundant, because Warn_restart_ready won't be set anyway.
141          */
142         if (lev == ERROR && IsInitProcessingMode())
143                 lev = FATAL;
144
145         /*
146          * If we are inside a critical section, all errors become PANIC
147          * errors.      See miscadmin.h.
148          */
149         if (lev >= ERROR)
150         {
151                 if (CritSectionCount > 0)
152                         lev = PANIC;
153         }
154
155         /* Determine whether message is enabled for server log output */
156         /* Complicated because LOG is sorted out-of-order for this purpose */
157         if (lev == LOG || lev == COMMERROR)
158         {
159                 if (server_min_messages == LOG)
160                         output_to_server = true;
161                 else if (server_min_messages < FATAL)
162                         output_to_server = true;
163         }
164         else
165         {
166                 /* lev != LOG */
167                 if (server_min_messages == LOG)
168                 {
169                         if (lev >= FATAL)
170                                 output_to_server = true;
171                 }
172                 /* Neither is LOG */
173                 else if (lev >= server_min_messages)
174                         output_to_server = true;
175         }
176
177         /* Determine whether message is enabled for client output */
178         if (whereToSendOutput == Remote && lev != COMMERROR)
179         {
180                 /*
181                  * client_min_messages is honored only after we complete the
182                  * authentication handshake.  This is required both for security
183                  * reasons and because many clients can't handle NOTICE messages
184                  * during authentication.
185                  */
186                 if (ClientAuthInProgress)
187                         output_to_client = (lev >= ERROR);
188                 else
189                         output_to_client = (lev >= client_min_messages || lev == INFO);
190         }
191
192         /* Skip formatting effort if non-error message will not be output */
193         if (lev < ERROR && !output_to_server && !output_to_client)
194                 return;
195
196         /* Save error str before calling any function that might change errno */
197         errorstr = useful_strerror(errno);
198
199         /* Internationalize the error format string */
200         fmt = gettext(fmt);
201
202         /* Begin formatting by determining prefix information */
203         prefix = elog_message_prefix(lev);
204
205         timestamp_size = 0;
206         if (Log_timestamp)
207                 timestamp_size += TIMESTAMP_SIZE;
208         if (Log_pid)
209                 timestamp_size += PID_SIZE;
210
211         /*
212          * Set up the expanded format, consisting of the prefix string plus
213          * input format, with any %m replaced by strerror() string (since
214          * vsnprintf won't know what to do with %m).  To keep space
215          * calculation simple, we only allow one %m.
216          */
217         space_needed = timestamp_size + strlen(prefix) +
218                                    strlen(fmt) + strlen(errorstr) + 1;
219
220         if (copy_lineno)
221         {
222                 /*
223                  * Prints the failure line of the COPY.  Wow, what a hack!  bjm
224                  * Translator:  Error message will be truncated at 31 characters.
225                  */
226                 snprintf(copylineno_buf, 32, gettext("copy: line %d, "), copy_lineno);
227                 space_needed += strlen(copylineno_buf);
228         }
229
230         if (space_needed > sizeof(fmt_fixedbuf))
231         {
232                 fmt_buf = malloc(space_needed);
233                 if (fmt_buf == NULL)
234                 {
235                         /* We're up against it, convert to out-of-memory error */
236                         fmt_buf = fmt_fixedbuf;
237                         if (lev < ERROR)
238                         {
239                                 lev = ERROR;
240                                 prefix = elog_message_prefix(lev);
241                         }
242
243                         /*
244                          * gettext doesn't allocate memory, except in the very first
245                          * call (which this isn't), so it's safe to translate here.
246                          * Worst case we get the untranslated string back.
247                          */
248                         /* translator: This must fit in fmt_fixedbuf. */
249                         fmt = gettext("elog: out of memory");
250                 }
251         }
252
253         fmt_buf[0] = '\0';
254
255         if (Log_timestamp)
256                 strcat(fmt_buf, print_timestamp());
257         if (Log_pid)
258                 strcat(fmt_buf, print_pid());
259
260         strcat(fmt_buf, prefix);
261
262         /* If error was in CopyFrom() print the offending line number -- dz */
263         if (copy_lineno)
264         {
265                 strcat(fmt_buf, copylineno_buf);
266                 if (lev >= ERROR)
267                         copy_lineno = 0;
268         }
269
270         bp = fmt_buf + strlen(fmt_buf);
271
272         for (cp = fmt; *cp; cp++)
273         {
274                 if (cp[0] == '%' && cp[1] != '\0')
275                 {
276                         if (cp[1] == 'm')
277                         {
278                                 /*
279                                  * XXX If there are any %'s in errorstr then vsnprintf
280                                  * will do the Wrong Thing; do we need to cope? Seems
281                                  * unlikely that % would appear in system errors.
282                                  */
283                                 strcpy(bp, errorstr);
284
285                                 /*
286                                  * copy the rest of fmt literally, since we can't afford
287                                  * to insert another %m.
288                                  */
289                                 strcat(bp, cp + 2);
290                                 bp += strlen(bp);
291                                 break;
292                         }
293                         else
294                         {
295                                 /* copy % and next char --- this avoids trouble with %%m */
296                                 *bp++ = *cp++;
297                                 *bp++ = *cp;
298                         }
299                 }
300                 else
301                         *bp++ = *cp;
302         }
303         *bp = '\0';
304
305         /*
306          * Now generate the actual output text using vsnprintf(). Be sure to
307          * leave space for \n added later as well as trailing null.
308          */
309         space_needed = sizeof(msg_fixedbuf);
310         for (;;)
311         {
312                 int                     nprinted;
313
314                 va_start(ap, fmt);
315                 nprinted = vsnprintf(msg_buf, space_needed - 2, fmt_buf, ap);
316                 va_end(ap);
317
318                 /*
319                  * Note: some versions of vsnprintf return the number of chars
320                  * actually stored, but at least one returns -1 on failure. Be
321                  * conservative about believing whether the print worked.
322                  */
323                 if (nprinted >= 0 && nprinted < space_needed - 3)
324                         break;
325                 /* It didn't work, try to get a bigger buffer */
326                 if (msg_buf != msg_fixedbuf)
327                         free(msg_buf);
328                 space_needed *= 2;
329                 msg_buf = malloc(space_needed);
330                 if (msg_buf == NULL)
331                 {
332                         /* We're up against it, convert to out-of-memory error */
333                         msg_buf = msg_fixedbuf;
334                         if (lev < ERROR)
335                         {
336                                 lev = ERROR;
337                                 prefix = elog_message_prefix(lev);
338                         }
339                         msg_buf[0] = '\0';
340                         if (Log_timestamp)
341                                 strcat(msg_buf, print_timestamp());
342                         if (Log_pid)
343                                 strcat(msg_buf, print_pid());
344                         strcat(msg_buf, prefix);
345                         strcat(msg_buf, gettext("elog: out of memory"));
346                         break;
347                 }
348         }
349
350         /*
351          * Message prepared; send it where it should go
352          */
353
354 #ifdef ENABLE_SYSLOG
355         /* Write to syslog, if enabled */
356         if (output_to_server && Use_syslog >= 1)
357         {
358                 int                     syslog_level;
359
360                 switch (lev)
361                 {
362                         case DEBUG5:
363                         case DEBUG4:
364                         case DEBUG3:
365                         case DEBUG2:
366                         case DEBUG1:
367                                 syslog_level = LOG_DEBUG;
368                                 break;
369                         case LOG:
370                         case COMMERROR:
371                         case INFO:
372                                 syslog_level = LOG_INFO;
373                                 break;
374                         case NOTICE:
375                         case WARNING:
376                                 syslog_level = LOG_NOTICE;
377                                 break;
378                         case ERROR:
379                                 syslog_level = LOG_WARNING;
380                                 break;
381                         case FATAL:
382                                 syslog_level = LOG_ERR;
383                                 break;
384                         case PANIC:
385                         default:
386                                 syslog_level = LOG_CRIT;
387                                 break;
388                 }
389
390                 write_syslog(syslog_level, msg_buf + timestamp_size);
391         }
392 #endif   /* ENABLE_SYSLOG */
393
394         /* syslog doesn't want a trailing newline, but other destinations do */
395         strcat(msg_buf, "\n");
396
397         /* Write to stderr, if enabled */
398         if (output_to_server && (Use_syslog <= 1 || whereToSendOutput == Debug))
399                 write(2, msg_buf, strlen(msg_buf));
400
401         /* Send to client, if enabled */
402         if (output_to_client)
403         {
404                 /* Send IPC message to the front-end program */
405                 MemoryContext oldcxt;
406
407                 /*
408                  * Since backend libpq may call palloc(), switch to a context
409                  * where there's fairly likely to be some free space.  After all
410                  * the pushups above, we don't want to drop the ball by running
411                  * out of space now...
412                  */
413                 oldcxt = MemoryContextSwitchTo(ErrorContext);
414
415                 if (lev <= WARNING)
416                         /* exclude the timestamp from msg sent to frontend */
417                         send_message_to_frontend(lev, msg_buf + timestamp_size);
418                 else
419                 {
420                         /*
421                          * Abort any COPY OUT in progress when an error is detected.
422                          * This hack is necessary because of poor design of copy
423                          * protocol.
424                          */
425                         pq_endcopyout(true);
426                         send_message_to_frontend(ERROR, msg_buf + timestamp_size);
427                 }
428
429                 MemoryContextSwitchTo(oldcxt);
430         }
431
432         /* done with the message, release space */
433         if (fmt_buf != fmt_fixedbuf)
434                 free(fmt_buf);
435         if (msg_buf != msg_fixedbuf)
436                 free(msg_buf);
437
438         /*
439          * Perform error recovery action as specified by lev.
440          */
441         if (lev == ERROR || lev == FATAL)
442         {
443                 /* Prevent immediate interrupt while entering error recovery */
444                 ImmediateInterruptOK = false;
445
446                 /*
447                  * If we just reported a startup failure, the client will
448                  * disconnect on receiving it, so don't send any more to the client.
449                  */
450                 if (!Warn_restart_ready && whereToSendOutput == Remote)
451                         whereToSendOutput = None;
452
453                 /*
454                  * For a FATAL error, we let proc_exit clean up and exit.
455                  *
456                  * If we have not yet entered the main backend loop (ie, we are in
457                  * the postmaster or in backend startup), we also go directly to
458                  * proc_exit.  The same is true if anyone tries to report an error
459                  * after proc_exit has begun to run.  (It's proc_exit's
460                  * responsibility to see that this doesn't turn into infinite
461                  * recursion!)  But in the latter case, we exit with nonzero exit
462                  * code to indicate that something's pretty wrong.  We also want
463                  * to exit with nonzero exit code if not running under the
464                  * postmaster (for example, if we are being run from the initdb
465                  * script, we'd better return an error status).
466                  */
467                 if (lev == FATAL || !Warn_restart_ready || proc_exit_inprogress)
468                 {
469                         /*
470                          * fflush here is just to improve the odds that we get to see
471                          * the error message, in case things are so hosed that
472                          * proc_exit crashes.  Any other code you might be tempted to
473                          * add here should probably be in an on_proc_exit callback
474                          * instead.
475                          */
476                         fflush(stdout);
477                         fflush(stderr);
478                         proc_exit(proc_exit_inprogress || !IsUnderPostmaster);
479                 }
480
481                 /*
482                  * Guard against infinite loop from elog() during error recovery.
483                  */
484                 if (InError)
485                         elog(PANIC, "elog: error during error recovery, giving up!");
486                 InError = true;
487
488                 /*
489                  * Otherwise we can return to the main loop in postgres.c.
490                  */
491                 siglongjmp(Warn_restart, 1);
492         }
493
494         if (lev == PANIC)
495         {
496                 /*
497                  * Serious crash time. Postmaster will observe nonzero process
498                  * exit status and kill the other backends too.
499                  *
500                  * XXX: what if we are *in* the postmaster?  proc_exit() won't kill
501                  * our children...
502                  */
503                 ImmediateInterruptOK = false;
504                 fflush(stdout);
505                 fflush(stderr);
506                 proc_exit(2);
507         }
508
509         /* We reach here if lev <= WARNING.     OK to return to caller. */
510 }
511
512
513 int
514 DebugFileOpen(void)
515 {
516         int                     fd,
517                                 istty;
518
519         Debugfile = -1;
520
521         if (OutputFileName[0])
522         {
523                 /*
524                  * A debug-output file name was given.
525                  *
526                  * Make sure we can write the file, and find out if it's a tty.
527                  */
528                 if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY,
529                                            0666)) < 0)
530                         elog(FATAL, "DebugFileOpen: open of %s: %m",
531                                  OutputFileName);
532                 istty = isatty(fd);
533                 close(fd);
534
535                 /*
536                  * Redirect our stderr to the debug output file.
537                  */
538                 if (!freopen(OutputFileName, "a", stderr))
539                         elog(FATAL, "DebugFileOpen: %s reopen as stderr: %m",
540                                  OutputFileName);
541                 Debugfile = fileno(stderr);
542
543                 /*
544                  * If the file is a tty and we're running under the postmaster,
545                  * try to send stdout there as well (if it isn't a tty then stderr
546                  * will block out stdout, so we may as well let stdout go wherever
547                  * it was going before).
548                  */
549                 if (istty && IsUnderPostmaster)
550                         if (!freopen(OutputFileName, "a", stdout))
551                                 elog(FATAL, "DebugFileOpen: %s reopen as stdout: %m",
552                                          OutputFileName);
553                 return Debugfile;
554         }
555
556         /*
557          * If no filename was specified, send debugging output to stderr. If
558          * stderr has been hosed, try to open a file.
559          */
560         fd = fileno(stderr);
561         if (fcntl(fd, F_GETFD, 0) < 0)
562         {
563                 snprintf(OutputFileName, MAXPGPATH, "%s/pg.errors.%d",
564                                  DataDir, (int) MyProcPid);
565                 fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666);
566         }
567         if (fd < 0)
568                 elog(FATAL, "DebugFileOpen: could not open debugging file");
569
570         Debugfile = fd;
571         return Debugfile;
572 }
573
574
575 /*
576  * Return a timestamp string like
577  *
578  *       "2000-06-04 13:12:03 "
579  */
580 static const char *
581 print_timestamp(void)
582 {
583         time_t          curtime;
584         static char buf[TIMESTAMP_SIZE + 1];
585
586         curtime = time(NULL);
587
588         strftime(buf, sizeof(buf),
589                          "%Y-%m-%d %H:%M:%S ",
590                          localtime(&curtime));
591
592         return buf;
593 }
594
595
596
597 /*
598  * Return a string like
599  *
600  *         "[123456] "
601  *
602  * with the current pid.
603  */
604 static const char *
605 print_pid(void)
606 {
607         static char buf[PID_SIZE + 1];
608
609         snprintf(buf, PID_SIZE + 1, "[%d]      ", (int) MyProcPid);
610         return buf;
611 }
612
613
614
615 #ifdef ENABLE_SYSLOG
616
617 #ifndef PG_SYSLOG_LIMIT
618 #define PG_SYSLOG_LIMIT 128
619 #endif
620
621 /*
622  * Write a message line to syslog if the syslog option is set.
623  *
624  * Our problem here is that many syslog implementations don't handle
625  * long messages in an acceptable manner. While this function doesn't
626  * help that fact, it does work around by splitting up messages into
627  * smaller pieces.
628  */
629 static void
630 write_syslog(int level, const char *line)
631 {
632         static bool openlog_done = false;
633         static unsigned long seq = 0;
634         static int      syslog_fac = LOG_LOCAL0;
635
636         int                     len = strlen(line);
637
638         if (Use_syslog == 0)
639                 return;
640
641         if (!openlog_done)
642         {
643                 if (strcasecmp(Syslog_facility, "LOCAL0") == 0)
644                         syslog_fac = LOG_LOCAL0;
645                 if (strcasecmp(Syslog_facility, "LOCAL1") == 0)
646                         syslog_fac = LOG_LOCAL1;
647                 if (strcasecmp(Syslog_facility, "LOCAL2") == 0)
648                         syslog_fac = LOG_LOCAL2;
649                 if (strcasecmp(Syslog_facility, "LOCAL3") == 0)
650                         syslog_fac = LOG_LOCAL3;
651                 if (strcasecmp(Syslog_facility, "LOCAL4") == 0)
652                         syslog_fac = LOG_LOCAL4;
653                 if (strcasecmp(Syslog_facility, "LOCAL5") == 0)
654                         syslog_fac = LOG_LOCAL5;
655                 if (strcasecmp(Syslog_facility, "LOCAL6") == 0)
656                         syslog_fac = LOG_LOCAL6;
657                 if (strcasecmp(Syslog_facility, "LOCAL7") == 0)
658                         syslog_fac = LOG_LOCAL7;
659                 openlog(Syslog_ident, LOG_PID | LOG_NDELAY, syslog_fac);
660                 openlog_done = true;
661         }
662
663         /*
664          * We add a sequence number to each log message to suppress "same"
665          * messages.
666          */
667         seq++;
668
669         /* divide into multiple syslog() calls if message is too long */
670         /* or if the message contains embedded NewLine(s) '\n' */
671         if (len > PG_SYSLOG_LIMIT || strchr(line, '\n') != NULL)
672         {
673                 int                     chunk_nr = 0;
674
675                 while (len > 0)
676                 {
677                         char            buf[PG_SYSLOG_LIMIT + 1];
678                         int                     buflen;
679                         int                     l;
680                         int                     i;
681
682                         /* if we start at a newline, move ahead one char */
683                         if (line[0] == '\n')
684                         {
685                                 line++;
686                                 len--;
687                                 continue;
688                         }
689
690                         strncpy(buf, line, PG_SYSLOG_LIMIT);
691                         buf[PG_SYSLOG_LIMIT] = '\0';
692                         if (strchr(buf, '\n') != NULL)
693                                 *strchr(buf, '\n') = '\0';
694
695                         l = strlen(buf);
696 #ifdef MULTIBYTE
697                         /* trim to multibyte letter boundary */
698                         buflen = pg_mbcliplen(buf, l, l);
699                         if (buflen <= 0)
700                                 return;
701                         buf[buflen] = '\0';
702                         l = strlen(buf);
703 #endif
704                         /* already word boundary? */
705                         if (isspace((unsigned char) line[l]) || line[l] == '\0')
706                                 buflen = l;
707                         else
708                         {
709                                 /* try to divide at word boundary */
710                                 i = l - 1;
711                                 while (i > 0 && !isspace((unsigned char) buf[i]))
712                                         i--;
713
714                                 if (i <= 0)             /* couldn't divide word boundary */
715                                         buflen = l;
716                                 else
717                                 {
718                                         buflen = i;
719                                         buf[i] = '\0';
720                                 }
721                         }
722
723                         chunk_nr++;
724
725                         syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf);
726                         line += buflen;
727                         len -= buflen;
728                 }
729         }
730         else
731         {
732                 /* message short enough */
733                 syslog(level, "[%lu] %s", seq, line);
734         }
735 }
736 #endif   /* ENABLE_SYSLOG */
737
738
739 static void
740 send_message_to_frontend(int type, const char *msg)
741 {
742         StringInfoData buf;
743
744         AssertArg(type <= ERROR);
745
746         pq_beginmessage(&buf);
747         pq_sendbyte(&buf, type != ERROR ? 'N' : 'E'); /* N is INFO, NOTICE,
748                                                                                                    * or WARNING */
749         pq_sendstring(&buf, msg);
750         pq_endmessage(&buf);
751
752         /*
753          * This flush is normally not necessary, since postgres.c will flush
754          * out waiting data when control returns to the main loop. But it
755          * seems best to leave it here, so that the client has some clue what
756          * happened if the backend dies before getting back to the main loop
757          * ... error/notice messages should not be a performance-critical path
758          * anyway, so an extra flush won't hurt much ...
759          */
760         pq_flush();
761 }
762
763
764 static const char *
765 useful_strerror(int errnum)
766 {
767         /* this buffer is only used if errno has a bogus value */
768         static char errorstr_buf[48];
769         char       *str;
770
771         if (errnum == ERANGE)
772                 /* small trick to save creating many regression test result files */
773                 str = gettext("Numerical result out of range");
774         else
775                 str = strerror(errnum);
776
777         /*
778          * Some strerror()s return an empty string for out-of-range errno.
779          * This is ANSI C spec compliant, but not exactly useful.
780          */
781         if (str == NULL || *str == '\0')
782         {
783                 /*
784                  * translator: This string will be truncated at 47 characters
785                  * expanded.
786                  */
787                 snprintf(errorstr_buf, 48, gettext("operating system error %d"),
788                                  errnum);
789                 str = errorstr_buf;
790         }
791
792         return str;
793 }
794
795
796
797 static const char *
798 elog_message_prefix(int lev)
799 {
800         const char *prefix = NULL;
801
802         switch (lev)
803         {
804                 case DEBUG1:
805                 case DEBUG2:
806                 case DEBUG3:
807                 case DEBUG4:
808                 case DEBUG5:
809                         prefix = gettext("DEBUG:  ");
810                         break;
811                 case LOG:
812                 case COMMERROR:
813                         prefix = gettext("LOG:  ");
814                         break;
815                 case INFO:
816                         prefix = gettext("INFO:  ");
817                         break;
818                 case NOTICE:
819                         prefix = gettext("NOTICE:  ");
820                         break;
821                 case WARNING:
822                         prefix = gettext("WARNING:  ");
823                         break;
824                 case ERROR:
825                         prefix = gettext("ERROR:  ");
826                         break;
827                 case FATAL:
828                         prefix = gettext("FATAL:  ");
829                         break;
830                 case PANIC:
831                         prefix = gettext("PANIC:  ");
832                         break;
833         }
834
835         Assert(prefix != NULL);
836         return prefix;
837 }
838
839
840 /*
841  * GUC support routines
842  */
843
844 bool
845 check_server_min_messages(const char *lev)
846 {
847         if (strcasecmp(lev, "debug") == 0 ||
848                 strcasecmp(lev, "debug5") == 0 ||
849                 strcasecmp(lev, "debug4") == 0 ||
850                 strcasecmp(lev, "debug3") == 0 ||
851                 strcasecmp(lev, "debug2") == 0 ||
852                 strcasecmp(lev, "debug1") == 0 ||
853                 strcasecmp(lev, "info") == 0 ||
854                 strcasecmp(lev, "notice") == 0 ||
855                 strcasecmp(lev, "warning") == 0 ||
856                 strcasecmp(lev, "error") == 0 ||
857                 strcasecmp(lev, "log") == 0 ||
858                 strcasecmp(lev, "fatal") == 0 ||
859                 strcasecmp(lev, "panic") == 0)
860                 return true;
861         return false;
862 }
863
864 void
865 assign_server_min_messages(const char *lev)
866 {
867         if (strcasecmp(lev, "debug") == 0)
868                 server_min_messages = DEBUG5;
869         else if (strcasecmp(lev, "debug5") == 0)
870                 server_min_messages = DEBUG5;
871         else if (strcasecmp(lev, "debug4") == 0)
872                 server_min_messages = DEBUG4;
873         else if (strcasecmp(lev, "debug3") == 0)
874                 server_min_messages = DEBUG3;
875         else if (strcasecmp(lev, "debug2") == 0)
876                 server_min_messages = DEBUG2;
877         else if (strcasecmp(lev, "debug1") == 0)
878                 server_min_messages = DEBUG1;
879         else if (strcasecmp(lev, "info") == 0)
880                 server_min_messages = INFO;
881         else if (strcasecmp(lev, "notice") == 0)
882                 server_min_messages = NOTICE;
883         else if (strcasecmp(lev, "warning") == 0)
884                 server_min_messages = WARNING;
885         else if (strcasecmp(lev, "error") == 0)
886                 server_min_messages = ERROR;
887         else if (strcasecmp(lev, "log") == 0)
888                 server_min_messages = LOG;
889         else if (strcasecmp(lev, "fatal") == 0)
890                 server_min_messages = FATAL;
891         else if (strcasecmp(lev, "panic") == 0)
892                 server_min_messages = PANIC;
893         else
894                 /* Can't get here unless guc.c screwed up */
895                 elog(ERROR, "bogus server_min_messages %s", lev);
896 }
897
898 bool
899 check_client_min_messages(const char *lev)
900 {
901         if (strcasecmp(lev, "debug") == 0 ||
902                 strcasecmp(lev, "debug5") == 0 ||
903                 strcasecmp(lev, "debug4") == 0 ||
904                 strcasecmp(lev, "debug3") == 0 ||
905                 strcasecmp(lev, "debug2") == 0 ||
906                 strcasecmp(lev, "debug1") == 0 ||
907                 strcasecmp(lev, "log") == 0 ||
908                 strcasecmp(lev, "info") == 0 ||
909                 strcasecmp(lev, "notice") == 0 ||
910                 strcasecmp(lev, "warning") == 0 ||
911                 strcasecmp(lev, "error") == 0)
912                 return true;
913         return false;
914 }
915
916 void
917 assign_client_min_messages(const char *lev)
918 {
919         if (strcasecmp(lev, "debug") == 0)
920                 client_min_messages = DEBUG5;
921         else if (strcasecmp(lev, "debug5") == 0)
922                 client_min_messages = DEBUG5;
923         else if (strcasecmp(lev, "debug4") == 0)
924                 client_min_messages = DEBUG4;
925         else if (strcasecmp(lev, "debug3") == 0)
926                 client_min_messages = DEBUG3;
927         else if (strcasecmp(lev, "debug2") == 0)
928                 client_min_messages = DEBUG2;
929         else if (strcasecmp(lev, "debug1") == 0)
930                 client_min_messages = DEBUG1;
931         else if (strcasecmp(lev, "log") == 0)
932                 client_min_messages = LOG;
933         else if (strcasecmp(lev, "info") == 0)
934                 client_min_messages = INFO;
935         else if (strcasecmp(lev, "notice") == 0)
936                 client_min_messages = NOTICE;
937         else if (strcasecmp(lev, "warning") == 0)
938                 client_min_messages = WARNING;
939         else if (strcasecmp(lev, "error") == 0)
940                 client_min_messages = ERROR;
941         else
942                 /* Can't get here unless guc.c screwed up */
943                 elog(ERROR, "bogus client_min_messages %s", lev);
944 }