GRASS Programmer's Manual
6.4.2(2012)
|
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 }