GRASS Programmer's Manual 6.4.1(2011)
error.c
Go to the documentation of this file.
00001 
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <time.h>
00019 #include <stdarg.h>
00020 #include <sys/types.h>
00021 #include <grass/glocale.h>
00022 #include <grass/gis.h>
00023 
00029 #define MSG  0
00030 
00035 #define WARN 1
00036 
00041 #define ERR  2
00042 
00043 
00044 /* static int (*error)() = 0; */
00045 static int (*ext_error) (const char *, int);    /* Roger Bivand 17 June 2000 */
00046 static int no_warn = 0;
00047 static int no_sleep = 1;
00048 static int message_id = 1;
00049 
00050 static int print_word(FILE *, char **, int *, const int);
00051 static void print_sentence(FILE *, const int, const char *);
00052 static int print_error(const char *, const int);
00053 static int mail_msg(const char *, int);
00054 static int write_error(const char *, int, time_t, const char *);
00055 static int log_error(const char *, int);
00056 
00057 static int vfprint_error(int type, const char *template, va_list ap)
00058 {
00059     char buffer[2000];          /* G_asprintf does not work */
00060 
00061     vsprintf(buffer, template, ap);
00062 
00063     /* . */
00064     return print_error(buffer, type);
00065 }
00066 
00074 void G_message(const char *msg, ...)
00075 {
00076     if (G_verbose() >= G_verbose_std()) {
00077         va_list ap;
00078 
00079         va_start(ap, msg);
00080         vfprint_error(MSG, msg, ap);
00081         va_end(ap);
00082     }
00083 
00084     return;
00085 }
00086 
00095 void G_verbose_message(const char *msg, ...)
00096 {
00097     if (G_verbose() > G_verbose_std()) {
00098         va_list ap;
00099 
00100         va_start(ap, msg);
00101         vfprint_error(MSG, msg, ap);
00102         va_end(ap);
00103     }
00104 
00105     return;
00106 }
00107 
00119 void G_important_message(const char *msg, ...)
00120 {
00121     if (G_verbose() > G_verbose_min()) {
00122         va_list ap;
00123 
00124         va_start(ap, msg);
00125         vfprint_error(MSG, msg, ap);
00126         va_end(ap);
00127     }
00128 
00129     return;
00130 }
00131 
00150 int G_fatal_error(const char *msg, ...)
00151 {
00152     va_list ap;
00153 
00154     va_start(ap, msg);
00155     vfprint_error(ERR, msg, ap);
00156     va_end(ap);
00157 
00158     exit(EXIT_FAILURE);
00159 }
00160 
00173 int G_warning(const char *msg, ...)
00174 {
00175     va_list ap;
00176 
00177     if (no_warn)
00178         return 0;
00179 
00180     va_start(ap, msg);
00181     vfprint_error(WARN, msg, ap);
00182     va_end(ap);
00183 
00184     return 0;
00185 }
00186 
00194 int G_suppress_warnings(int flag)
00195 {
00196     int prev;
00197 
00198     prev = no_warn;
00199     no_warn = flag;
00200     return prev;
00201 }
00202 
00210 int G_sleep_on_error(int flag)
00211 {
00212     int prev;
00213 
00214     prev = !no_sleep;
00215     no_sleep = !flag;
00216     return prev;
00217 }
00218 
00228 int G_set_error_routine(int (*error_routine) (const char *, int))
00229 {
00230     ext_error = error_routine;  /* Roger Bivand 17 June 2000 */
00231     return 0;
00232 }
00233 
00242 int G_unset_error_routine(void)
00243 {
00244     ext_error = 0;              /* Roger Bivand 17 June 2000 */
00245 
00246     return 0;
00247 }
00248 
00249 /* Print info to stderr and optionally to log file and optionally send mail */
00250 static int print_error(const char *msg, const int type)
00251 {
00252     static char *prefix_std[3];
00253     int fatal, format;
00254 
00255     if (!prefix_std[0]) {       /* First time: set prefixes  */
00256         prefix_std[0] = "";
00257         prefix_std[1] = _("WARNING: ");
00258         prefix_std[2] = _("ERROR: ");
00259     }
00260 
00261     if (type == ERR)
00262         fatal = TRUE;
00263     else                        /* WARN */
00264         fatal = FALSE;
00265 
00266     if ((type == WARN || type == ERR) && ext_error) {   /* Function defined by application */
00267         ext_error(msg, fatal);
00268     }
00269     else {
00270         char *w;
00271         int len, lead;
00272 
00273         format = G_info_format();
00274 
00275         if (format != G_INFO_FORMAT_GUI) {
00276             if (type == WARN || type == ERR) {
00277                 log_error(msg, fatal);
00278             }
00279 
00280             fprintf(stderr, "%s", prefix_std[type]);
00281             len = lead = strlen(prefix_std[type]);
00282             w = (char *)msg;
00283 
00284             while (print_word(stderr, &w, &len, lead)) ;
00285 
00286             if ((type != MSG) && isatty(fileno(stderr))
00287                 && (G_info_format() == G_INFO_FORMAT_STANDARD)) {       /* Bell */
00288                 fprintf(stderr, "\7");
00289                 fflush(stderr);
00290                 if (!no_sleep)
00291                     G_sleep(5);
00292             }
00293             else if ((type == WARN || type == ERR) && getenv("GRASS_ERROR_MAIL")) {     /* Mail */
00294                 mail_msg(msg, fatal);
00295             }
00296         }
00297         else {                  /* GUI */
00298             print_sentence(stderr, type, msg);
00299         }
00300     }
00301 
00302     return 0;
00303 }
00304 
00305 static int log_error(const char *msg, int fatal)
00306 {
00307     char cwd[GPATH_MAX];
00308     time_t clock;
00309     char *gisbase;
00310 
00311     /* get time */
00312     clock = time(NULL);
00313 
00314     /* get current working directory */
00315     getcwd(cwd, sizeof(cwd));
00316 
00317     /* write the error log file */
00318     if ((gisbase = G_gisbase()))
00319         write_error(msg, fatal, clock, cwd);
00320 
00321     return 0;
00322 }
00323 
00324 /* Write a message to the log file */
00325 static int write_error(const char *msg, int fatal,
00326                        time_t clock, const char *cwd)
00327 {
00328     static char *logfile;
00329     FILE *log;
00330 
00331     if (!logfile) {
00332         logfile = getenv("GIS_ERROR_LOG");
00333         if (!logfile) {
00334             char buf[GPATH_MAX];
00335 
00336             sprintf(buf, "%s/GIS_ERROR_LOG", G__home());
00337             logfile = G_store(buf);
00338         }
00339     }
00340 
00341     log = fopen(logfile, "r");
00342     if (!log)
00343         /* GIS_ERROR_LOG file is not readable or does not exist */
00344         return 1;
00345 
00346     log = freopen(logfile, "a", log);
00347     if (!log)
00348         /* the user doesn't have write permission */
00349         return 1;
00350 
00351     fprintf(log, "-------------------------------------\n");
00352     fprintf(log, "%-10s %s\n", "program:", G_program_name());
00353     fprintf(log, "%-10s %s\n", "user:", G_whoami());
00354     fprintf(log, "%-10s %s\n", "cwd:", cwd);
00355     fprintf(log, "%-10s %s\n", "date:", ctime(&clock));
00356     fprintf(log, "%-10s %s\n", fatal ? "error:" : "warning:", msg);
00357     fprintf(log, "-------------------------------------\n");
00358 
00359     fclose(log);
00360 
00361     return 0;
00362 }
00363 
00364 /* Mail a message */
00365 static int mail_msg(const char *msg, int fatal)
00366 {
00367     FILE *mail;
00368     char command[64];
00369     char *user;
00370 
00371     user = G_whoami();
00372     if (user == 0 || *user == 0)
00373         return 1;
00374 
00375     sprintf(command, "mail '%s'", G_whoami());
00376     if ((mail = popen(command, "w"))) {
00377         fprintf(mail, "GIS %s: %s\n", fatal ? "ERROR" : "WARNING", msg);
00378         G_pclose(mail);
00379     }
00380 
00381     return 0;
00382 }
00383 
00384 /* Print one word, new line if necessary */
00385 static int print_word(FILE * fd, char **word, int *len, const int lead)
00386 {
00387     int wlen, start, totlen;
00388     int nl;
00389     char *w, *b;
00390 
00391     start = *len;
00392     w = *word;
00393 
00394     nl = 0;
00395     while (*w == ' ' || *w == '\t' || *w == '\n')
00396         if (*w++ == '\n')
00397             nl++;
00398 
00399     wlen = 0;
00400     for (b = w; *b != 0 && *b != ' ' && *b != '\t' && *b != '\n'; b++)
00401         wlen++;
00402 
00403     if (wlen == 0) {
00404         fprintf(fd, "\n");
00405         return 0;
00406     }
00407 
00408     if (start > lead) {         /* add space */
00409         totlen = start + wlen + 1;
00410     }
00411     else {
00412         totlen = start + wlen;
00413     }
00414 
00415     if (nl != 0 || totlen > 75) {
00416         while (--nl > 0)
00417             fprintf(fd, "\n");
00418         fprintf(fd, "\n%*s", lead, "");
00419         start = lead;
00420     }
00421 
00422     if (start > lead) {
00423         fprintf(fd, " ");
00424         start++;
00425     }
00426 
00427     *len = start + wlen;
00428 
00429     fwrite(w, 1, wlen, fd);
00430     w += wlen;
00431 
00432     *word = w;
00433 
00434     return 1;
00435 }
00436 
00437 /* Print one message, prefix inserted before each new line */
00438 static void print_sentence(FILE * fd, const int type, const char *msg)
00439 {
00440     char prefix[100];
00441     const char *start;
00442 
00443     switch (type) {
00444     case MSG:
00445         sprintf(prefix, "GRASS_INFO_MESSAGE(%d,%d): ", getpid(), message_id);
00446         break;
00447     case WARN:
00448         sprintf(prefix, "GRASS_INFO_WARNING(%d,%d): ", getpid(), message_id);
00449         break;
00450     case ERR:
00451         sprintf(prefix, "GRASS_INFO_ERROR(%d,%d): ", getpid(), message_id);
00452         break;
00453     }
00454 
00455     start = msg;
00456 
00457     fprintf(stderr, "\n");
00458     while (*start != '\0') {
00459         const char *next = start;
00460 
00461         fprintf(fd, "%s", prefix);
00462 
00463         while (*next != '\0') {
00464             next++;
00465 
00466             if (*next == '\n') {
00467                 next++;
00468                 break;
00469             }
00470         }
00471 
00472         fwrite(start, 1, next - start, fd);
00473         fprintf(fd, "\n");
00474         start = next;
00475     }
00476     fprintf(stderr, "GRASS_INFO_END(%d,%d)\n", getpid(), message_id);
00477     message_id++;
00478 }
00479 
00487 int G_info_format(void)
00488 {
00489     static int grass_info_format = -1;
00490     char *fstr;
00491 
00492     if (grass_info_format < 0) {
00493         fstr = getenv("GRASS_MESSAGE_FORMAT");
00494 
00495         if (fstr && G_strcasecmp(fstr, "gui") == 0)
00496             grass_info_format = G_INFO_FORMAT_GUI;
00497         else if (fstr && G_strcasecmp(fstr, "silent") == 0)
00498             grass_info_format = G_INFO_FORMAT_SILENT;
00499         else if (fstr && G_strcasecmp(fstr, "plain") == 0)
00500             grass_info_format = G_INFO_FORMAT_PLAIN;
00501         else
00502             grass_info_format = G_INFO_FORMAT_STANDARD;
00503     }
00504 
00505     return grass_info_format;
00506 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines