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