1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2011 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #include "sfhdr.h"
23
24 /* Change the file descriptor
25 **
26 ** Written by Kiem-Phong Vo.
27 */
28
29 #if __STD_C
_sfdup(int fd,int newfd)30 static int _sfdup(int fd, int newfd)
31 #else
32 static int _sfdup(fd,newfd)
33 int fd;
34 int newfd;
35 #endif
36 {
37 reg int dupfd;
38
39 #ifdef F_DUPFD /* the simple case */
40 while((dupfd = sysfcntlf(fd,F_DUPFD,newfd)) < 0 && errno == EINTR)
41 errno = 0;
42 return dupfd;
43
44 #else /* do it the hard way */
45 if((dupfd = sysdupf(fd)) < 0 || dupfd >= newfd)
46 return dupfd;
47
48 /* dup() succeeded but didn't get the right number, recurse */
49 newfd = _sfdup(fd,newfd);
50
51 /* close the one that didn't match */
52 CLOSE(dupfd);
53
54 return newfd;
55 #endif
56 }
57
58 #if __STD_C
sfsetfd(Sfio_t * f,int newfd)59 int sfsetfd(Sfio_t* f, int newfd)
60 #else
61 int sfsetfd(f,newfd)
62 Sfio_t *f;
63 int newfd;
64 #endif
65 {
66 reg int oldfd;
67 SFMTXDECL(f);
68
69 SFMTXENTER(f, -1);
70
71 if(f->flags&SF_STRING)
72 SFMTXRETURN(f, -1);
73
74 if((f->mode&SF_INIT) && f->file < 0)
75 { /* restoring file descriptor after a previous freeze */
76 if(newfd < 0)
77 SFMTXRETURN(f, -1);
78 }
79 else
80 { /* change file descriptor */
81 if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
82 SFMTXRETURN(f, -1);
83 SFLOCK(f,0);
84
85 oldfd = f->file;
86 if(oldfd >= 0)
87 { if(newfd >= 0)
88 { if((newfd = _sfdup(oldfd,newfd)) < 0)
89 { SFOPEN(f,0);
90 SFMTXRETURN(f, -1);
91 }
92 CLOSE(oldfd);
93 }
94 else
95 { /* sync stream if necessary */
96 if(((f->mode&SF_WRITE) && f->next > f->data) ||
97 (f->mode&SF_READ) || f->disc == _Sfudisc)
98 { if(SFSYNC(f) < 0)
99 { SFOPEN(f,0);
100 SFMTXRETURN(f, -1);
101 }
102 }
103
104 if(((f->mode&SF_WRITE) && f->next > f->data) ||
105 ((f->mode&SF_READ) && f->extent < 0 &&
106 f->next < f->endb) )
107 { SFOPEN(f,0);
108 SFMTXRETURN(f, -1);
109 }
110
111 #ifdef MAP_TYPE
112 if((f->bits&SF_MMAP) && f->data)
113 { SFMUNMAP(f,f->data,f->endb-f->data);
114 f->data = NIL(uchar*);
115 }
116 #endif
117
118 /* make stream appears uninitialized */
119 f->endb = f->endr = f->endw = f->data;
120 f->extent = f->here = 0;
121 f->mode = (f->mode&SF_RDWR)|SF_INIT;
122 f->bits &= ~SF_NULL; /* off /dev/null handling */
123 }
124 }
125
126 SFOPEN(f,0);
127 }
128
129 /* notify changes */
130 if(_Sfnotify)
131 (*_Sfnotify)(f, SF_SETFD, (void*)((long)newfd));
132
133 f->file = newfd;
134
135 SFMTXRETURN(f,newfd);
136 }
137