Rework how sam handles remote control sockets. - sam - An updated version of th… | |
git clone git://vernunftzentrum.de/sam.git | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 8af7e5c04a842c0109e309b2a04c9140b7e3e9ac | |
parent 352fe7ddbeafce2db71b014625565a59b15c53c0 | |
Author: Rob King <[email protected]> | |
Date: Wed, 4 Jan 2017 17:32:49 -0600 | |
Rework how sam handles remote control sockets. | |
Originally, sam used a complex and buggy method for remote control, | |
requiring in-band messages and round-trips between the remote machine | |
and the terminal to accomplish anything. | |
Now, we take advantage of ssh(1)'s ability (present since 2014) to | |
forward UNIX domain sockets. The remote control mechanism has replaced | |
a FIFO with a UNIX domain socket. This simplifies the code in various places. | |
Diffstat: | |
Makefile | 7 +------ | |
README.rst | 4 ++-- | |
doc/B | 43 ------------------------------ | |
doc/Makefile | 4 +--- | |
doc/sam.1 | 103 +++++++++++++------------------ | |
include/libg.h | 2 +- | |
libXg/xtbinit.c | 15 +++++++++++++-- | |
rsam/Makefile | 16 ---------------- | |
rsam/rsam.c | 122 ------------------------------- | |
sam/Makefile | 9 +-------- | |
sam/io.c | 131 ++++++++++++++++++++++++------- | |
sam/mesg.c | 1 - | |
sam/mesg.h | 1 - | |
sam/sam.c | 122 ++++++++++++++++++++++++++----- | |
sam/sam.h | 4 ++-- | |
samterm/io.c | 7 +++++-- | |
samterm/main.c | 21 +++++++++++++++------ | |
samterm/mesg.c | 10 ---------- | |
samterm/samterm.h | 1 - | |
samterm/unix.c | 62 ++----------------------------- | |
20 files changed, 291 insertions(+), 394 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -6,7 +6,7 @@ | |
MODE?=user | |
-all: config.mk lXg lframe rsamdir samdir samtermdir docdir | |
+all: config.mk lXg lframe samdir samtermdir docdir | |
config.mk: | |
cp config.mk.def config.mk | |
@@ -20,9 +20,6 @@ lframe: | |
docdir: | |
cd doc; $(MAKE) | |
-rsamdir: | |
- cd rsam; $(MAKE) | |
- | |
samdir: | |
cd sam; $(MAKE) | |
@@ -36,14 +33,12 @@ install: | |
cd sam; $(MAKE) install | |
cd samterm; $(MAKE) install | |
cd doc; $(MAKE) install | |
- cd rsam; $(MAKE) install | |
clean: | |
cd libXg; $(MAKE) clean | |
cd libframe; $(MAKE) clean | |
cd sam; $(MAKE) clean | |
cd samterm; $(MAKE) clean | |
- cd rsam; $(MAKE) clean | |
nuke: clean | |
rm -f config.mk | |
diff --git a/README.rst b/README.rst | |
@@ -75,7 +75,7 @@ Both the `sam` and `B` commands accept an '-r' argument, | |
naming a remote machine or | |
(assuming you're using `ssh(1)`, | |
an SSH host entry). | |
-The remote machine needs to have both `sam` and `rsam` installed. | |
+The remote machine only needs to have the `sam` binary. | |
The remote machine may also have the `B` command installed. | |
If it is installed, | |
@@ -88,7 +88,7 @@ If you're using `ssh(1)` to run sam remotely, be sure to pass… | |
Installation Paths | |
------------------- | |
-By default, `sam`, `rsam`, `samterm`, and `B` all end up in '$(BINDIR)' as def… | |
+By default, `sam`, `samterm`, and `B` all end up in '$(BINDIR)' as defined in … | |
Compatibility | |
------------- | |
diff --git a/doc/B b/doc/B | |
@@ -1,43 +0,0 @@ | |
-#!/bin/sh | |
- | |
-if [ $# = 0 ] ; then | |
- echo "usage: B [-r machine] files..." 1>&2 | |
- exit 1 | |
-fi | |
- | |
-machine=localhost | |
-if [ $1 = "-r" ] ; then | |
- shift | |
- machine=$1 | |
- shift | |
- | |
- if [ "$machine" = "" ] ; then | |
- echo "usage: B [-r machine] files..." 1>&2 | |
- exit 1 | |
- fi | |
- echo "machine = $machine" | |
-fi | |
- | |
-pipe="${HOME}/.sam.${machine}" | |
-dir=`pwd` | |
-files= | |
-for i in $* | |
-do | |
- case "$i" in | |
- /*) files="$files $i" | |
- ;; | |
- *) files="$files $dir/$i" | |
- ;; | |
- esac | |
-done | |
- | |
-if [ ! -w "$pipe" ] ; then | |
- pipe="${HOME}/.sam.fifo" # created by rsam | |
-fi | |
- | |
-if [ ! -w "$pipe" ]; then | |
- sam $files & # start sam if it's not already running | |
-else | |
- echo "B $files" >> $pipe | |
-fi | |
- | |
diff --git a/doc/Makefile b/doc/Makefile | |
@@ -4,7 +4,7 @@ include ../config.mk | |
all: | |
-install: sam.1 B | |
+install: sam.1 | |
mkdir -p "$(MANDIR)/man1" | |
cp sam.1 "$(MANDIR)/man1" | |
ln -sf "$(MANDIR)/man1/sam.1" "$(MANDIR)/man1/B.1" | |
@@ -14,5 +14,3 @@ install: sam.1 B | |
mkdir -p "$(MANDIR)/man5" | |
cp keyboard.5 "$(MANDIR)/man5" | |
cp samrc.5 "$(MANDIR)/man5" | |
- mkdir -p "$(BINDIR)" | |
- cp B "$(BINDIR)" | |
diff --git a/doc/sam.1 b/doc/sam.1 | |
@@ -7,8 +7,6 @@ | |
.Sh SYNOPSIS | |
.Nm | |
.Op Fl d | |
-.Op Fl e | |
-.Op Fl f | |
.Op Fl t Ar terminal | |
.Ar | |
.Nm | |
@@ -40,24 +38,6 @@ Do not download the terminal part of | |
.Nm "." | |
Editing will be done with the command language only, as in | |
.Xr ed 1 "." | |
-.It Fl e | |
-Expand tabs to spaces during editing. | |
-Literal tabs may still be inserted using the character composition functionali… | |
-.Sx "Composed Text Input" "," | |
-or by holding Control while pressing the Tab key. | |
-.It Fl f | |
-Do not create or take ownership of the external command FIFO | |
-.Po | |
-see | |
-.Sx "Controlling running instances of sam" | |
-.Pc "." | |
-The | |
-.Nm B | |
-command will not communicate with this instance of | |
-.Nm sam "." | |
-This flag is useful for running | |
-.Dq "one-off" | |
-instances of sam. | |
.It Fl r Ar machine | |
Run the host part remotely on the specified machine, the terminal part locally… | |
commands to be sent to an instance of | |
@@ -66,13 +46,6 @@ associated with | |
.Ar machine "." | |
.It Fl s Ar file | |
Start the host part from the indicated file on the remote host. | |
-By default, this is | |
-.Pa rsam "," | |
-which is a program that interposes itself between the host and terminal parts … | |
-.Nm | |
-and allows | |
-.Nm | |
-to be controlled via commands on the remote system. | |
.It Fl t Ar file | |
Start the terminal part from the indicated file. | |
Useful for debugging. | |
@@ -918,25 +891,11 @@ option, which is used to specify a remote machine name su… | |
.Ev RSH | |
environment variable. | |
.Pp | |
-By default, | |
+The only component of | |
.Nm sam | |
-will run a command called | |
-.Nm rsam | |
-as the host-part on the remote machine. | |
-.Nm rsam | |
-opens up an additional control channel on the remote machine, allowing | |
-.Nm sam | |
-to be controlled via the | |
-.Nm B | |
-command on the remote machine as well. | |
-.Pp | |
-The only components of | |
-.Nm sam | |
-that need to be on the remote machine are | |
-.Nm rsam | |
-and | |
+that needs to be on the remote machine is | |
.Nm sam "," | |
-and any command specified as the argument to the | |
+or whatever command specified as the argument to the | |
.Fl s | |
option. | |
Users may also like to have the | |
@@ -946,7 +905,7 @@ command present on the remote system; invoking this command… | |
if | |
.Nm sam | |
was invoked with its default remote host command, i.e. | |
-.Nm rsam | |
+.Nm sam | |
.Pc | |
open files in the local terminal. | |
This allows users to run the terminal part of | |
@@ -967,14 +926,6 @@ to load the named files; the default is the most-recently … | |
.Pp | |
.Nm B | |
may also be called on a remote machine, causing the downloaded instance of sam… | |
-.Pp | |
-Note that | |
-.Nm B | |
-will only communicate with the most-recently-run instance of | |
-.Nm sam "," | |
-but see the | |
-.Fl f | |
-option above. | |
.Ss Composed Text Input | |
.Nm sam | |
allows the input of arbitrary Unicode characters from the Basic Multilingual P… | |
@@ -1071,11 +1022,29 @@ The name of a command to be used to connect to a remote… | |
is invoked with the | |
.Fl r | |
option. | |
-It will be passed at least two arguments: the name of the machine to connect t… | |
+It will be passed arguments of the form: | |
+.Bd -literal | |
+ | |
+ -R REMOTE:LOCAL MACHINE COMMAND | |
+ | |
+.Ed | |
+where | |
+.Em REMOTE | |
+is the name of the remote UNIX domain socket for remote control, | |
+.Em LOCAL | |
+is the name of the local UNIX domain socket for remote control, | |
+.Em MACHINE | |
+is the hostname to connect to, and | |
+.Em COMMAND | |
+is the command | |
.Po | |
e.g. | |
-.Nm rsam | |
-.Pc "." | |
+.Nm sam | |
+.Pc | |
+to execute on that machine. | |
+.Pp | |
+Note that this works out-of-the-box with recent versions of | |
+.Xr ssh 1 "." | |
Any additional arguments should be passed to the command on the remote machine. | |
By default, this is the string | |
.Dq "ssh" "." | |
@@ -1087,6 +1056,23 @@ file to read at startup. | |
By default, | |
this is | |
.Pa ${HOME}/.samrc "." | |
+.It Ev SAMSOCKETPATH | |
+Names a directory in which | |
+.Nm | |
+remote control sockets should be placed. | |
+By default, the contents of | |
+.Ev HOME | |
+are used. | |
+.It Ev SAMSOCKETNAME | |
+Gives a full path name for a | |
+.Nm | |
+remote control socket; this will be used in preference to any file in the | |
+.Ev SAMSOCKETPATH | |
+directory. | |
+.It Ev RSAMSOCKETPATH | |
+Names a directory in which | |
+.Nm | |
+remote control sockets should be placed on remote systems. | |
.It Ev TABS | |
A number between 1 and 12, indicating the width of a tab character. | |
This number is treated as a multiplier of the width of the '0' character. | |
@@ -1095,11 +1081,6 @@ The default is 8. | |
If the number specified for | |
.Ev TABS | |
is negative, the absolute value of that number is used and automatic tab expan… | |
-.Po | |
-as for the | |
-.Fl e | |
-flag | |
-.Pc | |
is enabled. | |
Tab behavior can also be controlled using the | |
.Em tabs | |
diff --git a/include/libg.h b/include/libg.h | |
@@ -197,7 +197,7 @@ extern int scrpix(int*,int*); | |
extern uint64_t getbg(void); | |
extern void einit(uint64_t); | |
-extern uint64_t estart(uint64_t, int, int); | |
+extern uint64_t estart(uint64_t, int, size_t, bool); | |
extern uint64_t event(Event*); | |
extern uint64_t eread(uint64_t, Event*); | |
diff --git a/libXg/xtbinit.c b/libXg/xtbinit.c | |
@@ -4,6 +4,8 @@ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
+#include <sys/types.h> | |
+#include <sys/socket.h> | |
#include "libgint.h" | |
#define Font xFont | |
@@ -74,6 +76,7 @@ typedef struct Ebuf { | |
} Ebuf; | |
typedef struct Esrc { | |
+ bool issocket; | |
bool inuse; | |
int size; | |
int count; | |
@@ -387,7 +390,14 @@ gotinput(XtPointer cldata, int *pfd, XtInputId *id) | |
if (eb == 0) | |
return; | |
if(es->size){ | |
- n = read(*pfd, (char *)eb->buf, es->size); | |
+ if (es->issocket){ | |
+ struct sockaddr addr; | |
+ socklen_t len; | |
+ int fd = accept(*pfd, &addr, &len); | |
+ n = read(fd, (char *)eb->buf, es->size); | |
+ close(fd); | |
+ } else | |
+ n = read(*pfd, (char *)eb->buf, es->size); | |
if (n < 0) | |
n = 0; | |
if(n < es->size) { | |
@@ -519,7 +529,7 @@ einit(uint64_t keys) | |
} | |
uint64_t | |
-estart(uint64_t key, int fd, int n) | |
+estart(uint64_t key, int fd, size_t n, bool issocket) | |
{ | |
int i; | |
@@ -532,6 +542,7 @@ estart(uint64_t key, int fd, int n) | |
if(nsrc <= i) | |
nsrc = i+1; | |
esrc[i].inuse = true; | |
+ esrc[i].issocket = issocket; | |
esrc[i].size = n; | |
esrc[i].count = 0; | |
XtAppAddInput(app, fd, (XtPointer)XtInputReadMask, | |
diff --git a/rsam/Makefile b/rsam/Makefile | |
@@ -1,16 +0,0 @@ | |
-# Copyright (C) 2013-2015 Rob King <[email protected]> | |
-# This file may be redistributed and modified for any purpose. | |
-# No warranty is expressed or implied; use at your own risk. | |
- | |
-include ../config.mk | |
- | |
-all: rsam | |
- | |
-rsam: rsam.o | |
- $(CC) -o rsam rsam.o $(LDFLAGS) | |
- | |
-clean: | |
- rm -f *.o rsam | |
- | |
-install: rsam | |
- cp rsam $(BINDIR) | |
diff --git a/rsam/rsam.c b/rsam/rsam.c | |
@@ -1,122 +0,0 @@ | |
-/* Copyright 2013-2015 Rob King <[email protected]> | |
- * This file may be freely redistributed in source or binary form with or with… | |
- * No warranty is expressed or implied; use at your own risk. | |
- */ | |
- | |
-#define _POSIX_C_SOURCE 200809L | |
-#include <fcntl.h> | |
-#include <limits.h> | |
-#include <pwd.h> | |
-#include <stdio.h> | |
-#include <stdlib.h> | |
-#include <string.h> | |
-#include <sys/select.h> | |
-#include <sys/stat.h> | |
-#include <sys/types.h> | |
-#include <unistd.h> | |
- | |
-#define PARENT_READ readpipe[0] | |
-#define CHILD_WRITE readpipe[1] | |
-#define CHILD_READ writepipe[0] | |
-#define PARENT_WRITE writepipe[1] | |
-#define MAX(x, y) ((x) > (y) ? (x) : (y)) | |
-#define CHECKEDWRITE(f, b, c) if (write(f, b, c) != c) exit(EXIT_FAILURE) | |
- | |
-char path[PATH_MAX + 1]; | |
- | |
-void | |
-cleanup(void) | |
-{ | |
- unlink(path); | |
-} | |
- | |
-int | |
-main(int argc, char **argv) | |
-{ | |
- int fifo = -1; | |
- int nfd = 0; | |
- int writepipe[2] = {-1}; | |
- int readpipe[2] = {-1}; | |
- struct passwd *pwent = NULL; | |
- pid_t child = -1; | |
- fd_set rfds; | |
- | |
- pwent = getpwuid(getuid()); | |
- if (!pwent || !pwent->pw_dir || !pwent->pw_dir[0]) | |
- return perror("pwent"), EXIT_FAILURE; | |
- | |
- strncpy(path, pwent->pw_dir, PATH_MAX); | |
- strncat(path, "/.sam.fifo", PATH_MAX); | |
- | |
- if (pipe(writepipe) != 0 || pipe(readpipe) != 0) | |
- return perror("pipe"), EXIT_FAILURE; | |
- | |
- unlink(path); | |
- if (mkfifo(path, 0600) != 0) | |
- return perror("mkfifo"), EXIT_FAILURE; | |
- | |
- atexit(cleanup); | |
- | |
- fifo = open(path, O_RDWR); | |
- if (fifo < 0) | |
- return perror("open"), EXIT_FAILURE; | |
- | |
- child = fork(); | |
- if (child == 0){ | |
- close(PARENT_WRITE); | |
- close(PARENT_READ); | |
- | |
- dup2(CHILD_READ, STDIN_FILENO); close(CHILD_READ); | |
- dup2(CHILD_WRITE, STDOUT_FILENO); close(CHILD_WRITE); | |
- | |
- execlp("sam", "sam", "-R", NULL); | |
- return EXIT_FAILURE; | |
- } else if (child < 0){ | |
- perror("fork"); | |
- return EXIT_FAILURE; | |
- } | |
- | |
- close(CHILD_READ); | |
- close(CHILD_WRITE); | |
- | |
- FD_ZERO(&rfds); | |
- FD_SET(STDIN_FILENO, &rfds); | |
- FD_SET(fifo, &rfds); | |
- FD_SET(PARENT_READ, &rfds); | |
- | |
- nfd = MAX(STDIN_FILENO, MAX(PARENT_READ, fifo)) + 1; | |
- while (select(nfd, &rfds, NULL, NULL, NULL) >= 0){ | |
- ssize_t count = 0; | |
- char buf[8192]; | |
- | |
- if (FD_ISSET(STDIN_FILENO, &rfds)){ | |
- count = read(STDIN_FILENO, buf, 8192); | |
- if (count <= 0) | |
- exit(EXIT_SUCCESS); | |
- CHECKEDWRITE(PARENT_WRITE, buf, count); | |
- } | |
- | |
- if (FD_ISSET(fifo, &rfds)){ | |
- memset(buf, 0, 256); | |
- count = read(fifo, buf, 253); | |
- if (count <= 0) | |
- exit(EXIT_SUCCESS); | |
- CHECKEDWRITE(STDOUT_FILENO, "\x19\xff\x00", 3); | |
- CHECKEDWRITE(STDOUT_FILENO, buf, 255); | |
- } | |
- | |
- if (FD_ISSET(PARENT_READ, &rfds)){ | |
- count = read(PARENT_READ, buf, 8192); | |
- if (count <= 0) | |
- exit(EXIT_SUCCESS); | |
- CHECKEDWRITE(STDOUT_FILENO, buf, count); | |
- } | |
- | |
- FD_ZERO(&rfds); | |
- FD_SET(STDIN_FILENO, &rfds); | |
- FD_SET(fifo, &rfds); | |
- FD_SET(PARENT_READ, &rfds); | |
- } | |
- | |
- return EXIT_SUCCESS; | |
-} | |
diff --git a/sam/Makefile b/sam/Makefile | |
@@ -20,14 +20,6 @@ SAMDIR=$(BINDIR) | |
SHELLNAME=sh | |
SHELLPATH=/bin/sh | |
-# Set RXNAME and RXPATHNAME to the name of the remote execution command | |
-# and the pathname of its executable | |
-RXNAME=ssh | |
-RXPATHNAME=/usr/bin/ssh | |
- | |
-# Set RXSAMNAME to the name of the command to run on the remote host. | |
-RXSAMNAME=rsam | |
- | |
CFLAGS=$(STANDARDS) $(INCS) $(INCLUDES) -DRXPATH='"$(RXPATH)"' | |
CC?=c99 | |
@@ -50,6 +42,7 @@ nuke: clean | |
install: sam | |
mkdir -p $(SAMDIR) | |
cp sam $(SAMDIR)/$(RSAMNAME) | |
+ ln -f $(SAMDIR)/$(RSAMNAME) $(SAMDIR)/B | |
$(OBJ): sam.h ../include/u.h errors.h mesg.h | |
diff --git a/sam/io.c b/sam/io.c | |
@@ -1,4 +1,10 @@ | |
/* Copyright (c) 1998 Lucent Technologies - All rights reserved. */ | |
+#include <sys/types.h> | |
+#include <sys/stat.h> | |
+#include <sys/socket.h> | |
+#include <sys/un.h> | |
+#include <fcntl.h> | |
+ | |
#include "sam.h" | |
#define NSYSFILE 3 | |
@@ -151,45 +157,57 @@ closeio(Posn p) | |
dprint(L"#%lu\n", p); | |
} | |
+char exname[PATH_MAX + 1]; | |
int remotefd0 = 0; | |
int remotefd1 = 1; | |
+int exfd = -1; | |
void | |
-bootterm(char *machine, char **argv, char **end) | |
+bootterm(char *machine) | |
{ | |
+ char fd[100]; | |
int ph2t[2], pt2h[2]; | |
- if(machine){ | |
+ snprintf(fd, sizeof(fd) - 1, "%d", exfd); | |
+ | |
+ if (machine){ | |
dup2(remotefd0, 0); | |
dup2(remotefd1, 1); | |
close(remotefd0); | |
close(remotefd1); | |
- argv[0] = "samterm"; | |
- *end = 0; | |
- execvp(samterm, argv); | |
- fprintf(stderr, "can't exec: "); | |
- perror(samterm); | |
+ if (exfd >= 0) | |
+ execlp(samterm, samterm, "-r", machine, "-f", fd, "-n", exname, NU… | |
+ else | |
+ execlp(samterm, samterm, "-r", machine, NULL); | |
+ perror("couldn't exec samterm"); | |
exit(EXIT_FAILURE); | |
} | |
- if(pipe(ph2t)==-1 || pipe(pt2h)==-1) | |
+ | |
+ if (pipe(ph2t)==-1 || pipe(pt2h)==-1) | |
panic("pipe"); | |
- switch(fork()){ | |
- case 0: | |
- dup2(ph2t[0], 0); | |
- dup2(pt2h[1], 1); | |
- close(ph2t[0]); | |
- close(ph2t[1]); | |
- close(pt2h[0]); | |
- close(pt2h[1]); | |
- argv[0] = "samterm"; | |
- *end = 0; | |
- execvp(samterm, argv); | |
- fprintf(stderr, "can't exec: "); | |
- perror(samterm); | |
- exit(EXIT_FAILURE); | |
- case -1: | |
- panic("can't fork samterm"); | |
+ | |
+ machine = machine? machine : "localhost"; | |
+ switch (fork()){ | |
+ case 0: | |
+ dup2(ph2t[0], 0); | |
+ dup2(pt2h[1], 1); | |
+ close(ph2t[0]); | |
+ close(ph2t[1]); | |
+ close(pt2h[0]); | |
+ close(pt2h[1]); | |
+ if (exfd >= 0) | |
+ execlp(samterm, samterm, "-r", machine, "-f", fd, "-n", exname… | |
+ else | |
+ execlp(samterm, samterm, "-r", machine, NULL); | |
+ perror("couldn't exec samterm"); | |
+ exit(EXIT_FAILURE); | |
+ break; | |
+ | |
+ case -1: | |
+ panic("can't fork samterm"); | |
+ break; | |
} | |
+ | |
dup2(pt2h[0], 0); | |
dup2(ph2t[1], 1); | |
close(ph2t[0]); | |
@@ -202,6 +220,14 @@ void | |
connectto(char *machine) | |
{ | |
int p1[2], p2[2]; | |
+ char sockname[FILENAME_MAX + 1] = {0}; | |
+ char rarg[FILENAME_MAX + 1] = {0}; | |
+ | |
+ snprintf(sockname, FILENAME_MAX, "%s/sam.remote.%s", | |
+ getenv("RSAMSOCKETPATH")? getenv("RSAMSOCKETPATH") : "/tmp", | |
+ getenv("USER")? getenv("USER") : getenv("LOGNAME")? getenv("LOGNA… | |
+ | |
+ snprintf(rarg, FILENAME_MAX, "%s:%s", sockname, exname); | |
if(pipe(p1)<0 || pipe(p2)<0){ | |
dprint(L"can't pipe\n"); | |
@@ -217,7 +243,11 @@ connectto(char *machine) | |
close(p1[1]); | |
close(p2[0]); | |
close(p2[1]); | |
- execlp(getenv("RSH") ? getenv("RSH") : RXPATH, getenv("RSH") ? getenv(… | |
+ execlp(getenv("RSH") ? getenv("RSH") : RXPATH, | |
+ getenv("RSH") ? getenv("RSH") : RXPATH, | |
+ "-R", rarg, | |
+ machine, rsamname, "-R", sockname, | |
+ NULL); | |
dprint(L"can't exec %s\n", RXPATH); | |
exit(EXIT_FAILURE); | |
@@ -230,12 +260,55 @@ connectto(char *machine) | |
} | |
void | |
-startup(char *machine, int Rflag, char **arg, char **end) | |
+removesocket(void) | |
+{ | |
+ close(exfd); | |
+ unlink(exname); | |
+ exname[0] = 0; | |
+} | |
+ | |
+void | |
+opensocket(const char *machine) | |
+{ | |
+ struct sockaddr_un un = {0}; | |
+ const char *path = getenv("SAMSOCKPATH")? getenv("SAMSOCKPATH") : getenv("… | |
+ | |
+ if (!path){ | |
+ fputs("could not determine command socket path\n", stderr); | |
+ return; | |
+ } | |
+ | |
+ snprintf(exname, PATH_MAX, "%s/.sam.%s", path, machine? machine : "localho… | |
+ if (strlen(exname) >= sizeof(un.sun_path) - 1){ | |
+ fputs("command socket path too long\n", stderr); | |
+ return; | |
+ } | |
+ | |
+ un.sun_family = AF_UNIX; | |
+ strncpy(un.sun_path, exname, sizeof(un.sun_path) - 1); | |
+ if ((exfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 | |
+ || bind(exfd, (struct sockaddr *)&un, sizeof(un)) < 0 | |
+ || listen(exfd, 10) < 0){ | |
+ perror("could not open command socket"); | |
+ exfd = -1; | |
+ return; | |
+ } | |
+ | |
+ atexit(removesocket); | |
+} | |
+ | |
+void | |
+startup(char *machine, bool rflag) | |
{ | |
- if(machine) | |
+ if (!rflag) | |
+ opensocket(machine); | |
+ | |
+ if (machine) | |
connectto(machine); | |
- if(!Rflag) | |
- bootterm(machine, arg, end); | |
+ | |
+ if (!rflag) | |
+ bootterm(machine); | |
+ | |
downloaded = true; | |
outTs(Hversion, VERSION); | |
} | |
diff --git a/sam/mesg.c b/sam/mesg.c | |
@@ -45,7 +45,6 @@ char *hname[] = { | |
[Hsetsnarf] = "Hsetsnarf", | |
[Hsnarflen] = "Hsnarflen", | |
[Hack] = "Hack", | |
- [Hextcmd] = "Hextcmd", | |
[Hexit] = "Hexit", | |
}; | |
diff --git a/sam/mesg.h b/sam/mesg.h | |
@@ -65,7 +65,6 @@ typedef enum Hmesg | |
Hsnarflen, /* report length of implicit snarf */ | |
Hack, /* request acknowledgement */ | |
Hexit, | |
- Hextcmd, /* execute a external command */ | |
HMAX | |
}Hmesg; | |
typedef struct Header{ | |
diff --git a/sam/sam.c b/sam/sam.c | |
@@ -4,6 +4,9 @@ | |
#include <libgen.h> | |
#include <signal.h> | |
#include <stdbool.h> | |
+#include <sys/types.h> | |
+#include <sys/socket.h> | |
+#include <sys/un.h> | |
#include <unistd.h> | |
wchar_t genbuf[BLOCKSIZE]; | |
@@ -26,15 +29,15 @@ bool quitok = true; | |
bool downloaded; | |
bool expandtabs; | |
bool dflag; | |
-bool Rflag; | |
char *machine; | |
char *home; | |
bool bpipeok; | |
int termlocked; | |
char *samterm = "samterm"; | |
-char *rsamname = "rsam"; | |
+char *rsamname = "sam"; | |
char *sh = "sh"; | |
char *shpath = "/bin/sh"; | |
+char *rmsocketname = NULL; | |
wchar_t baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; | |
@@ -47,41 +50,121 @@ hup(int sig) | |
exit(EXIT_FAILURE); | |
} | |
+int sammain(int argc, char *argv[]); | |
+int bmain(int argc, char *argv[]); | |
+ | |
int | |
main(int argc, char *argv[]) | |
{ | |
+ if (strcmp(basename(argv[0]), "B") == 0) | |
+ return bmain(argc, argv); | |
+ return sammain(argc, argv); | |
+} | |
+ | |
+#define B_CMD_MAX 4095 | |
+const char * | |
+getbsocketname(const char *machine) | |
+{ | |
+ const char *user = getenv("USER")? getenv("USER") : getenv("LOGNAME")? get… | |
+ const char *path = getenv("SAMSOCKETPATH")? getenv("SAMSOCKETPATH") : gete… | |
+ static char name[FILENAME_MAX + 1] = {0}; | |
+ | |
+ if (getenv("SAMSOCKETNAME")) | |
+ return getenv("SAMSOCKETNAME"); | |
+ | |
+ if (name[0]) | |
+ return name; | |
+ | |
+ snprintf(name, FILENAME_MAX, "%s/.sam.%s", path, machine); | |
+ if (access(name, R_OK) == 0) | |
+ return name; | |
+ | |
+ snprintf(name, FILENAME_MAX, "%s/.sam.remote.%s", path, user); | |
+ if (access(name, R_OK) == 0) | |
+ return name; | |
+ | |
+ snprintf(name, FILENAME_MAX, "/tmp/sam.remote.%s", user); | |
+ if (access(name, R_OK) == 0) | |
+ return name; | |
+ | |
+ return NULL; | |
+} | |
+ | |
+int | |
+bmain(int argc, char *argv[]) | |
+{ | |
+ int fd, o; | |
+ struct sockaddr_un un = {0}; | |
+ char cmd[B_CMD_MAX] = {0}; | |
+ | |
+ machine = "localhost"; | |
+ while ((o = getopt(argc, argv, "r:")) != -1){ | |
+ switch (o){ | |
+ case 'r': | |
+ machine = optarg; | |
+ break; | |
+ | |
+ default: | |
+ return fputs("usage: B [-r MACHINE] FILE...\n", stderr), EXIT_… | |
+ } | |
+ } | |
+ argc -= optind; | |
+ argv += optind; | |
+ | |
+ if (getbsocketname(machine) == NULL) | |
+ return fputs("could not determine controlling socket name\n", stderr),… | |
+ | |
+ memset(&un, 0, sizeof(un)); | |
+ un.sun_family = AF_UNIX; | |
+ strncpy(un.sun_path, getbsocketname(machine), sizeof(un.sun_path) - 1); | |
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 || connect(fd, (struct sock… | |
+ return perror("could not open socket"), EXIT_FAILURE; | |
+ | |
+ strncat(cmd, "B ", B_CMD_MAX); | |
+ for (int i = 0; i < argc; i++){ | |
+ strncat(cmd, " ", B_CMD_MAX); | |
+ strncat(cmd, argv[i], B_CMD_MAX); | |
+ } | |
+ strncat(cmd, "\n", B_CMD_MAX); | |
+ | |
+ if (write(fd, cmd, strlen(cmd)) <= 0) | |
+ return perror("could not send command"), EXIT_FAILURE; | |
+ | |
+ close(fd); | |
+ return EXIT_SUCCESS; | |
+} | |
+ | |
+void | |
+rmsocket(void) | |
+{ | |
+ if (rmsocketname) | |
+ unlink(rmsocketname); | |
+} | |
+ | |
+int | |
+sammain(int argc, char *argv[]) | |
+{ | |
int i, o; | |
String *t; | |
char *arg[argc + 1], **ap; | |
- int targc = 1; | |
ap = &arg[argc]; | |
arg[0] = "samterm"; | |
setlocale(LC_ALL, ""); | |
- while ((o = getopt(argc, argv, "efdRr:t:s:")) != -1){ | |
+ while ((o = getopt(argc, argv, "edR:r:t:s:")) != -1){ | |
switch (o){ | |
- case 'e': | |
- arg[targc++] = "-e"; | |
- break; | |
- | |
- case 'f': | |
- arg[targc++] = "-f"; | |
- break; | |
- | |
case 'd': | |
dflag = true; | |
break; | |
case 'r': | |
machine = optarg; | |
- rsamname = "rsam"; | |
- arg[targc++] = "-r"; | |
- arg[targc++] = optarg; | |
break; | |
case 'R': | |
- Rflag = true; | |
+ rmsocketname = optarg; | |
+ atexit(rmsocket); | |
break; | |
case 't': | |
@@ -98,7 +181,6 @@ main(int argc, char *argv[]) | |
} | |
argv += optind; | |
argc -= optind; | |
- arg[targc] = NULL; | |
Strinit(&cmdstr); | |
Strinit0(&lastpat); | |
@@ -113,7 +195,7 @@ main(int argc, char *argv[]) | |
shpath = getenv("SHELL") ? getenv("SHELL") : shpath; | |
sh = basename(shpath); | |
if(!dflag) | |
- startup(machine, Rflag, arg, ap); | |
+ startup(machine, rmsocketname != NULL); | |
Fstart(); | |
signal(SIGINT, SIG_IGN); | |
@@ -135,7 +217,7 @@ main(int argc, char *argv[]) | |
if(file.nused) | |
current(file.filepptr[0]); | |
- atexit(shutdown); | |
+ atexit(scram); | |
setjmp(mainloop); | |
cmdloop(); | |
@@ -145,7 +227,7 @@ main(int argc, char *argv[]) | |
} | |
void | |
-shutdown(void) | |
+scram(void) | |
{ | |
freecmd(); | |
for (int i = 0; i < file.nused; i++) | |
diff --git a/sam/sam.h b/sam/sam.h | |
@@ -240,11 +240,11 @@ void resetxec(void); | |
void rgrow(List*, Posn, Posn); | |
void samerr(char*); | |
void settempfile(void); | |
-void shutdown(void); | |
+void scram(void); | |
int skipbl(void); | |
void snarf(File*, Posn, Posn, Buffer*, bool); | |
void sortname(File*); | |
-void startup(char*, int, char**, char**); | |
+void startup(char*, bool); | |
void state(File*, state_t); | |
int statfd(int, uint64_t*, uint64_t*, int64_t*, int64_t*, int64_t*); | |
int statfile(char*, uint64_t*, uint64_t*, int64_t*, int64_t*, int64_t*); | |
diff --git a/samterm/io.c b/samterm/io.c | |
@@ -20,9 +20,12 @@ void panic(char*); | |
void | |
initio(void){ | |
+ extern int exfd; | |
+ | |
einit(Emouse|Ekeyboard); | |
- estart(Ehost, 0, 0); | |
- extstart(); | |
+ estart(Ehost, 0, 0, false); | |
+ if (exfd >= 0) | |
+ estart(Eextern, exfd, 8192, true); | |
} | |
void | |
diff --git a/samterm/main.c b/samterm/main.c | |
@@ -28,7 +28,15 @@ char lock = 1; | |
bool hasunlocked = false; | |
bool expandtabs = false; | |
char *machine = "localhost"; | |
-int nofifo = 0; | |
+int exfd = -1; | |
+const char *exname; | |
+ | |
+void | |
+removeext(void) | |
+{ | |
+ if (exname) | |
+ unlink(exname); | |
+} | |
int | |
main(int argc, char *argv[]) | |
@@ -49,18 +57,19 @@ main(int argc, char *argv[]) | |
else | |
snprintf(rcpath, PATH_MAX, "%s/.samrc", getenv("HOME") ? getenv("HOME"… | |
- while ((opt = getopt(argc, argv, "efr:")) != -1){ | |
+ while ((opt = getopt(argc, argv, "ef:n:r:")) != -1){ | |
switch (opt){ | |
case 'r': | |
machine = optarg; | |
break; | |
- case 'e': | |
- expandtabs = 1; | |
+ case 'f': | |
+ exfd = atoi(optarg); | |
break; | |
- case 'f': | |
- nofifo = 1; | |
+ case 'n': | |
+ exname = optarg; | |
+ atexit(removeext); | |
break; | |
} | |
} | |
diff --git a/samterm/mesg.c b/samterm/mesg.c | |
@@ -293,16 +293,6 @@ inmesg(Hmesg type, int count) | |
outT0(Tack); | |
break; | |
- case Hextcmd: | |
- if (exname[0]){ | |
- int fifofd = open(exname, O_WRONLY); | |
- if (fifofd >= 0){ | |
- dprintf(fifofd, "%511s", (char *)indata); | |
- close(fifofd); | |
- } | |
- } | |
- break; | |
- | |
case Hexit: | |
outT0(Texit); | |
mouseexit(); | |
diff --git a/samterm/samterm.h b/samterm/samterm.h | |
@@ -108,7 +108,6 @@ void cursorset(Point); | |
void getmouse(void); | |
void mouseunblock(void); | |
void kbdblock(void); | |
-void extstart(void); | |
int button(int but); | |
int waitforio(void); | |
int rcvchar(void); | |
diff --git a/samterm/unix.c b/samterm/unix.c | |
@@ -5,19 +5,20 @@ | |
#include "flayer.h" | |
#include "samterm.h" | |
+#include <sys/socket.h> | |
#include <sys/stat.h> | |
+#include <sys/types.h> | |
+#include <sys/un.h> | |
#include <errno.h> | |
#include <signal.h> | |
-char exname[PATH_MAX + 1] = {0}; | |
+char exname[FILENAME_MAX + 1] = {0}; | |
static char *fallbacks[] = { | |
"*scrollForwardR: true", | |
"*geometry: 740x780", | |
NULL | |
}; | |
-extern int nofifo; | |
- | |
void | |
getscreen(int argc, char **argv) | |
{ | |
@@ -54,58 +55,3 @@ dumperrmsg(int count, int type, int count0, int c) | |
cp++; | |
} | |
} | |
- | |
-void | |
-removeextern(void) | |
-{ | |
- unlink(exname); | |
- exname[0] = 0; | |
-} | |
- | |
-void | |
-extstart(void) | |
-{ | |
- extern char *machine; | |
- int fd; | |
- int flags; | |
- | |
- if (nofifo || !getenv("HOME")) | |
- return; | |
- | |
- snprintf(exname, PATH_MAX, "%s/.sam.%s", getenv("HOME"), machine); | |
- | |
- /* Make the named pipe. */ | |
- if (mkfifo(exname, 0600) == -1){ | |
- struct stat statb; | |
- | |
- if (errno != EEXIST || stat(exname, &statb) == -1) | |
- return; | |
- | |
- if (!S_ISFIFO(statb.st_mode)){ | |
- removeextern(); | |
- if (mkfifo(exname, 0600) == -1) | |
- return; | |
- } | |
- } | |
- | |
- fd = open(exname, O_RDONLY | O_NONBLOCK); | |
- if (fd == -1) { | |
- removeextern(); | |
- return; | |
- } | |
- | |
- /* | |
- * Turn off no-delay and provide ourselves as a lingering | |
- * writer so as not to get end of file on read. | |
- */ | |
- flags = fcntl(fd, F_GETFL, 0); | |
- if (flags == -1 || fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == -1 | |
- || open(exname, O_WRONLY) == -1){ | |
- (void)close(fd); | |
- removeextern(); | |
- return; | |
- } | |
- | |
- estart(Eextern, fd, 8192); | |
- atexit(removeextern); | |
-} |