# include <stdio.h> # include "messages.h" # include "lerror.h" # include <signal.h> extern int lineno; extern char ftitle[ ]; /* iscfile( name ) * * compares name with sourcename (file name from command line) * if it is the same then * if fileflag is false then print the source file name as a title * return true * * otherwise * return false */ static enum boolean fileflag = false; enum boolean iscfile( name ) char *name; { extern int strncmp( ); extern fprintf( ); extern char sourcename[ ]; if ( !strncmp( name, sourcename, LFNM ) ) { if ( fileflag == false ) { fileflag = true; fprintf( stderr, "\n%.14s\n==============\n", name ); } return( true ); } else { return( false ); } } /* tmpopen( ) * * open source message buffer file for writing * open header message file for updating * if open fails, open it for writing * otherwise * initialize header file name and count list from header message file * * if opens succeed return success * otherwise return failure */ static char ctmpname[ TMPLEN + 16 ] = ""; char *htmpname = NULL; static FILE *ctmpfile = NULL; static FILE *htmpfile = NULL; static HDRITEM hdrlist[ NUMHDRS ]; tmpopen( ) { extern sprintf( ); extern int getpid( ), getppid( ); extern FILE *fopen( ); extern rewind( ); extern int fread( ), fwrite( ); extern lerror( ), catchsig( ); sprintf( ctmpname, "%s/clint%d", TMPDIR, getpid( ) ); catchsig( ); if ( (ctmpfile = fopen( ctmpname, "w" )) == NULL ) { lerror( "cannot open message buffer file", ERRMSG | FATAL ); return; } if ( (htmpfile = fopen( htmpname, "r+" )) == NULL ) { /* the file does not exist -- create it */ if ( (htmpfile = fopen( htmpname, "w" )) == NULL ) { lerror( "cannot open header message buffer file", CCLOSE | FATAL | ERRMSG ); return; } else if (fwrite((char *) hdrlist, sizeof(HDRITEM), NUMHDRS, htmpfile) != NUMHDRS ) { lerror("cannot write header message buffer file", HCLOSE | CCLOSE | ERRMSG | FATAL ); return; } /* seek past header list for writing header information */ if ( fseek( htmpfile, (long) sizeof ( hdrlist ), 0 ) != OKFSEEK ) { lerror( "cannot seek in header message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); return; } } else { /* the file already exists -- initialize header information */ rewind( htmpfile ); if ( fread((char *) hdrlist, sizeof( HDRITEM ), NUMHDRS, htmpfile) != NUMHDRS ) { lerror( "cannot read header message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); return; } if ( fseek( htmpfile, 0L, 2 ) != OKFSEEK ) { lerror( "cannot seek in header message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); return; } } return; } /* hdrclose( ) * * write header file name/count list to and close header message buffer file */ hdrclose( ) { extern rewind( ); extern int fwrite( ); extern lerror( ); rewind( htmpfile ); if ( fwrite( (char *) hdrlist, sizeof( HDRITEM ), NUMHDRS, htmpfile ) != NUMHDRS ) { lerror( "cannot write header message buffer file", HCLOSE | ERRMSG ); return; } return; } /* lerror( ) * * lint error message routine * if code is [CH]CLOSE error close and unlink appropriate files * if code is FATAL exit */ lerror( message, code ) char *message; int code; { extern fprintf( ), fclose( ), unlink( ); if ( code & ERRMSG ) { fprintf( stderr, "lint error: %s\n", message ); } if ( code & CCLOSE ) { if ( ctmpfile != NULL ) { fclose( ctmpfile ); unlink( ctmpname ); } } if ( code & HCLOSE ) { if ( htmpfile != NULL ) { fclose( htmpfile ); unlink( htmpname ); } } if ( code & FATAL ) { exit( FATAL ); } return; } /* lwerror( ) * * determines whether a particular message is to be buffered * and if so, calls the appropriate buffer routine * bufhdr( ) for a header file * bufsource( ) for a source file * * if not, calls werror( ) */ /* VARARGS1 */ lwerror( msgndx, arg1, arg2 ) int msgndx; { extern char *strip( ); extern werror( ), bufsource( ), bufhdr( ); extern enum boolean iscfile( ); extern char *msgtext[ ]; extern short msgbuf[ ]; char *filename; filename = strip( ftitle ); if ( iscfile( filename ) == true ) { if ( msgbuf[ msgndx ] == 0 ) { werror( msgtext[ msgndx ], arg1, arg2 ); } else { bufsource( WERRTY, msgndx, arg1, arg2 ); } } else { bufhdr( WERRTY, filename, msgndx, arg1, arg2 ); } return; } /* VARARGS1 */ luerror( msgndx, arg1 ) short msgndx; { extern char *strip( ); extern uerror( ), bufsource( ), bufhdr( ); extern enum boolean iscfile( ); extern char *msgtext[ ]; extern short msgbuf[ ]; char *filename; filename = strip( ftitle ); if ( iscfile( filename ) == true ) { if ( msgbuf[ msgndx ] == 0 ) { uerror( msgtext[ msgndx ], arg1 ); } else { bufsource( UERRTY, msgndx, arg1 ); } } else { bufhdr( UERRTY, filename, msgndx, arg1 ); } return; } # define nextslot(x) ((PERMSG * ((x) - 1)) + (CRECSZ * msgtotals[(x)])) static int msgtotals[ NUMBUF ]; /* VARARGS2 */ bufsource( code, msgndx, arg1, arg2 ) int code, msgndx; { extern char *strncpy( ); extern int fseek( ), fwrite( ); extern lerror( ); extern short msgbuf[ ], msgtype[ ]; int bufndx; CRECORD record; bufndx = msgbuf[ msgndx ]; if (( bufndx == 0 ) || ( bufndx >= NUMBUF )) { lerror( "message buffering scheme flakey", CCLOSE | HCLOSE | FATAL | ERRMSG ); } else { if ( msgtotals[ bufndx ] < MAXBUF ) { record.code = code | msgtype[ msgndx ]; record.lineno = lineno; switch( msgtype[ msgndx ] & ~SIMPL ) { case DBLSTRTY: strncpy( record.name2, (char *) arg2, LCHNM ); /* no break */ case STRINGTY: strncpy( record.arg1.name1, (char *) arg1, LCHNM ); break; case CHARTY: record.arg1.char1 = (char) arg1; break; case NUMTY: record.arg1.number = (int) arg1; break; default: break; } if ( fseek( ctmpfile, nextslot( bufndx ), 0 ) == OKFSEEK ) { if ( fwrite( (char *) &record, CRECSZ, 1, ctmpfile ) != 1 ) { lerror( "cannot write to message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); } } else { lerror( "cannot seek in message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); } } ++msgtotals[ bufndx ]; } return; } static int curhdr = 0; static enum boolean activehdr = false; /* VARARGS3 */ bufhdr( code, filename, msgndx, arg1, arg2 ) int code; char *filename; int msgndx; { extern char *strncpy( ); extern int strncmp( ), fwrite( ); extern lerror( ); extern char sourcename[ ]; extern short msgtype[ ]; int i, emptyslot; HRECORD record; if ((activehdr == false ) || ( strncmp( hdrlist[ curhdr ].hname, filename, LFNM ) != 0 )) { /* that is, if we do not have a new (active) header file * or if this header file is not the same as the last one * see if we have already seen it */ activehdr = false; i = curhdr; emptyslot = curhdr; while( strncmp( hdrlist[ i ].hname, filename, LFNM ) != 0 ) { /* that is, while we haven't found a match on the filename */ if ( hdrlist[ i ].hname[ 0 ] == '\0' ) { emptyslot = i; i = 0; } else { ++i; if ( i == NUMHDRS ) { i = 0; } } if ( i == curhdr ) { if ( hdrlist[ emptyslot ].hname[ 0 ] != '\0' ) { lerror( "too many header files", ERRMSG ); return; } else { activehdr = true; strncpy( hdrlist[ emptyslot ].hname, filename, LFNM ); strncpy( hdrlist[ emptyslot ].sname, sourcename, LFNM ); i = emptyslot; curhdr = emptyslot; } } } if ( activehdr == false ) { return; } } /* activehdr is true, curhdr points to current header file name, buffer */ ++hdrlist[ curhdr ].hcount; record.msgndx = msgndx; record.code = code | msgtype[ msgndx ]; record.lineno = lineno; switch( msgtype[ msgndx ] & ~SIMPL ) { case DBLSTRTY: strncpy( record.name2, (char *) arg2, LCHNM ); /* no break */ case STRINGTY: strncpy( record.arg1.name1, (char *) arg1, LCHNM ); break; case CHARTY: record.arg1.char1 = (char) arg1; break; case NUMTY: record.arg1.number = (int) arg1; break; default: break; } if ( fwrite( (char *) &record, HRECSZ, 1, htmpfile ) != 1 ) { lerror( "cannot write to header message buffer file", CCLOSE | HCLOSE | FATAL | ERRMSG ); } return; } /* unbuffer( ) * * writes out information saved in ctmpfile * */ unbuffer( ) { extern fclose( ), fprintf( ), unlink( ); extern FILE *fopen( ); extern int fseek( ), fread( ); extern lerror( ); extern char *outmsg[ ], *outformat[ ]; int i, j, stop; int perline, toggle; enum boolean codeflag; CRECORD record; fclose( ctmpfile ); if ( (ctmpfile = fopen( ctmpname, "r" )) == NULL ) { lerror( "cannot open source buffer file for reading", CCLOSE | FATAL | ERRMSG ); return; } for ( i = 1; i < NUMBUF; ++i ) { if ( msgtotals[ i ] != 0 ) { codeflag = false; if ( fseek( ctmpfile, (PERMSG * (i - 1)), 0 ) != OKFSEEK ) { lerror( "cannot seek in source message buffer file", CCLOSE | FATAL | ERRMSG ); return; } stop = msgtotals[ i ]; if ( stop > MAXBUF ) { stop = MAXBUF; } for ( j = 0; j < stop; ++j ) { if ( fread( (char *) &record, CRECSZ, 1, ctmpfile ) != 1 ) { lerror( "cannot read source message buffer file", CCLOSE | FATAL | ERRMSG ); return; } if ( codeflag == false ) { if ( record.code & WERRTY ) { fprintf( stderr, "warning: " ); } perline = 1; toggle = 0; if ( record.code & SIMPL ) { perline = 2; } else if ( !( record.code & ~WERRTY ) ) { /* PLAINTY */ perline = 3; } fprintf( stderr, "%s\n", outmsg[ i ] ); codeflag = true; } fprintf( stderr, " (%d) ", record.lineno ); switch( record.code & ~( WERRTY | SIMPL ) ) { case DBLSTRTY: fprintf( stderr, outformat[ i ], record.arg1.name1, record.name2 ); break; case STRINGTY: fprintf( stderr, outformat[ i ], record.arg1.name1 ); break; case CHARTY: fprintf( stderr, outformat[ i ], record.arg1.char1 ); break; case NUMTY: fprintf( stderr, outformat[ i ], record.arg1.number ); break; default: fprintf( stderr, outformat[ i ] ); break; } if ( ++toggle == perline ) { fprintf( stderr, "\n" ); toggle = 0; } else { fprintf( stderr, "\t" ); } } if ( toggle != 0 ) { fprintf( stderr, "\n" ); } if ( stop < msgtotals[ i ] ) { fprintf( stderr, " %d messages suppressed for lack of space\n", msgtotals[ i ] - stop ); } } } fclose( ctmpfile ); unlink( ctmpname ); return; } /* catchsig( ) * * prepares to field interrupts with the routine onintr( ) * catchsig simply returns */ catchsig( ) { extern int (*signal( ))( ); extern onintr( ); if ((signal(SIGINT, SIG_IGN)) == SIG_DFL) signal(SIGINT, onintr); if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL) signal(SIGHUP, onintr); if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL) signal(SIGQUIT, onintr); if ((signal(SIGPIPE, SIG_IGN)) == SIG_DFL) signal(SIGPIPE, onintr); if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL) signal(SIGTERM, onintr); return; } /* onintr( ) * * cleans up after an interrupt happens * ignores signals (interrupts) during its work */ onintr( ) { extern int (*signal( ))( ); extern fprintf( ); extern lerror( ); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, SIG_IGN); fprintf( stderr, "\n" ); lerror( "interrupt", CCLOSE | HCLOSE | FATAL ); /* note that no error message is printed */ }