Netpbm subroutine library: pm_system() subroutine, etc.(3) Library Functions Manual Name pm_system - run a Netpbm program with program input and output Synopsis #include pm_system(void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm, const char * const shellCommand); pm_system_lp(const char * const progName, void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm, ...); pm_system_vp(const char * const progName, const char ** const argArray, void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm); pm_system2(void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm, const char * const shellCommand, int * const termStatusP ); pm_system2_lp(const char * const progName, void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm, int * const terminationStatusP, ...); pm_system2_vp(const char * const progName, const char ** const argArray, void stdinFeeder(int, void *), void * const feederParm, void stdoutAccepter(int, void *), void * const accepterParm, int * const termStatusP); Example This simple example converts a PNM image on Standard Input to a JFIF (JPEG) image on Standard Output. In this case, pm_system() is doing no more than system() would do. pm_system(NULL, NULL, NULL, NULL, "pnmtojpeg"); This example does the same thing, but moves the data through memory buffers to illustrate use with memory buffers, and we throw in a stage to shrink the image too: #include char pnmData[100*1024]; /* Input file better be < 100K */ char jfifData[100*1024]; struct bufferDesc pnmBuffer; struct bufferDesc jfifBuffer; unsigned int jfifSize; pnmBuffer.size = fread(pnmData, 1, sizeof(pnmData), stdin); pnmBuffer.buffer = pnmData; pnmBuffer.bytesTransferredP = NULL; jfifBuffer.size = sizeof(jfifData); jfifBuffer.buffer = jfifData; jfifBuffer.bytesTransferredP = &jfifSize; pm_system(&pm_feed_from_memory, &pnmBuffer, &pm_accept_to_memory, &jfifBuffer, "pamscale .5 | pnmtojpeg"); fwrite(jfifData, 1, jfifSize, stdout); This example reads an image into libnetpbm PAM structures, then brightens it, then writes it out, to illustrate use of pm_system with PAM structures. #include #include struct pam inpam; struct pam outpam; tuple ** inTuples; tuple ** outTuples; struct pamtuples inPamtuples; struct pamtuples outPamtuples; inTuples = pnm_readpam(stdin, &inpam, sizeof(inpam)); outpam = inpam; inPamtuples.pamP = &inpam; inPamtuples.tuplesP = &inTuples; outPamtuples.pamP = &outpam; outPamtuples.tuplesP = &outTuples; pm_system(&pm_feed_from_pamtuples, &inPamtuples, &pm_accept_to_pamtuples, &outPamtuples, "pambrighten -value +100"); outpam.file = stdout; pnm_writepam(&outpam, outTuples); DESCRIPTION These library functions are part of Netpbm(1). pm_system() is a lot like the standard C library system() subroutine. It runs a shell and has that shell execute a shell command that you specify. But pm_system() gives you more control over the Standard Input and Standard Output of that shell command than system(). system() passes to the shell command as Standard Input and Output whatever is the Standard Input and Output of the process that calls system(). But with pm_system(), you specify as arguments subroutines to execute to generate the shell command's Standard Input stream and to process the shell command's Standard Output stream. Your Standard Input feeder subroutine can generate the stream in limitless ways. pm_system() gives it a file descriptor of a pipe to which to write the stream it generates. pm_system() hooks up the other end of that pipe to the shell command's Standard Input. Likewise, your Standard Output accepter subroutine can do anything it wants with the stream it gets. pm_system() gives it a file descriptor of a pipe from which to read the stream. pm_system() hooks up the other end of that pipe to the shell command's Standard Output. The argument stdinFeeder is a function pointer that identifies your Standard Input feeder subroutine. pm_system() runs it in a child process and waits for that process to terminate (and accepts its completion status) before returning. feederParm is the argument that pm_system() passes to the subroutine; it is opaque to pm_system(). If you pass stdinFeeder = NULL, pm_system() simply passes your current Standard Input stream to the shell command (as system() would do), and does not create a child process. The argument stdoutAccepter is a function pointer that identifies your Standard Output accepter subroutine. pm_system() calls it in the current process. accepterParm is an argument analogous to feederParm. If you pass stdoutAccepter = NULL, pm_system() simply passes your current Standard Output stream to the shell command (as system() would do. The argument shellCommand is a null-terminated string containing the shell command that the shell is to execute. It can be any command that means something to the shell and can take a pipe for Standard Input and Output. Example: pambrighten -vale +100 | pamdepth 255 | pamscale .5 pm_system() creates a child process to run the shell and waits for that process to terminate (and accepts its completion status) before returning. If the shell fails, i.e. does not exit voluntarily with zero exit status, pm_system calls pm_error(), which normally issues an error message to Standard Error and exits the program. Use pm_system2() if you don't want that. Note that the 'termination status' of a Unix process is a value which is a combination of 1) whether the process exited voluntarily or was killed by the operating system; 2) in the case of termination by the OS, what class of signal did it; and 3) in the case of voluntary exit, what 'exit status' the program declared. Interface Header File These interfaces are declared by