Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: Unix domain socket module
- X-seq: zsh-workers 17558
- From: Clint Adams <clint@xxxxxxx>
- To: zsh-workers@xxxxxxxxxx
- Subject: PATCH: Unix domain socket module
- Date: Sat, 17 Aug 2002 22:09:05 -0400
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
This implements the zsocket builtin for IPC via local Unix domain
sockets. Omitted is the ability to do SOCK_DGRAM.
Index: Src/Modules/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/.distfiles,v
retrieving revision 1.6
diff -u -r1.6 .distfiles
--- Src/Modules/.distfiles 6 Jun 2002 04:54:50 -0000 1.6
+++ Src/Modules/.distfiles 18 Aug 2002 02:01:55 -0000
@@ -10,6 +10,7 @@
mathfunc.mdd mathfunc.c
parameter.mdd parameter.c
pcre.mdd pcre.c
+ socket.mdd socket.c
stat.mdd stat.c
tcp.mdd tcp.c tcp.h
termcap.mdd termcap.c
Index: Src/Modules/socket.c
===================================================================
RCS file: Src/Modules/socket.c
diff -N Src/Modules/socket.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Src/Modules/socket.c 18 Aug 2002 02:01:56 -0000
@@ -0,0 +1,286 @@
+/*
+ * socket.c - Unix domain socket module
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 2002 Peter Stephenson
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Peter Stephenson or the Zsh Development
+ * Group be liable to any party for direct, indirect, special, incidental,
+ * or consequential damages arising out of the use of this software and
+ * its documentation, even if Peter Stephenson, and the Zsh
+ * Development Group have been advised of the possibility of such damage.
+ *
+ * Peter Stephenson and the Zsh Development Group specifically
+ * disclaim any warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose. The
+ * software provided hereunder is on an "as is" basis, and Peter Stephenson
+ * and the Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "socket.mdh"
+#include "socket.pro"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX 108
+#endif
+
+/*
+ * We need to include the zsh headers later to avoid clashes with
+ * the definitions on some systems, however we need the configuration
+ * file to decide whether we can include netinet/in_systm.h, which
+ * doesn't exist on cygwin.
+ */
+
+/*
+ * We use poll() in preference to select because some subset of manuals says
+ * that's the thing to do, plus it's a bit less fiddly. I don't actually
+ * have access to a system with poll but not select, however, though
+ * both bits of the code have been tested on a machine with both.
+ */
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
+#if defined(HAVE_POLL) && !defined(POLLIN) && !defined(POLLNORM)
+# undef HAVE_POLL
+#endif
+
+static int
+bin_zsocket(char *nam, char **args, char *ops, int func)
+{
+ int err=1, verbose=0, test=0, targetfd=0;
+ SOCKLEN_T len;
+ char **dargs;
+ struct sockaddr_un sun;
+ int sfd;
+
+ if (ops['v'])
+ verbose = 1;
+
+ if (ops['t'])
+ test = 1;
+
+ if (ops['d']) {
+ targetfd = atoi(args[0]);
+ dargs = args + 1;
+ if (!targetfd) {
+ zwarnnam(nam, "%s is an invalid argument to -d", args[0], 0);
+ return 1;
+ }
+ }
+ else
+ dargs = args;
+
+
+ if (ops['l']) {
+ char *localfn;
+
+ if (!dargs[0]) {
+ zwarnnam(nam, "-l requires an argument", NULL, 0);
+ return 1;
+ }
+
+ localfn = dargs[0];
+
+ sfd = socket(PF_UNIX, SOCK_STREAM, 0);
+
+ if (sfd == -1) {
+ zwarnnam(nam, "socket error: %e ", NULL, errno);
+ return 1;
+ }
+
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, localfn, UNIX_PATH_MAX);
+
+ if (bind(sfd, (struct sockaddr *)&sun, sizeof(struct sockaddr_un)))
+ {
+ zwarnnam(nam, "could not bind to %s: %e", sun.sun_path, errno);
+ close(sfd);
+ return 1;
+ }
+
+ if (listen(sfd, 1))
+ {
+ zwarnnam(nam, "could not listen on socket: %e", NULL, errno);
+ close(sfd);
+ return 1;
+ }
+
+ if (targetfd) {
+ redup(sfd, targetfd);
+ sfd = targetfd;
+ }
+ else {
+ /* move the fd since no one will want to read from it */
+ sfd = movefd(sfd);
+ }
+
+ setiparam("REPLY", sfd);
+
+ if (verbose)
+ printf("%s listener is on fd %d\n", sun.sun_path, sfd);
+
+ return 0;
+
+ }
+ else if (ops['a'])
+ {
+ int lfd, rfd;
+
+ if (!dargs[0]) {
+ zwarnnam(nam, "-a requires an argument", NULL, 0);
+ return 1;
+ }
+
+ lfd = atoi(dargs[0]);
+
+ if (!lfd) {
+ zwarnnam(nam, "invalid numerical argument", NULL, 0);
+ return 1;
+ }
+
+ if (test) {
+#if defined(HAVE_POLL) || defined(HAVE_SELECT)
+# ifdef HAVE_POLL
+ struct pollfd pfd;
+ int ret;
+
+ pfd.fd = lfd;
+ pfd.events = POLLIN;
+ if ((ret = poll(&pfd, 1, 0)) == 0) return 1;
+ else if (ret == -1)
+ {
+ zwarnnam(nam, "poll error: %e", NULL, errno);
+ return 1;
+ }
+# else
+ fd_set rfds;
+ struct timeval tv;
+ int ret;
+
+ FD_ZERO(&rfds);
+ FD_SET(lfd, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ if (ret = select(lfd+1, &rfds, NULL, NULL, &tv)) return 1;
+ else if (ret == -1)
+ {
+ zwarnnam(nam, "select error: %e", NULL, errno);
+ return 1;
+ }
+
+# endif
+
+#else
+ zwarnnam(nam, "not currently supported", NULL, 0);
+ return 1;
+#endif
+ }
+
+ if ((rfd = accept(lfd, (struct sockaddr *)&sun, &len)) == -1)
+ {
+ zwarnnam(nam, "could not accept connection: %e", NULL, errno);
+ return 1;
+ }
+
+ if (targetfd) {
+ redup(rfd, targetfd);
+ sfd = targetfd;
+ }
+ else {
+ sfd = rfd;
+ }
+
+ setiparam("REPLY", sfd);
+
+ if (verbose)
+ printf("new connection from %s is on fd %d\n", sun.sun_path, sfd);
+ }
+ else
+ {
+ if (!dargs[0]) {
+ zwarnnam(nam, "zsocket requires an argument", NULL, 0);
+ return 1;
+ }
+
+ sfd = socket(PF_UNIX, SOCK_STREAM, 0);
+
+ if (sfd == -1) {
+ zwarnnam(nam, "socket creation failed: %e", NULL, errno);
+ return 1;
+ }
+
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, dargs[0], UNIX_PATH_MAX);
+
+ if ((err = connect(sfd, (struct sockaddr *)&sun, sizeof(struct sockaddr_un)))) {
+ zwarnnam(nam, "connection failed: %e", NULL, errno);
+ close(sfd);
+ return 1;
+ }
+ else
+ {
+ if (targetfd) {
+ redup(sfd, targetfd);
+ sfd = targetfd;
+ }
+
+ setiparam("REPLY", sfd);
+
+ if (verbose)
+ printf("%s is now on fd %d\n", sun.sun_path, sfd);
+ }
+
+ }
+
+ return 0;
+}
+
+static struct builtin bintab[] = {
+ BUILTIN("zsocket", 0, bin_zsocket, 0, 3, 0, "adltv", NULL),
+};
+
+/* The load/unload routines required by the zsh library interface */
+
+/**/
+int
+setup_(Module m)
+{
+ return 0;
+}
+
+/**/
+int
+boot_(Module m)
+{
+ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+}
+
+
+/**/
+int
+cleanup_(Module m)
+{
+ deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+ return 0;
+}
+
+/**/
+int
+finish_(Module m)
+{
+ return 0;
+}
Index: Src/Modules/socket.mdd
===================================================================
RCS file: Src/Modules/socket.mdd
diff -N Src/Modules/socket.mdd
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Src/Modules/socket.mdd 18 Aug 2002 02:01:56 -0000
@@ -0,0 +1,6 @@
+name=zsh/net/socket
+link=dynamic
+load=no
+
+objects="socket.o"
+autobins="zsocket"
Index: Doc/Zsh/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/.distfiles,v
retrieving revision 1.9
diff -u -r1.9 .distfiles
--- Doc/Zsh/.distfiles 17 Jun 2002 13:29:24 -0000 1.9
+++ Doc/Zsh/.distfiles 18 Aug 2002 02:01:56 -0000
@@ -6,7 +6,8 @@
mod_clone.yo mod_compctl.yo mod_complete.yo mod_complist.yo
mod_computil.yo mod_deltochar.yo mod_example.yo mod_files.yo mod_langinfo.yo
mod_mapfile.yo mod_mathfunc.yo mod_parameter.yo mod_pcre.yo mod_sched.yo
- mod_stat.yo mod_tcp.yo mod_termcap.yo mod_terminfo.yo mod_zftp.yo mod_zle.yo
+ mod_socket.yo mod_stat.yo mod_tcp.yo mod_termcap.yo mod_terminfo.yo
+ mod_zftp.yo mod_zle.yo
mod_zleparameter.yo mod_zselect.yo mod_zutil.yo mod_zprof.yo mod_zpty.yo
modules.yo modlist.yo modmenu.yo manmodmenu.yo
options.yo params.yo prompt.yo redirect.yo restricted.yo seealso.yo
Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.48
diff -u -r1.48 builtins.yo
--- Doc/Zsh/builtins.yo 6 Aug 2002 13:05:51 -0000 1.48
+++ Doc/Zsh/builtins.yo 18 Aug 2002 02:02:00 -0000
@@ -1733,6 +1733,7 @@
module(zprof)(zsh/zprof)
module(zpty)(zsh/zpty)
module(zregexparse)(zsh/zutil)
+module(zsocket)(zsh/net/socket)
module(zstyle)(zsh/zutil)
module(ztcp)(zsh/net/tcp)
enditem()
Index: Doc/Zsh/mod_socket.yo
===================================================================
RCS file: Doc/Zsh/mod_socket.yo
diff -N Doc/Zsh/mod_socket.yo
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Doc/Zsh/mod_socket.yo 18 Aug 2002 02:02:00 -0000
@@ -0,0 +1,64 @@
+COMMENT(!MOD!zsh/net/socket
+Manipulation of Unix domain sockets
+!MOD!)
+The tt(zsh/net/socket) module makes available one builtin command:
+
+startitem()
+findex(zsocket)
+cindex(sockets)
+cindex(sockets, Unix domain)
+item(tt(zsocket) [ tt(-adltv) ] [ var(args) ])(
+tt(zsocket) is implemented as a builtin to allow full use of shell
+command line editing, file I/O, and job control mechanisms.
+
+subsect(Outbound Connections)
+cindex(sockets, outbound Unix domain)
+
+startitem()
+item(tt(zsocket) [ tt(-v) ] [ tt(-d) var(fd) ] var(filename))(
+Open a new Unix domain connection to var(filename).
+The shell parameter tt(REPLY) will be set to the file descriptor
+associated with that connection. Currently, only stream connections
+are supported.
+
+If tt(-d) is specified, the first non-option argument
+will be taken as the target file descriptor for the
+connection.
+
+In order to elicit more verbose output, use tt(-v).
+)
+enditem()
+
+subsect(Inbound Connections)
+cindex(sockets, inbound Unix domain)
+
+startitem()
+item(tt(zsocket) tt(-l) [ tt(-v) ] [ tt(-d) var(fd) ] var(filename))(
+tt(zsocket -l) will open a socket listening on var(filename).
+The shell parameter tt(REPLY) will be set to the file descriptor
+associated with that listener.
+
+If tt(-d) is specified, the first non-option argument
+will be taken as the target file descriptor for
+the connection.
+
+In order to elicit more verbose output, use tt(-v).
+)
+item(tt(zsocket) tt(-a) [ tt(-tv) ] [ tt(-d) var(targetfd) ] var(listenfd))(
+tt(zsocket -a) will accept an incoming connection
+to the socket associated with var(listenfd).
+The shell parameter tt(REPLY) will
+be set to the file descriptor associated with
+the inbound connection.
+
+If tt(-d) is specified, the first non-option argument
+will be taken as the target file descriptor for the
+connection.
+
+If tt(-t) is specified, tt(zsocket) will return
+if no incoming connection is pending. Otherwise
+it will wait for one.
+
+In order to elicit more verbose output, use tt(-v).
+)
+enditem()
Messages sorted by:
Reverse Date,
Date,
Thread,
Author