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
57

Example

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

DESCRIPTION

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

Applications

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

Broken Pipe Behavior

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

Standard Feeders And Acceptors

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

HISTORY

418       pm_system() was introduced in Netpbm 10.13 (January 2003).
419
420       pm_system_lp() and pm_system_vp() were introduced in Netpbm 10.40 (Sep‐
421       tember 2007).
422
423       pm_system2(),  pm_system2_lp(),  and  pm_system2_vp() were introduce in
424       Netpbm 10.75 (June 2016).
425

DOCUMENT SOURCE

427       This manual page was generated by the Netpbm tool 'makeman'  from  HTML
428       source.  The master documentation is at
429
430              http://netpbm.sourceforge.net/doc/libsystem.html
431
432netpbm documentationNetpbm subrout1i2neMalyib2r0a1r6y: pm_system() subroutine, etc.(3)
Impressum