GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
lib/gis/error.c
Go to the documentation of this file.
1 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <stdarg.h>
20 #include <sys/types.h>
21 #include <grass/glocale.h>
22 #include <grass/gis.h>
23 
29 #define MSG 0
30 
35 #define WARN 1
36 
41 #define ERR 2
42 
43 
44 /* static int (*error)() = 0; */
45 static int (*ext_error) (const char *, int); /* Roger Bivand 17 June 2000 */
46 static int no_warn = 0;
47 static int no_sleep = 1;
48 static int message_id = 1;
49 
50 static int print_word(FILE *, char **, int *, const int);
51 static void print_sentence(FILE *, const int, const char *);
52 static int print_error(const char *, const int);
53 static int mail_msg(const char *, int);
54 static int write_error(const char *, int, time_t, const char *);
55 static int log_error(const char *, int);
56 
57 static int vfprint_error(int type, const char *template, va_list ap)
58 {
59  char buffer[2000]; /* G_asprintf does not work */
60 
61  vsprintf(buffer, template, ap);
62 
63  /* . */
64  return print_error(buffer, type);
65 }
66 
74 void G_message(const char *msg, ...)
75 {
76  if (G_verbose() >= G_verbose_std()) {
77  va_list ap;
78 
79  va_start(ap, msg);
80  vfprint_error(MSG, msg, ap);
81  va_end(ap);
82  }
83 
84  return;
85 }
86 
95 void G_verbose_message(const char *msg, ...)
96 {
97  if (G_verbose() > G_verbose_std()) {
98  va_list ap;
99 
100  va_start(ap, msg);
101  vfprint_error(MSG, msg, ap);
102  va_end(ap);
103  }
104 
105  return;
106 }
107 
119 void G_important_message(const char *msg, ...)
120 {
121  if (G_verbose() > G_verbose_min()) {
122  va_list ap;
123 
124  va_start(ap, msg);
125  vfprint_error(MSG, msg, ap);
126  va_end(ap);
127  }
128 
129  return;
130 }
131 
150 int G_fatal_error(const char *msg, ...)
151 {
152  static int busy;
153  va_list ap;
154 
155  if (busy)
156  exit(EXIT_FAILURE);
157  busy = 1;
158 
159  va_start(ap, msg);
160  vfprint_error(ERR, msg, ap);
161  va_end(ap);
162 
163  exit(EXIT_FAILURE);
164 }
165 
178 int G_warning(const char *msg, ...)
179 {
180  va_list ap;
181 
182  if (no_warn)
183  return 0;
184 
185  va_start(ap, msg);
186  vfprint_error(WARN, msg, ap);
187  va_end(ap);
188 
189  return 0;
190 }
191 
200 {
201  int prev;
202 
203  prev = no_warn;
204  no_warn = flag;
205  return prev;
206 }
207 
216 {
217  int prev;
218 
219  prev = !no_sleep;
220  no_sleep = !flag;
221  return prev;
222 }
223 
233 int G_set_error_routine(int (*error_routine) (const char *, int))
234 {
235  ext_error = error_routine; /* Roger Bivand 17 June 2000 */
236  return 0;
237 }
238 
248 {
249  ext_error = 0; /* Roger Bivand 17 June 2000 */
250 
251  return 0;
252 }
253 
254 /* Print info to stderr and optionally to log file and optionally send mail */
255 static int print_error(const char *msg, const int type)
256 {
257  static char *prefix_std[3];
258  int fatal, format;
259 
260  if (!prefix_std[0]) { /* First time: set prefixes */
261  prefix_std[0] = "";
262  prefix_std[1] = _("WARNING: ");
263  prefix_std[2] = _("ERROR: ");
264  }
265 
266  if (type == ERR)
267  fatal = TRUE;
268  else /* WARN */
269  fatal = FALSE;
270 
271  if ((type == MSG || type == WARN || type == ERR) && ext_error) { /* Function defined by application */
272  ext_error(msg, fatal);
273  }
274  else {
275  format = G_info_format();
276 
277  if (type == WARN || type == ERR)
278  log_error(msg, fatal);
279 
280  if (format == G_INFO_FORMAT_SILENT)
281  return 0;
282 
283  if (format != G_INFO_FORMAT_GUI) {
284  if (format != G_INFO_FORMAT_PLAIN) {
285  char *w;
286  int len, lead;
287 
288  fprintf(stderr, "%s", prefix_std[type]);
289  len = lead = strlen(prefix_std[type]);
290  w = (char *)msg;
291 
292  while (print_word(stderr, &w, &len, lead)) ;
293  }
294  else {
295  fprintf(stderr, "%s\n", msg);
296  }
297 
298  if ((type != MSG) && isatty(fileno(stderr))
299  && (G_info_format() == G_INFO_FORMAT_STANDARD)) { /* Bell */
300  fprintf(stderr, "\7");
301  fflush(stderr);
302  if (!no_sleep)
303  G_sleep(5);
304  }
305  else if ((type == WARN || type == ERR) && getenv("GRASS_ERROR_MAIL")) { /* Mail */
306  mail_msg(msg, fatal);
307  }
308  }
309  else { /* GUI */
310  print_sentence(stderr, type, msg);
311  }
312  }
313 
314  return 0;
315 }
316 
317 static int log_error(const char *msg, int fatal)
318 {
319  char cwd[GPATH_MAX];
320  time_t clock;
321  char *gisbase;
322 
323  /* get time */
324  clock = time(NULL);
325 
326  /* get current working directory */
327  getcwd(cwd, sizeof(cwd));
328 
329  /* write the error log file */
330  if ((gisbase = G_gisbase()))
331  write_error(msg, fatal, clock, cwd);
332 
333  return 0;
334 }
335 
336 /* Write a message to the log file */
337 static int write_error(const char *msg, int fatal,
338  time_t clock, const char *cwd)
339 {
340  static char *logfile;
341  FILE *log;
342 
343  if (!logfile) {
344  logfile = getenv("GIS_ERROR_LOG");
345  if (!logfile) {
346  char buf[GPATH_MAX];
347 
348  sprintf(buf, "%s/GIS_ERROR_LOG", G__home());
349  logfile = G_store(buf);
350  }
351  }
352 
353  log = fopen(logfile, "r");
354  if (!log)
355  /* GIS_ERROR_LOG file is not readable or does not exist */
356  return 1;
357 
358  log = freopen(logfile, "a", log);
359  if (!log)
360  /* the user doesn't have write permission */
361  return 1;
362 
363  fprintf(log, "-------------------------------------\n");
364  fprintf(log, "%-10s %s\n", "program:", G_program_name());
365  fprintf(log, "%-10s %s\n", "user:", G_whoami());
366  fprintf(log, "%-10s %s\n", "cwd:", cwd);
367  fprintf(log, "%-10s %s\n", "date:", ctime(&clock));
368  fprintf(log, "%-10s %s\n", fatal ? "error:" : "warning:", msg);
369  fprintf(log, "-------------------------------------\n");
370 
371  fclose(log);
372 
373  return 0;
374 }
375 
376 /* Mail a message */
377 static int mail_msg(const char *msg, int fatal)
378 {
379  FILE *mail;
380  char command[64];
381  char *user;
382 
383  user = G_whoami();
384  if (user == 0 || *user == 0)
385  return 1;
386 
387  sprintf(command, "mail '%s'", G_whoami());
388  if ((mail = popen(command, "w"))) {
389  fprintf(mail, "GIS %s: %s\n", fatal ? "ERROR" : "WARNING", msg);
390  pclose(mail);
391  }
392 
393  return 0;
394 }
395 
396 /* Print one word, new line if necessary */
397 static int print_word(FILE * fd, char **word, int *len, const int lead)
398 {
399  int wlen, start, totlen;
400  int nl;
401  char *w, *b;
402 
403  start = *len;
404  w = *word;
405 
406  nl = 0;
407  while (*w == ' ' || *w == '\t' || *w == '\n')
408  if (*w++ == '\n')
409  nl++;
410 
411  wlen = 0;
412  for (b = w; *b != 0 && *b != ' ' && *b != '\t' && *b != '\n'; b++)
413  wlen++;
414 
415  if (wlen == 0) {
416  fprintf(fd, "\n");
417  return 0;
418  }
419 
420  if (start > lead) { /* add space */
421  totlen = start + wlen + 1;
422  }
423  else {
424  totlen = start + wlen;
425  }
426 
427  if (nl != 0 || totlen > 75) {
428  while (--nl > 0)
429  fprintf(fd, "\n");
430  fprintf(fd, "\n%*s", lead, "");
431  start = lead;
432  }
433 
434  if (start > lead) {
435  fprintf(fd, " ");
436  start++;
437  }
438 
439  *len = start + wlen;
440 
441  fwrite(w, 1, wlen, fd);
442  w += wlen;
443 
444  *word = w;
445 
446  return 1;
447 }
448 
449 /* Print one message, prefix inserted before each new line */
450 static void print_sentence(FILE * fd, const int type, const char *msg)
451 {
452  char prefix[100];
453  const char *start;
454 
455  switch (type) {
456  case MSG:
457  sprintf(prefix, "GRASS_INFO_MESSAGE(%d,%d): ", getpid(), message_id);
458  break;
459  case WARN:
460  sprintf(prefix, "GRASS_INFO_WARNING(%d,%d): ", getpid(), message_id);
461  break;
462  case ERR:
463  sprintf(prefix, "GRASS_INFO_ERROR(%d,%d): ", getpid(), message_id);
464  break;
465  }
466 
467  start = msg;
468 
469  fprintf(stderr, "\n");
470  while (*start != '\0') {
471  const char *next = start;
472 
473  fprintf(fd, "%s", prefix);
474 
475  while (*next != '\0') {
476  next++;
477 
478  if (*next == '\n') {
479  next++;
480  break;
481  }
482  }
483 
484  fwrite(start, 1, next - start, fd);
485  fprintf(fd, "\n");
486  start = next;
487  }
488  fprintf(stderr, "GRASS_INFO_END(%d,%d)\n", getpid(), message_id);
489  message_id++;
490 }
491 
499 int G_info_format(void)
500 {
501  static int grass_info_format = -1;
502  char *fstr;
503 
504  if (grass_info_format < 0) {
505  fstr = getenv("GRASS_MESSAGE_FORMAT");
506 
507  if (fstr && G_strcasecmp(fstr, "gui") == 0)
508  grass_info_format = G_INFO_FORMAT_GUI;
509  else if (fstr && G_strcasecmp(fstr, "silent") == 0)
510  grass_info_format = G_INFO_FORMAT_SILENT;
511  else if (fstr && G_strcasecmp(fstr, "plain") == 0)
512  grass_info_format = G_INFO_FORMAT_PLAIN;
513  else
514  grass_info_format = G_INFO_FORMAT_STANDARD;
515  }
516 
517  return grass_info_format;
518 }
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:192
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
float b
Definition: named_colr.c:8
int G_unset_error_routine(void)
After this call subsequent error messages will be handled in the default method.
char * G_store(const char *s)
Copy string to allocated memory.
Definition: store.c:32
#define FALSE
Definition: dbfopen.c:117
FILE * fd
Definition: g3dcolor.c:368
void G_important_message(const char *msg,...)
Print a message to stderr even in brief mode (verbosity=1)
int G_suppress_warnings(int flag)
Suppress printing a warning message to stderr.
void print_error(int err_code, char *msg,...)
Definition: gem/error.c:32
int G_set_error_routine(int(*error_routine)(const char *, int))
Establishes error_routine as the routine that will handle the printing of subsequent error messages...
list command
Definition: render.py:1315
tuple gisbase
Definition: forms.py:59
#define ERR
A fatal error message.
Definition: lib/gis/error.c:41
char * getenv()
def fatal
Display an error message using g.message -e, then abort.
Definition: core.py:383
log
Definition: wxnviz.py:54
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition: lib/gis/error.c:95
void G_message(const char *msg,...)
Print a message to stderr.
Definition: lib/gis/error.c:74
#define WARN
A warning message.
Definition: lib/gis/error.c:35
#define TRUE
Definition: dbfopen.c:118
int G_info_format(void)
Get current message format.
void G_sleep(unsigned int seconds)
Definition: sleep.c:11
flag
Definition: tools.py:1403
#define MSG
A message.
Definition: lib/gis/error.c:29
int
Definition: g3dcolor.c:48
const char * G_program_name(void)
return module name
Definition: progrm_nme.c:33
int G_verbose_std(void)
Get standard verbosity level.
Definition: verbose.c:80
int G_verbose(void)
Get current verbosity level.
Definition: verbose.c:45
char * G_whoami(void)
Gets user&#39;s name.
Definition: gis/whoami.c:40
struct ellps_list * next
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
return NULL
Definition: dbfopen.c:1394
tuple msg
Definition: wxnviz.py:32
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
fclose(fd)
char * G_gisbase(void)
top level module directory
Definition: gisbase.c:42
char * G__home(void)
Definition: home.c:43
int G_verbose_min(void)
Get min verbosity level.
Definition: verbose.c:92
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
int G_sleep_on_error(int flag)
Turn on/off no_sleep flag.