|
Packit Service |
f629e6 |
/* gawkmisc.c --- miscellaneous gawk routines that are OS specific. -*-C-*- */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Copyright (C) 1986, 1988, 1989, 1991 - 2003, 2012, 2016
|
|
Packit Service |
f629e6 |
* the Free Software Foundation, Inc.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This file is part of GAWK, the GNU implementation of the
|
|
Packit Service |
f629e6 |
* AWK Progamming Language.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK 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 3 of the License, or
|
|
Packit Service |
f629e6 |
* (at your option) any later version.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK 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
|
|
Packit Service |
f629e6 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
char quote = '\'';
|
|
Packit Service |
f629e6 |
char envsep = ';';
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
# ifdef DEFPATH
|
|
Packit Service |
f629e6 |
char *defpath = DEFPATH;
|
|
Packit Service |
f629e6 |
# else
|
|
Packit Service |
f629e6 |
char *defpath = ".;c:\\lib\\awk;c:\\gnu\\lib\\awk";
|
|
Packit Service |
f629e6 |
# endif
|
|
Packit Service |
f629e6 |
/* the Makefile should define DEFLIBPATH */
|
|
Packit Service |
f629e6 |
char *deflibpath = DEFLIBPATH;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __EMX__
|
|
Packit Service |
f629e6 |
#include<io.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static int _os2_is_abs_path(const char *dirname);
|
|
Packit Service |
f629e6 |
static char* _os2_unixroot(const char *path);
|
|
Packit Service |
f629e6 |
static const char* _os2_unixroot_path(const char *path);
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __MINGW32__
|
|
Packit Service |
f629e6 |
#ifdef HAVE_SOCKETS
|
|
Packit Service |
f629e6 |
#include <socket.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#undef socket
|
|
Packit Service |
f629e6 |
#undef setsockopt
|
|
Packit Service |
f629e6 |
#undef bind
|
|
Packit Service |
f629e6 |
#undef connect
|
|
Packit Service |
f629e6 |
#undef listen
|
|
Packit Service |
f629e6 |
#undef accept
|
|
Packit Service |
f629e6 |
#undef recvfrom
|
|
Packit Service |
f629e6 |
#undef shutdown
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#define WIN32_LEAN_AND_MEAN
|
|
Packit Service |
f629e6 |
#include <windows.h>
|
|
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(filespec)
|
|
Packit Service |
f629e6 |
const char *filespec;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char *p, *q;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
p = (char *) filespec; /* Sloppy... */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* OS/2 allows / for directory separator too */
|
|
Packit Service |
f629e6 |
if ((q = strrchr(p, '\\')) != NULL)
|
|
Packit Service |
f629e6 |
p = q + 1;
|
|
Packit Service |
f629e6 |
if ((q = strrchr(p, '/')) != NULL
|
|
Packit Service |
f629e6 |
&& (p == NULL || q > p)) /* support mixed d:\foo/bar\gawk.exe */
|
|
Packit Service |
f629e6 |
p = q + 1;
|
|
Packit Service |
f629e6 |
if ((q = strchr(p, '.')) != NULL)
|
|
Packit Service |
f629e6 |
*q = '\0';
|
|
Packit Service |
f629e6 |
return strlwr(p);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* memcpy_long() & memset_ulong() are 32-bit replacements for MSC which
|
|
Packit Service |
f629e6 |
* has a 16-bit size_t.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
char *
|
|
Packit Service |
f629e6 |
memcpy_ulong (dest, src, l)
|
|
Packit Service |
f629e6 |
register char *dest;
|
|
Packit Service |
f629e6 |
register const char *src;
|
|
Packit Service |
f629e6 |
register unsigned long l;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
register char *ret = dest;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
while (l--)
|
|
Packit Service |
f629e6 |
*dest++ = *src++;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return ret;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void *
|
|
Packit Service |
f629e6 |
memset_ulong(dest, val, l)
|
|
Packit Service |
f629e6 |
void *dest;
|
|
Packit Service |
f629e6 |
register int val;
|
|
Packit Service |
f629e6 |
register unsigned long l;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
register char *ret = dest;
|
|
Packit Service |
f629e6 |
register char *d = dest;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
while (l--)
|
|
Packit Service |
f629e6 |
*d++ = val;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return ((void *) ret);
|
|
Packit Service |
f629e6 |
}
|
|
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(argcp, argvp)
|
|
Packit Service |
f629e6 |
int *argcp;
|
|
Packit Service |
f629e6 |
char ***argvp;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
#ifdef __EMX__
|
|
Packit Service |
f629e6 |
# ifdef initialize_main
|
|
Packit Service |
f629e6 |
initialize_main(argcp, argvp);
|
|
Packit Service |
f629e6 |
# else
|
|
Packit Service |
f629e6 |
_wildcard(argcp, argvp);
|
|
Packit Service |
f629e6 |
_response(argcp, argvp);
|
|
Packit Service |
f629e6 |
# endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
|
|
Packit Service |
f629e6 |
defpath = (char*) _os2_unixroot_path(defpath);
|
|
Packit Service |
f629e6 |
#endif /* __EMX__ */
|
|
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(name, flag)
|
|
Packit Service |
f629e6 |
const char *name;
|
|
Packit Service |
f629e6 |
int flag;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
#ifdef __EMX__
|
|
Packit Service |
f629e6 |
/* do not use open(name, flag) here !!! */
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
#else
|
|
Packit Service |
f629e6 |
if (strcmp(name, "/dev/null") == 0)
|
|
Packit Service |
f629e6 |
return open("NUL", flag);
|
|
Packit Service |
f629e6 |
/* FIXME: */
|
|
Packit Service |
f629e6 |
/* else if (strcmp(name, "/dev/tty") == 0)
|
|
Packit Service |
f629e6 |
* return open("???", flag);
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* optimal_bufsize --- determine optimal buffer size */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
size_t
|
|
Packit Service |
f629e6 |
optimal_bufsize(fd, stb)
|
|
Packit Service |
f629e6 |
int fd;
|
|
Packit Service |
f629e6 |
struct stat *stb;
|
|
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 |
/*
|
|
Packit Service |
f629e6 |
* DOS 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 |
#define DEFBLKSIZE BUFSIZ
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fstat(fd, stb) == -1)
|
|
Packit Service |
f629e6 |
fatal("can't stat fd %d (%s)", fd, strerror(errno));
|
|
Packit Service |
f629e6 |
if (S_ISREG(stb->st_mode)
|
|
Packit Service |
f629e6 |
&& 0 < stb->st_size && stb->st_size < DEFBLKSIZE) /* small file */
|
|
Packit Service |
f629e6 |
return stb->st_size;
|
|
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(file)
|
|
Packit Service |
f629e6 |
const char *file;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
#ifdef __EMX__
|
|
Packit Service |
f629e6 |
return (strpbrk(file, "/\\") != NULL ||
|
|
Packit Service |
f629e6 |
(toupper(file[0]) >= 'A' && toupper(file[0]) <= 'Z' && file[1] == ':'));
|
|
Packit Service |
f629e6 |
#else
|
|
Packit Service |
f629e6 |
for (; *file; file++) {
|
|
Packit Service |
f629e6 |
switch (*file) {
|
|
Packit Service |
f629e6 |
case '/':
|
|
Packit Service |
f629e6 |
case '\\':
|
|
Packit Service |
f629e6 |
case ':':
|
|
Packit Service |
f629e6 |
return 1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
#endif
|
|
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(c)
|
|
Packit Service |
f629e6 |
int c;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return (strchr(":\\/", c) != NULL);
|
|
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(fd, name, what, dir)
|
|
Packit Service |
f629e6 |
int fd;
|
|
Packit Service |
f629e6 |
const char *name, *what, *dir;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
#if (defined(__DJGPP__) && (__DJGPP__ > 2 || __DJGPP_MINOR__ >= 4)) || defined __EMX__
|
|
Packit Service |
f629e6 |
if (fd <= 2) /* sanity */
|
|
Packit Service |
f629e6 |
return;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fcntl(fd, F_SETFD, 1) < 0)
|
|
Packit Service |
f629e6 |
warning("%s %s `%s': could not set close-on-exec: %s",
|
|
Packit Service |
f629e6 |
what, dir, name, strerror(errno));
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
#ifdef __MINGW32__
|
|
Packit Service |
f629e6 |
HANDLE fh = (HANDLE)_get_osfhandle(fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fh && fh != INVALID_HANDLE_VALUE)
|
|
Packit Service |
f629e6 |
SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0);
|
|
Packit Service |
f629e6 |
#endif
|
|
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(fd)
|
|
Packit Service |
f629e6 |
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 |
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 |
#ifdef __EMX__
|
|
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 |
#else
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* os_setbinmode --- set binary mode on file */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __DJGPP__
|
|
Packit Service |
f629e6 |
#include <sys/exceptn.h>
|
|
Packit Service |
f629e6 |
#include <io.h>
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
static int orig_tty_mode = -1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
os_setbinmode(fd, mode)
|
|
Packit Service |
f629e6 |
int fd, mode;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int prev_mode = setmode(fd, mode);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __DJGPP__
|
|
Packit Service |
f629e6 |
if ((mode & O_BINARY) != 0)
|
|
Packit Service |
f629e6 |
__djgpp_set_ctrl_c(1); /* allow to interrupt with Ctrl-C */
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
/* Save the original tty mode as we found it. */
|
|
Packit Service |
f629e6 |
if (orig_tty_mode == -1 && fd >= 0 && fd <= 2)
|
|
Packit Service |
f629e6 |
orig_tty_mode = prev_mode;
|
|
Packit Service |
f629e6 |
return prev_mode;
|
|
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 (fd)
|
|
Packit Service |
f629e6 |
int fd;
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (orig_tty_mode != -1) {
|
|
Packit Service |
f629e6 |
setmode(fd, orig_tty_mode);
|
|
Packit Service |
f629e6 |
}
|
|
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 |
#if defined(__MINGW32__) || defined(_MSC_VER)
|
|
Packit Service |
f629e6 |
return (isatty(fd) && lseek(fd, SEEK_CUR, 0) == -1);
|
|
Packit Service |
f629e6 |
#else
|
|
Packit Service |
f629e6 |
return isatty(fd);
|
|
Packit Service |
f629e6 |
#endif
|
|
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 |
size_t pathlen;
|
|
Packit Service |
f629e6 |
char *p, *s;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (stat (path, & st) == 0) {
|
|
Packit Service |
f629e6 |
/* If they have a working `stat', honor that. */
|
|
Packit Service |
f629e6 |
if (!(st.st_dev == src->sbuf.st_dev
|
|
Packit Service |
f629e6 |
&& st.st_ino == src->sbuf.st_ino))
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Compare modification times. */
|
|
Packit Service |
f629e6 |
if (st.st_mtime != src->mtime)
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Compare absolute file names case-insensitively, and
|
|
Packit Service |
f629e6 |
treat forward- and back-slashes as equal. */
|
|
Packit Service |
f629e6 |
pathlen = strlen(path);
|
|
Packit Service |
f629e6 |
for (p = path, s = src->fullpath;
|
|
Packit Service |
f629e6 |
p <= path + pathlen;
|
|
Packit Service |
f629e6 |
p++, s++) {
|
|
Packit Service |
f629e6 |
if (tolower(*p) != tolower(*s)
|
|
Packit Service |
f629e6 |
&& !((*p == '/' || *p == '\\')
|
|
Packit Service |
f629e6 |
&& (*s == '/' || *s == '\\')))
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return 1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __EMX__
|
|
Packit Service |
f629e6 |
# ifndef PATH_SEPARATOR
|
|
Packit Service |
f629e6 |
# define PATH_SEPARATOR ';'
|
|
Packit Service |
f629e6 |
# endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* result is 0 if dirname is no absolute path, 1 otherwise */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static int
|
|
Packit Service |
f629e6 |
_os2_is_abs_path(const char *dirname)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int result = 0;
|
|
Packit Service |
f629e6 |
if (dirname != NULL && dirname[0] != '\0') {
|
|
Packit Service |
f629e6 |
/* if dirname contains a valid drive letter like "c:" */
|
|
Packit Service |
f629e6 |
if (((dirname[0] >= 'A' && dirname[0] <= 'Z') || (dirname[0] >= 'a' && dirname[0] <= 'z'))
|
|
Packit Service |
f629e6 |
&& dirname[1] == ':') dirname += 2; /* remove the drive letter */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (dirname[0] == '/' || dirname[0] == '\\') result = 1; /* asbolute path */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
|
|
Packit Service |
f629e6 |
This function determines if the first directory of path is on the
|
|
Packit Service |
f629e6 |
drive specified by the environment variable UNIXROOT.
|
|
Packit Service |
f629e6 |
If it is the case, NULL is returned, otherwise a new directory name
|
|
Packit Service |
f629e6 |
is allocated using the drive letter from UNIXROOT and returned as result.
|
|
Packit Service |
f629e6 |
If the first directory is a relative path NULL is returned, too.
|
|
Packit Service |
f629e6 |
The new directory name is allocated by malloc().
|
|
Packit Service |
f629e6 |
Example (UNIXROOT is set to "e:"):
|
|
Packit Service |
f629e6 |
"c:/usr/share" -> "e:/usr/share"
|
|
Packit Service |
f629e6 |
"e:/usr/share" -> NULL (already on the $UNIXROOT drive)
|
|
Packit Service |
f629e6 |
"/usr/share" -> "e:/usr/share"
|
|
Packit Service |
f629e6 |
"." -> NULL (not an absolute path)
|
|
Packit Service |
f629e6 |
"usr/share" -> NULL (not an absolute path)
|
|
Packit Service |
f629e6 |
"c:usr/share" -> NULL (not an absolute path)
|
|
Packit Service |
f629e6 |
"c:/usr/share;d:/etc" -> "e:/usr/share" (only the first directory in path is used) */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static char*
|
|
Packit Service |
f629e6 |
_os2_unixroot(const char *path)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
static const char *unixroot = NULL;
|
|
Packit Service |
f629e6 |
static int unixroot_init = 0;
|
|
Packit Service |
f629e6 |
char *result = NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (unixroot_init == 0) {
|
|
Packit Service |
f629e6 |
/* get $UNIXROOT only one time */
|
|
Packit Service |
f629e6 |
unixroot = getenv("UNIXROOT");
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* check whether unixroot is valid (must be "x:") */
|
|
Packit Service |
f629e6 |
if (unixroot != NULL) {
|
|
Packit Service |
f629e6 |
int drive = toupper(unixroot[0]);
|
|
Packit Service |
f629e6 |
if (drive < 'A' || drive > 'Z' || unixroot[1] != ':' || unixroot[2] != '\0')
|
|
Packit Service |
f629e6 |
unixroot = NULL; /* unixroot not valid */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unixroot_init = 1; /* initialized */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* note: if unixroot != NULL then it contains a valid drive letter */
|
|
Packit Service |
f629e6 |
if (unixroot != NULL && _os2_is_abs_path(path)) {
|
|
Packit Service |
f629e6 |
/* dirname is an absolute path and unixroot is a drive letter, "c:" for example */
|
|
Packit Service |
f629e6 |
size_t old_path_len = strlen(path);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* end points to the first ';' in path or to NULL */
|
|
Packit Service |
f629e6 |
const char *end = strchr(path, PATH_SEPARATOR);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* dir_len is the length of the first directory in path */
|
|
Packit Service |
f629e6 |
size_t dir_len = (end) ? end - path : old_path_len;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (toupper(unixroot[0]) != toupper(path[0]) || path[1] != ':') {
|
|
Packit Service |
f629e6 |
/* the first directory of path does not start with the string $UNIXROOT */
|
|
Packit Service |
f629e6 |
if (path[1] == ':') {
|
|
Packit Service |
f629e6 |
/* if there is a drive letter remove it */
|
|
Packit Service |
f629e6 |
dir_len -= 2;
|
|
Packit Service |
f629e6 |
path += 2;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
result = malloc(dir_len + 3);
|
|
Packit Service |
f629e6 |
if (result) { /* do nothing if we are out of memory */
|
|
Packit Service |
f629e6 |
result[0] = unixroot[0];
|
|
Packit Service |
f629e6 |
result[1] = unixroot[1];
|
|
Packit Service |
f629e6 |
memcpy(result + 2, path, dir_len);
|
|
Packit Service |
f629e6 |
result[dir_len + 2] = '\0';
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
|
|
Packit Service |
f629e6 |
Every directory is processed. _os2_unixroot() is used to find out whether
|
|
Packit Service |
f629e6 |
these directories are on the drive specified by the environment variable
|
|
Packit Service |
f629e6 |
UNIXROOT. If this is not the case the same directory on the UNIXROOT drive
|
|
Packit Service |
f629e6 |
is added to the end of path. If path is a valid path this function returns a valid path, too.
|
|
Packit Service |
f629e6 |
Example ($UNIXROOT is set to "e:"):
|
|
Packit Service |
f629e6 |
".;c:/usr/local;d:/usr/local;d:/etc;e:/etc"
|
|
Packit Service |
f629e6 |
-> ".;c:/usr/local;d:/usr/local;d:/etc;e:/etc;e:/usr/local;e:/usr/local;e:/etc" */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static const char*
|
|
Packit Service |
f629e6 |
_os2_unixroot_path(const char *path)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char *result = NULL;
|
|
Packit Service |
f629e6 |
const char *p = path;
|
|
Packit Service |
f629e6 |
unsigned dir_count = 1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (path == NULL || path[0] == '\0') return NULL; /* empty path */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* save number of path components in dir_count */
|
|
Packit Service |
f629e6 |
while(*p) {
|
|
Packit Service |
f629e6 |
if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
|
|
Packit Service |
f629e6 |
dir_count += 1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
const char *list[dir_count]; /* list of char pointers */
|
|
Packit Service |
f629e6 |
size_t dir_len[dir_count]; /* the according directory length */
|
|
Packit Service |
f629e6 |
size_t old_path_len = strlen(path); /* the old path length */
|
|
Packit Service |
f629e6 |
size_t total_len;
|
|
Packit Service |
f629e6 |
unsigned i = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (path[old_path_len - 1] == PATH_SEPARATOR) /* last character is ';' */
|
|
Packit Service |
f629e6 |
old_path_len--;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
list[0] = p = path; /* first directory */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
while(*p) {
|
|
Packit Service |
f629e6 |
if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
|
|
Packit Service |
f629e6 |
list[++i] = p;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
/* now list[i] contains the ith directory of path (no 0-terminated strings!!!) */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* determine the total length for the new path */
|
|
Packit Service |
f629e6 |
total_len = old_path_len;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for(i = 0; i < dir_count; i++) {
|
|
Packit Service |
f629e6 |
list[i] = _os2_unixroot(list[i]);
|
|
Packit Service |
f629e6 |
if (list[i] != NULL) {
|
|
Packit Service |
f629e6 |
dir_len[i] = strlen(list[i]);
|
|
Packit Service |
f629e6 |
total_len += dir_len[i] + 1; /* one character for ';' or '\0' */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
else dir_len[i] = 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
/* now list[] contains the according directories on the UNIXROOT drive or NULL
|
|
Packit Service |
f629e6 |
total_len contains the total length for the new path */
|
|
Packit Service |
f629e6 |
result = malloc(total_len + 1);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (result) {
|
|
Packit Service |
f629e6 |
/* copy the old path and the new directories into the new path */
|
|
Packit Service |
f629e6 |
char *q = result;
|
|
Packit Service |
f629e6 |
memcpy(q, path, old_path_len);
|
|
Packit Service |
f629e6 |
q += old_path_len;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for(i = 0; i < dir_count; i++) {
|
|
Packit Service |
f629e6 |
if (dir_len[i] != 0) {
|
|
Packit Service |
f629e6 |
*q++ = PATH_SEPARATOR;
|
|
Packit Service |
f629e6 |
memcpy(q, list[i], dir_len[i]);
|
|
Packit Service |
f629e6 |
q += dir_len[i];
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
*q = '\0'; /* terminating '\0' */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for(i = 0; i < dir_count; i++) free((void*) list[i]);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return (result) ? (const char*) result : path;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* limit a length of DLL name up to 8 characters. If dst is not enough for
|
|
Packit Service |
f629e6 |
a fixed dll name, it is truncated. */
|
|
Packit Service |
f629e6 |
char *os2_fixdllname(char *dst, const char *src, size_t n)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char drive[_MAX_DRIVE];
|
|
Packit Service |
f629e6 |
char dir[_MAX_DIR];
|
|
Packit Service |
f629e6 |
char name[_MAX_FNAME];
|
|
Packit Service |
f629e6 |
char ext[_MAX_EXT];
|
|
Packit Service |
f629e6 |
char dll_file[_MAX_PATH];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
_splitpath(src, drive, dir, name, ext);
|
|
Packit Service |
f629e6 |
if (strlen(name) > 8)
|
|
Packit Service |
f629e6 |
name[8] = '\0';
|
|
Packit Service |
f629e6 |
_makepath(dll_file, drive, dir, name, ext);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
strncpy(dst, dll_file, n);
|
|
Packit Service |
f629e6 |
dst[n - 1] = '\0';
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return dst;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __KLIBC__
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* replacement of dlopen(). This limits a length of a base name up to 8
|
|
Packit Service |
f629e6 |
characters. */
|
|
Packit Service |
f629e6 |
void *os2_dlopen(const char *file, int mode)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char dll_file[strlen(file) + 1];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return (dlopen)(os2_fixdllname(dll_file, file, sizeof(dll_file)), mode);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* replacement of dlsym(). This prepends '_' to name. */
|
|
Packit Service |
f629e6 |
void *os2_dlsym(void *handle, const char *name)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char sym[strlen(name) + 1 + 1]; /* 1 for '_', 1 for NUL */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
sym[0] = '_';
|
|
Packit Service |
f629e6 |
strcpy(sym + 1, name);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return (dlsym)(handle, sym);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* __KLIBC__ */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* __EMX__ */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __MINGW32__
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
extern void *xmalloc (size_t);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
setenv (const char *name, const char *value, int rewrite)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char *entry;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (*value == '=')
|
|
Packit Service |
f629e6 |
++value;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (getenv (name) && !rewrite)
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
entry = xmalloc (strlen (name) + 1 + strlen (value) + 1);
|
|
Packit Service |
f629e6 |
strcat (strcat (strcpy (entry, name), "="), value);
|
|
Packit Service |
f629e6 |
if (putenv (entry) != 0)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
free (entry);
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
unsetenv (const char *name)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (!name || !*name || strchr (name, '=') != NULL)
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return setenv (name, "", 1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* MinGW 3.21 and later defines usleep as an inline function in
|
|
Packit Service |
f629e6 |
unistd.h, which conflicts with the version below. */
|
|
Packit Service |
f629e6 |
#if __MINGW32_MAJOR_VERSION + (__MINGW32_MINOR_VERSION > 20) < 4
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
usleep(unsigned int usec)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
double msecf = usec / 1000.0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
Sleep ((DWORD)msecf);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return usec - msecf * 1000 < 0 ? 0 : (int)(usec - msecf * 1000);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* The implementation of wctob in the MS runtime is problematic
|
|
Packit Service |
f629e6 |
because it doesn't allow to distinguish between WEOF and 0xff, due
|
|
Packit Service |
f629e6 |
to integer sign extension. It also causes failures in dfa.c when
|
|
Packit Service |
f629e6 |
characters with the 8th bit set are involved. This replacement
|
|
Packit Service |
f629e6 |
version fixes that. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include <wchar.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
wctob (wint_t wc)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char buf[64];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!(MB_CUR_MAX <= sizeof (buf)))
|
|
Packit Service |
f629e6 |
abort ();
|
|
Packit Service |
f629e6 |
/* Handle the case where WEOF is a value that does not fit in a wchar_t. */
|
|
Packit Service |
f629e6 |
if (wc == (wchar_t)wc)
|
|
Packit Service |
f629e6 |
if (wctomb (buf, (wchar_t)wc) == 1)
|
|
Packit Service |
f629e6 |
return (unsigned char) buf[0];
|
|
Packit Service |
f629e6 |
return EOF;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#undef setlocale
|
|
Packit Service |
f629e6 |
#include <locale.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* On Posix systems, 'setlocale' looks at LC_* variables in the
|
|
Packit Service |
f629e6 |
environment, and Gawk users might expect that on Windows as well.
|
|
Packit Service |
f629e6 |
The replacement implementation below does that, and also fixes a
|
|
Packit Service |
f629e6 |
few additional quirks with locales on Windows. */
|
|
Packit Service |
f629e6 |
static const char *
|
|
Packit Service |
f629e6 |
lc_var (int category)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
static const char *loc_name[LC_MAX - LC_MIN + 1] = {
|
|
Packit Service |
f629e6 |
"LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", "LC_TIME"
|
|
Packit Service |
f629e6 |
};
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* This function assumes LC_* categories are small numbers between 0
|
|
Packit Service |
f629e6 |
and 5, as shown above, so if that changes at some point, complain
|
|
Packit Service |
f629e6 |
vociferously. */
|
|
Packit Service |
f629e6 |
if (LC_ALL != 0 || LC_CTYPE != 2 || LC_TIME != 5)
|
|
Packit Service |
f629e6 |
abort ();
|
|
Packit Service |
f629e6 |
/* Ensured by the caller, so should never happen. */
|
|
Packit Service |
f629e6 |
if (category < LC_MIN || category > LC_MAX)
|
|
Packit Service |
f629e6 |
return "????";
|
|
Packit Service |
f629e6 |
return loc_name[category];
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
char *
|
|
Packit Service |
f629e6 |
w32_setlocale (int category, const char *value)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
const char *new_locale = value;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (LC_MIN <= category && category <= LC_MAX
|
|
Packit Service |
f629e6 |
&& value && *value == '\0')
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
const char *lc_val = getenv ("LC_ALL");
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!lc_val)
|
|
Packit Service |
f629e6 |
lc_val = getenv (lc_var (category));
|
|
Packit Service |
f629e6 |
if (!lc_val)
|
|
Packit Service |
f629e6 |
lc_val = getenv ("LANG");
|
|
Packit Service |
f629e6 |
if (lc_val)
|
|
Packit Service |
f629e6 |
new_locale = lc_val;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* If VALUE includes a codeset, i.e. a Windows codepage number, we
|
|
Packit Service |
f629e6 |
must also set the LC_CTYPE locale to the same value, because
|
|
Packit Service |
f629e6 |
LC_CTYPE is the only category which is documented to be able to
|
|
Packit Service |
f629e6 |
change the codepage. */
|
|
Packit Service |
f629e6 |
if (category != LC_ALL && category != LC_CTYPE)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
const char *p = strchr (new_locale, '.');
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (p && isdigit (p[1]))
|
|
Packit Service |
f629e6 |
setlocale (LC_CTYPE, new_locale);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return setlocale (category, new_locale);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* On MS-Windows with MinGW, execvp causes the shell and the re-exec'ed
|
|
Packit Service |
f629e6 |
* dgawk to compete for the keyboard input.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This will need work if we ever need a real version of execvp.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
int execvp(const char *file, const char *const *argv)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (_spawnvp(_P_WAIT, file, (const char * const *)argv) != -1)
|
|
Packit Service |
f629e6 |
exit(EXIT_SUCCESS);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef DYNAMIC
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include <dlfcn.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static DWORD last_err;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void *
|
|
Packit Service |
f629e6 |
dlopen (const char *file, int mode)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
char dllfn[MAX_PATH], *p;
|
|
Packit Service |
f629e6 |
HANDLE dllhandle;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (mode != RTLD_LAZY)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
last_err = ERROR_INVALID_PARAMETER;
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* MSDN says to be sure to use backslashes in the DLL file name. */
|
|
Packit Service |
f629e6 |
strcpy (dllfn, file);
|
|
Packit Service |
f629e6 |
for (p = dllfn; *p; p++)
|
|
Packit Service |
f629e6 |
if (*p == '/')
|
|
Packit Service |
f629e6 |
*p = '\\';
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
dllhandle = LoadLibrary (dllfn);
|
|
Packit Service |
f629e6 |
if (!dllhandle)
|
|
Packit Service |
f629e6 |
last_err = GetLastError ();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return dllhandle;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
char *
|
|
Packit Service |
f629e6 |
dlerror (void)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
static char errbuf[1024];
|
|
Packit Service |
f629e6 |
DWORD ret;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!last_err)
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
|
Packit Service |
f629e6 |
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
Packit Service |
f629e6 |
NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
|
|
Packit Service |
f629e6 |
while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r'))
|
|
Packit Service |
f629e6 |
--ret;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
errbuf[ret] = '\0';
|
|
Packit Service |
f629e6 |
if (!ret)
|
|
Packit Service |
f629e6 |
sprintf (errbuf, "Error code %lu", last_err);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
last_err = 0;
|
|
Packit Service |
f629e6 |
return errbuf;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
dlclose (void *handle)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (!handle || handle == INVALID_HANDLE_VALUE)
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
if (!FreeLibrary (handle))
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void *
|
|
Packit Service |
f629e6 |
dlsym (void *handle, const char *name)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
FARPROC addr = NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!handle || handle == INVALID_HANDLE_VALUE)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
last_err = ERROR_INVALID_PARAMETER;
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
addr = GetProcAddress (handle, name);
|
|
Packit Service |
f629e6 |
if (!addr)
|
|
Packit Service |
f629e6 |
last_err = GetLastError ();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return (void *)addr;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
#endif /* DYNAMIC */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef HAVE_SOCKETS
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
socket_to_fd(SOCKET s)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return (s == INVALID_SOCKET
|
|
Packit Service |
f629e6 |
? INVALID_HANDLE
|
|
Packit Service |
f629e6 |
: _open_osfhandle (s, O_BINARY | O_NOINHERIT));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_socket(int family, int type, int protocol)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
/* We need to use WSASocket rather than socket, since the latter
|
|
Packit Service |
f629e6 |
creates overlapped sockets that cannot be used in file I/O
|
|
Packit Service |
f629e6 |
APIs. */
|
|
Packit Service |
f629e6 |
SOCKET s = WSASocket (family, type, protocol, NULL, 0, 0);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (s == INVALID_SOCKET)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
switch (WSAGetLastError ())
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
case WSAEMFILE:
|
|
Packit Service |
f629e6 |
errno = EMFILE;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case WSANOTINITIALISED:
|
|
Packit Service |
f629e6 |
case WSAENETDOWN:
|
|
Packit Service |
f629e6 |
errno = EACCES;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case WSAENOBUFS:
|
|
Packit Service |
f629e6 |
errno = ENOMEM;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case WSAEFAULT:
|
|
Packit Service |
f629e6 |
errno = EFAULT;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return socket_to_fd (s);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_setsockopt (int fd, int level, int optname, const char *optval, int optlen)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return setsockopt (s, level, optname, optval, optlen);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_bind (int fd, const struct sockaddr *name, int namelen)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return bind (s, name, namelen);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_connect (int fd, const struct sockaddr *name, int namelen)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return connect (s, name, namelen);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_listen (int fd, int backlog)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return listen (s, backlog);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_accept (int fd, struct sockaddr *addr, int *addrlen)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return socket_to_fd (accept (s, addr, addrlen));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
SOCKET
|
|
Packit Service |
f629e6 |
valid_socket (int fd)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
int ov, ol = 4;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (s == INVALID_SOCKET
|
|
Packit Service |
f629e6 |
|| (getsockopt (s, SOL_SOCKET, SO_TYPE, (char *)&ov, &ol) == SOCKET_ERROR
|
|
Packit Service |
f629e6 |
&& WSAGetLastError() == WSAENOTSOCK))
|
|
Packit Service |
f629e6 |
return (SOCKET)0;
|
|
Packit Service |
f629e6 |
return s;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_closesocket (int fd)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = valid_socket (fd);
|
|
Packit Service |
f629e6 |
int res1, res2 = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!s && fd == FAKE_FD_VALUE)
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
res1 = close (fd);
|
|
Packit Service |
f629e6 |
if (s)
|
|
Packit Service |
f629e6 |
res2 = closesocket (s);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (res1 == -1 || res2 == SOCKET_ERROR)
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_recvfrom (int fd, char *buf, int len, int flags,
|
|
Packit Service |
f629e6 |
struct sockaddr *from, int *fromlen)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return recvfrom (s, buf, len, flags, from, fromlen);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_shutdown (int fd, int how)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
SOCKET s = FD_TO_SOCKET (fd);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return shutdown (s, how);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* HAVE_SOCKETS */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Translate abnormal exit status of Windows programs into the signal
|
|
Packit Service |
f629e6 |
that terminated the program. This is required to support scm_kill
|
|
Packit Service |
f629e6 |
and WTERMSIG. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include <signal.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
struct signal_and_status {
|
|
Packit Service |
f629e6 |
int sig;
|
|
Packit Service |
f629e6 |
unsigned status;
|
|
Packit Service |
f629e6 |
};
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static const struct signal_and_status sigtbl[] = {
|
|
Packit Service |
f629e6 |
{SIGSEGV, 0xC0000005}, /* access to invalid address */
|
|
Packit Service |
f629e6 |
{SIGSEGV, 0xC0000008}, /* invalid handle */
|
|
Packit Service |
f629e6 |
{SIGILL, 0xC000001D}, /* illegal instruction */
|
|
Packit Service |
f629e6 |
{SIGILL, 0xC0000025}, /* non-continuable instruction */
|
|
Packit Service |
f629e6 |
{SIGSEGV, 0xC000008C}, /* array bounds exceeded */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC000008D}, /* float denormal */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC000008E}, /* float divide by zero */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC000008F}, /* float inexact */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000090}, /* float invalid operation */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000091}, /* float overflow */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000092}, /* float stack check */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000093}, /* float underflow */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000094}, /* integer divide by zero */
|
|
Packit Service |
f629e6 |
{SIGFPE, 0xC0000095}, /* integer overflow */
|
|
Packit Service |
f629e6 |
{SIGILL, 0xC0000096}, /* privileged instruction */
|
|
Packit Service |
f629e6 |
{SIGSEGV, 0xC00000FD}, /* stack overflow */
|
|
Packit Service |
f629e6 |
{SIGTERM, 0xC000013A}, /* Ctrl-C exit */
|
|
Packit Service |
f629e6 |
{SIGINT, 0xC000013A}
|
|
Packit Service |
f629e6 |
};
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
w32_status_to_termsig (unsigned status)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int i;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < sizeof (sigtbl) / sizeof (sigtbl[0]); i++)
|
|
Packit Service |
f629e6 |
if (status == sigtbl[i].status)
|
|
Packit Service |
f629e6 |
return sigtbl[i].sig;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return SIGTERM;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
w32_maybe_set_errno (void)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
DWORD w32err = GetLastError ();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
switch (w32err)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
/* When stdout is redirected to a pipe, and the program that
|
|
Packit Service |
f629e6 |
reads the pipe (e.g., a pager) exits, Windows doesn't set
|
|
Packit Service |
f629e6 |
errno to a useful value. Help it DTRT. */
|
|
Packit Service |
f629e6 |
case ERROR_BAD_PIPE:
|
|
Packit Service |
f629e6 |
case ERROR_PIPE_BUSY:
|
|
Packit Service |
f629e6 |
case ERROR_NO_DATA:
|
|
Packit Service |
f629e6 |
case ERROR_PIPE_NOT_CONNECTED:
|
|
Packit Service |
f629e6 |
errno = EPIPE;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* __MINGW32__ */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#if defined(__DJGPP__) || defined(__MINGW32__) || defined(__EMX__)
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
void
|
|
Packit Service |
f629e6 |
init_sockets(void)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
#if defined(HAVE_SOCKETS) && !defined(__EMX__)
|
|
Packit Service |
f629e6 |
WSADATA winsockData;
|
|
Packit Service |
f629e6 |
int errcode;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ((errcode = WSAStartup (0x101, &winsockData)) != 0
|
|
Packit Service |
f629e6 |
|| winsockData.wVersion != 0x101)
|
|
Packit Service |
f629e6 |
fatal(_("cannot start Winsock (%d)"), errcode);
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* __DJGPP__ || __MINGW32__ */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __DJGPP__
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
# if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
unsetenv (const char *name)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (!name || !*name || strchr (name, '=') != NULL)
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return putenv (name);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* This is needed to defeat too-clever GCC warnings in dfa.c about
|
|
Packit Service |
f629e6 |
comparison being always false due to limited range of data type. */
|
|
Packit Service |
f629e6 |
wint_t
|
|
Packit Service |
f629e6 |
btowc (int c)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return c;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
wint_t
|
|
Packit Service |
f629e6 |
putwc(wchar_t wc, FILE *stream)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
return MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX
|
|
Packit Service |
f629e6 |
&& putc((unsigned char)wc, stream) != EOF ? (wint_t)wc : WEOF;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /* __DJGPP__ */
|