Merge branch 'master' into cde-next
[oweals/cde.git] / cde / lib / DtHelp / bufio.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * $XConsortium: bufio.c /main/5 1996/11/01 10:11:35 drk $
25  *
26  * Copyright 1991 Massachusetts Institute of Technology
27  *
28  * Permission to use, copy, modify, distribute, and sell this software and its
29  * documentation for any purpose is hereby granted without fee, provided that
30  * the above copyright notice appear in all copies and that both that
31  * copyright notice and this permission notice appear in supporting
32  * documentation, and that the name of M.I.T. not be used in advertising or
33  * publicity pertaining to distribution of the software without specific,
34  * written prior permission.  M.I.T. makes no representations about the
35  * suitability of this software for any purpose.  It is provided "as is"
36  * without express or implied warranty.
37  *
38  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
40  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
42  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
43  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44  *
45  * Author:  Keith Packard, MIT X Consortium
46  */
47
48
49 /* #include    "fontmisc.h" */
50 #include    <errno.h>
51 #include    <stdio.h>
52 #include    <stdlib.h>
53 #include    <stdint.h>
54 #include    <unistd.h>
55 #include    "bufioI.h"
56
57 #include <X11/Xos.h>
58 #ifdef X_NOT_STDC_ENV
59 extern int errno;
60 #endif
61
62 #ifndef MIN
63 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
64 #endif
65
66 #define FileDes(f)              ((intptr_t) (f)->hidden)
67 #define CompressFileDes(f)      (((CECompressInfoPtr) (f)->hidden)->fd)
68 #define CompressSize(f)         (((CECompressInfoPtr) (f)->hidden)->size)
69
70 static int
71 BufFileRawSkip (
72     BufFilePtr  f,
73     int         count )
74 {
75     int     curoff;
76     int     fileoff;
77     int     todo;
78
79     curoff = f->bufp - f->buffer;
80     fileoff = curoff + f->left;
81     if (curoff + count <= fileoff) {
82         f->bufp += count;
83         f->left -= count;
84     } else {
85         todo = count - (fileoff - curoff);
86         if (lseek (FileDes(f), todo, 1) == -1) {
87             if (errno != ESPIPE)
88                 return BUFFILEEOF;
89             while (todo) {
90                 curoff = BUFFILESIZE;
91                 if (curoff > todo)
92                     curoff = todo;
93                 fileoff = read (FileDes(f), f->buffer, curoff);
94                 if (fileoff <= 0)
95                     return BUFFILEEOF;
96                 todo -= fileoff;
97             }
98         }
99         f->left = 0;
100     }
101     return count;
102 }
103
104 static int
105 BufFileRawFlush (
106     int         c,
107     BufFilePtr  f )
108 {
109     int cnt;
110
111     if (c != BUFFILEEOF)
112         *f->bufp++ = c;
113     cnt = f->bufp - f->buffer;
114     f->bufp = f->buffer;
115     f->left = BUFFILESIZE;
116     if (write (FileDes(f), f->buffer, cnt) != cnt)
117         return BUFFILEEOF;
118     return c;
119 }
120
121 BufFilePtr
122 _DtHelpCeBufFileOpenWr (int fd)
123 {
124     BufFilePtr  f;
125
126     f = _DtHelpCeBufFileCreate ((char *) (intptr_t) fd, BufFileRawFlush, NULL, _DtHelpCeBufFileFlush);
127     f->bufp = f->buffer;
128     f->left = BUFFILESIZE;
129     return f;
130 }
131
132 #ifdef  obsolete_function
133 _DtHelpCeBufFileWrite (
134     BufFilePtr  f,
135     char        *b,
136     int         n )
137 {
138     int     cnt;
139     cnt = n;
140     while (cnt--) {
141         if (BufFilePut (*b++, f) == BUFFILEEOF)
142             return BUFFILEEOF;
143     }
144     return n;
145 }
146 #endif
147
148 int
149 _DtHelpCeBufFileFlush (BufFilePtr f, int doClose)
150 {
151     if (f->bufp != f->buffer)
152         (*f->io) (BUFFILEEOF, f);
153
154     if (doClose)
155         return (close (FileDes(f)));
156
157     return 0;
158 }
159
160 /*****************************************************************************
161  *                      Private Routines
162  *****************************************************************************/
163 /*****************************************************************************
164  *                      Routines working on a File descriptor
165  *****************************************************************************/
166 static int
167 FdRawRead (BufFilePtr f)
168 {
169     int left;
170
171     left = read (FileDes(f), f->buffer, BUFFILESIZE);
172     if (left <= 0) {
173         f->left = 0;
174         return BUFFILEEOF;
175     }
176     f->left = left - 1;
177     f->bufp = f->buffer + 1;
178     return f->buffer[0];
179 }
180
181 static  int
182 FdClose (
183     BufFilePtr  f,
184     int         doClose)
185 {
186     if (doClose)
187         close (FileDes (f));
188     return 1;
189 }
190
191 /*****************************************************************************
192  *                      Routines working on a Raw Compressed file
193  *****************************************************************************/
194 static int
195 CompressRawRead (BufFilePtr f)
196 {
197     int left;
198
199
200     left = read (CompressFileDes(f), f->buffer,
201                                         MIN(CompressSize(f),BUFFILESIZE));
202     if (left <= 0) {
203         f->left = 0;
204         CompressSize(f) = 0;
205         return BUFFILEEOF;
206     }
207     CompressSize(f) -= left;
208     f->left = left - 1;
209     f->bufp = f->buffer + 1;
210     return f->buffer[0];
211 }
212
213 static  int
214 CompressRawClose (
215     BufFilePtr  f,
216     int         doClose)
217 {
218     if (doClose)
219         close (CompressFileDes (f));
220     free(f->hidden);
221     return 1;
222 }
223
224 /*****************************************************************************
225  *                      Routines working on a Pipe
226  *****************************************************************************/
227 /*****************************************************************************
228  * Function:    int RdPipeStream (BufFilePtr f)
229  *
230  * Returns:
231  *
232  * Purpose:
233  *
234  *****************************************************************************/
235 static int
236 RdPipeStream (BufFilePtr f)
237 {
238     int    left;
239
240     left = fread(f->buffer, 1, BUFFILESIZE, FileStream(f));
241
242     if (left <= 0)
243       {
244         f->left = 0;
245         return BUFFILEEOF;
246       }
247
248     clearerr(FileStream(f));
249     f->left = left - 1;
250     f->bufp = f->buffer + 1;
251     return f->buffer[0];
252 }
253
254 /*********************************************************************
255  * Procedure: int ClosePipeStream (BufFilePtr f);
256  *
257  * Returns:
258  *
259  * Purpose:
260  *
261  ********************************************************************/
262 static int
263 ClosePipeStream (
264     BufFilePtr  f,
265     int         doClose)
266 {
267     if (doClose)
268         pclose(FileStream(f));
269
270     return 1;
271 }
272
273 /*****************************************************************************
274  *                      Semi-Public Routines
275  *****************************************************************************/
276 /*****************************************************************************
277  * Function:    BufFilePtr _DtHelpCeBufFileCreate (char *hidden,
278  *                                      int (*io)(), int (*skip)(),
279  *                                      int (*close)())
280  *
281  * Returns:     A pointer to malloc'ed memory or NULL.
282  *
283  * Purpose:     Create a buffered i/o mechanism.
284  *
285  *****************************************************************************/
286 BufFilePtr
287 _DtHelpCeBufFileCreate (
288     char    *hidden,
289     int     (*io)(),
290     int     (*skip)(),
291     int     (*close)() )
292 {
293     BufFilePtr  f;
294
295     f = (BufFilePtr) malloc (sizeof *f);
296     if (!f)
297         return 0;
298     f->hidden = hidden;
299     f->bufp = f->buffer;
300     f->left = 0;
301     f->io = io;
302     f->skip = skip;
303     f->close = close;
304     return f;
305 }
306
307 /*****************************************************************************
308  * Function:    BufFilePtr _DtHelpCeBufFileRdWithFd (int fd)
309  *
310  * Returns:     A pointer to malloc'ed memory or NULL.
311  *
312  * Purpose:     Create a buffered i/o mechanism using a file descriptor
313  *              as private data and attaching a raw read to the i/o
314  *              routine.
315  *
316  *****************************************************************************/
317 BufFilePtr
318 _DtHelpCeBufFileRdWithFd (int fd)
319 {
320     return _DtHelpCeBufFileCreate ((char *) (intptr_t) fd, FdRawRead, BufFileRawSkip, FdClose);
321 }
322
323 /*****************************************************************************
324  * Function:    BufFilePtr _DtHelpCeBufFileRdRawZ (CECompressInfoPtr file)
325  *
326  * Returns:     A pointer to malloc'ed memory or NULL.
327  *
328  * Purpose:     Create a buffered i/o mechanism using a file descriptor
329  *              as private data and attaching a raw read of compressed
330  *              data to the i/o routine.
331  *
332  *****************************************************************************/
333 BufFilePtr
334 _DtHelpCeBufFileRdRawZ (CECompressInfoPtr file)
335 {
336     return _DtHelpCeBufFileCreate ((char *) file, CompressRawRead, NULL,
337                                                         CompressRawClose);
338 }
339
340 /*****************************************************************************
341  * Function:    void _DtHelpCeBufFileClose (BufFilePtr file, int doClose)
342  *
343  * Returns:     nothing
344  *
345  * Purpose:     Calls the close routine associated with the pointer.
346  *              Frees the BufFile information.
347  *
348  *****************************************************************************/
349 void
350 _DtHelpCeBufFileClose (
351     BufFilePtr  f,
352     int         doClose )
353 {
354     (void) (*f->close) (f, doClose);
355     free (f);
356 }
357
358 /*****************************************************************************
359  * Function:    void _DtHelpCeBufFileRd (BufFilePtr file, int doClose)
360  *
361  * Returns:     nothing
362  *
363  * Purpose:     Calls the close routine associated with the pointer.
364  *              Frees the BufFile information.
365  *
366  *****************************************************************************/
367 int
368 _DtHelpCeBufFileRd (
369     BufFilePtr  f,
370     char        *b,
371     int         n )
372 {
373     int     c, cnt;
374     cnt = n;
375     while (cnt--) {
376         c = BufFileGet (f);
377         if (c == BUFFILEEOF)
378             break;
379         *b++ = c;
380     }
381     return n - cnt - 1;
382 }
383
384 /*****************************************************************************
385  * Function:    BufFilePtr _DtHelpCeCreatePipeBufFile (FILE *stream)
386  *
387  * Returns:     A pointer to malloc'ed memory or NULL.
388  *
389  * Purpose:     Create a buffered i/o mechanism using a pipe descriptor
390  *              as private data and attaching a raw read to the i/o
391  *              routine.
392  *
393  *****************************************************************************/
394 BufFilePtr
395 _DtHelpCeCreatePipeBufFile (FILE *stream)
396 {
397     return _DtHelpCeBufFileCreate ((char *) stream,
398                                         RdPipeStream, NULL, ClosePipeStream);
399 }