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
33
35 This simple example converts a PNM image on Standard Input to a JFIF
36 (JPEG) image on Standard Output. In this case, pm_system() is doing no
37 more than system() would do.
38
39 pm_system(NULL, NULL, NULL, NULL, "pnmtojpeg");
40
41 This example does the same thing, but moves the data through memory
42 buffers to illustrate use with memory buffers, and we throw in a stage
43 to shrink the image too:
44 #include <netpbm/pm_system.h>
45
46 char pnmData[100*1024]; /* Input file better be < 100K */
47 char jfifData[100*1024];
48 struct bufferDesc pnmBuffer;
49 struct bufferDesc jfifBuffer;
50 unsigned int jfifSize;
51
52 pnmBuffer.size = fread(pnmData, 1, sizeof(pnmData), stdin);
53 pnmBuffer.buffer = pnmData;
54 pnmBuffer.bytesTransferredP = NULL;
55
56 jfifBuffer.size = sizeof(jfifData);
57 jfifBuffer.buffer = jfifData;
58 jfifBuffer.bytesTransferredP = &jfifSize;
59
60 pm_system(&pm_feed_from_memory, &pnmBuffer,
61 &pm_accept_to_memory, &jfifBuffer,
62 "pamscale .5 | pnmtojpeg");
63
64 fwrite(jfifData, 1, jfifSize, stdout);
65
66
67 This example reads an image into libnetpbm PAM structures, then bright‐
68 ens it, then writes it out, to illustrate use of pm_system with PAM
69 structures.
70 #include <netpbm/pam.h>
71 #include <netpbm/pm_system.h>
72
73 struct pam inpam;
74 struct pam outpam;
75 tuple ** inTuples;
76 tuple ** outTuples;
77 struct pamtuples inPamtuples;
78 struct pamtuples outPamtuples;
79
80 inTuples = pnm_readpam(stdin, &inpam, sizeof(inpam));
81
82 outpam = inpam;
83
84 inPamtuples.pamP = &inpam;
85 inPamtuples.tuplesP = &inTuples;
86 outPamtuples.pamP = &outpam;
87 outPamtuples.tuplesP = &outTuples;
88
89 pm_system(&pm_feed_from_pamtuples, &inPamtuples,
90 &pm_accept_to_pamtuples, &outPamtuples,
91 "ppmbrighten -v 100");
92
93 outpam.file = stdout;
94 pnm_writepam(&outpam, outTuples);
95
96
97
98
99
101 These library functions are part of Netpbm(1).
102
103 pm_system() is a lot like the standard C library system() subroutine.
104 It runs a shell and has that shell execute a shell command that you
105 specify. But pm_system() gives you more control over the Standard
106 Input and Standard Output of that shell command than system(). sys‐
107 tem() passes to the shell command as Standard Input and Output whatever
108 is the Standard Input and Output of the process that calls system().
109 But with pm_system(), you specify as arguments subroutines to execute
110 to generate the shell command's Standard Input stream and to process
111 the shell command's Standard Output stream.
112
113 Your Standard Input feeder subroutine can generate the stream in limit‐
114 less ways. pm_system() gives it a file descriptor of a pipe to which
115 to write the stream it generates. pm_system() hooks up the other end
116 of that pipe to the shell command's Standard Input.
117
118 Likewise, your Standard Output accepter subroutine can do anything it
119 wants with the stream it gets. pm_system() gives it a file descriptor
120 of a pipe from which to read the stream. pm_system() hooks up the
121 other end of that pipe to the shell command's Standard Output.
122
123 The argument stdinFeeder is a function pointer that identifies your
124 Standard Input feeder subroutine. pm_system() runs it in a child
125 process and waits for that process to terminate (and accepts its com‐
126 pletion status) before returning. feederParm is the argument that
127 pm_system() passes to the subroutine; it is opaque to pm_system().
128
129 If you pass stdinFeeder = NULL, pm_system() simply passes your current
130 Standard Input stream to the shell command (as system() would do), and
131 does not create a child process.
132
133 The argument stdoutAccepter is a function pointer that identifies your
134 Standard Output accepter subroutine. pm_system() calls it in the cur‐
135 rent process. accepterParm is an argument analogous to feederParm.
136
137 If you pass stdoutAccepter = NULL, pm_system() simply passes your cur‐
138 rent Standard Output stream to the shell command (as system() would do.
139
140 The argument shellCommand is a null-terminated string containing the
141 shell command that the shell is to execute. It can be any command that
142 means something to the shell and can take a pipe for Standard Input and
143 Output. Example:
144
145 ppmbrighten -v 100 | pamdepth 255 | pamscale .5
146
147 pm_system() creates a child process to run the shell and waits for that
148 process to terminate (and accepts its completion status) before return‐
149 ing.
150
151
152 pm_system_lp()
153 pm_system_lp() is like pm_system() except that instead of running a
154 shell, which in turn typically runs another program, you run a program
155 of your choice directly.
156
157 Argument progName identifies the program to run, the same way as with
158 execlp() or a shell command: if it contains a slash (/), it is the full
159 name of the file that contains the program. If not, it is a name to be
160 looked up in the system's program search path (determined by the PATH
161 environment variable).
162
163 You identify the arguments to the program the same way as for execlp():
164 with the variable arguments at the end of the pm_system_lp() argument
165 list. Each is a NUL-terminated string. The last argument must be NULL
166 to tell pm_system_lp() where the arguments end.
167
168 Note that the first argument ('arg0') to a program is conventionally
169 the first word of the command used to run the program, as if it were
170 being run due to a shell command. In other words, typically the name
171 of the program.
172
173 Example:
174
175 pm_system_lp('pnmtojpeg', NULL, NULL, NULL, NULL,
176 'pnmtojpeg', 'mypicture.jpg', '-quality=50', NULL);
177
178 pm_system_lp() is much safer than pm_system() when your program com‐
179 putes the arguments or gets them from a user. If you build a shell
180 command using such arguments, unless you're really careful, you may end
181 up building a shell command that does something very different from
182 what you intended, because the argument could contain characters that
183 mean something to the shell such as '|'.
184
185 pm_system_lp() can also be considerably faster that pm_system(), since
186 it skips the whole running of the shell.
187
188
189
190 pm_system_vp()
191 pm_system_vp() is like pm_system_lp() except that instead of supplying
192 the program arguments as variable arguments, you supply them as an
193 array, as with execvp(). A NULL element in the array identifies the
194 end of the arguments.
195
196 Example:
197
198 const char * argArray[3];
199
200 argArray[0] = 'pnmtojpeg';
201 argArray[1] = '-quality=50';
202 argArray[2] = NULL;
203
204 pm_system_vp('pnmtojpeg', argArray, NULL, NULL, NULL, NULL);
205
206
207
209 The point of pm_system() and friends is to allow you to write a C pro‐
210 gram that uses other programs internally, as a shell script would.
211 This is particularly desirable with Netpbm, because Netpbm consists of
212 a lot of programs that perform basic graphic manipulations and you'd
213 like to be able to build a program that does a more sophisticated
214 graphic manipulation by calling the more basic Netpbm programs. These
215 building block programs typically take input from Standard Input and
216 write output to Standard Output.
217
218 The obvious alternative is to use a higher level language -- Bourne
219 Shell or Perl, for example. But often you want your program to do
220 manipulations of your graphical data that are easier and more efficient
221 in C. Or you want to use the Netpbm subroutine library in your pro‐
222 gram. The Netpbm subroutine library is a C-linkage library; the sub‐
223 routines in it are not usable from a Bourne Shell or Perl program.
224
225 A typical use of pm_system() is to place the contents of some graphical
226 image file in memory, run a Netpbm program against it, and have what
227 would ordinarily go into an output file in memory too, for further pro‐
228 cessing. To do that, you can use the memory buffer Standard Input
229 feeder and Standard Output accepter described below.
230
231 If your program uses the Netpbm subroutine library to read, write, and
232 manipulate images, you may have an image in an array of PAM tuples. If
233 you want to manipulate that image with a Netpbm program (perhaps remap
234 the colors using pnmremap), you can use the pamtuple Standard Input
235 feeder and Standard Output acceptor described below.
236
237
239 When you set up a shell command to take input from a pipe, as you do
240 with pm_system(), you need to understand how pipes work with respect to
241 the programs at either end of the pipe agreeing to how much data is to
242 be transferred. Here are some notes on that.
243
244 It is normal to read a pipe before the process on the other end has
245 written the data you hope to read, and it is normal to write to a pipe
246 before the process on the other end has tried to read your data.
247 Writes to a pipe can be buffered until the reading end requests the
248 data. A process reading or writing a pipe can block until the other
249 end is ready. Or a read or write can complete with an indication that
250 the other end is not ready at the moment and therefore no data, or less
251 data than was requested, was transferred.
252
253 The pipe is normally controlled by the writing end. When you read from
254 a pipe, you keep reading until the program on the other end of the pipe
255 closes it, and then you get an end-of-file indication. You then nor‐
256 mally close the reading end of the pipe, since it is no longer useful.
257
258 When you close the reading end of a pipe before getting the end-of-file
259 indication and the writer subsequently tries to write to the pipe, that
260 is an error condition for the writer. In a typical default Unix envi‐
261 ronment, that error causes the writer to receive a SIGPIPE signal and
262 that signal causes the writer process to terminate abnormally. But if,
263 alternatively, the writer has ordered that SIGPIPE be blocked, ignored,
264 or handled, the signal does not cause the death of the writer.
265 Instead, the write operation simply completes with an error indication.
266
267
268
270 You can supply anything you like as a Standard Input feeder or Standard
271 Output acceptor, but the Netpbm subroutine library comes with a few
272 that perform commonly needed functions.
273
274
275 Memory Buffer
276 These routines are for when you just want to treat an area of memory as
277 a file. If the shell command would ordinarily read a 513 byte regular
278 file from its Standard Input, you want it to take 513 bytes from a cer‐
279 tain address in your process' memory. Whatever bytes the shell command
280 wants to write to its output file you want it to store at another
281 address in your process' memory.
282
283 The Standard Input feeder for this is called pm_feed_from_memory. The
284 Standard Output accepter is pm_accept_to_memory.
285
286 For both of these, the argument is the address of a struct bufferDesc,
287 which is defined as follows:
288
289 struct bufferDesc {
290 unsigned int size;
291 unsigned char * buffer;
292 unsigned int * bytesTransferredP;
293 };
294
295 size is the size of the memory buffer and buffer is its location in
296 memory (address). The Standard Input feeder will attempt to feed the
297 entire buffer to the shell command's Standard Input; the Standard Out‐
298 put accepter will not accept any more data from the shell command's
299 Standard Output than will fit in the buffer. Both return the actual
300 amount of data read or written, in bytes, at the location identified by
301 bytesTransferredP. Unless bytesTransferredP is NULL.
302
303 Because a process typically terminates abnormally when it is not able
304 to write everything to a pipe that it wanted to, bytesTransferredP is
305 not usually useful in the Standard Input feeder case.
306
307
308
309 Pamtuple
310 These routines are for when you have images in memory in the data
311 structures used by the PAM family of subroutines in the Netpbm library
312 -- i.e. struct PAM and an array of struct tuple. With these routines,
313 you can run a Netpbm program against such an image just as you would
314 against the same image in a regular file.
315
316 The Standard Input feeder for this is called pm_feed_from_pamtuples.
317 The Standard Output accepter is pm_accept_to_pamtuples.
318
319 For both of these, the argument is the address of a struct pamtuples,
320 which is defined as follows:
321
322 struct pamtuples {
323 struct pam * pamP;
324 tuple *** tuplesP;
325 };
326
327 For the Standard Input feeder, you supply a struct pam, valid up
328 through the tuple_type member (except it doesn't matter what the file
329 member is) and array of tuples.
330
331 For the Standard Output Accepter, you supply only space in memory for
332 the struct pam and the address of the tuple array. The routine fills
333 in the struct pam up through the tuple_type member (except leaves the
334 file member undefined) and allocates space for the tuple array with
335 malloc(). You are responsible for freeing that memory.
336
337
339 pm_system() was introduced in Netpbm 10.13 (January 2003).
340
341
342
343netpbm documentationNetpbm subro1u7tiOncetolbiebrra2r0y0:6pm_system() subroutine, etc.(3)