Re: [PATCH] dired mg patch

2011-08-29 Thread Henri Kemppainen
 It fixes the issue that if a filename has a space at the start of
 it, the point will stay in the first character column and not jump
 to the first non ' ' character in the filename.

Yup, this looks good to me.

 However, it does seem to expose a bug in dired, that if a filename
 has a space at the start of it, mg doesn't find it if you try and 
 open it. mg gives a message of (New File) and creates and empty 
 buffer. But in the mean time, I think this change does make this
 diff more correct.

Indeed.  This looks like a flaw in d_makename, which seems to implement
its own warpdot() :-)  This should be changed to use our new function
(and we could make use of NAME_FIELD).  That fix, along with the one
for dealing with shell metacharacters, should probably be a separate
diff though.



Re: [PATCH] dired mg patch

2011-08-29 Thread Henri Kemppainen
  However, it does seem to expose a bug in dired, that if a filename
  has a space at the start of it, mg doesn't find it if you try and 
  open it. mg gives a message of (New File) and creates and empty 
  buffer. But in the mean time, I think this change does make this
  diff more correct.

 Indeed.  This looks like a flaw in d_makename, which seems to implement
 its own warpdot() :-)  This should be changed to use our new function
 (and we could make use of NAME_FIELD).  That fix, along with the one
 for dealing with shell metacharacters, should probably be a separate
 diff though.

And here's that diff.  Makename() uses warpdot().  I also refined warpdot
to use NAME_FIELD and return (FALSE) if the field cannot be located (this
is the change I anticipated earlier).  This return value should make a
couple conditions easier to understand.

Then there's ls.  Trying to escape shell metacharacters is one of the
uglier things a program can do, if the alternative of passing the string
directly to a program is available.  Most of this code (fork  exec) is
already in dired.c in shell_command().  I took this code and put it
into a separate function, d_exec(), and added some vararg magic.  Using
this function instead of popen() eliminates the issues with metachars
while making dired_() quite a bit simpler.

One bit I'm not particularly fond of is the first parameter of d_exec,
which is used to prefix the lines with spaces (needed so the action chars
like '!' fit on the line in front of ls output).  On the principle of YAGNI,
however, I did not implement a bigger hammer that would've let the caller
read  process lines one at a time; this would've involved more functions
and state.

I also added a few relevant comments.

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.49
diff -u -p -r1.49 dired.c
--- dired.c 29 Aug 2011 11:02:06 -  1.49
+++ dired.c 29 Aug 2011 13:54:10 -
@@ -21,6 +21,7 @@
 #include fcntl.h
 #include errno.h
 #include libgen.h
+#include stdarg.h
 
 voiddired_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_tpid;
-   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,11 +504,61 @@ 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, *cp;
+   FILE*fin;
+   pid_tpid;
+   int  infd, fds[2];
+   int  n;
+
+   /* 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));
+   return (FALSE);
+   }
+
+   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);
}
+
if (pipe(fds) == -1) {
ewprintf(Can't create pipe : %s, 

Re: [PATCH} dired mg patch

2011-08-29 Thread Loganaden Velvindron
This fixes Nima's PR and mark's issue with 
filenames that start with a space.

Index: src/usr.bin/mg/dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.48
diff -u -p -r1.48 dired.c
--- src/usr.bin/mg/dired.c  23 Jan 2011 00:45:03 -  1.48
+++ src/usr.bin/mg/dired.c  29 Aug 2011 15:17:15 -
@@ -36,6 +36,11 @@ static intd_rename(int, int);
 static int  d_shell_command(int, int);
 static int  d_create_directory(int, int);
 static int  d_makename(struct line *, char *, size_t);
+static int  d_warpdot(char *);
+static int  d_forwpage(int, int);
+static int  d_backpage(int, int);
+static int  d_forwline(int, int);
+static int  d_backline(int, int);
 static void reaper(int);
 
 extern struct keymap_s helpmap, cXmap, metamap;
@@ -57,15 +62,15 @@ static PF dirednul[] = {
 static PF diredcl[] = {
reposition, /* ^L */
d_findfile, /* ^M */
-   forwline,   /* ^N */
+   d_forwline, /* ^N */
rescan, /* ^O */
-   backline,   /* ^P */
+   d_backline, /* ^P */
rescan, /* ^Q */
backisearch,/* ^R */
forwisearch,/* ^S */
rescan, /* ^T */
universal_argument, /* ^U */
-   forwpage,   /* ^V */
+   d_forwpage, /* ^V */
rescan, /* ^W */
NULL/* ^X */
 };
@@ -77,7 +82,7 @@ static PF diredcz[] = {
rescan, /* ^] */
rescan, /* ^^ */
rescan, /* ^_ */
-   forwline,   /* SP */
+   d_forwline, /* SP */
d_shell_command,/* ! */
rescan, /*  */
rescan, /* # */
@@ -99,9 +104,9 @@ static PF diredc[] = {
 };
 
 static PF diredn[] = {
-   forwline,   /* n */
+   d_forwline, /* n */
d_ffotherwindow,/* o */
-   backline,   /* p */
+   d_backline, /* p */
rescan, /* q */
d_rename,   /* r */
rescan, /* s */
@@ -116,13 +121,32 @@ static PF direddl[] = {
d_undelbak  /* del */
 };
 
+static PF diredbp[] = {
+   d_backpage  /* v */ 
+};
+
+static PF dirednull[] = {
+   NULL
+};
+
 #ifndefDIRED_XMAPS
 #defineNDIRED_XMAPS0   /* number of extra map sections */
 #endif /* DIRED_XMAPS */
 
-static struct KEYMAPE (6 + NDIRED_XMAPS + IMAPEXT) diredmap = {
-   6 + NDIRED_XMAPS,
-   6 + NDIRED_XMAPS + IMAPEXT,
+static struct KEYMAPE (1 + IMAPEXT) d_backpagemap = {
+   1,
+   1 + IMAPEXT,
+   rescan, 
+   {
+   {
+   'v', 'v', diredbp, NULL
+   }
+   }
+};
+
+static struct KEYMAPE (7 + NDIRED_XMAPS + IMAPEXT) diredmap = {
+   7 + NDIRED_XMAPS,
+   7 + NDIRED_XMAPS + IMAPEXT,
rescan,
{
 #ifndef NO_HELP
@@ -138,6 +162,10 @@ static struct KEYMAPE (6 + NDIRED_XMAPS 
CCHR('L'), CCHR('X'), diredcl, (KEYMAP *)  cXmap
},
{
+   CCHR('['), CCHR('['), dirednull, (KEYMAP *)  
+   d_backpagemap
+   },
+   {
CCHR('Z'), '+', diredcz, (KEYMAP *)  metamap
},
{
@@ -165,8 +193,12 @@ dired_init(void)
funmap_add(d_findfile, dired-find-file);
funmap_add(d_ffotherwindow, dired-find-file-other-window);
funmap_add(d_del, dired-flag-file-deleted);
+   funmap_add(d_forwline, dired-next-line);
funmap_add(d_otherwindow, dired-other-window);
+   funmap_add(d_backline, dired-previous-line);
funmap_add(d_rename, dired-rename-file);
+   funmap_add(d_backpage, dired-scroll-down);
+   funmap_add(d_forwpage, dired-scroll-up);
funmap_add(d_undel, dired-unflag);
maps_add((KEYMAP *)diredmap, dired);
dobindkey(fundamental_map, dired, ^Xd);
@@ -563,13 +595,13 @@ 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;
+   int  i, col;
char*p, *ep;
+   col = 0;
 
if (strlcpy(fn, curbp-b_fname, len) = len)
return (FALSE);
@@ -577,21 +609,98 @@ d_makename(struct line *lp, char *fn, si
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  

Re: [PATCH] dired mg patch

2011-08-29 Thread Loganaden Velvindron
This diff works fine.

Not using metacharacters and passing it
as argv is the proper fix. Escaping 
shell metacharacters isn't the proper way.

Warpdot() is also a little bit safer now.

It addresses some of the issues I was a bit
worried about.

This should go in !



APC Smart-UPS 2200 con poco uso - Escucho 0fertas

2011-08-29 Thread Carlos
APC Smart-UPS 2200VA USB  Serial RM 2U 230V  $ 2200 Consulte
respondiendo el presente mensaje  Salida Capacidad de Potencia de Salida
1980 Vatios / 2200 VA / Max Potencia Configurable1980 Vatios / 2200
VA Voltaje de salida nominal 230V / Nota de voltaje de salida Configurable  
 a una tensioacute;n nominal de salida de 220 : 230 o 240 /
Distorsioacute;nde Voltaje de Salida Menos del 3% / Frecuencia de
salida (sincronizado paraprincipales) 47-53 Hz para 50 Hz nominal,57
- 63 Hz para 60 Hz nominal /Tipo de forma de onda Onda senoidal / 
Conexiones de salida (8) IEC 320 C13 / (1) IEC 320 C19 / (2) IEC Jumpers 
Entrada Voltaje Nominal de Entrada 230V / Frecuencia de entrada 50/60 Hz +/-
3 Hz(deteccioacute;n automaacute;tica) / Tipo de Conexioacute;n
de Entrada/ IEC-320 C20 / Schuko CEE 7 / EU1-16P / British BS1363A 
Rango de voltaje de entrada  En operaciones principales 160 - 286V / Rango
de voltaje ajustable paraoperaciones principales 151 - 302V
Bateriacute;as y tiempo de autonomiacute;a Tipo de bateriacute;a
Bateriacute;a libre de mantenimiento sellada alplomo con
electrolito suspendido : a prueba de fugas / Tiempo tiacute;picode
recarga 3 hour(s) / Cartucho de bateriacute;a de repuesto RBC43 / Cantidad 
  de RBCtrade; 1  Comunicaciones Gestioacute;n Puerto
Interfaz DB-9 RS-232,SmartSlot,USB / Interfaces SmartSlottrade; disponibles
   1 / Panel de Control Diodos luminosos de Estado, con barras graficas
decarga y bateriacute;a e Indicadores de En Red : Bateriacute;a
activada: Cambiar Bateriacute;a : y Sobrecarga / Alarma
Acuacute;stica Alarmaen caso de funcionar con bateriacute;as :
alarma especial de bateriacute;abaja : Retardos configurables /
Desconexioacute;n de Emergencia (EPO) Siacute;/ Proteccioacute;n
y Filtro contra Picos de Voltaje / Medicioacute;n deEnergiacute;a
de Picos de Voltaje (Julios ) 480 Julios / Filtro Filtracioacute;n   
multipolar permanente de ruido : Paso de tensioacute;n ante pico de voltage
   0.3% IEEE : tiempo de reaccioacute;n de bloqueo cero : acorde con UL
1449 Descripcioacute;n fiacute;sica Altura maacute;xima 89.00 mm
/ Anchura maacute;xima 483.00 mm / Profundidadmaacute;xima 660.00
mm / Altura del bastidor 2U / Peso neto 43.64 KG /Peso de
enviacute;o 51.50 KG / Altura de Enviacute;o 260.00 mm / Anchurade
Enviacute;o 600.00 mm / Profundidad de enviacute;o 980.00 mm / Color  
 Negro / Unidades en Palet 8.00  Descripcioacute;n medioambiental
Temperatura de trabajo 0 - 40 deg;C / Humedad Relativa de Trabajo 0 - 95%  
 / Elevacioacute;n de Trabajo 0-3000 metros / Temperatura de
Almacenamiento-15 - 45 deg;C / Humedad Relativa de Almacenamiento 0
- 95% / Elevacioacute;nde Almacenamiento 0-15000 metros / Ruido
perceptible a 1 metro desde lasuperficie de la unidad 47.00 dBA /
Disipacioacute;n teacute;rmica online300.00 BTU/h  Conformidad
Aceptaciones Ciclo C,CE,EN 50091-1,EN 50091-2,GOST,VDE / Cumplimiento
medioambientalRoHS 7b Exemption,China RoHS



quotacheck(8) and duid

2011-08-29 Thread Rogier Krieger
...at present do not seem to go together nicely:

# tail -n 1 /etc/fstab
73123067c3dc34d4.a /data ffs rw,userquota,groupquota 1 1

# /sbin/quotacheck /data
quotacheck: 73123067c3dc34d4.a: No such file or directory


Would the attached diff be acceptable? It appears to solve my issue,
working with both the /dev/sd0a and duid forms. Note that (for
unchanged fstab and patch applied), using quotacheck with the
then-current physical device (sd0a) complains.
# /sbin/quotacheck /dev/sd0a
/dev/sd0a not found in /etc/fstab

Hardly surprising, since it's indeed not in fstab; I suppose it's
overkill to add logic for this. In case the diff gets mangled in
transit, alternatively try: http://pastebin.com/VRN8wZX6

Regards,

Rogier


Index: Makefile
===
RCS file: /cvs/src/sbin/quotacheck/Makefile,v
retrieving revision 1.6
diff -u -r1.6 Makefile
--- Makefile21 Sep 1997 11:37:57 -  1.6
+++ Makefile29 Aug 2011 23:20:47 -
@@ -6,4 +6,7 @@
 MAN=   quotacheck.8
 .PATH: ${.CURDIR}/../fsck

+LDADD+=-lutil
+DPADD+=${LIBUTIL}
+
 .include bsd.prog.mk
Index: quotacheck.c
===
RCS file: /cvs/src/sbin/quotacheck/quotacheck.c,v
retrieving revision 1.25
diff -u -r1.25 quotacheck.c
--- quotacheck.c27 Oct 2009 23:59:34 -  1.25
+++ quotacheck.c29 Aug 2011 23:20:47 -
@@ -50,6 +50,7 @@
 #include grp.h
 #include errno.h
 #include unistd.h
+#include util.h
 #include stdio.h
 #include stdlib.h
 #include string.h
@@ -263,13 +264,14 @@
ino_t ino, inosused;
pid_t pid;
char *cp;
+   char *realdev;

switch (pid = fork()) {
case -1:/* error */
warn(fork);
return 1;
case 0: /* child */
-   if ((fi = open(fsname, O_RDONLY, 0))  0)
+   if ((fi = opendev(fsname, O_RDONLY, 0, realdev))  0)
err(1, %s, fsname);
sync();
dev_bsize = 1;



Re: [PATCH] dired mg patch

2011-08-29 Thread Henri Kemppainen
 And here's that diff.  [..]

It never hurts to re-read a diff before going to bed.  Indeed, I
forgot to free argv (execlp uses alloca).  The number of things
to clean up after one thing fails is almost getting out of hand,
and at least the fork() case wasn't handled properly.  In this new
revision of d_exec, argv and all the fds are checked and freed
(only) at the end of the function, if necessary.  That's where we
jump to, should anything fail.

The rest of the diff is as before.

Index: dired.c
===
RCS file: /cvs/src/usr.bin/mg/dired.c,v
retrieving revision 1.49
diff -u -p -r1.49 dired.c
--- dired.c 29 Aug 2011 11:02:06 -  1.49
+++ dired.c 29 Aug 2011 23:27:09 -
@@ -21,6 +21,7 @@
 #include fcntl.h
 #include errno.h
 #include libgen.h
+#include stdarg.h
 
 voiddired_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_tpid;
-   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,124 @@ 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_tpid;
+
+   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);
+   execvp(argv[0], argv);
exit(1);
break;
-   default:
+   default: /* Parent */

Re: quotacheck(8) and duid

2011-08-29 Thread Rogier Krieger
On Tue, Aug 30, 2011 at 01:25, Rogier Krieger rkrie...@gmail.com wrote:
 Would the attached diff be acceptable?

Sorry, no real point in adding a variable that is not really used. I
should've read the man page more thoroughly. New diff, without that
junk. Also at http://pastebin.com/bRiUuX1J

Index: Makefile
===
RCS file: /cvs/src/sbin/quotacheck/Makefile,v
retrieving revision 1.6
diff -u -r1.6 Makefile
--- Makefile21 Sep 1997 11:37:57 -  1.6
+++ Makefile30 Aug 2011 02:59:22 -
@@ -6,4 +6,7 @@
 MAN=   quotacheck.8
 .PATH: ${.CURDIR}/../fsck

+LDADD+=-lutil
+DPADD+=${LIBUTIL}
+
 .include bsd.prog.mk
Index: quotacheck.c
===
RCS file: /cvs/src/sbin/quotacheck/quotacheck.c,v
retrieving revision 1.25
diff -u -r1.25 quotacheck.c
--- quotacheck.c27 Oct 2009 23:59:34 -  1.25
+++ quotacheck.c30 Aug 2011 02:59:22 -
@@ -50,6 +50,7 @@
 #include grp.h
 #include errno.h
 #include unistd.h
+#include util.h
 #include stdio.h
 #include stdlib.h
 #include string.h
@@ -269,7 +270,7 @@
warn(fork);
return 1;
case 0: /* child */
-   if ((fi = open(fsname, O_RDONLY, 0))  0)
+   if ((fi = opendev(fsname, O_RDONLY, 0, NULL))  0)
err(1, %s, fsname);
sync();
dev_bsize = 1;



Re: [PATCH] dired mg patch

2011-08-29 Thread Loganaden Velvindron
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 -  1.49
+++ src/usr.bin/mg/dired.c  30 Aug 2011 03:39:11 -
@@ -21,6 +21,7 @@
 #include fcntl.h
 #include errno.h
 #include libgen.h
+#include stdarg.h
 
 voiddired_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_tpid;
-   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_tpid;
+
+   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 =