error.c

Go to the documentation of this file.
00001 /*
00002  **********************************************************************
00003  *
00004  * G_fatal_error (msg)
00005  *      char *msg          One line error message
00006  *
00007  * G_warning (msg)
00008  *      char *msg
00009  *
00010  *   Gives the message, msg, to the user.  Also print a message to 
00011  *   $GISBASE/GIS_ERROR_LOG if the file exists and is writeable; 
00012  *   and to the file $HOME/GIS_ERROR_LOG in the user's home directory 
00013  *   if $HOME is set and the file exists.
00014  *   G_warning() returns, which G_fatal_error() exits.
00015  *
00016  *   note:  By default, the message is handled by an internal routine
00017  *      which prints the message to the screen.   Using G_set_error_routine()
00018  *      the programmer can have the message handled by another routine.
00019  *      This is especially useful if the message should go to a particular
00020  *      location on the screen when using curses or to a location on
00021  *      a graphics device (monitor).
00022  *          
00023  **********************************************************************
00024  * G_set_error_routine (error_routine)
00025  *      int (*error_routine)()
00026  *
00027  *   Establishes error_routine as the routine that will handle 
00028  *   the printing of subsequent error messages. error_routine
00029  *   will be called like this:
00030  *      error_routine(msg, fatal)  
00031  *         char *msg ;
00032  **********************************************************************
00033  * G_unset_error_routine ()
00034  *
00035  *   After this call subsequent error messages will be handled in the
00036  *   default method.  Error messages are printed directly to the
00037  *   screen:
00038  *           ERROR: message
00039  *   -or-    WARNING: message
00040  *
00041  **********************************************************************/
00042 /*
00043      Throughout the code the references to these routines attempt to
00044         send format strings and arguments.  It seems that we expect
00045         these to handle varargs, so now they do.    7-Mar-1999
00046                 Bill Hughes
00047 */
00048 
00049 #include <stdlib.h>
00050 #include <string.h>
00051 #include <unistd.h>
00052 #include <time.h>
00053 #include <stdarg.h>
00054 #include <sys/types.h>
00055 #include <grass/glocale.h>
00056 #include <grass/gis.h>
00057 
00058 #define MSG  0
00059 #define WARN 1
00060 #define ERR  2
00061 
00062 /* static int (*error)() = 0; */
00063 static int (*ext_error)() = 0; /* Roger Bivand 17 June 2000 */
00064 static int no_warn = 0;
00065 static int no_sleep = 1;
00066 static int message_id = 1;
00067 
00068 extern char *getenv();
00069 static int print_word (FILE *, char **, int *, const int);
00070 static void print_sentence (FILE *, const int, const char *);
00071 static int print_error (const char *, const int);
00072 static int mail_msg (const char *, const int);
00073 static int write_error (const char *, const int, const char *, 
00074                         const time_t, const char *);
00075 static int log_error (const char *, const int);
00076 
00082 void G_message (char *msg,...)
00083 {
00084     char buffer[2000];  /* G_asprintf does not work */
00085     va_list ap;
00086 
00087     va_start(ap, msg);
00088     vsprintf(buffer,msg,ap);
00089     va_end(ap);
00090 
00091     print_error (buffer,MSG);
00092 }
00093 
00094 int G_fatal_error ( char *msg,...)
00095 {
00096     char buffer[2000];  /* No novels to the error logs, OK? */
00097     va_list ap;
00098 
00099     va_start(ap,msg);
00100     vsprintf(buffer,msg,ap);
00101     va_end(ap);
00102 
00103     print_error (buffer,ERR);
00104 
00105     if ( ext_error ) return 0; /* do not exit error routine is specified */
00106     
00107     exit (EXIT_FAILURE);
00108 }
00109 
00110 int G_warning ( char *msg, ...)
00111 {
00112     char buffer[2000];
00113     va_list ap;
00114 
00115     if (no_warn) return 0;
00116 
00117     va_start(ap,msg);
00118     vsprintf(buffer,msg,ap);
00119     va_end(ap);
00120     print_error (buffer,WARN);
00121 
00122     return 0;
00123 }
00124 
00125 int G_suppress_warnings (int flag)
00126 {
00127     int prev;
00128 
00129     prev = no_warn;
00130     no_warn = flag;
00131     return prev;
00132 }
00133 
00134 int G_sleep_on_error (int flag)
00135 {
00136     int prev;
00137 
00138     prev = !no_sleep;
00139     no_sleep = !flag;
00140     return prev;
00141 }
00142 
00143 int G_set_error_routine ( int (*error_routine)())
00144 {
00145     ext_error = error_routine; /* Roger Bivand 17 June 2000 */
00146     return 0;
00147 }
00148 
00149 int G_unset_error_routine ()
00150 {
00151     ext_error = 0; /* Roger Bivand 17 June 2000 */
00152 
00153     return 0;
00154 }
00155 
00156 /* Print info to stderr and optionaly to log file and optionaly send mail */
00157 static int print_error(const char *msg, const int type)
00158 {
00159     static char *prefix_std[3];
00160     int fatal, format;
00161     
00162     if ( !prefix_std[0] ) { /* First time: set prefixes  */
00163         prefix_std[0] = "";
00164         prefix_std[1] = _("WARNING: ");
00165         prefix_std[2] = _("ERROR: ");
00166     }
00167     
00168     if ( type == ERR )
00169         fatal = 1;
00170     else /* WARN */
00171         fatal = 0;
00172 
00173     if ( (type == WARN || type == ERR) && ext_error) { /* Function defined by application */
00174         ext_error (msg, fatal);
00175     } else {
00176         char *w;
00177         int len, lead;
00178 
00179         format = G_info_format();
00180 
00181         if ( format == G_INFO_FORMAT_STANDARD ) {
00182             if ( type == WARN || type == ERR ) { 
00183                 log_error (msg, fatal);
00184             }
00185 
00186             fprintf(stderr,"%s", prefix_std[type] );
00187             len = lead = strlen ( prefix_std[type] );
00188             w = (char *)msg;
00189 
00190             while (print_word(stderr,&w,&len,lead))
00191                     ;
00192 
00193             if ( (type != MSG) && isatty(fileno(stderr))) { /* Bell */
00194                 fprintf(stderr,"\7");
00195                 fflush (stderr);
00196                 if (!no_sleep)
00197                     G_sleep (5);
00198             } else if ( (type == WARN || type == ERR) && getenv("GRASS_ERROR_MAIL")) { /* Mail */
00199                 mail_msg (msg, fatal);
00200             }
00201         } else { /* GUI */
00202             print_sentence ( stderr, type, msg );
00203         }
00204     }
00205 
00206     return 0;
00207 }
00208 
00209 static int log_error (const char *msg, const int fatal)
00210 {
00211     FILE *pwd;
00212     char cwd[1024];
00213     time_t clock;
00214     char *home;
00215     char *gisbase;
00216 
00217     /* get time */
00218     clock = time(NULL);
00219 
00220     /* get current working directory */
00221     sprintf(cwd,"?");
00222     if ( (pwd = G_popen ("pwd","r")) )
00223     {
00224         if (fgets(cwd, sizeof(cwd), pwd))
00225         {
00226             char *c;
00227 
00228             for (c = cwd; *c; c++)
00229                 if (*c == '\n')
00230                     *c = 0;
00231         }
00232         G_pclose (pwd);
00233     }
00234 
00235     /* write the 2 possible error log files */
00236     if ((gisbase = G_gisbase ()))
00237         write_error (msg, fatal, gisbase, clock, cwd);
00238 
00239     home = G__home();
00240     if (home && gisbase && strcmp (home, gisbase))
00241         write_error (msg, fatal, home, clock, cwd);
00242 
00243     return 0;
00244 }
00245 
00246 static int write_error (const char *msg, const int fatal,
00247                         const char *dir, const time_t clock,
00248                         const char *cwd)
00249 {
00250     char logfile[GNAME_MAX];
00251     FILE *log;
00252 
00253     if (dir == 0 || *dir == 0)
00254         return 1;
00255     sprintf (logfile, "%s/GIS_ERROR_LOG", dir) ;
00256 
00257     log = fopen (logfile,"r");
00258     if (!log)
00259         /* GIS_ERROR_LOG file is not readable or does not exist */
00260         return 1;
00261 
00262     log = freopen(logfile, "a", log);
00263     if (!log)
00264         /* the user doesn't have write permission */
00265         return 1;
00266 
00267     fprintf(log,"-------------------------------------\n");
00268     fprintf(log,"%-10s %s\n", "program:", G_program_name());
00269     fprintf(log,"%-10s %s\n", "user:", G_whoami());
00270     fprintf(log,"%-10s %s\n", "cwd:", cwd);
00271     fprintf(log,"%-10s %s\n", "date:", ctime(&clock));
00272     fprintf(log,"%-10s %s\n", fatal?"error:":"warning:", msg);
00273     fprintf(log,"-------------------------------------\n");
00274 
00275     fclose (log);
00276 
00277     return 0;
00278 }
00279 
00280 static int mail_msg (const char *msg, const int fatal)
00281 {
00282     FILE *mail;
00283     char command[64];
00284     char *user;
00285 
00286     user = G_whoami();
00287     if (user == 0 || *user == 0)
00288         return 1;
00289 
00290     sprintf (command, "mail '%s'", G_whoami());
00291     if ( (mail = G_popen (command, "w")) )
00292     {
00293         fprintf(mail,"GIS %s: %s\n",fatal?"ERROR":"WARNING",msg);
00294         G_pclose (mail);
00295     }
00296 
00297     return 0;
00298 }
00299 
00300 /* Print one word, new line if necessary */
00301 static int print_word (FILE *fd, char **word, int *len, const int lead)
00302 {
00303     int  wlen, start, totlen;
00304     int  nl;
00305     char *w,*b;
00306 
00307     start = *len;
00308     w = *word;
00309 
00310     nl = 0;
00311     while (*w == ' ' || *w == '\t' || *w == '\n')
00312         if(*w++ == '\n')
00313             nl++;
00314 
00315     wlen = 0;
00316     for (b = w; *b != 0 && *b != ' ' && *b != '\t' && *b != '\n'; b++)
00317         wlen++;
00318 
00319     if (wlen == 0)
00320     {
00321         fprintf (fd, "\n");
00322         return 0;
00323     }
00324 
00325     if ( start > lead ) { /* add space */
00326         totlen = start + wlen + 1;
00327     } else {
00328         totlen = start + wlen; 
00329     }
00330     
00331     if ( nl != 0 || totlen > 75)
00332     {
00333         while (--nl > 0)
00334             fprintf (fd, "\n");
00335         fprintf (fd, "\n%*s",lead,"");
00336         start = lead;
00337     }
00338 
00339     if ( start > lead ) {
00340       fprintf (fd, " ");
00341       start++;
00342     }
00343 
00344     *len = start + wlen;
00345 
00346     while (wlen-- > 0)
00347         fprintf (fd, "%c", *w++);
00348 
00349     *word = w;
00350 
00351     return 1;
00352 }
00353 
00354 /* Print one message, prefix inserted before each new line */
00355 static void print_sentence (FILE *fd, const int type, const char *msg)
00356 {
00357     char *start;
00358     static char prefix[100];
00359 
00360     switch ( type ) {
00361         case MSG: 
00362             sprintf (prefix, "GRASS_INFO_MESSAGE(%d,%d): ", getpid(), message_id);
00363             break;
00364         case WARN:
00365             sprintf (prefix, "GRASS_INFO_WARNING(%d,%d): ", getpid(), message_id);
00366             break;
00367         case ERR:
00368             sprintf (prefix, "GRASS_INFO_ERROR(%d,%d): ", getpid(), message_id);
00369             break;
00370     }
00371 
00372     start = (char *)msg;
00373 
00374     fprintf(stderr, "\n" );
00375     while ( *start != '\0' ) {
00376         fprintf ( fd, "%s", prefix);
00377 
00378         while ( *start != '\0' ) {
00379             fprintf (fd, "%c", *start++);
00380                 
00381             if ( *start == '\n' ) {
00382                 *start++;
00383                 break;
00384             }
00385         }
00386         
00387         fprintf (fd, "\n" );
00388     }
00389     fprintf(stderr, "GRASS_INFO_END(%d,%d)\n", getpid(), message_id );
00390     message_id++;
00391 }
00392     
00393 int G_info_format ( void ) 
00394 {
00395     static int grass_info_format = -1;
00396     char    *fstr;
00397     
00398     if ( grass_info_format < 0) {
00399         fstr = getenv( "GRASS_MESSAGE_FORMAT" );
00400 
00401         if ( fstr && G_strcasecmp(fstr,"gui") == 0 )
00402             grass_info_format = G_INFO_FORMAT_GUI;
00403         else
00404             grass_info_format = G_INFO_FORMAT_STANDARD;
00405     }
00406 
00407     return grass_info_format;
00408 }
00409 

Generated on Wed Dec 19 14:59:05 2007 for GRASS by  doxygen 1.5.4