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

Generated on Wed Aug 23 17:49:22 2006 for GRASS by  doxygen 1.4.7