~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to tools/sfio/sfmode.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include        "sfhdr.h"
 
2
static char*    Version = "\n@(#)sfio (AT&T Labs - kpv) 2001-02-01\0\n";
 
3
 
 
4
/*      Functions to set a given stream to some desired mode
 
5
**
 
6
**      Written by Kiem-Phong Vo.
 
7
**
 
8
**      Modifications:
 
9
**              06/27/1990 (first version)
 
10
**              01/06/1991
 
11
**              07/08/1991
 
12
**              06/18/1992
 
13
**              02/02/1993
 
14
**              05/25/1993
 
15
**              02/07/1994
 
16
**              05/21/1996
 
17
**              08/01/1997
 
18
**              08/01/1998 (extended formatting)
 
19
**              09/09/1999 (thread-safe)
 
20
**              02/01/2001 (adaptive buffering)
 
21
*/
 
22
 
 
23
/* the below is for protecting the application from SIGPIPE */
 
24
#if _PACKAGE_ast
 
25
#include                <sig.h>
 
26
#include                <wait.h>
 
27
#define Sfsignal_f      Sig_handler_t
 
28
#else
 
29
#include                <signal.h>
 
30
typedef void(*          Sfsignal_f)_ARG_((int));
 
31
#endif
 
32
static int              _Sfsigp = 0; /* # of streams needing SIGPIPE protection */ 
 
33
 
 
34
/* done at exiting time */
 
35
#if __STD_C
 
36
static void _sfcleanup(void)
 
37
#else
 
38
static void _sfcleanup()
 
39
#endif
 
40
{
 
41
        reg Sfpool_t*   p;
 
42
        reg Sfio_t*     f;
 
43
        reg int         n;
 
44
        reg int         pool;
 
45
 
 
46
        f = (Sfio_t*)Version; /* shut compiler warning */
 
47
 
 
48
        /* set this so that no more buffering is allowed for write streams */
 
49
        _Sfexiting = 1001;
 
50
 
 
51
        sfsync(NIL(Sfio_t*));
 
52
 
 
53
        for(p = &_Sfpool; p; p = p->next)
 
54
        {       for(n = 0; n < p->n_sf; ++n)
 
55
                {       if(!(f = p->sf[n]) || SFFROZEN(f) )
 
56
                                continue;
 
57
 
 
58
                        SFLOCK(f,0);
 
59
                        SFMTXLOCK(f);
 
60
 
 
61
                        /* let application know that we are leaving */
 
62
                        (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*));
 
63
 
 
64
                        if(f->flags&SF_STRING)
 
65
                                continue;
 
66
 
 
67
                        /* from now on, write streams are unbuffered */
 
68
                        pool = f->mode&SF_POOL;
 
69
                        f->mode &= ~SF_POOL;
 
70
                        if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE))
 
71
                                (void)_sfmode(f,SF_WRITE,1);
 
72
                        if(((f->bits&SF_MMAP) && f->data) ||
 
73
                           ((f->mode&SF_WRITE) && f->next == f->data) )
 
74
                                (void)SFSETBUF(f,NIL(Void_t*),0);
 
75
                        f->mode |= pool;
 
76
 
 
77
                        SFMTXUNLOCK(f);
 
78
                        SFOPEN(f,0);
 
79
                }
 
80
        }
 
81
}
 
82
 
 
83
/* put into discrete pool */
 
84
#if __STD_C
 
85
int _sfsetpool(Sfio_t* f)
 
86
#else
 
87
int _sfsetpool(f)
 
88
Sfio_t* f;
 
89
#endif
 
90
{
 
91
        reg Sfpool_t*   p;
 
92
        reg Sfio_t**    array;
 
93
        reg int         n, rv;
 
94
 
 
95
        if(!_Sfcleanup)
 
96
        {       _Sfcleanup = _sfcleanup;
 
97
                (void)atexit(_sfcleanup);
 
98
        }
 
99
 
 
100
        if(!(p = f->pool) )
 
101
                p = f->pool = &_Sfpool;
 
102
 
 
103
        POOLMTXSTART(p);
 
104
 
 
105
        rv = -1;
 
106
 
 
107
        if(p->n_sf >= p->s_sf)
 
108
        {       if(p->s_sf == 0) /* initialize pool array */
 
109
                {       p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
 
110
                        p->sf = p->array;
 
111
                }
 
112
                else    /* allocate a larger array */
 
113
                {       n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4;
 
114
                        if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) )
 
115
                                goto done;
 
116
 
 
117
                        /* move old array to new one */
 
118
                        memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*));
 
119
                        if(p->sf != p->array)
 
120
                                free((Void_t*)p->sf);
 
121
 
 
122
                        p->sf = array;
 
123
                        p->s_sf = n;
 
124
                }
 
125
        }
 
126
 
 
127
        /* always add at end of array because if this was done during some sort
 
128
           of walk thru all streams, we'll want the new stream to be seen.
 
129
        */
 
130
        p->sf[p->n_sf++] = f;
 
131
        rv = 0;
 
132
 
 
133
done:
 
134
        POOLMTXRETURN(p, rv);
 
135
}
 
136
 
 
137
/* create an auxiliary buffer for sfgetr/sfreserve/sfputr */
 
138
#if __STD_C
 
139
Sfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size)
 
140
#else
 
141
Sfrsrv_t* _sfrsrv(f,size)
 
142
reg Sfio_t*     f;
 
143
reg ssize_t     size;
 
144
#endif
 
145
{
 
146
        Sfrsrv_t        *rsrv, *rs;
 
147
 
 
148
        /* make buffer if nothing yet */
 
149
        size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
 
150
        if(!(rsrv = f->rsrv) || size > rsrv->size)
 
151
        {       if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t))))
 
152
                        size = -1;
 
153
                else
 
154
                {       if(rsrv)
 
155
                        {       if(rsrv->slen > 0)
 
156
                                        memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen);
 
157
                                free(rsrv);
 
158
                        }
 
159
                        f->rsrv = rsrv = rs;
 
160
                        rsrv->size = size;
 
161
                        rsrv->slen = 0;
 
162
                }
 
163
        }
 
164
 
 
165
        if(rsrv && size > 0)
 
166
                rsrv->slen = 0;
 
167
 
 
168
        return size >= 0 ? rsrv : NIL(Sfrsrv_t*);
 
169
}
 
170
 
 
171
#ifdef SIGPIPE
 
172
#if __STD_C
 
173
static void ignoresig(int sig)
 
174
#else
 
175
static void ignoresig(sig)
 
176
int sig;
 
177
#endif
 
178
{
 
179
        signal(sig, ignoresig);
 
180
}
 
181
#endif
 
182
 
 
183
#if __STD_C
 
184
int _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio)
 
185
#else
 
186
int _sfpopen(f, fd, pid, stdio)
 
187
reg Sfio_t*     f;
 
188
int             fd;
 
189
int             pid;
 
190
int             stdio;  /* stdio popen() does not reset SIGPIPE handler */
 
191
#endif
 
192
{
 
193
        reg Sfproc_t*   p;
 
194
 
 
195
        if(f->proc)
 
196
                return 0;
 
197
 
 
198
        if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) )
 
199
                return -1;
 
200
 
 
201
        p->pid = pid;
 
202
        p->size = p->ndata = 0;
 
203
        p->rdata = NIL(uchar*);
 
204
        p->file = fd;
 
205
        p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0;
 
206
 
 
207
#ifdef SIGPIPE  /* protect from broken pipe signal */
 
208
        if(p->sigp)
 
209
        {       Sfsignal_f      handler;
 
210
 
 
211
                vtmtxlock(_Sfmutex);
 
212
                if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL &&
 
213
                    handler != ignoresig)
 
214
                        signal(SIGPIPE, handler); /* honor user handler */
 
215
                _Sfsigp += 1;
 
216
                vtmtxunlock(_Sfmutex);
 
217
        }
 
218
#endif
 
219
 
 
220
        return 0;
 
221
}
 
222
 
 
223
#if __STD_C
 
224
int _sfpclose(reg Sfio_t* f)
 
225
#else
 
226
int _sfpclose(f)
 
227
reg Sfio_t*     f;      /* stream to close */
 
228
#endif
 
229
{
 
230
        Sfproc_t*       p;
 
231
        int             pid, status;
 
232
 
 
233
        if(!(p = f->proc))
 
234
                return -1;
 
235
        f->proc = NIL(Sfproc_t*);
 
236
 
 
237
        if(p->rdata)
 
238
                free(p->rdata);
 
239
 
 
240
        if(p->pid < 0)
 
241
                status = 0;
 
242
        else
 
243
        {       /* close the associated stream */
 
244
                if(p->file >= 0)
 
245
                        CLOSE(p->file);
 
246
 
 
247
                /* wait for process termination */
 
248
#if _PACKAGE_ast
 
249
                sigcritical(1);
 
250
#endif
 
251
                while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR)
 
252
                        ;
 
253
                if(pid < 0)
 
254
                        status = -1;
 
255
#if _PACKAGE_ast
 
256
                sigcritical(0);
 
257
#endif
 
258
 
 
259
#ifdef SIGPIPE
 
260
                vtmtxlock(_Sfmutex);
 
261
                if(p->sigp && (_Sfsigp -= 1) <= 0)
 
262
                {       Sfsignal_f      handler;
 
263
                        if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL &&
 
264
                           handler != ignoresig)
 
265
                                signal(SIGPIPE,handler); /* honor user handler */
 
266
                        _Sfsigp = 0;
 
267
                }
 
268
                vtmtxunlock(_Sfmutex);
 
269
#endif
 
270
        }
 
271
 
 
272
        free(p);
 
273
        return status;
 
274
}
 
275
 
 
276
#if __STD_C
 
277
static int _sfpmode(Sfio_t* f, int type)
 
278
#else
 
279
static int _sfpmode(f,type)
 
280
Sfio_t* f;
 
281
int     type;
 
282
#endif
 
283
{
 
284
        Sfproc_t*       p;
 
285
 
 
286
        if(!(p = f->proc) )
 
287
                return -1;
 
288
 
 
289
        if(type == SF_WRITE)
 
290
        {       /* save unread data */
 
291
                p->ndata = f->endb-f->next;
 
292
                if(p->ndata > p->size)
 
293
                {       if(p->rdata)
 
294
                                free((char*)p->rdata);
 
295
                        if((p->rdata = (uchar*)malloc(p->ndata)) )
 
296
                                p->size = p->ndata;
 
297
                        else
 
298
                        {       p->size = 0;
 
299
                                return -1;
 
300
                        }
 
301
                }
 
302
                if(p->ndata > 0)
 
303
                        memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata);
 
304
                f->endb = f->data;
 
305
        }
 
306
        else
 
307
        {       /* restore read data */
 
308
                if(p->ndata > f->size)  /* may lose data!!! */
 
309
                        p->ndata = f->size;
 
310
                if(p->ndata > 0)
 
311
                {       memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata);
 
312
                        f->endb = f->data+p->ndata;
 
313
                        p->ndata = 0;
 
314
                }
 
315
        }
 
316
 
 
317
        /* switch file descriptor */
 
318
        if(p->pid >= 0)
 
319
        {       type = f->file;
 
320
                f->file = p->file;
 
321
                p->file = type;
 
322
        }
 
323
 
 
324
        return 0;
 
325
}
 
326
 
 
327
#if __STD_C
 
328
int _sfmode(reg Sfio_t* f, reg int wanted, reg int local)
 
329
#else
 
330
int _sfmode(f, wanted, local)
 
331
reg Sfio_t*     f;      /* change r/w mode and sync file pointer for this stream */
 
332
reg int         wanted; /* desired mode */
 
333
reg int         local;  /* a local call */
 
334
#endif
 
335
{
 
336
        reg int n;
 
337
        Sfoff_t addr;
 
338
        reg int rv = 0;
 
339
 
 
340
        SFONCE();       /* initialize mutexes */
 
341
 
 
342
        if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0))
 
343
        {       if(local || !f->disc || !f->disc->exceptf)
 
344
                {       local = 1;
 
345
                        goto err_notify;
 
346
                }
 
347
 
 
348
                for(;;)
 
349
                {       if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0)
 
350
                                return rv;
 
351
                        if((!local && SFFROZEN(f)) ||
 
352
                           (!(f->flags&SF_STRING) && f->file < 0) )
 
353
                        {       if(rv == 0)
 
354
                                {       local = 1;
 
355
                                        goto err_notify;
 
356
                                }
 
357
                                else    continue;
 
358
                        }
 
359
                        else    break;
 
360
                }
 
361
        }
 
362
 
 
363
        if(f->mode&SF_GETR)
 
364
        {       f->mode &= ~SF_GETR;
 
365
#ifdef MAP_TYPE
 
366
                if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) )
 
367
                {       /* turn off mmap to avoid page faulting */
 
368
                        sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
 
369
                        f->tiny[0] = 0;
 
370
                }
 
371
                else
 
372
#endif
 
373
                if(f->getr)
 
374
                {       f->next[-1] = f->getr;
 
375
                        f->getr = 0;
 
376
                }
 
377
        }
 
378
 
 
379
        if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */
 
380
                (*_Sfstdsync)(f);
 
381
 
 
382
        if(f->disc == _Sfudisc && wanted == SF_WRITE &&
 
383
           sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 )
 
384
        {       local = 1;
 
385
                goto err_notify;
 
386
        }
 
387
 
 
388
        if(f->mode&SF_POOL)
 
389
        {       /* move to head of pool */
 
390
                if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 )
 
391
                {       local = 1;
 
392
                        goto err_notify;
 
393
                }
 
394
                f->mode &= ~SF_POOL;
 
395
        }
 
396
 
 
397
        SFLOCK(f,local);
 
398
 
 
399
        /* buffer initialization */
 
400
        wanted &= SF_RDWR;
 
401
        if(f->mode&SF_INIT)
 
402
        {       
 
403
                if(!f->pool && _sfsetpool(f) < 0)
 
404
                {       rv = -1;
 
405
                        goto done;
 
406
                }
 
407
 
 
408
                if(wanted == 0)
 
409
                        goto done;
 
410
 
 
411
                if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) )
 
412
                        goto err_notify;
 
413
 
 
414
                if((f->flags&SF_STRING) && f->size >= 0 && f->data)
 
415
                {       f->mode &= ~SF_INIT;
 
416
                        f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ?
 
417
                                        f->size : 0;
 
418
                        f->here = 0;
 
419
                        f->endb = f->data + f->size;
 
420
                        f->next = f->endr = f->endw = f->data;
 
421
                        if(f->mode&SF_READ)
 
422
                                f->endr = f->endb;
 
423
                        else    f->endw = f->endb;
 
424
                }
 
425
                else
 
426
                {       n = f->flags;
 
427
                        (void)SFSETBUF(f,f->data,f->size);
 
428
                        f->flags |= (n&SF_MALLOC);
 
429
                }
 
430
        }
 
431
 
 
432
        if(wanted == (int)SFMODE(f,1))
 
433
                goto done;
 
434
 
 
435
        switch(SFMODE(f,1))
 
436
        {
 
437
        case SF_WRITE: /* switching to SF_READ */
 
438
                if(wanted == 0 || wanted == SF_WRITE)
 
439
                        break;
 
440
                if(!(f->flags&SF_READ) )
 
441
                        goto err_notify;
 
442
                else if(f->flags&SF_STRING)
 
443
                {       SFSTRSIZE(f);
 
444
                        f->endb = f->data+f->extent;
 
445
                        f->mode = SF_READ;
 
446
                        break;
 
447
                }
 
448
 
 
449
                /* reset buffer */
 
450
                if(f->next > f->data && SFFLSBUF(f,-1) < 0)
 
451
                        goto err_notify;
 
452
 
 
453
                if(f->size == 0)
 
454
                {       /* unbuffered */
 
455
                        f->data = f->tiny;
 
456
                        f->size = sizeof(f->tiny);
 
457
                }
 
458
                f->next = f->endr = f->endw = f->endb = f->data;
 
459
                f->mode = SF_READ|SF_LOCK;
 
460
 
 
461
                /* restore saved read data for coprocess */
 
462
                if(f->proc && _sfpmode(f,wanted) < 0)
 
463
                        goto err_notify;
 
464
 
 
465
                break;
 
466
 
 
467
        case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */
 
468
                if(wanted != SF_WRITE)
 
469
                {       /* just reset the pointers */
 
470
                        f->mode = SF_READ|SF_LOCK;
 
471
 
 
472
                        /* see if must go with new physical location */
 
473
                        if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
 
474
                           (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here)
 
475
                        {
 
476
#ifdef MAP_TYPE
 
477
                                if((f->bits&SF_MMAP) && f->data)
 
478
                                {       SFMUNMAP(f,f->data,f->endb-f->data);
 
479
                                        f->data = NIL(uchar*);
 
480
                                }
 
481
#endif
 
482
                                f->endb = f->endr = f->endw = f->next = f->data;
 
483
                                f->here = addr;
 
484
                        }
 
485
                        else
 
486
                        {       addr = f->here + (f->endb - f->next);
 
487
                                if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
 
488
                                        goto err_notify;
 
489
                                f->here = addr;
 
490
                        }
 
491
 
 
492
                        break;
 
493
                }
 
494
                /* fall thru */
 
495
 
 
496
        case SF_READ: /* switching to SF_WRITE */
 
497
                if(wanted != SF_WRITE)
 
498
                        break;
 
499
                else if(!(f->flags&SF_WRITE))
 
500
                        goto err_notify;
 
501
                else if(f->flags&SF_STRING)
 
502
                {       f->endb = f->data+f->size;
 
503
                        f->mode = SF_WRITE|SF_LOCK;
 
504
                        break;
 
505
                }
 
506
 
 
507
                /* save unread data before switching mode */
 
508
                if(f->proc && _sfpmode(f,wanted) < 0)
 
509
                        goto err_notify;
 
510
 
 
511
                /* reset buffer and seek pointer */
 
512
                if(!(f->mode&SF_SYNCED) )
 
513
                {       n = f->endb - f->next;
 
514
                        if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) )
 
515
                        {       /* reset file pointer */
 
516
                                addr = f->here - n;
 
517
                                if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
 
518
                                        goto err_notify;
 
519
                                f->here = addr;
 
520
                        }
 
521
                }
 
522
 
 
523
                f->mode = SF_WRITE|SF_LOCK;
 
524
#ifdef MAP_TYPE
 
525
                if(f->bits&SF_MMAP)
 
526
                {       if(f->data)
 
527
                                SFMUNMAP(f,f->data,f->endb-f->data);
 
528
                        (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
 
529
                }
 
530
#endif
 
531
                if(f->data == f->tiny)
 
532
                {       f->endb = f->data = f->next = NIL(uchar*);
 
533
                        f->size = 0;
 
534
                }
 
535
                else    f->endb = (f->next = f->data) + f->size;
 
536
 
 
537
                break;
 
538
 
 
539
        default: /* unknown case */
 
540
        err_notify:
 
541
                if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR)
 
542
                        wanted = SF_READ;
 
543
 
 
544
                /* set errno for operations that access wrong stream type */
 
545
                if(wanted != (f->mode&SF_RDWR) && f->file >= 0)
 
546
                        errno = EBADF;
 
547
 
 
548
                if(_Sfnotify) /* notify application of the error */
 
549
                        (*_Sfnotify)(f,wanted,f->file);
 
550
 
 
551
                rv = -1;
 
552
                break;
 
553
        }
 
554
 
 
555
done:
 
556
        SFOPEN(f,local);
 
557
        return rv;
 
558
}