1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#include "sfhdr.h"
1N/A
1N/A/* Change the file descriptor
1N/A**
1N/A** Written by Kiem-Phong Vo.
1N/A*/
1N/A
1N/A#if __STD_C
1N/Astatic int _sfdup(int fd, int newfd)
1N/A#else
1N/Astatic int _sfdup(fd,newfd)
1N/Aint fd;
1N/Aint newfd;
1N/A#endif
1N/A{
1N/A reg int dupfd;
1N/A
1N/A#ifdef F_DUPFD /* the simple case */
1N/A while((dupfd = sysfcntlf(fd,F_DUPFD,newfd)) < 0 && errno == EINTR)
1N/A errno = 0;
1N/A return dupfd;
1N/A
1N/A#else /* do it the hard way */
1N/A if((dupfd = sysdupf(fd)) < 0 || dupfd >= newfd)
1N/A return dupfd;
1N/A
1N/A /* dup() succeeded but didn't get the right number, recurse */
1N/A newfd = _sfdup(fd,newfd);
1N/A
1N/A /* close the one that didn't match */
1N/A CLOSE(dupfd);
1N/A
1N/A return newfd;
1N/A#endif
1N/A}
1N/A
1N/A#if __STD_C
1N/Aint sfsetfd(Sfio_t* f, int newfd)
1N/A#else
1N/Aint sfsetfd(f,newfd)
1N/ASfio_t *f;
1N/Aint newfd;
1N/A#endif
1N/A{
1N/A reg int oldfd;
1N/A SFMTXDECL(f);
1N/A
1N/A SFMTXENTER(f, -1);
1N/A
1N/A if(f->flags&SF_STRING)
1N/A SFMTXRETURN(f, -1);
1N/A
1N/A if((f->mode&SF_INIT) && f->file < 0)
1N/A { /* restoring file descriptor after a previous freeze */
1N/A if(newfd < 0)
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A else
1N/A { /* change file descriptor */
1N/A if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
1N/A SFMTXRETURN(f, -1);
1N/A SFLOCK(f,0);
1N/A
1N/A oldfd = f->file;
1N/A if(oldfd >= 0)
1N/A { if(newfd >= 0)
1N/A { if((newfd = _sfdup(oldfd,newfd)) < 0)
1N/A { SFOPEN(f,0);
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A CLOSE(oldfd);
1N/A }
1N/A else
1N/A { /* sync stream if necessary */
1N/A if(((f->mode&SF_WRITE) && f->next > f->data) ||
1N/A (f->mode&SF_READ) || f->disc == _Sfudisc)
1N/A { if(SFSYNC(f) < 0)
1N/A { SFOPEN(f,0);
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A }
1N/A
1N/A if(((f->mode&SF_WRITE) && f->next > f->data) ||
1N/A ((f->mode&SF_READ) && f->extent < 0 &&
1N/A f->next < f->endb) )
1N/A { SFOPEN(f,0);
1N/A SFMTXRETURN(f, -1);
1N/A }
1N/A
1N/A#ifdef MAP_TYPE
1N/A if((f->bits&SF_MMAP) && f->data)
1N/A { SFMUNMAP(f,f->data,f->endb-f->data);
1N/A f->data = NIL(uchar*);
1N/A }
1N/A#endif
1N/A
1N/A /* make stream appears uninitialized */
1N/A f->endb = f->endr = f->endw = f->data;
1N/A f->extent = f->here = 0;
1N/A f->mode = (f->mode&SF_RDWR)|SF_INIT;
1N/A f->bits &= ~SF_NULL; /* off /dev/null handling */
1N/A }
1N/A }
1N/A
1N/A SFOPEN(f,0);
1N/A }
1N/A
1N/A /* notify changes */
1N/A if(_Sfnotify)
1N/A (*_Sfnotify)(f, SF_SETFD, (void*)((long)newfd));
1N/A
1N/A f->file = newfd;
1N/A
1N/A SFMTXRETURN(f,newfd);
1N/A}