
/*
 *  $Id: agPrint.c,v 2.7 1999/07/07 19:30:52 bkorb Exp $
 *
 *  The following code is necessary because the user can give us
 *  a printf format requiring a string pointer yet fail to provide
 *  a valid pointer, thus it will fault.  This code protects
 *  against the fault so an error message can be emitted instead of
 *  a core dump :-)
 */

/*
 *  AutoGen copyright 1992-1999 Bruce Korb
 *
 *  AutoGen is free software.
 *  You may redistribute it and/or modify it under the terms of the
 *  GNU General Public License, as published by the Free Software
 *  Foundation; either version 2, or (at your option) any later version.
 *
 *  AutoGen is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with AutoGen.  See the file "COPYING".  If not,
 *  write to:  The Free Software Foundation, Inc.,
 *             59 Temple Place - Suite 330,
 *             Boston,  MA  02111-1307, USA.
 */

#include <signal.h>
#include <compat/compat.h>

#ifndef HAVE_STRSIGNAL
#  include <compat/strsignal.c>
#endif

#include "autogen.h"


STATIC sigjmp_buf printJumpEnv;

    STATIC void
printFault( int sig )
{
    siglongjmp( printJumpEnv, sig );
}

    int
safePrintf( char* pzBuf, size_t bufSize, char* pzFmt, snv_constpointer argV[] )
{
    tSCC zOvfloFmt[] = "%s ERROR:  formating error with:\n\t`%s'\n";

    size_t printSize;
    int    faultType;

    struct sigaction  sa;
    struct sigaction  saSave1;
    struct sigaction  saSave2;

    sa.sa_handler = printFault;
    sa.sa_flags   = 0;
    sigemptyset( &sa.sa_mask );

    sigaction( SIGBUS,  &sa, &saSave1 );
    sigaction( SIGSEGV, &sa, &saSave2 );

    /*
     *  IF the sprintfv call below is going to address fault,
     *  THEN ...
     */
    if (faultType = sigsetjmp( printJumpEnv, 0 ),
        faultType != 0) {

        /*
         *  IF the fprintf command in the then clause has not failed yet,
         *  THEN perform that fprintf
         */
        if (sigsetjmp( printJumpEnv, 0 ) == 0)
            fprintf( stderr, "%s ERROR:  %s processing printf format:\n"
                     "\t%s\n", pzProg,
                     strsignal( faultType ), pzFmt );

        /*
         *  The "sprintfv" command below faulted, so we exit
         */
        LOAD_ABORT;
    }

    printSize = snprintfv( pzBuf, bufSize, pzFmt, argV );

    if (printSize < 0) {
        fprintf( stderr, zOvfloFmt, pzProg, pzFmt );
        LOAD_ABORT;
    }

    sigaction( SIGBUS,  &saSave1, (struct sigaction*)NULL );
    sigaction( SIGSEGV, &saSave2, (struct sigaction*)NULL );
    return (int)printSize;
}

/* end of agPrint.c */
/* end of agPrint.c */
