|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
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 == MSG || type == WARN || type == ERR) && ext_error) { /* Function defined by application */ 00267 ext_error(msg, fatal); 00268 } 00269 else { 00270 format = G_info_format(); 00271 00272 if (type == WARN || type == ERR) 00273 log_error(msg, fatal); 00274 00275 if (format == G_INFO_FORMAT_SILENT) 00276 return; 00277 00278 if (format != G_INFO_FORMAT_GUI) { 00279 if (format != G_INFO_FORMAT_PLAIN) { 00280 char *w; 00281 int len, lead; 00282 00283 fprintf(stderr, "%s", prefix_std[type]); 00284 len = lead = strlen(prefix_std[type]); 00285 w = (char *)msg; 00286 00287 while (print_word(stderr, &w, &len, lead)) ; 00288 } 00289 else { 00290 fprintf(stderr, "%s\n", msg); 00291 } 00292 00293 if ((type != MSG) && isatty(fileno(stderr)) 00294 && (G_info_format() == G_INFO_FORMAT_STANDARD)) { /* Bell */ 00295 fprintf(stderr, "\7"); 00296 fflush(stderr); 00297 if (!no_sleep) 00298 G_sleep(5); 00299 } 00300 else if ((type == WARN || type == ERR) && getenv("GRASS_ERROR_MAIL")) { /* Mail */ 00301 mail_msg(msg, fatal); 00302 } 00303 } 00304 else { /* GUI */ 00305 print_sentence(stderr, type, msg); 00306 } 00307 } 00308 00309 return 0; 00310 } 00311 00312 static int log_error(const char *msg, int fatal) 00313 { 00314 char cwd[GPATH_MAX]; 00315 time_t clock; 00316 char *gisbase; 00317 00318 /* get time */ 00319 clock = time(NULL); 00320 00321 /* get current working directory */ 00322 getcwd(cwd, sizeof(cwd)); 00323 00324 /* write the error log file */ 00325 if ((gisbase = G_gisbase())) 00326 write_error(msg, fatal, clock, cwd); 00327 00328 return 0; 00329 } 00330 00331 /* Write a message to the log file */ 00332 static int write_error(const char *msg, int fatal, 00333 time_t clock, const char *cwd) 00334 { 00335 static char *logfile; 00336 FILE *log; 00337 00338 if (!logfile) { 00339 logfile = getenv("GIS_ERROR_LOG"); 00340 if (!logfile) { 00341 char buf[GPATH_MAX]; 00342 00343 sprintf(buf, "%s/GIS_ERROR_LOG", G__home()); 00344 logfile = G_store(buf); 00345 } 00346 } 00347 00348 log = fopen(logfile, "r"); 00349 if (!log) 00350 /* GIS_ERROR_LOG file is not readable or does not exist */ 00351 return 1; 00352 00353 log = freopen(logfile, "a", log); 00354 if (!log) 00355 /* the user doesn't have write permission */ 00356 return 1; 00357 00358 fprintf(log, "-------------------------------------\n"); 00359 fprintf(log, "%-10s %s\n", "program:", G_program_name()); 00360 fprintf(log, "%-10s %s\n", "user:", G_whoami()); 00361 fprintf(log, "%-10s %s\n", "cwd:", cwd); 00362 fprintf(log, "%-10s %s\n", "date:", ctime(&clock)); 00363 fprintf(log, "%-10s %s\n", fatal ? "error:" : "warning:", msg); 00364 fprintf(log, "-------------------------------------\n"); 00365 00366 fclose(log); 00367 00368 return 0; 00369 } 00370 00371 /* Mail a message */ 00372 static int mail_msg(const char *msg, int fatal) 00373 { 00374 FILE *mail; 00375 char command[64]; 00376 char *user; 00377 00378 user = G_whoami(); 00379 if (user == 0 || *user == 0) 00380 return 1; 00381 00382 sprintf(command, "mail '%s'", G_whoami()); 00383 if ((mail = popen(command, "w"))) { 00384 fprintf(mail, "GIS %s: %s\n", fatal ? "ERROR" : "WARNING", msg); 00385 pclose(mail); 00386 } 00387 00388 return 0; 00389 } 00390 00391 /* Print one word, new line if necessary */ 00392 static int print_word(FILE * fd, char **word, int *len, const int lead) 00393 { 00394 int wlen, start, totlen; 00395 int nl; 00396 char *w, *b; 00397 00398 start = *len; 00399 w = *word; 00400 00401 nl = 0; 00402 while (*w == ' ' || *w == '\t' || *w == '\n') 00403 if (*w++ == '\n') 00404 nl++; 00405 00406 wlen = 0; 00407 for (b = w; *b != 0 && *b != ' ' && *b != '\t' && *b != '\n'; b++) 00408 wlen++; 00409 00410 if (wlen == 0) { 00411 fprintf(fd, "\n"); 00412 return 0; 00413 } 00414 00415 if (start > lead) { /* add space */ 00416 totlen = start + wlen + 1; 00417 } 00418 else { 00419 totlen = start + wlen; 00420 } 00421 00422 if (nl != 0 || totlen > 75) { 00423 while (--nl > 0) 00424 fprintf(fd, "\n"); 00425 fprintf(fd, "\n%*s", lead, ""); 00426 start = lead; 00427 } 00428 00429 if (start > lead) { 00430 fprintf(fd, " "); 00431 start++; 00432 } 00433 00434 *len = start + wlen; 00435 00436 fwrite(w, 1, wlen, fd); 00437 w += wlen; 00438 00439 *word = w; 00440 00441 return 1; 00442 } 00443 00444 /* Print one message, prefix inserted before each new line */ 00445 static void print_sentence(FILE * fd, const int type, const char *msg) 00446 { 00447 char prefix[100]; 00448 const char *start; 00449 00450 switch (type) { 00451 case MSG: 00452 sprintf(prefix, "GRASS_INFO_MESSAGE(%d,%d): ", getpid(), message_id); 00453 break; 00454 case WARN: 00455 sprintf(prefix, "GRASS_INFO_WARNING(%d,%d): ", getpid(), message_id); 00456 break; 00457 case ERR: 00458 sprintf(prefix, "GRASS_INFO_ERROR(%d,%d): ", getpid(), message_id); 00459 break; 00460 } 00461 00462 start = msg; 00463 00464 fprintf(stderr, "\n"); 00465 while (*start != '\0') { 00466 const char *next = start; 00467 00468 fprintf(fd, "%s", prefix); 00469 00470 while (*next != '\0') { 00471 next++; 00472 00473 if (*next == '\n') { 00474 next++; 00475 break; 00476 } 00477 } 00478 00479 fwrite(start, 1, next - start, fd); 00480 fprintf(fd, "\n"); 00481 start = next; 00482 } 00483 fprintf(stderr, "GRASS_INFO_END(%d,%d)\n", getpid(), message_id); 00484 message_id++; 00485 } 00486 00494 int G_info_format(void) 00495 { 00496 static int grass_info_format = -1; 00497 char *fstr; 00498 00499 if (grass_info_format < 0) { 00500 fstr = getenv("GRASS_MESSAGE_FORMAT"); 00501 00502 if (fstr && G_strcasecmp(fstr, "gui") == 0) 00503 grass_info_format = G_INFO_FORMAT_GUI; 00504 else if (fstr && G_strcasecmp(fstr, "silent") == 0) 00505 grass_info_format = G_INFO_FORMAT_SILENT; 00506 else if (fstr && G_strcasecmp(fstr, "plain") == 0) 00507 grass_info_format = G_INFO_FORMAT_PLAIN; 00508 else 00509 grass_info_format = G_INFO_FORMAT_STANDARD; 00510 } 00511 00512 return grass_info_format; 00513 }