Blame posix/gawkmisc.c

Packit Service f629e6
/* gawkmisc.c --- miscellaneous gawk routines that are OS specific.
Packit Service f629e6
Packit Service f629e6
   Copyright (C) 1986, 1988, 1989, 1991 - 1998, 2001 - 2004, 2011
Packit Service f629e6
   the Free Software Foundation, Inc.
Packit Service f629e6
Packit Service f629e6
   This program is free software; you can redistribute it and/or modify
Packit Service f629e6
   it under the terms of the GNU General Public License as published by
Packit Service f629e6
   the Free Software Foundation; either version 2, or (at your option)
Packit Service f629e6
   any later version.
Packit Service f629e6
Packit Service f629e6
   This program is distributed in the hope that it will be useful,
Packit Service f629e6
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service f629e6
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service f629e6
   GNU General Public License for more details.
Packit Service f629e6
Packit Service f629e6
   You should have received a copy of the GNU General Public License
Packit Service f629e6
   along with this program; if not, write to the Free Software Foundation,
Packit Service f629e6
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
Packit Service f629e6
Packit Service f629e6
#ifdef __CYGWIN__
Packit Service f629e6
#include <stdio.h>
Packit Service f629e6
#include <windows.h>
Packit Service f629e6
#include <sys/cygwin.h>
Packit Service f629e6
#include <io.h>
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
char quote = '\'';
Packit Service f629e6
char *defpath = DEFPATH;
Packit Service f629e6
char *deflibpath = DEFLIBPATH;
Packit Service f629e6
char envsep = ':';
Packit Service f629e6
Packit Service f629e6
#ifndef INVALID_HANDLE
Packit Service f629e6
/* FIXME: is this value for INVALID_HANDLE correct? */
Packit Service f629e6
#define INVALID_HANDLE -1
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
/* gawk_name --- pull out the "gawk" part from how the OS called us */
Packit Service f629e6
Packit Service f629e6
char *
Packit Service f629e6
gawk_name(const char *filespec)
Packit Service f629e6
{
Packit Service f629e6
	char *p;
Packit Service f629e6
Packit Service f629e6
	/* "path/name" -> "name" */
Packit Service f629e6
	p = strrchr(filespec, '/');
Packit Service f629e6
	return (p == NULL ? (char *) filespec : p + 1);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_arg_fixup --- fixup the command line */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
os_arg_fixup(int *argcp, char ***argvp)
Packit Service f629e6
{
Packit Service f629e6
	/* no-op */
Packit Service f629e6
	return;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_devopen --- open special per-OS devices */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_devopen(const char *name, int flag)
Packit Service f629e6
{
Packit Service f629e6
	/* no-op */
Packit Service f629e6
	return INVALID_HANDLE;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* optimal_bufsize --- determine optimal buffer size */
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * Enhance this for debugging purposes, as follows:
Packit Service f629e6
 *
Packit Service f629e6
 * Always stat the file, stat buffer is used by higher-level code.
Packit Service f629e6
 *
Packit Service f629e6
 * if (AWKBUFSIZE == "exact")
Packit Service f629e6
 * 	return the file size
Packit Service f629e6
 * else if (AWKBUFSIZE == a number)
Packit Service f629e6
 * 	always return that number
Packit Service f629e6
 * else
Packit Service f629e6
 * 	if the size is < default_blocksize
Packit Service f629e6
 * 		return the size
Packit Service f629e6
 *	else
Packit Service f629e6
 *		return default_blocksize
Packit Service f629e6
 *	end if
Packit Service f629e6
 * endif
Packit Service f629e6
 *
Packit Service f629e6
 * Hair comes in an effort to only deal with AWKBUFSIZE
Packit Service f629e6
 * once, the first time this routine is called, instead of
Packit Service f629e6
 * every time.  Performance, dontyaknow.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
size_t
Packit Service f629e6
optimal_bufsize(int fd, struct stat *stb)
Packit Service f629e6
{
Packit Service f629e6
	char *val;
Packit Service f629e6
	static size_t env_val = 0;
Packit Service f629e6
	static bool first = true;
Packit Service f629e6
	static bool exact = false;
Packit Service f629e6
Packit Service f629e6
	/* force all members to zero in case OS doesn't use all of them. */
Packit Service f629e6
	memset(stb, '\0', sizeof(struct stat));
Packit Service f629e6
Packit Service f629e6
	/* always stat, in case stb is used by higher level code. */
Packit Service f629e6
	if (fstat(fd, stb) == -1)
Packit Service f629e6
		fatal("can't stat fd %d (%s)", fd, strerror(errno));
Packit Service f629e6
Packit Service f629e6
	if (first) {
Packit Service f629e6
		first = false;
Packit Service f629e6
Packit Service f629e6
		if ((val = getenv("AWKBUFSIZE")) != NULL) {
Packit Service f629e6
			if (strcmp(val, "exact") == 0)
Packit Service f629e6
				exact = true;
Packit Service f629e6
			else if (isdigit((unsigned char) *val)) {
Packit Service f629e6
				for (; *val && isdigit((unsigned char) *val); val++)
Packit Service f629e6
					env_val = (env_val * 10) + *val - '0';
Packit Service f629e6
Packit Service f629e6
				return env_val;
Packit Service f629e6
			}
Packit Service f629e6
		}
Packit Service f629e6
	} else if (! exact && env_val > 0)
Packit Service f629e6
		return env_val;
Packit Service f629e6
	/* else
Packit Service f629e6
	  	fall through */
Packit Service f629e6
Packit Service f629e6
	/*
Packit Service f629e6
	 * System V.n, n < 4, doesn't have the file system block size in the
Packit Service f629e6
	 * stat structure. So we have to make some sort of reasonable
Packit Service f629e6
	 * guess. We use stdio's BUFSIZ, since that is what it was
Packit Service f629e6
	 * meant for in the first place.
Packit Service f629e6
	 */
Packit Service f629e6
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
Packit Service f629e6
#define DEFBLKSIZE	(stb->st_blksize > 0 ? stb->st_blksize : BUFSIZ)
Packit Service f629e6
#else
Packit Service f629e6
#define DEFBLKSIZE	BUFSIZ
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
	if (S_ISREG(stb->st_mode)		/* regular file */
Packit Service f629e6
	    && 0 < stb->st_size			/* non-zero size */
Packit Service f629e6
	    && (stb->st_size < DEFBLKSIZE	/* small file */
Packit Service f629e6
		|| exact))			/* or debugging */
Packit Service f629e6
		return stb->st_size;		/* use file size */
Packit Service f629e6
Packit Service f629e6
	return DEFBLKSIZE;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* ispath --- return true if path has directory components */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
ispath(const char *file)
Packit Service f629e6
{
Packit Service f629e6
	return (strchr(file, '/') != NULL);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* isdirpunct --- return true if char is a directory separator */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
isdirpunct(int c)
Packit Service f629e6
{
Packit Service f629e6
	return (c == '/');
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_close_on_exec --- set close on exec flag, print warning if fails */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
os_close_on_exec(int fd, const char *name, const char *what, const char *dir)
Packit Service f629e6
{
Packit Service f629e6
	int curflags = 0;
Packit Service f629e6
Packit Service f629e6
	if (fd <= 2)	/* sanity */
Packit Service f629e6
		return;
Packit Service f629e6
Packit Service f629e6
	/*
Packit Service f629e6
	 * Per POSIX, use Read/Modify/Write - get the flags,
Packit Service f629e6
	 * add FD_CLOEXEC, set the flags back.
Packit Service f629e6
	 */
Packit Service f629e6
Packit Service f629e6
	if ((curflags = fcntl(fd, F_GETFD)) < 0) {
Packit Service f629e6
		warning(_("%s %s `%s': could not get fd flags: (fcntl F_GETFD: %s)"),
Packit Service f629e6
			what, dir, name, strerror(errno));
Packit Service f629e6
		return;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
#ifndef FD_CLOEXEC
Packit Service f629e6
#define FD_CLOEXEC	1
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
	curflags |= FD_CLOEXEC;
Packit Service f629e6
Packit Service f629e6
	if (fcntl(fd, F_SETFD, curflags) < 0)
Packit Service f629e6
		warning(_("%s %s `%s': could not set close-on-exec: (fcntl F_SETFD: %s)"),
Packit Service f629e6
			what, dir, name, strerror(errno));
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_isdir --- is this an fd on a directory? */
Packit Service f629e6
Packit Service f629e6
#if ! defined(S_ISDIR) && defined(S_IFDIR)
Packit Service f629e6
#define	S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_isdir(int fd)
Packit Service f629e6
{
Packit Service f629e6
	struct stat sbuf;
Packit Service f629e6
Packit Service f629e6
	return (fstat(fd, &sbuf) == 0 && S_ISDIR(sbuf.st_mode));
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_isreadable --- fd can be read from */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_isreadable(const awk_input_buf_t *iobuf, bool *isdir)
Packit Service f629e6
{
Packit Service f629e6
	*isdir = false;
Packit Service f629e6
Packit Service f629e6
	if (iobuf->fd == INVALID_HANDLE)
Packit Service f629e6
		return false;
Packit Service f629e6
Packit Service f629e6
	switch (iobuf->sbuf.st_mode & S_IFMT) {
Packit Service f629e6
	case S_IFREG:
Packit Service f629e6
	case S_IFCHR:	/* ttys, /dev/null, .. */
Packit Service f629e6
#ifdef S_IFSOCK
Packit Service f629e6
	case S_IFSOCK:
Packit Service f629e6
#endif
Packit Service f629e6
#ifdef S_IFIFO
Packit Service f629e6
	case S_IFIFO:
Packit Service f629e6
#endif
Packit Service f629e6
		return true;
Packit Service f629e6
	case S_IFDIR:
Packit Service f629e6
		*isdir = true;
Packit Service f629e6
		/* fall through */
Packit Service f629e6
	default:
Packit Service f629e6
		return false;
Packit Service f629e6
	}
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_is_setuid --- true if running setuid root */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_is_setuid()
Packit Service f629e6
{
Packit Service f629e6
	long uid, euid;
Packit Service f629e6
Packit Service f629e6
	uid = getuid();
Packit Service f629e6
	euid = geteuid();
Packit Service f629e6
Packit Service f629e6
	return (euid == 0 && euid != uid);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_setbinmode --- set binary mode on file */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_setbinmode(int fd, int mode)
Packit Service f629e6
{
Packit Service f629e6
#ifdef __CYGWIN__
Packit Service f629e6
	setmode (fd, mode);
Packit Service f629e6
#endif
Packit Service f629e6
	return 0;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_restore_mode --- restore the original mode of the console device */
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
os_restore_mode(int fd)
Packit Service f629e6
{
Packit Service f629e6
	/* no-op */
Packit Service f629e6
	return;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* os_isatty --- return true if fd is a tty */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_isatty(int fd)
Packit Service f629e6
{
Packit Service f629e6
	return isatty(fd);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* files_are_same --- return true if files are identical */
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
files_are_same(char *path, SRCFILE *src)
Packit Service f629e6
{
Packit Service f629e6
	struct stat st;
Packit Service f629e6
Packit Service f629e6
	return (stat(path, & st) == 0
Packit Service f629e6
		&& st.st_dev == src->sbuf.st_dev
Packit Service f629e6
		&& st.st_ino == src->sbuf.st_ino);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
void
Packit Service f629e6
init_sockets(void)
Packit Service f629e6
{
Packit Service f629e6
}