Header And Logo

PostgreSQL
| The world's most advanced open source database.

util.c

Go to the documentation of this file.
00001 /*
00002  *  util.c
00003  *
00004  *  utility functions
00005  *
00006  *  Copyright (c) 2010-2013, PostgreSQL Global Development Group
00007  *  contrib/pg_upgrade/util.c
00008  */
00009 
00010 #include "postgres_fe.h"
00011 
00012 #include "pg_upgrade.h"
00013 
00014 #include <signal.h>
00015 
00016 
00017 LogOpts     log_opts;
00018 
00019 /*
00020  * report_status()
00021  *
00022  *  Displays the result of an operation (ok, failed, error message,...)
00023  */
00024 void
00025 report_status(eLogType type, const char *fmt,...)
00026 {
00027     va_list     args;
00028     char        message[MAX_STRING];
00029 
00030     va_start(args, fmt);
00031     vsnprintf(message, sizeof(message), fmt, args);
00032     va_end(args);
00033 
00034     pg_log(type, "%s\n", message);
00035 }
00036 
00037 
00038 /* force blank output for progress display */
00039 void
00040 end_progress_output(void)
00041 {
00042     /*
00043      *  In case nothing printed; pass a space so gcc doesn't complain about
00044      *  empty format string.
00045      */
00046     prep_status(" ");
00047 }
00048 
00049 
00050 /*
00051  * prep_status
00052  *
00053  *  Displays a message that describes an operation we are about to begin.
00054  *  We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
00055  *  "failed" indicators line up nicely.
00056  *
00057  *  A typical sequence would look like this:
00058  *      prep_status("about to flarb the next %d files", fileCount );
00059  *
00060  *      if(( message = flarbFiles(fileCount)) == NULL)
00061  *        report_status(PG_REPORT, "ok" );
00062  *      else
00063  *        pg_log(PG_FATAL, "failed - %s\n", message );
00064  */
00065 void
00066 prep_status(const char *fmt,...)
00067 {
00068     va_list     args;
00069     char        message[MAX_STRING];
00070 
00071     va_start(args, fmt);
00072     vsnprintf(message, sizeof(message), fmt, args);
00073     va_end(args);
00074 
00075     if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
00076         pg_log(PG_REPORT, "%s", message);
00077     else
00078         /* trim strings that don't end in a newline */
00079         pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
00080 }
00081 
00082 
00083 void
00084 pg_log(eLogType type, char *fmt,...)
00085 {
00086     va_list     args;
00087     char        message[MAX_STRING];
00088 
00089     va_start(args, fmt);
00090     vsnprintf(message, sizeof(message), fmt, args);
00091     va_end(args);
00092 
00093     /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
00094     /* fopen() on log_opts.internal might have failed, so check it */
00095     if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
00096         log_opts.internal != NULL)
00097     {
00098         if (type == PG_STATUS)
00099             /* status messages need two leading spaces and a newline */
00100             fprintf(log_opts.internal, "  %s\n", message);
00101         else
00102             fprintf(log_opts.internal, "%s", message);
00103         fflush(log_opts.internal);
00104     }
00105 
00106     switch (type)
00107     {
00108         case PG_VERBOSE:
00109             if (log_opts.verbose)
00110                 printf("%s", _(message));
00111             break;
00112 
00113         case PG_STATUS:
00114             /* for output to a display, do leading truncation and append \r */
00115             if (isatty(fileno(stdout)))
00116                 /* -2 because we use a 2-space indent */
00117                 printf("  %s%-*.*s\r", 
00118                         /* prefix with "..." if we do leading truncation */
00119                         strlen(message) <= MESSAGE_WIDTH - 2 ? "" : "...",
00120                         MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
00121                         /* optional leading truncation */
00122                         strlen(message) <= MESSAGE_WIDTH - 2 ? message :
00123                         message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
00124             else
00125                 printf("  %s\n", _(message));
00126             break;
00127 
00128         case PG_REPORT:
00129         case PG_WARNING:
00130             printf("%s", _(message));
00131             break;
00132 
00133         case PG_FATAL:
00134             printf("\n%s", _(message));
00135             printf("Failure, exiting\n");
00136             exit(1);
00137             break;
00138 
00139         default:
00140             break;
00141     }
00142     fflush(stdout);
00143 }
00144 
00145 
00146 void
00147 check_ok(void)
00148 {
00149     /* all seems well */
00150     report_status(PG_REPORT, "ok");
00151     fflush(stdout);
00152 }
00153 
00154 
00155 /*
00156  * quote_identifier()
00157  *      Properly double-quote a SQL identifier.
00158  *
00159  * The result should be pg_free'd, but most callers don't bother because
00160  * memory leakage is not a big deal in this program.
00161  */
00162 char *
00163 quote_identifier(const char *s)
00164 {
00165     char       *result = pg_malloc(strlen(s) * 2 + 3);
00166     char       *r = result;
00167 
00168     *r++ = '"';
00169     while (*s)
00170     {
00171         if (*s == '"')
00172             *r++ = *s;
00173         *r++ = *s;
00174         s++;
00175     }
00176     *r++ = '"';
00177     *r++ = '\0';
00178 
00179     return result;
00180 }
00181 
00182 
00183 /*
00184  * get_user_info()
00185  * (copied from initdb.c) find the current user
00186  */
00187 int
00188 get_user_info(char **user_name)
00189 {
00190     int         user_id;
00191 
00192 #ifndef WIN32
00193     struct passwd *pw = getpwuid(geteuid());
00194 
00195     user_id = geteuid();
00196 #else                           /* the windows code */
00197     struct passwd_win32
00198     {
00199         int         pw_uid;
00200         char        pw_name[128];
00201     }           pass_win32;
00202     struct passwd_win32 *pw = &pass_win32;
00203     DWORD       pwname_size = sizeof(pass_win32.pw_name) - 1;
00204 
00205     GetUserName(pw->pw_name, &pwname_size);
00206 
00207     user_id = 1;
00208 #endif
00209 
00210     *user_name = pg_strdup(pw->pw_name);
00211 
00212     return user_id;
00213 }
00214 
00215 
00216 /*
00217  * getErrorText()
00218  *
00219  *  Returns the text of the error message for the given error number
00220  *
00221  *  This feature is factored into a separate function because it is
00222  *  system-dependent.
00223  */
00224 const char *
00225 getErrorText(int errNum)
00226 {
00227 #ifdef WIN32
00228     _dosmaperr(GetLastError());
00229 #endif
00230     return pg_strdup(strerror(errNum));
00231 }
00232 
00233 
00234 /*
00235  *  str2uint()
00236  *
00237  *  convert string to oid
00238  */
00239 unsigned int
00240 str2uint(const char *str)
00241 {
00242     return strtoul(str, NULL, 10);
00243 }
00244 
00245 
00246 /*
00247  *  pg_putenv()
00248  *
00249  *  This is like putenv(), but takes two arguments.
00250  *  It also does unsetenv() if val is NULL.
00251  */
00252 void
00253 pg_putenv(const char *var, const char *val)
00254 {
00255     if (val)
00256     {
00257 #ifndef WIN32
00258         char       *envstr = (char *) pg_malloc(strlen(var) +
00259                                                 strlen(val) + 2);
00260 
00261         sprintf(envstr, "%s=%s", var, val);
00262         putenv(envstr);
00263 
00264         /*
00265          * Do not free envstr because it becomes part of the environment on
00266          * some operating systems.  See port/unsetenv.c::unsetenv.
00267          */
00268 #else
00269         SetEnvironmentVariableA(var, val);
00270 #endif
00271     }
00272     else
00273     {
00274 #ifndef WIN32
00275         unsetenv(var);
00276 #else
00277         SetEnvironmentVariableA(var, "");
00278 #endif
00279     }
00280 }