1Netpbm subroutine libNreatrpyb:m pLsmiu_bbsrryaosrutyteimFn(ue)nclstiuibborrnaosruytM:iannpeum,a_lseytsct.e(m3()) subroutine, etc.(3)
2
3
4

Name

6       pm_system - run a Netpbm program with program input and output
7
8

Synopsis

10       #include <netpbm/pm_system.h>
11
12       pm_system(void                  stdinFeeder(int, void *),
13                 void *          const feederParm,
14                 void                  stdoutAccepter(int, void *),
15                 void *          const accepterParm,
16                 const char *    const shellCommand);
17
18       pm_system_lp(const char *  const progName,
19                    void                stdinFeeder(int, void *),
20                    void *        const feederParm,
21                    void                stdoutAccepter(int, void *),
22                    void *        const accepterParm,
23                    ...);
24
25       pm_system_vp(const char *  const progName,
26                    const char ** const argArray,
27                    void                stdinFeeder(int, void *),
28                    void *        const feederParm,
29                    void                stdoutAccepter(int, void *),
30                    void *        const accepterParm);
31
32       pm_system2(void                  stdinFeeder(int, void *),
33                  void *          const feederParm,
34                  void                  stdoutAccepter(int, void *),
35                  void *          const accepterParm,
36                  const char *    const shellCommand,
37                  int *           const termStatusP );
38
39       pm_system2_lp(const char *  const progName,
40                    void                stdinFeeder(int, void *),
41                    void *        const feederParm,
42                    void                stdoutAccepter(int, void *),
43                    int *         const terminationStatusP,
44                    void *        const accepterParm,
45                    ...);
46
47       pm_system2_vp(const char *  const progName,
48                    const char ** const argArray,
49                    void                stdinFeeder(int, void *),
50                    void *        const feederParm,
51                    void                stdoutAccepter(int, void *),
52                    void *        const accepterParm,
53                    int *         const termStatusP);
54
55
56

Example

58       This  simple  example  converts a PNM image on Standard Input to a JFIF
59       (JPEG) image on Standard Output.  In this case, pm_system() is doing no
60       more than system() would do.
61
62           pm_system(NULL, NULL, NULL, NULL, "pnmtojpeg");
63
64       This  example  does  the  same thing, but moves the data through memory
65       buffers to illustrate use with memory buffers, and we throw in a  stage
66       to shrink the image too:
67       #include <netpbm/pm_system.h>
68
69       char              pnmData[100*1024];   /* Input file better be < 100K */
70       char              jfifData[100*1024];
71       struct bufferDesc pnmBuffer;
72       struct bufferDesc jfifBuffer;
73       unsigned int      jfifSize;
74
75       pnmBuffer.size = fread(pnmData, 1, sizeof(pnmData), stdin);
76       pnmBuffer.buffer = pnmData;
77       pnmBuffer.bytesTransferredP = NULL;
78
79       jfifBuffer.size = sizeof(jfifData);
80       jfifBuffer.buffer = jfifData;
81       jfifBuffer.bytesTransferredP = &jfifSize;
82
83       pm_system(&pm_feed_from_memory, &pnmBuffer,
84                 &pm_accept_to_memory, &jfifBuffer,
85                 "pamscale .5 | pnmtojpeg");
86
87       fwrite(jfifData, 1, jfifSize, stdout);
88
89
90       This example reads an image into libnetpbm PAM structures, then bright‐
91       ens it, then writes it out, to illustrate use  of  pm_system  with  PAM
92       structures.
93       #include <netpbm/pam.h>
94       #include <netpbm/pm_system.h>
95
96       struct pam       inpam;
97       struct pam       outpam;
98       tuple **         inTuples;
99       tuple **         outTuples;
100       struct pamtuples inPamtuples;
101       struct pamtuples outPamtuples;
102
103       inTuples = pnm_readpam(stdin, &inpam, sizeof(inpam));
104
105       outpam = inpam;
106
107       inPamtuples.pamP = &inpam;
108       inPamtuples.tuplesP = &inTuples;
109       outPamtuples.pamP = &outpam;
110       outPamtuples.tuplesP = &outTuples;
111
112       pm_system(&pm_feed_from_pamtuples, &inPamtuples,
113                 &pm_accept_to_pamtuples, &outPamtuples,
114                 "pambrighten -value +100");
115
116       outpam.file = stdout;
117       pnm_writepam(&outpam, outTuples);
118
119
120
121
122

DESCRIPTION

124       These library functions are part of Netpbm(1).
125
126       pm_system()  is  a lot like the standard C library system() subroutine.
127       It runs a shell and has that shell execute a  shell  command  that  you
128       specify.   But  pm_system()  gives  you  more control over the Standard
129       Input and Standard Output of that shell command  than  system().   sys‐
130       tem() passes to the shell command as Standard Input and Output whatever
131       is the Standard Input and Output of the process  that  calls  system().
132       But  with  pm_system(), you specify as arguments subroutines to execute
133       to generate the shell command's Standard Input stream  and  to  process
134       the shell command's Standard Output stream.
135
136       Your Standard Input feeder subroutine can generate the stream in limit‐
137       less ways.  pm_system() gives it a file descriptor of a pipe  to  which
138       to  write  the stream it generates.  pm_system() hooks up the other end
139       of that pipe to the shell command's Standard Input.
140
141       Likewise, your Standard Output accepter subroutine can do  anything  it
142       wants  with the stream it gets.  pm_system() gives it a file descriptor
143       of a pipe from which to read the  stream.   pm_system()  hooks  up  the
144       other end of that pipe to the shell command's Standard Output.
145
146       The  argument  stdinFeeder  is  a function pointer that identifies your
147       Standard Input feeder subroutine.   pm_system()  runs  it  in  a  child
148       process  and  waits for that process to terminate (and accepts its com‐
149       pletion status) before returning.   feederParm  is  the  argument  that
150       pm_system() passes to the subroutine; it is opaque to pm_system().
151
152       If  you pass stdinFeeder = NULL, pm_system() simply passes your current
153       Standard Input stream to the shell command (as system() would do),  and
154       does not create a child process.
155
156       The  argument stdoutAccepter is a function pointer that identifies your
157       Standard Output accepter subroutine.  pm_system() calls it in the  cur‐
158       rent process.  accepterParm is an argument analogous to feederParm.
159
160       If  you pass stdoutAccepter = NULL, pm_system() simply passes your cur‐
161       rent Standard Output stream to the shell command (as system() would do.
162
163       The argument shellCommand is a null-terminated  string  containing  the
164       shell command that the shell is to execute.  It can be any command that
165       means something to the shell and can take a pipe for Standard Input and
166       Output.  Example:
167
168           pambrighten -vale +100 | pamdepth 255 | pamscale .5
169
170       pm_system() creates a child process to run the shell and waits for that
171       process to terminate (and accepts its completion status) before return‐
172       ing.
173
174       If  the shell fails, i.e. does not exit voluntarily with zero exit sta‐
175       tus, pm_system calls pm_error(), which normally issues an error message
176       to Standard Error and exits the program.  Use pm_system2() if you don't
177       want that.
178
179       Note that the 'termination status' of a Unix process is a  value  which
180       is  a  combination  of 1) whether the process exited voluntarily or was
181       killed by the operating system; 2) in the case of  termination  by  the
182       OS,  what class of signal did it; and 3) in the case of voluntary exit,
183       what 'exit status' the program declared.
184
185
186   Interface Header File
187       These interfaces are declared by <netpbm/pm_system.h<.
188
189
190
191   pm_system2()
192       This is the same as pm_system() except that rather than respond to  the
193       shell  process' termination status, it just returns it to you (via your
194       termStatusP argument).
195
196
197
198   pm_system_lp()
199       pm_system_lp() is like pm_system() except that  instead  of  running  a
200       shell,  which in turn typically runs another program, you run a program
201       of your choice directly.
202
203       Argument progName identifies the program to run, the same way  as  with
204       execlp() or a shell command: if it contains a slash (/), it is the full
205       name of the file that contains the program.  If not, it is a name to be
206       looked  up  in the system's program search path (determined by the PATH
207       environment variable).
208
209       You identify the arguments to the program the same way as for execlp():
210       with  the  variable arguments at the end of the pm_system_lp() argument
211       list.  Each is a NUL-terminated string.  The last argument must be NULL
212       to tell pm_system_lp() where the arguments end.
213
214       Note  that  the  first argument ("arg0") to a program is conventionally
215       the first word of the command used to run the program, as  if  it  were
216       being  run  for a shell command.  In other words, typically the name of
217       the program.
218
219       Example:
220
221           pm_system_lp("pnmtojpeg", NULL, NULL, NULL, NULL,
222                        "pnmtojpeg", "mypicture.jpg", "-quality=50", NULL);
223
224       pm_system_lp() is much safer than pm_system() when  your  program  com‐
225       putes  the  arguments  or  gets them from a user.  If you build a shell
226       command using such arguments, unless you're really careful, you may end
227       up  building  a  shell  command that does something very different from
228       what you intended, because the argument could contain  characters  that
229       mean something to the shell such as "|".
230
231       pm_system_lp()  can also be considerably faster that pm_system(), since
232       it skips the whole running of the shell.
233
234       If the process fails, i.e. produces nonzero termination status, pm_sys‐
235       tem_lp  calls  pm_error(),  which  normally  issues an error message to
236       Standard Error and exits the program.  Use pm_system2_lp() if you don't
237       want that.
238
239
240
241   pm_system2_lp()
242       This  is  the same as pm_system_lp() except that rather than respond to
243       the process' termination status, it just returns it to  you  (via  your
244       termStatusP argument).
245
246
247
248   pm_system_vp()
249       pm_system_vp()  is like pm_system_lp() except that instead of supplying
250       the program arguments as variable arguments,  you  supply  them  as  an
251       array,  as  with  execvp().  A NULL element in the array identifies the
252       end of the arguments.
253
254       Example:
255
256           const char * argArray[3];
257
258           argArray[0] = "pnmtojpeg";
259           argArray[1] = "-quality=50";
260           argArray[2] = NULL;
261
262           pm_system_vp("pnmtojpeg", argArray, NULL, NULL, NULL, NULL);
263
264       If the process fails, i.e. produces nonzero termination status, pm_sys‐
265       tem_vp  calls  pm_error(),  which  normally  issues an error message to
266       Standard Error and exits the program.  Use pm_system2_vp() if you don't
267       want that.
268
269
270
271   pm_system2_vp()
272       This  is  the same as pm_system_vp() except that rather than respond to
273       the process' termination status, it just returns it to  you  (via  your
274       termStatusP argument).
275
276
277

Applications

279       The  point of pm_system() and friends is to allow you to write a C pro‐
280       gram that uses other programs internally,  as  a  shell  script  would.
281       This  is particularly desirable with Netpbm, because Netpbm consists of
282       a lot of programs that perform basic graphic  manipulations  and  you'd
283       like  to  be  able  to  build  a program that does a more sophisticated
284       graphic manipulation by calling the more basic Netpbm programs.   These
285       building  block  programs  typically take input from Standard Input and
286       write output to Standard Output.
287
288       The obvious alternative is to use a higher  level  language  --  Bourne
289       Shell  or  Perl,  for  example.   But often you want your program to do
290       manipulations of your graphical data that are easier and more efficient
291       in  C.   Or  you want to use the Netpbm subroutine library in your pro‐
292       gram.  The Netpbm subroutine library is a C-linkage library;  the  sub‐
293       routines in it are not usable from a Bourne Shell or Perl program.
294
295       A typical use of pm_system() is to place the contents of some graphical
296       image file in memory, run a Netpbm program against it,  and  have  what
297       would ordinarily go into an output file in memory too, for further pro‐
298       cessing.  To do that, you can use  the  memory  buffer  Standard  Input
299       feeder and Standard Output accepter described below.
300
301       If  your program uses the Netpbm subroutine library to read, write, and
302       manipulate images, you may have an image in an array of PAM tuples.  If
303       you  want to manipulate that image with a Netpbm program (perhaps remap
304       the colors using pnmremap), you can use  the  pamtuple  Standard  Input
305       feeder and Standard Output acceptor described below.
306
307

Broken Pipe Behavior

309       When  you  set  up a shell command to take input from a pipe, as you do
310       with pm_system(), you need to understand how pipes work with respect to
311       the  programs at either end of the pipe agreeing to how much data is to
312       be transferred.  Here are some notes on that.
313
314       It is normal to read a pipe before the process on  the  other  end  has
315       written  the data you hope to read, and it is normal to write to a pipe
316       before the process on the other  end  has  tried  to  read  your  data.
317       Writes  to  a  pipe  can be buffered until the reading end requests the
318       data.  A process reading or writing a pipe can block  until  the  other
319       end  is ready.  Or a read or write can complete with an indication that
320       the other end is not ready at the moment and therefore no data, or less
321       data than was requested, was transferred.
322
323       The pipe is normally controlled by the writing end.  When you read from
324       a pipe, you keep reading until the program on the other end of the pipe
325       closes  it,  and then you get an end-of-file indication.  You then nor‐
326       mally close the reading end of the pipe, since it is no longer useful.
327
328       When you close the reading end of a pipe before getting the end-of-file
329       indication and the writer subsequently tries to write to the pipe, that
330       is an error condition for the writer.  In a typical default Unix  envi‐
331       ronment,  that  error causes the writer to receive a SIGPIPE signal and
332       that signal causes the writer process to terminate abnormally.  But if,
333       alternatively, the writer has ordered that SIGPIPE be blocked, ignored,
334       or handled, the  signal  does  not  cause  the  death  of  the  writer.
335       Instead, the write operation simply completes with an error indication.
336
337
338

Standard Feeders And Acceptors

340       You can supply anything you like as a Standard Input feeder or Standard
341       Output acceptor, but the Netpbm subroutine library  comes  with  a  few
342       that perform commonly needed functions.
343
344
345   Memory Buffer
346       These routines are for when you just want to treat an area of memory as
347       a file.  If the shell command would ordinarily read a 513 byte  regular
348       file from its Standard Input, you want it to take 513 bytes from a cer‐
349       tain address in your process' memory.  Whatever bytes the shell command
350       wants  to  write  to  its  output  file you want it to store at another
351       address in your process' memory.
352
353       The Standard Input feeder for this is called pm_feed_from_memory.   The
354       Standard Output accepter is pm_accept_to_memory.
355
356       For  both of these, the argument is the address of a struct bufferDesc,
357       which is defined as follows:
358
359       struct bufferDesc {
360           unsigned int    size;
361           unsigned char * buffer;
362           unsigned int *  bytesTransferredP;
363       };
364
365       size is the size of the memory buffer and buffer  is  its  location  in
366       memory  (address).   The Standard Input feeder will attempt to feed the
367       entire buffer to the shell command's Standard Input; the Standard  Out‐
368       put  accepter  will  not  accept any more data from the shell command's
369       Standard Output than will fit in the buffer.  Both  return  the  actual
370       amount of data read or written, in bytes, at the location identified by
371       bytesTransferredP.  Unless bytesTransferredP is NULL.
372
373       Because a process typically terminates abnormally when it is  not  able
374       to  write  everything to a pipe that it wanted to, bytesTransferredP is
375       not usually useful in the Standard Input feeder case.
376
377
378
379   Pamtuple
380       These routines are for when you have  images  in  memory  in  the  data
381       structures  used by the PAM family of subroutines in the Netpbm library
382       -- i.e. struct PAM and an array of struct tuple.  With these  routines,
383       you  can  run  a Netpbm program against such an image just as you would
384       against the same image in a regular file.
385
386       The Standard Input feeder for this  is  called  pm_feed_from_pamtuples.
387       The Standard Output accepter is pm_accept_to_pamtuples.
388
389       For  both  of these, the argument is the address of a struct pamtuples,
390       which is defined as follows:
391
392       struct pamtuples {
393           struct pam * pamP;
394           tuple ***    tuplesP;
395       };
396
397       For the Standard Input feeder,  you  supply  a  struct  pam,  valid  up
398       through  the  tuple_type member (except it doesn't matter what the file
399       member is) and array of tuples.
400
401       For the Standard Output Accepter, you supply only space in  memory  for
402       the  struct  pam and the address of the tuple array.  The routine fills
403       in the struct pam up through the tuple_type member (except  leaves  the
404       file  member  undefined)  and  allocates space for the tuple array with
405       malloc().  You are responsible for freeing that memory.
406
407

HISTORY

409       pm_system() was introduced in Netpbm 10.13 (January 2003).
410
411       pm_system_lp() and pm_system_vp() were introduced in Netpbm 10.40 (Sep‐
412       tember 2007).
413
414       pm_system2(),  pm_system2_lp(),  and  pm_system2_vp() were introduce in
415       Netpbm 10.75 (June 2016).
416

DOCUMENT SOURCE

418       This manual page was generated by the Netpbm tool 'makeman'  from  HTML
419       source.  The master documentation is at
420
421              http://netpbm.sourceforge.net/doc/libsystem.html
422
423netpbm documentationNetpbm subrout1i2neMalyib2r0a1r6y: pm_system() subroutine, etc.(3)
Impressum