xref: /aosp_15_r20/external/libcups/examples/ppdx.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Example code for encoding and decoding large amounts of data in a PPD file.
3*5e7646d2SAndroid Build Coastguard Worker  * This would typically be used in a driver to save configuration/state
4*5e7646d2SAndroid Build Coastguard Worker  * information that could be used by an application.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2012 by Apple Inc.
7*5e7646d2SAndroid Build Coastguard Worker  *
8*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "ppdx.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <stdio.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <stdlib.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <string.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <zlib.h>			/* For compression of the data */
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker  * Constants...
24*5e7646d2SAndroid Build Coastguard Worker  */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker #define PPDX_MAX_VALUE	(PPD_MAX_LINE - PPD_MAX_NAME - 4)
27*5e7646d2SAndroid Build Coastguard Worker 					/* Max value length with delimiters + nul */
28*5e7646d2SAndroid Build Coastguard Worker #define PPDX_MAX_CHUNK	(PPDX_MAX_VALUE * 3 / 4)
29*5e7646d2SAndroid Build Coastguard Worker 					/* Max length of each chunk when Base64-encoded */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * 'ppdxReadData()' - Read encoded data from a ppd_file_t *.
34*5e7646d2SAndroid Build Coastguard Worker  *
35*5e7646d2SAndroid Build Coastguard Worker  * Reads chunked data in the PPD file "ppd" using the prefix "name".  Returns
36*5e7646d2SAndroid Build Coastguard Worker  * an allocated pointer to the data (which is nul-terminated for convenience)
37*5e7646d2SAndroid Build Coastguard Worker  * along with the length of the data in the variable pointed to by "datasize",
38*5e7646d2SAndroid Build Coastguard Worker  * which can be NULL to indicate the caller doesn't need the length.
39*5e7646d2SAndroid Build Coastguard Worker  *
40*5e7646d2SAndroid Build Coastguard Worker  * Returns NULL if no data is present in the PPD with the prefix.
41*5e7646d2SAndroid Build Coastguard Worker  */
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker void *					/* O - Data or NULL */
ppdxReadData(ppd_file_t * ppd,const char * name,size_t * datasize)44*5e7646d2SAndroid Build Coastguard Worker ppdxReadData(ppd_file_t *ppd,		/* I - PPD file */
45*5e7646d2SAndroid Build Coastguard Worker              const char *name,		/* I - Keyword prefix */
46*5e7646d2SAndroid Build Coastguard Worker              size_t     *datasize)	/* O - Size of data or NULL for don't care */
47*5e7646d2SAndroid Build Coastguard Worker {
48*5e7646d2SAndroid Build Coastguard Worker   char		keyword[PPD_MAX_NAME],	/* Keyword name */
49*5e7646d2SAndroid Build Coastguard Worker 		decoded[PPDX_MAX_CHUNK + 1];
50*5e7646d2SAndroid Build Coastguard Worker 					/* Decoded string */
51*5e7646d2SAndroid Build Coastguard Worker   unsigned	chunk = 0;		/* Current chunk number */
52*5e7646d2SAndroid Build Coastguard Worker   int		len;			/* Length of current chunk */
53*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*attr;			/* Keyword/value from PPD file */
54*5e7646d2SAndroid Build Coastguard Worker   Bytef		*data;			/* Pointer to data */
55*5e7646d2SAndroid Build Coastguard Worker   size_t	alloc_size;		/* Allocated size of data buffer */
56*5e7646d2SAndroid Build Coastguard Worker   z_stream	decomp;			/* Decompressor stream */
57*5e7646d2SAndroid Build Coastguard Worker   int		error;			/* Error/status from inflate() */
58*5e7646d2SAndroid Build Coastguard Worker 
59*5e7646d2SAndroid Build Coastguard Worker 
60*5e7646d2SAndroid Build Coastguard Worker  /*
61*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
62*5e7646d2SAndroid Build Coastguard Worker   */
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker   if (datasize)
65*5e7646d2SAndroid Build Coastguard Worker     *datasize = 0;
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !name)
68*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
69*5e7646d2SAndroid Build Coastguard Worker 
70*5e7646d2SAndroid Build Coastguard Worker  /*
71*5e7646d2SAndroid Build Coastguard Worker   * First see if there are any instances of the named keyword in the PPD...
72*5e7646d2SAndroid Build Coastguard Worker   */
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker   snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk);
75*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ppdFindAttr(ppd, keyword, NULL)) == NULL)
76*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker  /*
79*5e7646d2SAndroid Build Coastguard Worker   * Allocate some memory and start decoding...
80*5e7646d2SAndroid Build Coastguard Worker   */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker   data       = malloc(257);
83*5e7646d2SAndroid Build Coastguard Worker   alloc_size = 256;
84*5e7646d2SAndroid Build Coastguard Worker 
85*5e7646d2SAndroid Build Coastguard Worker   memset(&decomp, 0, sizeof(decomp));
86*5e7646d2SAndroid Build Coastguard Worker   decomp.next_out  = data;
87*5e7646d2SAndroid Build Coastguard Worker   decomp.avail_out = 256;
88*5e7646d2SAndroid Build Coastguard Worker 
89*5e7646d2SAndroid Build Coastguard Worker   inflateInit(&decomp);
90*5e7646d2SAndroid Build Coastguard Worker 
91*5e7646d2SAndroid Build Coastguard Worker   do
92*5e7646d2SAndroid Build Coastguard Worker   {
93*5e7646d2SAndroid Build Coastguard Worker    /*
94*5e7646d2SAndroid Build Coastguard Worker     * Grab the data from the current attribute and decode it...
95*5e7646d2SAndroid Build Coastguard Worker     */
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker     len = sizeof(decoded);
98*5e7646d2SAndroid Build Coastguard Worker     if (!httpDecode64_2(decoded, &len, attr->value) || len == 0)
99*5e7646d2SAndroid Build Coastguard Worker       break;
100*5e7646d2SAndroid Build Coastguard Worker 
101*5e7646d2SAndroid Build Coastguard Worker //    printf("chunk %04x has length %d\n", chunk, len);
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker    /*
104*5e7646d2SAndroid Build Coastguard Worker     * Decompress this chunk...
105*5e7646d2SAndroid Build Coastguard Worker     */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker     decomp.next_in  = decoded;
108*5e7646d2SAndroid Build Coastguard Worker     decomp.avail_in = len;
109*5e7646d2SAndroid Build Coastguard Worker 
110*5e7646d2SAndroid Build Coastguard Worker     do
111*5e7646d2SAndroid Build Coastguard Worker     {
112*5e7646d2SAndroid Build Coastguard Worker       Bytef	*temp;			/* Temporary pointer */
113*5e7646d2SAndroid Build Coastguard Worker       size_t	temp_size;		/* Temporary allocation size */
114*5e7646d2SAndroid Build Coastguard Worker 
115*5e7646d2SAndroid Build Coastguard Worker //      printf("Before inflate: avail_in=%d, avail_out=%d\n", decomp.avail_in,
116*5e7646d2SAndroid Build Coastguard Worker //             decomp.avail_out);
117*5e7646d2SAndroid Build Coastguard Worker 
118*5e7646d2SAndroid Build Coastguard Worker       if ((error = inflate(&decomp, Z_NO_FLUSH)) < Z_OK)
119*5e7646d2SAndroid Build Coastguard Worker       {
120*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: inflate returned %d (%s)\n", error, decomp.msg);
121*5e7646d2SAndroid Build Coastguard Worker         break;
122*5e7646d2SAndroid Build Coastguard Worker       }
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker //      printf("After inflate: avail_in=%d, avail_out=%d, error=%d\n",
125*5e7646d2SAndroid Build Coastguard Worker //             decomp.avail_in, decomp.avail_out, error);
126*5e7646d2SAndroid Build Coastguard Worker 
127*5e7646d2SAndroid Build Coastguard Worker       if (decomp.avail_out == 0)
128*5e7646d2SAndroid Build Coastguard Worker       {
129*5e7646d2SAndroid Build Coastguard Worker 	if (alloc_size < 2048)
130*5e7646d2SAndroid Build Coastguard Worker 	  temp_size = alloc_size * 2;
131*5e7646d2SAndroid Build Coastguard Worker 	else if (alloc_size < PPDX_MAX_DATA)
132*5e7646d2SAndroid Build Coastguard Worker 	  temp_size = alloc_size + 2048;
133*5e7646d2SAndroid Build Coastguard Worker 	else
134*5e7646d2SAndroid Build Coastguard Worker 	  break;
135*5e7646d2SAndroid Build Coastguard Worker 
136*5e7646d2SAndroid Build Coastguard Worker 	if ((temp = realloc(data, temp_size + 1)) == NULL)
137*5e7646d2SAndroid Build Coastguard Worker 	{
138*5e7646d2SAndroid Build Coastguard Worker 	  free(data);
139*5e7646d2SAndroid Build Coastguard Worker 	  return (NULL);
140*5e7646d2SAndroid Build Coastguard Worker 	}
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker 	decomp.next_out  = temp + (decomp.next_out - data);
143*5e7646d2SAndroid Build Coastguard Worker 	decomp.avail_out = temp_size - alloc_size;
144*5e7646d2SAndroid Build Coastguard Worker 	data             = temp;
145*5e7646d2SAndroid Build Coastguard Worker 	alloc_size       = temp_size;
146*5e7646d2SAndroid Build Coastguard Worker       }
147*5e7646d2SAndroid Build Coastguard Worker     }
148*5e7646d2SAndroid Build Coastguard Worker     while (decomp.avail_in > 0);
149*5e7646d2SAndroid Build Coastguard Worker 
150*5e7646d2SAndroid Build Coastguard Worker     chunk ++;
151*5e7646d2SAndroid Build Coastguard Worker     snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk);
152*5e7646d2SAndroid Build Coastguard Worker   }
153*5e7646d2SAndroid Build Coastguard Worker   while ((attr = ppdFindAttr(ppd, keyword, NULL)) != NULL);
154*5e7646d2SAndroid Build Coastguard Worker 
155*5e7646d2SAndroid Build Coastguard Worker   inflateEnd(&decomp);
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker  /*
158*5e7646d2SAndroid Build Coastguard Worker   * Nul-terminate the data (usually a string)...
159*5e7646d2SAndroid Build Coastguard Worker   */
160*5e7646d2SAndroid Build Coastguard Worker 
161*5e7646d2SAndroid Build Coastguard Worker   *(decomp.next_out) = '\0';
162*5e7646d2SAndroid Build Coastguard Worker 
163*5e7646d2SAndroid Build Coastguard Worker   if (datasize)
164*5e7646d2SAndroid Build Coastguard Worker     *datasize = decomp.next_out - data;
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker   return (data);
167*5e7646d2SAndroid Build Coastguard Worker }
168*5e7646d2SAndroid Build Coastguard Worker 
169*5e7646d2SAndroid Build Coastguard Worker 
170*5e7646d2SAndroid Build Coastguard Worker /*
171*5e7646d2SAndroid Build Coastguard Worker  * 'ppdxWriteData()' - Writes encoded data to stderr using PPD: messages.
172*5e7646d2SAndroid Build Coastguard Worker  *
173*5e7646d2SAndroid Build Coastguard Worker  * Writes chunked data to the PPD file using PPD: messages sent to stderr for
174*5e7646d2SAndroid Build Coastguard Worker  * cupsd.  "name" must be a valid PPD keyword string whose length is less than
175*5e7646d2SAndroid Build Coastguard Worker  * 37 characters to allow for chunk numbering.  "data" provides a pointer to the
176*5e7646d2SAndroid Build Coastguard Worker  * data to be written, and "datasize" provides the length.
177*5e7646d2SAndroid Build Coastguard Worker  */
178*5e7646d2SAndroid Build Coastguard Worker 
179*5e7646d2SAndroid Build Coastguard Worker extern void
ppdxWriteData(const char * name,const void * data,size_t datasize)180*5e7646d2SAndroid Build Coastguard Worker ppdxWriteData(const char *name,		/* I - Base name of keyword */
181*5e7646d2SAndroid Build Coastguard Worker               const void *data,		/* I - Data to write */
182*5e7646d2SAndroid Build Coastguard Worker               size_t     datasize)	/* I - Number of bytes in data */
183*5e7646d2SAndroid Build Coastguard Worker {
184*5e7646d2SAndroid Build Coastguard Worker   char		buffer[PPDX_MAX_CHUNK],	/* Chunk buffer */
185*5e7646d2SAndroid Build Coastguard Worker 		encoded[PPDX_MAX_VALUE + 1],
186*5e7646d2SAndroid Build Coastguard Worker 					/* Encoded data */
187*5e7646d2SAndroid Build Coastguard Worker 		pair[PPD_MAX_LINE],	/* name=value pair */
188*5e7646d2SAndroid Build Coastguard Worker 		line[PPDX_MAX_STATUS],	/* Line buffer */
189*5e7646d2SAndroid Build Coastguard Worker 		*lineptr,		/* Current position in line buffer */
190*5e7646d2SAndroid Build Coastguard Worker 		*lineend;		/* End of line buffer */
191*5e7646d2SAndroid Build Coastguard Worker   unsigned	chunk = 0;		/* Current chunk number */
192*5e7646d2SAndroid Build Coastguard Worker   int		len;			/* Length of current chunk */
193*5e7646d2SAndroid Build Coastguard Worker   z_stream	comp;			/* Compressor stream */
194*5e7646d2SAndroid Build Coastguard Worker   int		error;			/* Error/status from deflate() */
195*5e7646d2SAndroid Build Coastguard Worker 
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker  /*
198*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
199*5e7646d2SAndroid Build Coastguard Worker   */
200*5e7646d2SAndroid Build Coastguard Worker 
201*5e7646d2SAndroid Build Coastguard Worker   if (!name || (!data && datasize > 0) || datasize > PPDX_MAX_DATA)
202*5e7646d2SAndroid Build Coastguard Worker     return;
203*5e7646d2SAndroid Build Coastguard Worker 
204*5e7646d2SAndroid Build Coastguard Worker   strlcpy(line, "PPD:", sizeof(line));
205*5e7646d2SAndroid Build Coastguard Worker   lineptr = line + 4;
206*5e7646d2SAndroid Build Coastguard Worker   lineend = line + sizeof(line) - 2;
207*5e7646d2SAndroid Build Coastguard Worker 
208*5e7646d2SAndroid Build Coastguard Worker   if (datasize > 0)
209*5e7646d2SAndroid Build Coastguard Worker   {
210*5e7646d2SAndroid Build Coastguard Worker    /*
211*5e7646d2SAndroid Build Coastguard Worker     * Compress and encode output...
212*5e7646d2SAndroid Build Coastguard Worker     */
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker     memset(&comp, 0, sizeof(comp));
215*5e7646d2SAndroid Build Coastguard Worker     comp.next_in   = (Bytef *)data;
216*5e7646d2SAndroid Build Coastguard Worker     comp.avail_in  = datasize;
217*5e7646d2SAndroid Build Coastguard Worker 
218*5e7646d2SAndroid Build Coastguard Worker     deflateInit(&comp, 9);
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker     do
221*5e7646d2SAndroid Build Coastguard Worker     {
222*5e7646d2SAndroid Build Coastguard Worker      /*
223*5e7646d2SAndroid Build Coastguard Worker       * Compress a chunk...
224*5e7646d2SAndroid Build Coastguard Worker       */
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker       comp.next_out  = buffer;
227*5e7646d2SAndroid Build Coastguard Worker       comp.avail_out = sizeof(buffer);
228*5e7646d2SAndroid Build Coastguard Worker 
229*5e7646d2SAndroid Build Coastguard Worker       if ((error = deflate(&comp, Z_FINISH)) < Z_OK)
230*5e7646d2SAndroid Build Coastguard Worker       {
231*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: deflate returned %d (%s)\n", error, comp.msg);
232*5e7646d2SAndroid Build Coastguard Worker         break;
233*5e7646d2SAndroid Build Coastguard Worker       }
234*5e7646d2SAndroid Build Coastguard Worker 
235*5e7646d2SAndroid Build Coastguard Worker      /*
236*5e7646d2SAndroid Build Coastguard Worker       * Write a chunk...
237*5e7646d2SAndroid Build Coastguard Worker       */
238*5e7646d2SAndroid Build Coastguard Worker 
239*5e7646d2SAndroid Build Coastguard Worker       len = sizeof(buffer) - comp.avail_out;
240*5e7646d2SAndroid Build Coastguard Worker       httpEncode64_2(encoded, sizeof(encoded), buffer, len);
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker       len = (int)snprintf(pair, sizeof(pair), " %s%04x=%s", name, chunk,
243*5e7646d2SAndroid Build Coastguard Worker 			  encoded);
244*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
245*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: *%s%04x: \"%s\"\n", name, chunk, encoded);
246*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
247*5e7646d2SAndroid Build Coastguard Worker 
248*5e7646d2SAndroid Build Coastguard Worker       if ((lineptr + len) >= lineend)
249*5e7646d2SAndroid Build Coastguard Worker       {
250*5e7646d2SAndroid Build Coastguard Worker 	*lineptr++ = '\n';
251*5e7646d2SAndroid Build Coastguard Worker 	*lineptr   = '\0';
252*5e7646d2SAndroid Build Coastguard Worker 
253*5e7646d2SAndroid Build Coastguard Worker 	fputs(line, stderr);
254*5e7646d2SAndroid Build Coastguard Worker 	lineptr = line + 4;
255*5e7646d2SAndroid Build Coastguard Worker       }
256*5e7646d2SAndroid Build Coastguard Worker 
257*5e7646d2SAndroid Build Coastguard Worker       strlcpy(lineptr, pair, lineend - lineptr);
258*5e7646d2SAndroid Build Coastguard Worker       lineptr += len;
259*5e7646d2SAndroid Build Coastguard Worker 
260*5e7646d2SAndroid Build Coastguard Worker      /*
261*5e7646d2SAndroid Build Coastguard Worker       * Setup for the next one...
262*5e7646d2SAndroid Build Coastguard Worker       */
263*5e7646d2SAndroid Build Coastguard Worker 
264*5e7646d2SAndroid Build Coastguard Worker       chunk ++;
265*5e7646d2SAndroid Build Coastguard Worker     }
266*5e7646d2SAndroid Build Coastguard Worker     while (comp.avail_out == 0);
267*5e7646d2SAndroid Build Coastguard Worker   }
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker   deflateEnd(&comp);
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker  /*
272*5e7646d2SAndroid Build Coastguard Worker   * Write a trailing empty chunk to signal EOD...
273*5e7646d2SAndroid Build Coastguard Worker   */
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker   len = (int)snprintf(pair, sizeof(pair), " %s%04x=\"\"", name, chunk);
276*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
277*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: *%s%04x: \"\"\n", name, chunk);
278*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
279*5e7646d2SAndroid Build Coastguard Worker 
280*5e7646d2SAndroid Build Coastguard Worker   if ((lineptr + len) >= lineend)
281*5e7646d2SAndroid Build Coastguard Worker   {
282*5e7646d2SAndroid Build Coastguard Worker     *lineptr++ = '\n';
283*5e7646d2SAndroid Build Coastguard Worker     *lineptr   = '\0';
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker     fputs(line, stderr);
286*5e7646d2SAndroid Build Coastguard Worker     lineptr = line + 4;
287*5e7646d2SAndroid Build Coastguard Worker   }
288*5e7646d2SAndroid Build Coastguard Worker 
289*5e7646d2SAndroid Build Coastguard Worker   strlcpy(lineptr, pair, lineend - lineptr);
290*5e7646d2SAndroid Build Coastguard Worker   lineptr += len;
291*5e7646d2SAndroid Build Coastguard Worker 
292*5e7646d2SAndroid Build Coastguard Worker   *lineptr++ = '\n';
293*5e7646d2SAndroid Build Coastguard Worker   *lineptr   = '\0';
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker   fputs(line, stderr);
296*5e7646d2SAndroid Build Coastguard Worker }
297