1Netpbm subroutine libNreatrpyb:m pLsmiu_bbsrryaosrutyteimFn(ue)nclstiuibborrnaosruytM:iannpeum,a_lseytsct.e(m3()) subroutine, etc.(3)
2
3
4
6 pm_system - run a Netpbm program with program input and output
7
8
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
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 "ppmbrighten -v 100");
115
116 outpam.file = stdout;
117 pnm_writepam(&outpam, outTuples);
118
119
120
121
122
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 ppmbrighten -v 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
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
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
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
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
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)