aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--common.c53
-rw-r--r--common.h34
-rw-r--r--copier.c46
-rw-r--r--editasroot.c56
5 files changed, 117 insertions, 86 deletions
diff --git a/Makefile b/Makefile
index eff2603..74bce68 100644
--- a/Makefile
+++ b/Makefile
@@ -5,19 +5,23 @@ include $(CONFIGFILE)
OBJ =\
editasroot.o\
+ common.o\
copier.o
+HDR =\
+ common.h
+
all: editasroot copier
-$(OBJ): $(@:.o=.c)
+$(OBJ): $(HDR)
.c.o:
$(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
-editasroot: editasroot.o
- $(CC) -o $@ $@.o $(LDFLAGS)
+editasroot: editasroot.o common.o
+ $(CC) -o $@ $@.o common.o $(LDFLAGS)
-copier: copier.o
- $(CC) -o $@ $@.o $(LDFLAGS)
+copier: copier.o common.o
+ $(CC) -o $@ $@.o common.o $(LDFLAGS)
install: editasroot copier
mkdir -p -- "$(DESTDIR)$(PREFIX)/bin"
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..5379f89
--- /dev/null
+++ b/common.c
@@ -0,0 +1,53 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+void
+copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname, int *okp)
+{
+ char buf[BUFSIZ];
+ ssize_t r, w, p, ok_off;
+ size_t read_off;
+
+ if (okp) {
+ *okp = 0;
+ ok_off = 1;
+ read_off = 0;
+ } else {
+ ok_off = 0;
+ read_off = 1;
+ buf[0] = 0;
+ }
+
+ for (;;) {
+ r = read(srcfd, &buf[read_off], sizeof(buf) - read_off);
+ if (r <= 0) {
+ if (!r)
+ break;
+ fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno));
+ exit(1);
+ }
+
+ if (r == ok_off) { /* Only possible if okp != NULL */
+ *okp = 1;
+ break;
+ }
+
+ r += (ssize_t)read_off;
+ for (p = ok_off; p < r; p += w) {
+ w = write(destfd, buf, (size_t)(r - p));
+ if (r <= 0) {
+ fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ if (!okp) {
+ w = write(destfd, buf, 1);
+ if (r <= 0) {
+ fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno));
+ exit(1);
+ }
+ }
+}
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..ac73c43
--- /dev/null
+++ b/common.h
@@ -0,0 +1,34 @@
+/* See LICENSE file for copyright and license details. */
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* We need at least 2 bytes we are sending 1 addition byte in each chunk */
+#if BUFSIZ < 2
+# undef BUFSIZ
+# define BUFSIZ 2
+#endif
+
+/* We impose a limit because PF_UNIX/SOCK_SEQPACKET can block if sending
+ * too much (I don't know the exact limit and it can change), without
+ * first setting up a socket options, which is overkill for this application,
+ * and there is also a hard limit just above 210000B for each EMSGSIZE will
+ * be thrown. */
+#if BUFSIZ > (8 << 10)
+# undef BUFSIZ
+# define BUFSIZ (8 << 10)
+#endif
+
+
+extern const char *argv0;
+
+void copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname, int *okp);
diff --git a/copier.c b/copier.c
index 231e515..3e7a6c6 100644
--- a/copier.c
+++ b/copier.c
@@ -1,46 +1,14 @@
/* See LICENSE file for copyright and license details. */
-#include <sys/socket.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include "common.h"
-static const char *argv0 = "editasroot/copier";
-
-
-static void
-copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname)
-{
- char buf[BUFSIZ];
- ssize_t r, w, p;
-
- for (;;) {
- r = read(srcfd, buf, sizeof(buf));
- if (r <= 0) {
- if (!r)
- break;
- fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno));
- exit(1);
- }
-
- for (p = 0; p < r; p += w) {
- w = write(destfd, buf, (size_t)(r - p));
- if (r <= 0) {
- fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno));
- exit(1);
- }
- }
- }
-}
+const char *argv0 = "editasroot/copier";
int
main(int argc, char *argv[])
{
- int filefd, parentfd;
+ int filefd, parentfd, ok;
const char *path;
ssize_t r;
char b;
@@ -59,7 +27,7 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: open %s O_RDWR: %s\n", argv0, path, strerror(errno));
exit(1);
}
- copy_file(parentfd, "<socket to parent>", filefd, path);
+ copy_file(parentfd, "<socket to parent>", filefd, path, NULL);
if (close(filefd)) {
fprintf(stderr, "%s: read %s: %s\n", argv0, path, strerror(errno));
exit(1);
@@ -81,7 +49,7 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: open %s O_WRONLY|O_TRUNC: %s\n", argv0, path, strerror(errno));
exit(1);
}
- copy_file(filefd, path, parentfd, "<socket to parent>");
+ copy_file(filefd, path, parentfd, "<socket to parent>", &ok);
if (close(filefd)) {
fprintf(stderr, "%s: write %s: %s\n", argv0, path, strerror(errno));
exit(1);
@@ -90,6 +58,10 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: read <socket to parent>: %s\n", argv0, strerror(errno));
exit(1);
}
+ if (!ok) {
+ fprintf(stderr, "%s: parent exited before sending file termination message, file may be truncated\n", argv0);
+ exit(1);
+ }
return 0;
}
diff --git a/editasroot.c b/editasroot.c
index c6ce396..09479f8 100644
--- a/editasroot.c
+++ b/editasroot.c
@@ -1,21 +1,11 @@
/* See LICENSE file for copyright and license details. */
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
+#include "common.h"
#define TEMPFILEPATTERN "tmpXXXXXX"
-static const char *argv0 = "editasroot";
+const char *argv0 = "editasroot";
+
static const char *unlink_this = NULL;
static int ttyfd = -1;
static int tcattrs_fetched = 0;
@@ -101,32 +91,6 @@ get_tmpfile_pattern(void)
}
-static void
-copy_file(int destfd, const char *destfname, int srcfd, const char *srcfname)
-{
- char buf[BUFSIZ];
- ssize_t r, w, p;
-
- for (;;) {
- r = read(srcfd, buf, sizeof(buf));
- if (r <= 0) {
- if (!r)
- break;
- fprintf(stderr, "%s: read %s: %s", argv0, srcfname, strerror(errno));
- exit(1);
- }
-
- for (p = 0; p < r; p += w) {
- w = write(destfd, buf, (size_t)(r - p));
- if (r <= 0) {
- fprintf(stderr, "%s: write %s: %s", argv0, destfname, strerror(errno));
- exit(1);
- }
- }
- }
-}
-
-
static pid_t
run_child(const char *file, int fd, int close_this)
{
@@ -191,7 +155,7 @@ main(int argc, char *argv[])
{
const char *editor;
char *path;
- int fd, fds[2], status, i;
+ int fd, fds[2], status, i, ok;
pid_t pid;
if (!argc)
@@ -226,8 +190,8 @@ main(int argc, char *argv[])
editor = get_editor();
/* Start copier, with a bidirectional channel to it for copying the file */
- if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds)) {
- fprintf(stderr, "%s: socketpair PF_LOCAL SOCK_STREAM 0: %s", argv0, strerror(errno));
+ if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, fds)) {
+ fprintf(stderr, "%s: socketpair PF_LOCAL SOCK_SEQPACKET 0: %s", argv0, strerror(errno));
exit(1);
}
pid = run_child(argv[0], fds[1], fds[0]);
@@ -246,7 +210,7 @@ main(int argc, char *argv[])
exit(1);
}
unlink_this = path;
- copy_file(fd, path, fds[0], "<socket to child>");
+ copy_file(fd, path, fds[0], "<socket to child>", &ok);
if (close(fd)) {
fprintf(stderr, "%s: write %s: %s", argv0, path, strerror(errno));
exit(1);
@@ -255,6 +219,10 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: shutdown <socket to child> SHUT_RD: %s\n", argv0, strerror(errno));
exit(1);
}
+ if (!ok) {
+ fprintf(stderr, "%s: child exited before sending file termination message\n", argv0);
+ exit(1);
+ }
/* Don't need to restore terminal attributes, if we got here, asroot as not interrupted */
close(ttyfd);
@@ -274,7 +242,7 @@ main(int argc, char *argv[])
fprintf(stderr, "%s: open %s O_RDONLY: %s", argv0, path, strerror(errno));
exit(1);
}
- copy_file(fds[0], "<socket to child>", fd, path);
+ copy_file(fds[0], "<socket to child>", fd, path, NULL);
if (close(fd)) {
fprintf(stderr, "%s: read %s: %s", argv0, path, strerror(errno));
exit(1);