/** * 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 }
/* * 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 }