Example #1
0
/**
 *  The purpose of this function is to assign "long usage", short usage
 *  and version information to a shell variable.  Rather than wind our
 *  way through all the logic necessary to emit the text directly, we
 *  fork(), have our child process emit the text the normal way and
 *  capture the output in the parent process.
 *
 * @param[in] opts  the program options
 * @param[in] which what to print: long usage, usage or version
 * @param[in] od    for TT_VERSION, it is the version option
 */
static void
text_to_var(tOptions * opts, teTextTo which, tOptDesc * od)
{
#   define _TT_(n) static char const z ## n [] = #n;
    TEXTTO_TABLE
#   undef _TT_
#   define _TT_(n) z ## n ,
      static char const * ttnames[] = { TEXTTO_TABLE };
#   undef _TT_

#if ! defined(HAVE_WORKING_FORK)
    printf(SET_NO_TEXT_FMT, opts->pzPROGNAME, ttnames[which]);
#else
    int  fdpair[2];

    fflush(stdout);
    fflush(stderr);

    if (pipe(fdpair) != 0)
        fserr_exit(opts->pzProgName, "pipe", zinter_proc_pipe);

    switch (fork()) {
    case -1:
        fserr_exit(opts->pzProgName, "fork", opts->pzProgName);
        /* NOTREACHED */

    case 0:
        /*
         * Send both stderr and stdout to the pipe.  No matter which
         * descriptor is used, we capture the output on the read end.
         */
        dup2(fdpair[1], STDERR_FILENO);
        dup2(fdpair[1], STDOUT_FILENO);
        close(fdpair[0]);

        switch (which) {
        case TT_LONGUSAGE:
            (*(opts->pUsageProc))(opts, EXIT_SUCCESS);
            /* NOTREACHED */

        case TT_USAGE:
            (*(opts->pUsageProc))(opts, EXIT_FAILURE);
            /* NOTREACHED */

        case TT_VERSION:
            if (od->fOptState & OPTST_ALLOC_ARG) {
                AGFREE(od->optArg.argString);
                od->fOptState &= ~OPTST_ALLOC_ARG;
            }
            od->optArg.argString = "c";
            optionPrintVersion(opts, od);
            /* NOTREACHED */

        default:
            option_exits(EXIT_FAILURE);
            /* NOTREACHED */
        }
        /* NOTREACHED */

    default:
        close(fdpair[1]);
    }

    emit_var_text(opts->pzPROGNAME, ttnames[which], fdpair[0]);
#endif
}
Example #2
0
/*
 *  The purpose of this function is to assign "long usage", short usage
 *  and version information to a shell variable.  Rather than wind our
 *  way through all the logic necessary to emit the text directly, we
 *  fork(), have our child process emit the text the normal way and
 *  capture the output in the parent process.
 */
static void
text_to_var(tOptions * pOpts, teTextTo whichVar, tOptDesc * pOD)
{
#   define _TT_(n) static char const z ## n [] = #n;
    TEXTTO_TABLE
#   undef _TT_
#   define _TT_(n) z ## n ,
      static char const * apzTTNames[] = { TEXTTO_TABLE };
#   undef _TT_

#if ! defined(HAVE_WORKING_FORK)
    printf(SET_NO_TEXT_FMT, pOpts->pzPROGNAME, apzTTNames[ whichVar]);
#else
    int  pipeFd[2];

    fflush(stdout);
    fflush(stderr);

    if (pipe(pipeFd) != 0) {
        fprintf(stderr, zBadPipe, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    switch (fork()) {
    case -1:
        fprintf(stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
        exit(EXIT_FAILURE);
        break;

    case 0:
        /*
         * Send both stderr and stdout to the pipe.  No matter which
         * descriptor is used, we capture the output on the read end.
         */
        dup2(pipeFd[1], STDERR_FILENO);
        dup2(pipeFd[1], STDOUT_FILENO);
        close(pipeFd[0]);

        switch (whichVar) {
        case TT_LONGUSAGE:
            (*(pOpts->pUsageProc))(pOpts, EXIT_SUCCESS);
            /* NOTREACHED */

        case TT_USAGE:
            (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
            /* NOTREACHED */

        case TT_VERSION:
            if (pOD->fOptState & OPTST_ALLOC_ARG) {
                AGFREE(pOD->optArg.argString);
                pOD->fOptState &= ~OPTST_ALLOC_ARG;
            }
            pOD->optArg.argString = "c";
            optionPrintVersion(pOpts, pOD);
            /* NOTREACHED */

        default:
            exit(EXIT_FAILURE);
        }

    default:
        close(pipeFd[1]);
    }

    emit_var_text(pOpts->pzPROGNAME, apzTTNames[whichVar], pipeFd[0]);
#endif
}