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
00045 static int (*ext_error) (const char *, int);
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];
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;
00231 return 0;
00232 }
00233
00242 int G_unset_error_routine(void)
00243 {
00244 ext_error = 0;
00245
00246 return 0;
00247 }
00248
00249
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]) {
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
00264 fatal = FALSE;
00265
00266 if ((type == WARN || type == ERR) && ext_error) {
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)) {
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")) {
00294 mail_msg(msg, fatal);
00295 }
00296 }
00297 else {
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
00312 clock = time(NULL);
00313
00314
00315 getcwd(cwd, sizeof(cwd));
00316
00317
00318 if ((gisbase = G_gisbase()))
00319 write_error(msg, fatal, clock, cwd);
00320
00321 return 0;
00322 }
00323
00324
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
00344 return 1;
00345
00346 log = freopen(logfile, "a", log);
00347 if (!log)
00348
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
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
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) {
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
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 }