[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    Re: [PATCH] dired mg patch
From:       Loganaden Velvindron <loganaden () wolfman ! devio ! us>
Date:       2011-08-30 3:45:32
Message-ID: 20110830034532.GA3283 () wolfman ! devio ! us
[Download RAW message or body]

The latest diff has no issues so far.

I just added the error message in case
execvp() fails.

Index: src/usr.bin/mg/dired.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.49
diff -u -p -r1.49 dired.c
--- src/usr.bin/mg/dired.c	29 Aug 2011 11:02:06 -0000	1.49
+++ src/usr.bin/mg/dired.c	30 Aug 2011 03:39:11 -0000
@@ -21,6 +21,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <libgen.h>
+#include <stdarg.h>
 
 void		 dired_init(void);
 static int	 dired(int, int);
@@ -33,6 +34,7 @@ static int	 d_expunge(int, int);
 static int	 d_copy(int, int);
 static int	 d_del(int, int);
 static int	 d_rename(int, int);
+static int	 d_exec(int, struct buffer *, const char *, const char *, ...);
 static int	 d_shell_command(int, int);
 static int	 d_create_directory(int, int);
 static int	 d_makename(struct line *, char *, size_t);
@@ -483,14 +485,10 @@ reaper(int signo __attribute__((unused))
 int
 d_shell_command(int f, int n)
 {
-	char	 command[512], fname[MAXPATHLEN], buf[BUFSIZ], *bufp, *cp;
-	int	 infd, fds[2];
-	pid_t	 pid;
-	struct	 sigaction olda, newa;
+	char		 command[512], fname[MAXPATHLEN], *bufp;
 	struct buffer	*bp;
 	struct mgwin	*wp;
-	FILE	*fin;
-	char	 sname[NFILEN];
+	char		 sname[NFILEN];
 
 	bp = bfind("*Shell Command Output*", TRUE);
 	if (bclear(bp) != TRUE)
@@ -506,68 +504,125 @@ d_shell_command(int f, int n)
 	bufp = eread("! on %s: ", command, sizeof(command), EFNEW, sname);
 	if (bufp == NULL)
 		return (ABORT);
-	infd = open(fname, O_RDONLY);
-	if (infd == -1) {
+
+	if (d_exec(0, bp, fname, "sh", "-c", command, NULL) != TRUE)
+		return (ABORT);
+
+	if ((wp = popbuf(bp, WNONE)) == NULL)
+		return (ABORT);	/* XXX - free the buffer?? */
+	curwp = wp;
+	curbp = wp->w_bufp;
+	return (TRUE);
+}
+
+/*
+ * Pipe input file to cmd and insert the command's output in the
+ * given buffer.  Each line will be prefixed with the given
+ * number of spaces.
+ */
+static int
+d_exec(int space, struct buffer *bp, const char *input, const char *cmd, ...)
+{
+	char	 buf[BUFSIZ];
+	va_list	 ap;
+	struct	 sigaction olda, newa;
+	char	**argv = NULL, *cp;
+	FILE	*fin;
+	int	 fds[2] = { -1, -1 };
+	int	 infd = -1;
+	int	 ret = (ABORT), n;
+	pid_t	 pid;
+
+	if (sigaction(SIGCHLD, NULL, &olda) == -1)
+		return (ABORT);
+
+	/* Find the number of arguments. */
+	va_start(ap, cmd);
+	for (n = 2; va_arg(ap, char *) != NULL; n++)
+		;
+	va_end(ap);
+
+	/* Allocate and build the argv. */
+	if ((argv = calloc(n, sizeof(*argv))) == NULL) {
+		ewprintf("Can't allocate argv : %s", strerror(errno));
+		goto out;
+	}
+
+	n = 1;
+	argv[0] = (char *)cmd;
+	va_start(ap, cmd);
+	while ((argv[n] = va_arg(ap, char *)) != NULL)
+		n++;
+	va_end(ap);
+
+	if (input == NULL)
+		input = "/dev/null";
+
+	if ((infd = open(input, O_RDONLY)) == -1) {
 		ewprintf("Can't open input file : %s", strerror(errno));
-		return (FALSE);
+		goto out;
 	}
+
 	if (pipe(fds) == -1) {
 		ewprintf("Can't create pipe : %s", strerror(errno));
-		close(infd);
-		return (FALSE);
+		goto out;
 	}
 
 	newa.sa_handler = reaper;
 	newa.sa_flags = 0;
-	if (sigaction(SIGCHLD, &newa, &olda) == -1) {
-		close(infd);
-		close(fds[0]);
-		close(fds[1]);
-		return (ABORT);
+	if (sigaction(SIGCHLD, &newa, NULL) == -1)
+		goto out;
+
+	if ((pid = fork()) == -1) {
+		ewprintf("Can't fork");
+		goto out;
 	}
-	pid = fork();
+
 	switch (pid) {
-	case -1:
-		ewprintf("Can't fork");
-		return (ABORT);
-	case 0:
+	case 0: /* Child */
 		close(fds[0]);
 		dup2(infd, STDIN_FILENO);
 		dup2(fds[1], STDOUT_FILENO);
 		dup2(fds[1], STDERR_FILENO);
-		execl("/bin/sh", "sh", "-c", bufp, (char *)NULL);
+		if (execvp(argv[0], argv) == -1)
+			printf("cmd error: %s", strerror(errno));
 		exit(1);
 		break;
-	default:
+	default: /* Parent */
 		close(infd);
 		close(fds[1]);
-		fin = fdopen(fds[0], "r");
-		if (fin == NULL)	/* "r" is surely a valid mode! */
-			panic("can't happen");
+		infd = fds[1] = -1;
+		if ((fin = fdopen(fds[0], "r")) == NULL)
+			goto out;
 		while (fgets(buf, sizeof(buf), fin) != NULL) {
 			cp = strrchr(buf, '\n');
 			if (cp == NULL && !feof(fin)) {	/* too long a line */
 				int c;
-				addlinef(bp, "%s...", buf);
+				addlinef(bp, "%*s%s...", space, "", buf);
 				while ((c = getc(fin)) != EOF && c != '\n')
 					;
 				continue;
 			} else if (cp)
 				*cp = '\0';
-			addline(bp, buf);
+			addlinef(bp, "%*s%s", space, "", buf);
 		}
 		fclose(fin);
-		close(fds[0]);
 		break;
 	}
-	wp = popbuf(bp, WNONE);
-	if (wp == NULL)
-		return (ABORT);	/* XXX - free the buffer?? */
-	curwp = wp;
-	curbp = wp->w_bufp;
+	ret = (TRUE);
+
+out:
 	if (sigaction(SIGCHLD, &olda, NULL) == -1)
 		ewprintf("Warning, couldn't reset previous signal handler");
-	return (TRUE);
+	if (fds[0] != -1)
+		close(fds[0]);
+	if (fds[1] != -1)
+		close(fds[1]);
+	if (infd != -1)
+		close(infd);
+	if (argv != NULL)
+		free(argv);
+	return ret;
 }
 
 /* ARGSUSED */
@@ -595,35 +650,26 @@ d_create_directory(int f, int n)
 	return (showbuffer(bp, curwp, WFFULL | WFMODE));
 }
 
-#define NAME_FIELD	8
-
 static int
 d_makename(struct line *lp, char *fn, size_t len)
 {
-	int	 i;
-	char	*p, *ep;
+	int	 start, nlen;
+	char	*namep;
 
-	if (strlcpy(fn, curbp->b_fname, len) >= len)
-		return (FALSE);
-	if ((p = lp->l_text) == NULL)
+	if (d_warpdot(lp, &start) == FALSE)
 		return (ABORT);
-	ep = lp->l_text + llength(lp);
-	p++; /* skip action letter, if any */
-	for (i = 0; i < NAME_FIELD; i++) {
-		while (p < ep && isspace(*p))
-			p++;
-		while (p < ep && !isspace(*p))
-			p++;
-		while (p < ep && isspace(*p))
-			p++;
-		if (p == ep)
-			return (ABORT);
-	}
-	if (strlcat(fn, p, len) >= len)
-		return (FALSE);
+	namep = &lp->l_text[start];
+	nlen = llength(lp) - start;
+
+	if (snprintf(fn, len, "%s%.*s", curbp->b_fname, nlen, namep) >= len)
+		return (ABORT); /* Name is too long. */
+
+	/* Return TRUE if the entry is a directory. */
 	return ((lgetc(lp, 2) == 'd') ? TRUE : FALSE);
 }
 
+#define NAME_FIELD	9
+
 static int
 d_warpdot(struct line *dotp, int *doto)
 {
@@ -637,15 +683,18 @@ d_warpdot(struct line *dotp, int *doto)
 	len = llength(dotp);
 	while (off < len) {
 		if (tp[off++] == ' ') {
-			if (++field == 9)
-				break;
+			if (++field == NAME_FIELD) {
+				*doto = off;
+				return (TRUE);
+			}
 			/* Skip the space. */
 			while (off < len && tp[off] == ' ')
 				off++;
 		}
 	}
-	*doto = off;
-	return (TRUE);
+	/* We didn't find the field. */
+	*doto = 0;
+	return (FALSE);
 }
 
 static int
@@ -683,9 +732,7 @@ struct buffer *
 dired_(char *dname)
 {
 	struct buffer	*bp;
-	FILE	*dirpipe;
-	char	 line[256];
-	int	 len, ret, i;
+	int		 len, i;
 
 	if ((fopen(dname,"r")) == NULL) {
 		if (errno == EACCES)
@@ -709,32 +756,15 @@ dired_(char *dname)
 	if (bclear(bp) != TRUE)
 		return (NULL);
 	bp->b_flag |= BFREADONLY;
-	ret = snprintf(line, sizeof(line), "ls -al %s", dname);
-	if (ret < 0 || ret  >= sizeof(line)) {
-		ewprintf("Path too long");
-		return (NULL);
-	}
-	if ((dirpipe = popen(line, "r")) == NULL) {
-		ewprintf("Problem opening pipe to ls");
-		return (NULL);
-	}
-	line[0] = line[1] = ' ';
-	while (fgets(&line[2], sizeof(line) - 2, dirpipe) != NULL) {
-		line[strcspn(line, "\n")] = '\0'; /* remove ^J	 */
-		(void) addline(bp, line);
-	}
-	if (pclose(dirpipe) == -1) {
-		ewprintf("Problem closing pipe to ls : %s",
-		    strerror(errno));
+
+	if ((d_exec(2, bp, NULL, "ls", "-al", dname, NULL)) != TRUE)
 		return (NULL);
-	}
 
 	/* Find the line with ".." on it. */
 	bp->b_dotp = bfirstlp(bp);
 	for (i = 0; i < bp->b_lines; i++) {
 		bp->b_dotp = lforw(bp->b_dotp);
-		d_warpdot(bp->b_dotp, &bp->b_doto);
-		if (bp->b_doto >= llength(bp->b_dotp))
+		if (d_warpdot(bp->b_dotp, &bp->b_doto) == FALSE)
 			continue;
 		if (strcmp(ltext(bp->b_dotp) + bp->b_doto, "..") == 0)
 			break;

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic