diff options
Diffstat (limited to 'pc')
-rw-r--r-- | pc/ChangeLog | 42 | ||||
-rw-r--r-- | pc/Makefile | 14 | ||||
-rw-r--r-- | pc/Makefile.tst | 18 | ||||
-rw-r--r-- | pc/config.h | 12 | ||||
-rw-r--r-- | pc/config.sed | 12 | ||||
-rw-r--r-- | pc/gawkmisc.pc | 177 | ||||
-rw-r--r-- | pc/in.h | 1 | ||||
-rw-r--r-- | pc/popen.c | 72 | ||||
-rw-r--r-- | pc/popen.h | 5 | ||||
-rw-r--r-- | pc/socket.h | 42 |
10 files changed, 370 insertions, 25 deletions
diff --git a/pc/ChangeLog b/pc/ChangeLog index 3cb6ce11..f1d1978b 100644 --- a/pc/ChangeLog +++ b/pc/ChangeLog @@ -1,3 +1,45 @@ +2013-06-01 Eli Zaretskii <eliz@gnu.org> + + * popen.h (SIGKILL) [__MINGW32__]: Define. + (kill, quote_cmd): New prototypes. + + * popen.c: Include popen.h and errno.h. + (popen, pclose, system): Undefine macros. + (WIN32_LEAN_AND_MEAN) [__MINGW32__]: Define and include windows.h. + (kill, quote_cmd) [!PIPES_SIMULATED]: New functions. + (os_popen): Make the function definition match its prototype + exactly. + + * gawkmisc.pc [HAVE_SOCKETS]: Include socket.h and windows.h. + (socket, setsockopt, bind, connect, listen, accept, recvfrom) + (shutdown): Undefine macros. + (os_close_on_exec) [__MINGW32__]: Non-trivial implementation. + (init_sockets, socket_to_fd, w32_socket, w32_setsockopt) + (w32_bind, w32_connect, w32_listen, w32_accept, valid_socket) + (w32_closesocket, w32_recvfrom, w32_shutdown) [HAVE_SOCKETS]: New + functions for MinGW, emulate Posix sockets specified by file + descriptors. + + * config.h (HAVE_GETADDRINFO, HAVE_SOCKADDR_STORAGE) + (HAVE_SOCKETS) [__MINGW32__]: Define. + + * config.sed (HAVE_GETADDRINFO, HAVE_SOCKADDR_STORAGE) + (HAVE_SOCKETS) [__MINGW32__]: Define. + + * Makefile.tst (fmtspcl): Announce expected failure only if not + built with MPFR. + (inetecht, inetdayt): For MinGW, warn about time-outs. + (beginfile1, clos1way, getlndir): Announce expected failure only + with DJGPP. + (exit): Describe the failure on MinGW. + (readdir): Explain why test might fail with bad ls.exe. + + * Makefile (mingw32, mingw32-readline, mingw32-mpfr) + (mingw32-readline-mpfr): Add -lws2_32 to the link flags. + (gawkmisc$O): Depend on socket.h. + (io$O): Depend on socket.h and in.h. + (popen$O): New dependency. + 2013-05-27 Arnold D. Robbins <arnold@skeeve.com> * config.h: Remove obsolete HAVE_ST_BLKSIZE. diff --git a/pc/Makefile b/pc/Makefile index 4152ed24..9d98cb1c 100644 --- a/pc/Makefile +++ b/pc/Makefile @@ -158,28 +158,29 @@ LMINGW32 = $(CC) $(LF) -o $@ $(GAWKOBJS) $(LF2) mingw32: $(MAK) all \ CC=gcc O=.o CF="-D__USE_MINGW_ANSI_STDIO -O2 -gdwarf-2 -g3" \ - OBJ=popen.o LNK=LMINGW32 LF="-gdwarf-2 -g3" LF2=-lmsvcp60 RSP= + OBJ=popen.o LNK=LMINGW32 LF="-gdwarf-2 -g3" \ + LF2="-lws2_32 -lmsvcp60" RSP= mingw32-readline: $(MAK) all \ CC=gcc O=.o \ CF="-D__USE_MINGW_ANSI_STDIO -DHAVE_LIBREADLINE -O2 -gdwarf-2 -g3" \ OBJ=popen.o LNK=LMINGW32 LF="-gdwarf-2 -g3" \ - LF2="-lreadline -lmsvcp60 -Wl,--enable-auto-import" RSP= + LF2="-lreadline -lws2_32 -lmsvcp60 -Wl,--enable-auto-import" RSP= mingw32-mpfr: $(MAK) all \ CC=gcc O=.o \ CF="-D__USE_MINGW_ANSI_STDIO -DHAVE_MPFR -O2 -gdwarf-2 -g3" \ OBJ=popen.o LNK=LMINGW32 LF="-gdwarf-2 -g3" \ - LF2="-lmpfr -lgmp -lmsvcp60 -Wl,--enable-auto-import" RSP= + LF2="-lmpfr -lgmp -lws2_32 -lmsvcp60 -Wl,--enable-auto-import" RSP= mingw32-readline-mpfr: $(MAK) all \ CC=gcc O=.o \ CF="-D__USE_MINGW_ANSI_STDIO -DHAVE_LIBREADLINE -DHAVE_MPFR -O2 -gdwarf-2 -g3" \ OBJ=popen.o LNK=LMINGW32 LF="-gdwarf-2 -g3" \ - LF2="-lmpfr -lgmp -lreadline -lmsvcp60 -Wl,--enable-auto-import" RSP= + LF2="-lmpfr -lgmp -lreadline -lws2_32 -lmsvcp60 -Wl,--enable-auto-import" RSP= # Define BIND for BINDless compiles, otherwise $($(BIND)) may break. BIND = EMPTY @@ -242,11 +243,11 @@ command$O debug$O: cmd.h dfa$O: xalloc.h -gawkmisc$O: pc/gawkmisc.pc +gawkmisc$O: pc/gawkmisc.pc socket.h getopt$O getopt1$O : getopt_int.h -io$O: popen.h +io$O: popen.h socket.h in.h regex$O: regcomp.c regexec.c regex_internal.h @@ -261,6 +262,7 @@ awkgram.c: awkgram.y alloca$O: alloca.c +popen$O: popen.h install: install$(install) -$(MAKE) -C extension install-extensions diff --git a/pc/Makefile.tst b/pc/Makefile.tst index cc188fda..6e6992c2 100644 --- a/pc/Makefile.tst +++ b/pc/Makefile.tst @@ -60,7 +60,7 @@ SHELL = /bin/sh # Point to gawk -AWK = AWKLIBPATH=../extension ../gawk.exe +AWK = AWKLIBPATH=../extension $(AWKPROG) # Also point to gawk but for DOS commands needing backslashes. We need # the forward slash version too or 'arrayparam' fails. AWK2 = '..\gawk.exe' @@ -500,7 +500,7 @@ fmtspcl.ok: fmtspcl.tok fmtspcl: fmtspcl.ok @echo $@ - @echo Expect $@ to fail with MinGW + @echo Expect $@ to fail on MinGW if not built with MPFR @$(AWK) $(AWKFLAGS) -f $(srcdir)/fmtspcl.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-if test -z "$$AWKFLAGS" ; then $(CMP) $@.ok _$@ && rm -f _$@ ; else \ $(CMP) $(srcdir)/$@-mpfr.ok _$@ && rm -f _$@ ; \ @@ -553,6 +553,7 @@ inetechu:: inetecht:: @echo Expect inetecht to fail with DJGPP. + @echo Expect inetecht to time out with MinGW after 20 sec. @echo This test is for establishing TCP connections # @$(AWK) 'BEGIN {print "" |& "/inet/tcp/0/127.0.0.1/9"}' @-$(AWK) 'BEGIN {print "" |& "/inet/tcp/0/127.0.0.1/9"}' @@ -567,6 +568,7 @@ inetdayu:: inetdayt:: @echo Expect inetdayt to fail with DJGPP. + @echo Expect inetdayt to time out with MinGW after 41 sec. @echo This test is for bidirectional TCP transmission # @$(AWK) 'BEGIN { print "" |& "/inet/tcp/0/127.0.0.1/13"; \ # "/inet/tcp/0/127.0.0.1/13" |& getline; print $0}' @@ -820,7 +822,7 @@ printfbad2: printfbad2.ok beginfile1:: @echo $@ - @echo Expect beginfile1 to fail with DJGPP and MinGW + @echo Expect beginfile1 to fail with DJGPP @AWKPATH=$(srcdir) $(AWK) -f $@.awk $(srcdir)/$@.awk . ./no/such/file Makefile >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ @@ -868,7 +870,7 @@ next: exit: @echo $@ - @echo Expect exit to fail with MinGW + @echo Expect exit to fail with MinGW due to null vs nul difference @-AWK="$(AWKPROG)" $(srcdir)/$@.sh > _$@ 2>&1 @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ @@ -1010,7 +1012,7 @@ readdir: echo If it does, try rerunning on an ext'[234]' filesystem. ; \ fi @echo $@ - @echo This test may fail if $(LS) does not report full Windows file index as the inode + @echo This test may fail on MinGW if $(LS) does not report full Windows file index as the inode @$(AWK) -f $(srcdir)/readdir.awk $(top_srcdir) > _$@ @$(LS) -afli $(top_srcdir) | sed 1d | $(AWK) -f $(srcdir)/readdir0.awk -v extout=_$@ > $@.ok @-$(CMP) $@.ok _$@ && rm -f $@.ok _$@ @@ -1998,8 +2000,8 @@ backw: clos1way: @echo $@ - @echo Expect clos1way to fail with DJGPP and MinGW. - @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @echo Expect clos1way to fail with DJGPP. + @AWKPATH=$(srcdir) LC_ALL=C $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ delsub: @@ -2084,7 +2086,7 @@ gensub2: getlndir: @echo $@ - @echo Expect getlndir to fail with DJGPP and MinGW. + @echo Expect getlndir to fail with DJGPP. @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ diff --git a/pc/config.h b/pc/config.h index 1d373b01..92e1b4e3 100644 --- a/pc/config.h +++ b/pc/config.h @@ -59,7 +59,9 @@ #define HAVE_FMOD 1 /* have getaddrinfo */ -#undef HAVE_GETADDRINFO +#ifdef __MINGW32__ +#define HAVE_GETADDRINFO 1 +#endif /* Define to 1 if you have the `getgrent' function. */ #undef HAVE_GETGRENT @@ -210,10 +212,14 @@ #endif /* newer systems define this type here */ -#undef HAVE_SOCKADDR_STORAGE +#ifdef __MINGW32__ +#define HAVE_SOCKADDR_STORAGE 1 +#endif /* we have sockets on this system */ -#undef HAVE_SOCKETS +#ifdef __MINGW32__ +#define HAVE_SOCKETS 1 +#endif /* Define to 1 if you have the <stdarg.h> header file. */ #define HAVE_STDARG_H 1 diff --git a/pc/config.sed b/pc/config.sed index 18d33297..e18a6e68 100644 --- a/pc/config.sed +++ b/pc/config.sed @@ -48,6 +48,10 @@ s/^#undef HAVE_ATEXIT *$/#define HAVE_ATEXIT 1/ #endif s/^#undef HAVE_FCNTL_H *$/#define HAVE_FCNTL_H 1/ s/^#undef HAVE_FMOD *$/#define HAVE_FMOD 1/ +/^#undef HAVE_GETADDRINFO *$/c\ +#ifdef __MINGW32__\ +#define HAVE_GETADDRINFO 1\ +#endif /^#undef HAVE_INTMAX_T *$/c\ #ifdef __MINGW32__\ #define HAVE_INTMAX_T 1\ @@ -122,6 +126,14 @@ s/^#undef HAVE_MKTIME *$/#define HAVE_MKTIME 1/ #ifdef __MINGW32__\ #define HAVE_SNPRINTF 1\ #endif +/^#undef HAVE_SOCKADDR_STORAGE *$/c\ +#ifdef __MINGW32__\ +#define HAVE_SOCKADDR_STORAGE 1\ +#endif +/^#undef HAVE_SOCKETS *$/c\ +#ifdef __MINGW32__\ +#define HAVE_SOCKETS 1\ +#endif s/^#undef HAVE_STDARG_H *$/#define HAVE_STDARG_H 1/ /^#undef HAVE_STDDEF_H *$/c\ #ifdef __GNUC__\ diff --git a/pc/gawkmisc.pc b/pc/gawkmisc.pc index 5e412d71..ce45b6d8 100644 --- a/pc/gawkmisc.pc +++ b/pc/gawkmisc.pc @@ -42,6 +42,24 @@ static char* _os2_unixroot(const char *path); static const char* _os2_unixroot_path(const char *path); #endif +#ifdef __MINGW32__ +#ifdef HAVE_SOCKETS +#include <socket.h> + +#undef socket +#undef setsockopt +#undef bind +#undef connect +#undef listen +#undef accept +#undef recvfrom +#undef shutdown +#endif + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + /* gawk_name --- pull out the "gawk" part from how the OS called us */ char * @@ -205,15 +223,19 @@ os_close_on_exec(fd, name, what, dir) int fd; const char *name, *what, *dir; { -#if ! defined(_MSC_VER) && ! defined(__MINGW32__) -# if (defined(__DJGPP__) && (__DJGPP__ > 2 || __DJGPP_MINOR__ >= 4)) || defined __EMX__ +#if (defined(__DJGPP__) && (__DJGPP__ > 2 || __DJGPP_MINOR__ >= 4)) || defined __EMX__ if (fd <= 2) /* sanity */ return; if (fcntl(fd, F_SETFD, 1) < 0) warning("%s %s `%s': could not set close-on-exec: %s", what, dir, name, strerror(errno)); -# endif +#endif +#ifdef __MINGW32__ + HANDLE fh = (HANDLE)_get_osfhandle(fd); + + if (fh && fh != INVALID_HANDLE_VALUE) + SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0); #endif } @@ -562,8 +584,6 @@ unsetenv (const char *name) return setenv (name, "", 1); } -#include <windows.h> - int usleep(unsigned int usec) { @@ -693,7 +713,152 @@ dlsym (void *handle, const char *name) return (void *)addr; } -#endif +#endif /* DYNAMIC */ + +#ifdef HAVE_SOCKETS + +void +init_sockets(void) +{ + WSADATA winsockData; + int errcode; + + if ((errcode = WSAStartup (0x101, &winsockData)) != 0 + || winsockData.wVersion != 0x101) + fatal(_("cannot start Winsock (%d)"), errcode); +} + +int +socket_to_fd(SOCKET s) +{ + return (s == INVALID_SOCKET + ? INVALID_HANDLE + : _open_osfhandle (s, O_BINARY | O_NOINHERIT)); +} + +int +w32_socket(int family, int type, int protocol) +{ + /* We need to use WSASocket rather than socket, since the latter + creates overlapped sockets that cannot be used in file I/O + APIs. */ + SOCKET s = WSASocket (family, type, protocol, NULL, 0, 0); + + if (s == INVALID_SOCKET) + { + switch (WSAGetLastError ()) + { + case WSAEMFILE: + errno = EMFILE; + break; + case WSANOTINITIALISED: + case WSAENETDOWN: + errno = EACCES; + break; + case WSAENOBUFS: + errno = ENOMEM; + break; + case WSAEFAULT: + errno = EFAULT; + break; + default: + errno = EINVAL; + break; + } + } + + return socket_to_fd (s); +} + +int +w32_setsockopt (int fd, int level, int optname, const char *optval, int optlen) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return setsockopt (s, level, optname, optval, optlen); +} + +int +w32_bind (int fd, const struct sockaddr *name, int namelen) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return bind (s, name, namelen); +} + +int +w32_connect (int fd, const struct sockaddr *name, int namelen) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return connect (s, name, namelen); +} + +int +w32_listen (int fd, int backlog) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return listen (s, backlog); +} + +int +w32_accept (int fd, struct sockaddr *addr, int *addrlen) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return socket_to_fd (accept (s, addr, addrlen)); +} + +SOCKET +valid_socket (int fd) +{ + SOCKET s = FD_TO_SOCKET (fd); + int ov, ol = 4; + + if (s == INVALID_SOCKET + || (getsockopt (s, SOL_SOCKET, SO_TYPE, (char *)&ov, &ol) == SOCKET_ERROR + && WSAGetLastError() == WSAENOTSOCK)) + return (SOCKET)0; + return s; +} + +int +w32_closesocket (int fd) +{ + SOCKET s = valid_socket (fd); + int res1, res2 = 0; + + if (!s && fd == FAKE_FD_VALUE) + return 0; + + res1 = close (fd); + if (s) + res2 = closesocket (s); + + if (res1 == -1 || res2 == SOCKET_ERROR) + return -1; + return 0; +} + +int +w32_recvfrom (int fd, char *buf, int len, int flags, + struct sockaddr *from, int *fromlen) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return recvfrom (s, buf, len, flags, from, fromlen); +} + +int +w32_shutdown (int fd, int how) +{ + SOCKET s = FD_TO_SOCKET (fd); + + return shutdown (s, how); +} + +#endif /* HAVE_SOCKETS */ #endif /* __MINGW32__ */ diff --git a/pc/in.h b/pc/in.h new file mode 100644 index 00000000..d0833805 --- /dev/null +++ b/pc/in.h @@ -0,0 +1 @@ +/* A dummy in.h for pc/ systems. */ @@ -3,6 +3,11 @@ #include <io.h> #include <string.h> #include <process.h> +#include <errno.h> +#include "popen.h" +#undef popen +#undef pclose +#undef system #ifndef _NFILE #define _NFILE 40 @@ -26,6 +31,9 @@ static struct { #if defined(__MINGW32__) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + static int unixshell(char *p) { @@ -127,13 +135,75 @@ os_system(const char *cmd) unlink_and_free(cmd1); return(i); } + +#ifndef PIPES_SIMULATED +int +kill (int pid, int sig) +{ + HANDLE ph; + int retval = 0; + + /* We only support SIGKILL. */ + if (sig != SIGKILL) + { + errno = ENOSYS; + return -1; + } + + ph = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (ph) + { + BOOL status = TerminateProcess(ph, -1); + + if (!status) + { + errno = EPERM; + retval = -1; + } + } + else + { + /* If we cannot open the process, it means we eaither aren't + allowed to (e.g., a process of another user), or such a + process doesn't exist. */ + switch (GetLastError ()) + { + case ERROR_ACCESS_DENIED: + errno = EPERM; + break; + default: + errno = ESRCH; + break; + } + retval = -1; + } + CloseHandle (ph); + return retval; +} + +char * +quote_cmd(const char *cmd) +{ + char *quoted; + + /* The command will be invoked via cmd.exe, whose behavior wrt + quoted commands is to remove the first and the last quote + characters, and leave the rest (including any quote characters + inside the outer pair) intact. */ + quoted = malloc(strlen (cmd) + 2 + 1); + sprintf(quoted, "\"%s\"", cmd); + + return quoted; +} +#endif + #else /* !__MINGW32__ */ #define os_system(cmd) system(cmd) #endif FILE * -os_popen(const char *command, char *mode ) +os_popen(const char *command, const char *mode ) { FILE *current; char *name; @@ -12,6 +12,9 @@ extern int os_pclose( FILE * ); # ifdef __MINGW32__ # define system(c) os_system(c) - extern int os_system( const char * ); + extern int os_system( const char * ); +# define SIGKILL 9 + extern int kill( int, int ); + extern char *quote_cmd( const char * ); # endif /* __MINGW32__ */ #endif /* !__DJGPP__ */ diff --git a/pc/socket.h b/pc/socket.h new file mode 100644 index 00000000..41dd23cf --- /dev/null +++ b/pc/socket.h @@ -0,0 +1,42 @@ +/* An emulation for socket.h header for pc/ systems. */ + +#ifndef GAWK_SOCKET_H +#define GAWK_SOCKET_H + +#ifdef __MINGW32__ + +#include <io.h> + +#define _WIN32_WINNT 0x501 +#include <winsock2.h> +#include <ws2tcpip.h> + +#define socket(f,t,p) w32_socket(f,t,p) +#define setsockopt(f,l,o,v,s) w32_setsockopt(f,l,o,v,s) +#define bind(f,a,l) w32_bind(f,a,l) +#define connect(f,a,l) w32_connect(f,a,l) +#define listen(f,b) w32_listen(f,b) +#define accept(f,a,l) w32_accept(f,a,l) +#define closemaybesocket(f) w32_closesocket(f) +#define recvfrom(f,b,l,fl,fr,ln) w32_recvfrom(f,b,l,fl,fr,ln) +#define shutdown(f,h) w32_shutdown(f,h) + +#define SOCKET_TO_FD(s) socket_to_fd(s) +#define FD_TO_SOCKET(fd) \ + ((fd) == INVALID_HANDLE ? INVALID_SOCKET : _get_osfhandle(fd)) + +int w32_socket (int, int, int); +int w32_setsockopt (int, int, int, const char *, int); +int w32_bind (int, const struct sockaddr *, int); +int w32_connect (int, const struct sockaddr *, int); +int w32_listen (int, int); +int w32_accept (int, struct sockaddr *, int *); +int w32_closesocket (int); +int w32_recvfrom (int, char *, int, int, struct sockaddr *, int *); +int w32_shutdown (int, int); +int socket_to_fd (SOCKET); +SOCKET valid_socket (int); + +#endif /* __MINGW32__ */ + +#endif /* GAWK_SOCKET_H */ |