1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 30 static int _sfdup(reg int fd, reg int newfd) 31 #else 32 static int _sfdup(fd,newfd) 33 reg int fd; 34 reg 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 59 int sfsetfd(reg Sfio_t* f, reg int newfd) 60 #else 61 int sfsetfd(f,newfd) 62 reg Sfio_t *f; 63 reg int newfd; 64 #endif 65 { 66 reg int oldfd; 67 68 SFMTXSTART(f, -1); 69 70 if(f->flags&SF_STRING) 71 SFMTXRETURN(f, -1); 72 73 if((f->mode&SF_INIT) && f->file < 0) 74 { /* restoring file descriptor after a previous freeze */ 75 if(newfd < 0) 76 SFMTXRETURN(f, -1); 77 } 78 else 79 { /* change file descriptor */ 80 if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) 81 SFMTXRETURN(f, -1); 82 SFLOCK(f,0); 83 84 oldfd = f->file; 85 if(oldfd >= 0) 86 { if(newfd >= 0) 87 { if((newfd = _sfdup(oldfd,newfd)) < 0) 88 { SFOPEN(f,0); 89 SFMTXRETURN(f, -1); 90 } 91 CLOSE(oldfd); 92 } 93 else 94 { /* sync stream if necessary */ 95 if(((f->mode&SF_WRITE) && f->next > f->data) || 96 (f->mode&SF_READ) || f->disc == _Sfudisc) 97 { if(SFSYNC(f) < 0) 98 { SFOPEN(f,0); 99 SFMTXRETURN(f, -1); 100 } 101 } 102 103 if(((f->mode&SF_WRITE) && f->next > f->data) || 104 ((f->mode&SF_READ) && f->extent < 0 && 105 f->next < f->endb) ) 106 { SFOPEN(f,0); 107 SFMTXRETURN(f, -1); 108 } 109 110 #ifdef MAP_TYPE 111 if((f->bits&SF_MMAP) && f->data) 112 { SFMUNMAP(f,f->data,f->endb-f->data); 113 f->data = NIL(uchar*); 114 } 115 #endif 116 117 /* make stream appears uninitialized */ 118 f->endb = f->endr = f->endw = f->data; 119 f->extent = f->here = 0; 120 f->mode = (f->mode&SF_RDWR)|SF_INIT; 121 f->bits &= ~SF_NULL; /* off /dev/null handling */ 122 } 123 } 124 125 SFOPEN(f,0); 126 } 127 128 /* notify changes */ 129 if(_Sfnotify) 130 (*_Sfnotify)(f,SF_SETFD,newfd); 131 132 f->file = newfd; 133 134 SFMTXRETURN(f,newfd); 135 } 136