static void textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD ) { # define _TT_(n) tSCC 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( "%1$s_%2$s_TEXT='no %2$s text'\n", pOpts->pzPROGNAME, apzTTNames[ whichVar ]); #else int nlHoldCt = 0; int pipeFd[2]; FILE* fp; printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]); fflush( stdout ); 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: dup2( pipeFd[1], STDERR_FILENO ); dup2( pipeFd[1], STDOUT_FILENO ); close( pipeFd[0] ); switch (whichVar) { case TT_LONGUSAGE: (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS ); /* NOTREACHED */ exit( EXIT_FAILURE ); case TT_USAGE: (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE ); /* NOTREACHED */ exit( EXIT_FAILURE ); 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] ); fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG ); } for (;;) { int ch = fgetc( fp ); switch (ch) { case '\n': nlHoldCt++; break; case '\'': while (nlHoldCt > 0) { fputc( '\n', stdout ); nlHoldCt--; } fputs( "'\\''", stdout ); break; case EOF: goto endCharLoop; default: while (nlHoldCt > 0) { fputc( '\n', stdout ); nlHoldCt--; } fputc( ch, stdout ); break; } } endCharLoop:; fputs( "'\n\n", stdout ); close( pipeFd[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. * * @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 }