⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 doio.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $RCSfile: doio.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:08:16 $ * *    Copyright (c) 1991, Larry Wall * *    You may distribute under the terms of either the GNU General Public *    License or the Artistic License, as specified in the README file. * * $Log:	doio.c,v $ * Revision 4.0.1.6  92/06/11  21:08:16  lwall * patch34: some systems don't declare h_errno extern in header files *  * Revision 4.0.1.5  92/06/08  13:00:21  lwall * patch20: some machines don't define ENOTSOCK in errno.h * patch20: new warnings for failed use of stat operators on filenames with \n * patch20: wait failed when STDOUT or STDERR reopened to a pipe * patch20: end of file latch not reset on reopen of STDIN * patch20: seek(HANDLE, 0, 1) went to eof because of ancient Ultrix workaround * patch20: fixed memory leak on system() for vfork() machines * patch20: get*by* routines now return something useful in a scalar context * patch20: h_errno now accessible via $? *  * Revision 4.0.1.4  91/11/05  16:51:43  lwall * patch11: prepared for ctype implementations that don't define isascii() * patch11: perl mistook some streams for sockets because they return mode 0 too * patch11: reopening STDIN, STDOUT and STDERR failed on some machines * patch11: certain perl errors should set EBADF so that $! looks better * patch11: truncate on a closed filehandle could dump * patch11: stats of _ forgot whether prior stat was actually lstat * patch11: -T returned true on NFS directory *  * Revision 4.0.1.3  91/06/10  01:21:19  lwall * patch10: read didn't work from character special files open for writing * patch10: close-on-exec wrongly set on system file descriptors *  * Revision 4.0.1.2  91/06/07  10:53:39  lwall * patch4: new copyright notice * patch4: system fd's are now treated specially * patch4: added $^F variable to specify maximum system fd, default 2 * patch4: character special files now opened with bidirectional stdio buffers * patch4: taintchecks could improperly modify parent in vfork() * patch4: many, many itty-bitty portability fixes *  * Revision 4.0.1.1  91/04/11  17:41:06  lwall * patch1: hopefully straightened out some of the Xenix mess *  * Revision 4.0  91/03/20  01:07:06  lwall * 4.0 baseline. *  */#include "EXTERN.h"#include "perl.h"#ifdef HAS_SOCKET#include <sys/socket.h>#include <netdb.h>#ifndef ENOTSOCK#include <net/errno.h>#endif#endif#ifdef HAS_SELECT#ifdef I_SYS_SELECT#ifndef I_SYS_TIME#include <sys/select.h>#endif#endif#endif#ifdef HOST_NOT_FOUNDextern int h_errno;#endif#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)#include <sys/ipc.h>#ifdef HAS_MSG#include <sys/msg.h>#endif#ifdef HAS_SEM#include <sys/sem.h>#endif#ifdef HAS_SHM#include <sys/shm.h>#endif#endif#ifdef I_PWD#include <pwd.h>#endif#ifdef I_GRP#include <grp.h>#endif#ifdef I_UTIME#include <utime.h>#endif#ifdef I_FCNTL#include <fcntl.h>#endif#ifdef I_SYS_FILE#include <sys/file.h>#endifint laststatval = -1;int laststype = O_STAT;static char* warn_nl = "Unsuccessful %s on filename containing newline";booldo_open(stab,name,len)STAB *stab;register char *name;int len;{    FILE *fp;    register STIO *stio = stab_io(stab);    char *myname = savestr(name);    int result;    int fd;    int writing = 0;    char mode[3];		/* stdio file mode ("r\0" or "r+\0") */    FILE *saveifp = Nullfp;    FILE *saveofp = Nullfp;    char savetype = ' ';    mode[0] = mode[1] = mode[2] = '\0';    name = myname;    forkprocess = 1;		/* assume true if no fork */    while (len && isSPACE(name[len-1]))	name[--len] = '\0';    if (!stio)	stio = stab_io(stab) = stio_new();    else if (stio->ifp) {	fd = fileno(stio->ifp);	if (stio->type == '-')	    result = 0;	else if (fd <= maxsysfd) {	    saveifp = stio->ifp;	    saveofp = stio->ofp;	    savetype = stio->type;	    result = 0;	}	else if (stio->type == '|')	    result = mypclose(stio->ifp);	else if (stio->ifp != stio->ofp) {	    if (stio->ofp) {		result = fclose(stio->ofp);		fclose(stio->ifp);	/* clear stdio, fd already closed */	    }	    else		result = fclose(stio->ifp);	}	else	    result = fclose(stio->ifp);	if (result == EOF && fd > maxsysfd)	    fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",	      stab_ename(stab));	stio->ofp = stio->ifp = Nullfp;    }    if (*name == '+' && len > 1 && name[len-1] != '|') {	/* scary */	mode[1] = *name++;	mode[2] = '\0';	--len;	writing = 1;    }    else  {	mode[1] = '\0';    }    stio->type = *name;    if (*name == '|') {	/*SUPPRESS 530*/	for (name++; isSPACE(*name); name++) ;#ifdef TAINT	taintenv();	taintproper("Insecure dependency in piped open");#endif	fp = mypopen(name,"w");	writing = 1;    }    else if (*name == '>') {#ifdef TAINT	taintproper("Insecure dependency in open");#endif	name++;	if (*name == '>') {	    mode[0] = stio->type = 'a';	    name++;	}	else	    mode[0] = 'w';	writing = 1;	if (*name == '&') {	  duplicity:	    name++;	    while (isSPACE(*name))		name++;	    if (isDIGIT(*name))		fd = atoi(name);	    else {		stab = stabent(name,FALSE);		if (!stab || !stab_io(stab)) {#ifdef EINVAL		    errno = EINVAL;#endif		    goto say_false;		}		if (stab_io(stab) && stab_io(stab)->ifp) {		    fd = fileno(stab_io(stab)->ifp);		    if (stab_io(stab)->type == 's')			stio->type = 's';		}		else		    fd = -1;	    }	    if (!(fp = fdopen(fd = dup(fd),mode))) {		close(fd);	    }	}	else {	    while (isSPACE(*name))		name++;	    if (strEQ(name,"-")) {		fp = stdout;		stio->type = '-';	    }	    else  {		fp = fopen(name,mode);	    }	}    }    else {	if (*name == '<') {	    mode[0] = 'r';	    name++;	    while (isSPACE(*name))		name++;	    if (*name == '&')		goto duplicity;	    if (strEQ(name,"-")) {		fp = stdin;		stio->type = '-';	    }	    else		fp = fopen(name,mode);	}	else if (name[len-1] == '|') {#ifdef TAINT	    taintenv();	    taintproper("Insecure dependency in piped open");#endif	    name[--len] = '\0';	    while (len && isSPACE(name[len-1]))		name[--len] = '\0';	    /*SUPPRESS 530*/	    for (; isSPACE(*name); name++) ;	    fp = mypopen(name,"r");	    stio->type = '|';	}	else {	    stio->type = '<';	    /*SUPPRESS 530*/	    for (; isSPACE(*name); name++) ;	    if (strEQ(name,"-")) {		fp = stdin;		stio->type = '-';	    }	    else		fp = fopen(name,"r");	}    }    if (!fp) {	if (dowarn && stio->type == '<' && index(name, '\n'))	    warn(warn_nl, "open");	Safefree(myname);	goto say_false;    }    Safefree(myname);    if (stio->type &&      stio->type != '|' && stio->type != '-') {	if (fstat(fileno(fp),&statbuf) < 0) {	    (void)fclose(fp);	    goto say_false;	}	if (S_ISSOCK(statbuf.st_mode))	    stio->type = 's';	/* in case a socket was passed in to us */#ifdef HAS_SOCKET	else if (#ifdef S_IFMT	    !(statbuf.st_mode & S_IFMT)#else	    !statbuf.st_mode#endif	) {	    int buflen = sizeof tokenbuf;	    if (getsockname(fileno(fp), tokenbuf, &buflen) >= 0		|| errno != ENOTSOCK)		stio->type = 's'; /* some OS's return 0 on fstat()ed socket */				/* but some return 0 for streams too, sigh */	}#endif    }    if (saveifp) {		/* must use old fp? */	fd = fileno(saveifp);	if (saveofp) {	    fflush(saveofp);		/* emulate fclose() */	    if (saveofp != saveifp) {	/* was a socket? */		fclose(saveofp);		if (fd > 2)		    Safefree(saveofp);	    }	}	if (fd != fileno(fp)) {	    int pid;	    STR *str;	    dup2(fileno(fp), fd);	    str = afetch(fdpid,fileno(fp),TRUE);	    pid = str->str_u.str_useful;	    str->str_u.str_useful = 0;	    str = afetch(fdpid,fd,TRUE);	    str->str_u.str_useful = pid;	    fclose(fp);	}	fp = saveifp;	clearerr(fp);    }#if defined(HAS_FCNTL) && defined(F_SETFD)    fd = fileno(fp);    fcntl(fd,F_SETFD,fd > maxsysfd);#endif    stio->ifp = fp;    if (writing) {	if (stio->type == 's'	  || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {	    if (!(stio->ofp = fdopen(fileno(fp),"w"))) {		fclose(fp);		stio->ifp = Nullfp;		goto say_false;	    }	}	else	    stio->ofp = fp;    }    return TRUE;say_false:    stio->ifp = saveifp;    stio->ofp = saveofp;    stio->type = savetype;    return FALSE;}FILE *nextargv(stab)register STAB *stab;{    register STR *str;#ifndef FLEXFILENAMES    int filedev;    int fileino;#endif    int fileuid;    int filegid;    static int filemode = 0;    static int lastfd;    static char *oldname;    if (!argvoutstab)	argvoutstab = stabent("ARGVOUT",TRUE);    if (filemode & (S_ISUID|S_ISGID)) {	fflush(stab_io(argvoutstab)->ifp);  /* chmod must follow last write */#ifdef HAS_FCHMOD	(void)fchmod(lastfd,filemode);#else	(void)chmod(oldname,filemode);#endif    }    filemode = 0;    while (alen(stab_xarray(stab)) >= 0) {	str = ashift(stab_xarray(stab));	str_sset(stab_val(stab),str);	STABSET(stab_val(stab));	oldname = str_get(stab_val(stab));	if (do_open(stab,oldname,stab_val(stab)->str_cur)) {	    if (inplace) {#ifdef TAINT		taintproper("Insecure dependency in inplace open");#endif		if (strEQ(oldname,"-")) {		    str_free(str);		    defoutstab = stabent("STDOUT",TRUE);		    return stab_io(stab)->ifp;		}#ifndef FLEXFILENAMES		filedev = statbuf.st_dev;		fileino = statbuf.st_ino;#endif		filemode = statbuf.st_mode;		fileuid = statbuf.st_uid;		filegid = statbuf.st_gid;		if (!S_ISREG(filemode)) {		    warn("Can't do inplace edit: %s is not a regular file",		      oldname );		    do_close(stab,FALSE);		    str_free(str);		    continue;		}		if (*inplace) {#ifdef SUFFIX		    add_suffix(str,inplace);#else		    str_cat(str,inplace);#endif#ifndef FLEXFILENAMES		    if (stat(str->str_ptr,&statbuf) >= 0		      && statbuf.st_dev == filedev		      && statbuf.st_ino == fileino ) {			warn("Can't do inplace edit: %s > 14 characters",			  str->str_ptr );			do_close(stab,FALSE);			str_free(str);			continue;		    }#endif#ifdef HAS_RENAME#ifndef DOSISH		    if (rename(oldname,str->str_ptr) < 0) {			warn("Can't rename %s to %s: %s, skipping file",			  oldname, str->str_ptr, strerror(errno) );			do_close(stab,FALSE);			str_free(str);			continue;		    }#else		    do_close(stab,FALSE);		    (void)unlink(str->str_ptr);		    (void)rename(oldname,str->str_ptr);		    do_open(stab,str->str_ptr,stab_val(stab)->str_cur);#endif /* MSDOS */#else		    (void)UNLINK(str->str_ptr);		    if (link(oldname,str->str_ptr) < 0) {			warn("Can't rename %s to %s: %s, skipping file",			  oldname, str->str_ptr, strerror(errno) );			do_close(stab,FALSE);			str_free(str);			continue;		    }		    (void)UNLINK(oldname);#endif		}		else {#ifndef DOSISH		    if (UNLINK(oldname) < 0) {			warn("Can't rename %s to %s: %s, skipping file",			  oldname, str->str_ptr, strerror(errno) );			do_close(stab,FALSE);			str_free(str);			continue;		    }#else		    fatal("Can't do inplace edit without backup");#endif		}		str_nset(str,">",1);		str_cat(str,oldname);		errno = 0;		/* in case sprintf set errno */		if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {		    warn("Can't do inplace edit on %s: %s",		      oldname, strerror(errno) );		    do_close(stab,FALSE);		    str_free(str);		    continue;		}		defoutstab = argvoutstab;		lastfd = fileno(stab_io(argvoutstab)->ifp);		(void)fstat(lastfd,&statbuf);#ifdef HAS_FCHMOD		(void)fchmod(lastfd,filemode);#else		(void)chmod(oldname,filemode);#endif		if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {#ifdef HAS_FCHOWN		    (void)fchown(lastfd,fileuid,filegid);#else#ifdef HAS_CHOWN		    (void)chown(oldname,fileuid,filegid);#endif#endif		}	    }	    str_free(str);	    return stab_io(stab)->ifp;	}	else	    fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));	str_free(str);    }    if (inplace) {	(void)do_close(argvoutstab,FALSE);	defoutstab = stabent("STDOUT",TRUE);    }    return Nullfp;}#ifdef HAS_PIPEvoiddo_pipe(str, rstab, wstab)STR *str;STAB *rstab;STAB *wstab;{    register STIO *rstio;    register STIO *wstio;    int fd[2];    if (!rstab)	goto badexit;    if (!wstab)	goto badexit;    rstio = stab_io(rstab);    wstio = stab_io(wstab);    if (!rstio)	rstio = stab_io(rstab) = stio_new();    else if (rstio->ifp)	do_close(rstab,FALSE);    if (!wstio)	wstio = stab_io(wstab) = stio_new();    else if (wstio->ifp)	do_close(wstab,FALSE);    if (pipe(fd) < 0)	goto badexit;    rstio->ifp = fdopen(fd[0], "r");    wstio->ofp = fdopen(fd[1], "w");    wstio->ifp = wstio->ofp;    rstio->type = '<';    wstio->type = '>';    if (!rstio->ifp || !wstio->ofp) {	if (rstio->ifp) fclose(rstio->ifp);	else close(fd[0]);	if (wstio->ofp) fclose(wstio->ofp);	else close(fd[1]);	goto badexit;    }    str_sset(str,&str_yes);    return;badexit:    str_sset(str,&str_undef);    return;}#endifbooldo_close(stab,explicit)STAB *stab;bool explicit;{    bool retval = FALSE;    register STIO *stio;    int status;    if (!stab)	stab = argvstab;    if (!stab) {	errno = EBADF;	return FALSE;    }    stio = stab_io(stab);    if (!stio) {		/* never opened */	if (dowarn && explicit)	    warn("Close on unopened file <%s>",stab_ename(stab));	return FALSE;    }    if (stio->ifp) {	if (stio->type == '|') {	    status = mypclose(stio->ifp);	    retval = (status == 0);	    statusvalue = (unsigned short)status & 0xffff;	}	else if (stio->type == '-')	    retval = TRUE;	else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -