about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2015-07-31 14:48:08 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2015-07-31 14:48:08 +0200
commit3602eb91c82eb8db8e5a15abbedb3b4483a1613c (patch)
tree9e84079fdfad812d9fb6757be420da632ce42bef
parenta45deb01daa2c2fb67361ea8ffce6b63ad020558 (diff)
downloadnq-3602eb91c82eb8db8e5a15abbedb3b4483a1613c.tar.gz
nq-3602eb91c82eb8db8e5a15abbedb3b4483a1613c.tar.xz
nq-3602eb91c82eb8db8e5a15abbedb3b4483a1613c.zip
clean up, use a pipe instead of signals
-rw-r--r--nq.c90
1 files changed, 44 insertions, 46 deletions
diff --git a/nq.c b/nq.c
index 7611395..5636332 100644
--- a/nq.c
+++ b/nq.c
@@ -1,5 +1,5 @@
 /*
-  ##% gcc -Wall -g -o $STEM $FILE
+##% gcc -Wall -g -o $STEM $FILE
 */
 
 #include <sys/file.h>
@@ -17,39 +17,22 @@
 #include <time.h>
 #include <unistd.h>
 
-static void
-quit(int sig)
+void
+swrite(int fd, char *str)
 {
-	exit(0);
+	if (write(fd, str, strlen(str)) < 0) {
+		perror("write");
+		exit(222);
+	}
 }
 
-/*
-  char *
-  timestamp() {
-  struct timeval tv;
-  gettimeofday(&tv, NULL);
-  static char buf[10];
-
-  int64_t ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-
-  buf[9] = 0;
-  int i;
-  for (i = 8; i >= 0; i--) {
-  buf[i] = 'a' + (ms % 26);
-  ms /= 26;
-  }
-  
-  return buf;
-  }
-*/
-
 int
 main(int argc, char *argv[])
 {
 	pid_t child;
-	int lockfd;
-	char lockfile[128];
-	int dirfd;
+	int lockfd, dirfd;
+	char lockfile[32];
+	int pipefd[2];
 
 	struct timeval tv;
 	gettimeofday(&tv, NULL);
@@ -65,45 +48,58 @@ main(int argc, char *argv[])
 		exit(111);
 	}
 
+	pipe(pipefd);
+
 	child = fork();
 	if (child == -1) {
 		perror("fork");
 		exit(111);
 	}
-
-	if (child > 0) {
+	else if (child > 0) {
 		// background
-		signal(SIGINT, quit);
-		pause();
+		close(pipefd[1]);
+		char c;
+		read(pipefd[0], &c, 1);
 		exit(0);
 	}
 
+	close(pipefd[0]);
+
 	child = fork();
 	if (child == -1) {
 		perror("fork");
 		exit(111);
 	}
-	if (child > 0) {
+	else if (child > 0) {
 		int status;
 		sprintf(lockfile, ",%lx.%d", ms, child);
 
-		puts(lockfile);
+		dprintf(1, "%s\n", lockfile);
 
 		// signal parent to exit
-		kill(getppid(), SIGINT);
+		close(pipefd[1]);
 
 		wait(&status);
-		int fd;
-		fd = openat(dirfd, lockfile, O_RDWR | O_APPEND);
-		fchmod(fd, 0600);
+
+		lockfd = openat(dirfd, lockfile, O_RDWR | O_APPEND);
+		if (lockfd < 0) {
+			perror("open");
+			exit(222);
+		}
+
+		fchmod(lockfd, 0600);
 		if (WIFEXITED(status))
-			dprintf(fd, "\n[exited with status %d.]\n", WEXITSTATUS(status));
+			dprintf(lockfd, "\n[exited with status %d.]\n",
+			    WEXITSTATUS(status));
 		else
-			dprintf(fd, "\n[killed by signal %d.]\n", WTERMSIG(status));
+			dprintf(lockfd, "\n[killed by signal %d.]\n",
+			    WTERMSIG(status));
 
 		exit(0);
 	}
 
+	close(pipefd[1]);
+
 	sprintf(lockfile, ".,%lx.%d", ms, getpid());
 	lockfd = openat(dirfd, lockfile, O_CREAT | O_EXCL | O_RDWR | O_APPEND, 0600);
   
@@ -114,21 +110,21 @@ main(int argc, char *argv[])
 
 	flock(lockfd, LOCK_EX);
   
-	// drop leading .
+	// drop leading '.'
 	renameat(dirfd, lockfile, dirfd, lockfile+1);
 
-	write(lockfd, "exec", 4);
+	swrite(lockfd, "exec");
 	int i;
 	for (i = 0; i < argc; i++) {
 		int j, l = strlen(argv[i]);
-		write(lockfd, " '", 2);
+		swrite(lockfd, " '");
 		for (j = 0; j < l; j++) {
 			if (argv[i][j] == '\'')
-				write(lockfd, "'\\''", 4);
+				swrite(lockfd, "'\\''");
 			else
 				write(lockfd, argv[i]+j, 1);
 		}
-		write(lockfd, "'", 1);
+		swrite(lockfd, "'");
 	}
 
 	DIR *dir = fdopendir(dirfd);
@@ -141,10 +137,12 @@ main(int argc, char *argv[])
 
 again:
 	while ((ent = readdir(dir))) {
-		if (ent->d_name[0] == ',' && strcmp(ent->d_name, lockfile+1) < 0) {
+		if (ent->d_name[0] == ',' &&
+		    strcmp(ent->d_name, lockfile+1) < 0) {
 			int f = openat(dirfd, ent->d_name, O_RDWR);
     
-			if (flock(f, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK) {
+			if (flock(f, LOCK_EX | LOCK_NB) == -1 &&
+			    errno == EWOULDBLOCK) {
 				flock(f, LOCK_EX);   // sit it out
 
 				rewinddir(dir);