]> git.wh0rd.org Git - nano.git/commitdiff
Add David Benbennick's changes to open_pipe() and move it to nano.c, and add his...
authorChris Allegretta <chrisa@asty.org>
Fri, 29 Mar 2002 16:31:29 +0000 (16:31 +0000)
committerChris Allegretta <chrisa@asty.org>
Fri, 29 Mar 2002 16:31:29 +0000 (16:31 +0000)
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1159 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
files.c
nano.c
proto.h
utils.c

index 540ea9f46a19000ae879f705eb01a8bd6a2cc858..edbcf316bb7c81dc3263e11a0d958c7dbb84e01b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,9 +3,10 @@ CVS code -
        - Type misalignments and mem leaks in renumber_all, do_justify
          and do_spell (Rocco & Steven Kneizys).
        - New "External Command" code, originally by Dwayne Rightler,
-         Chris & Rocco. New function files.c:open_pipe(), changes to
-         do_insertfile(), new list extcmd_list, cmd is ^X after ^R by
-         default.
+         various fixes and changes by Chris, Rocco and David Benbennick. 
+         New function nano.c:open_pipe() and signal handler cancel_fork(), 
+         changes to do_insertfile(), new list extcmd_list, cmd is 
+         ^X after ^R.
        - Added separate regex variable (color_regex and colormatches)
          so that color syntax and regex search/replace can coexist.
 - files.c:
@@ -50,6 +51,8 @@ CVS code -
 - utils.c:
   stristr() 
        - Defined regardless of NANO_SMALL (noticed by Jordi).
+  nperror()
+       - New wrapper for perror (David Benbennick).
 - winio.c:
   do_credits()
        - Add Thomas Dickey.
diff --git a/files.c b/files.c
index 0df7b24db261e23baac9d9c6b0b5b07934b92c76..5a9a7238ae971ac5489addd471329b3fef2da074 100644 (file)
--- a/files.c
+++ b/files.c
@@ -110,12 +110,8 @@ int read_byte(int fd, char *filename, char *input)
        index = 0;
        size = read(fd, buf, BUFSIZ);
        if (size == -1) {
-           clear();
-           refresh();
-           resetty();
-           endwin();
-           perror(filename);
-           total_refresh();
+           size = index;       /* note index==0 */
+           nperror(filename);
            return -1;
        }
        if (!size)
@@ -292,49 +288,6 @@ int read_file(int fd, char *filename, int quiet)
     return 1;
 }
 
-#ifndef NANO_SMALL
-int open_pipe(char *command)
-{
-    int fd[2], pid;
-    int fork_status;
-  
-  /* Make our pipes. */
-
-    if (pipe(fd) == -1) {
-       statusbar(_("Could not pipe"));
-       return 1;
-    }
-
-    /* Fork a child */
-
-    if ((pid = fork()) == 0) {
-       close(fd[0]);
-       dup2(fd[1], fileno(stdout));
-       dup2(fd[1], fileno(stderr));
-       /* If execl() returns at all, there was an error. */
-      
-       execl("/bin/sh","sh","-c",command,0);
-       exit(0);
-    }
-
-    /* Else continue as parent */
-
-    close(fd[1]);
-
-    if (pid == -1) {
-       close(fd[0]);
-       statusbar(_("Could not fork"));
-       return 1;
-    }
-
-    read_file(fd[0],"stdin",0);
-    set_modified();
-
-    wait(&fork_status);
-
-    return 0;
-}
-#endif /* NANO_SMALL */
 
 /* Open the file (and decide if it exists) */
 int open_file(char *filename, int insert, int quiet)
diff --git a/nano.c b/nano.c
index cfb666f358a1434e1771863deeb183c21f78fdd6..bb75156f1edfe2de310f4c40a4932653c5298e23 100644 (file)
--- a/nano.c
+++ b/nano.c
@@ -1733,6 +1733,111 @@ int do_spell(void)
 #endif
 }
 
+#ifndef NANO_SMALL
+static int pid;                /* this is the PID of the newly forked process below.  
+                        * It must be global since the signal handler needs it.
+                        */
+
+RETSIGTYPE cancel_fork(int signal) {
+    if (kill(pid, SIGKILL)==-1) nperror("kill");
+}
+
+int open_pipe(char *command)
+{
+    int fd[2];
+    struct sigaction oldaction, newaction;
+                       /* original and temporary handlers for SIGINT */
+#ifdef _POSIX_VDISABLE
+    struct termios term, newterm;
+#endif   /* _POSIX_VDISABLE */
+    int cancel_sigs = 0;
+    /* cancel_sigs==1 means that sigaction failed without changing the 
+     * signal handlers.  cancel_sigs==2 means the signal handler was
+     * changed, but the tcsetattr didn't succeed.
+     * I use this variable since it is important to put things back when
+     * we finish, even if we get errors.
+     */
+
+  /* Make our pipes. */
+
+    if (pipe(fd) == -1) {
+       statusbar(_("Could not pipe"));
+       return 1;
+    }
+
+    /* Fork a child */
+
+    if ((pid = fork()) == 0) {
+       close(fd[0]);
+       dup2(fd[1], fileno(stdout));
+       dup2(fd[1], fileno(stderr));
+       /* If execl() returns at all, there was an error. */
+      
+       execl("/bin/sh","sh","-c",command,0);
+       exit(0);
+    }
+
+    /* Else continue as parent */
+
+    close(fd[1]);
+
+    if (pid == -1) {
+       close(fd[0]);
+       statusbar(_("Could not fork"));
+       return 1;
+    }
+
+    /* before we start reading the forked command's output, we set 
+     * things up so that ^C will cancel the new process.
+     */
+    if (sigaction(SIGINT, NULL, &newaction)==-1) {
+       cancel_sigs = 1;
+       nperror("sigaction");
+    } else {
+       newaction.sa_handler = cancel_fork;
+       if (sigaction(SIGINT, &newaction, &oldaction)==-1) {
+           cancel_sigs = 1;
+           nperror("sigaction");
+       }
+    }
+    /* note that now oldaction is the previous SIGINT signal handler, to 
+       be restored later */
+
+    /* if the platform supports disabling individual control characters */
+#ifdef _POSIX_VDISABLE
+    if (!cancel_sigs && tcgetattr(0, &term) == -1) {
+       cancel_sigs = 2;
+       nperror("tcgetattr");
+    }
+    if (!cancel_sigs) {
+       newterm = term;
+       /* Grab oldterm's VINTR key :-) */
+       newterm.c_cc[VINTR] = oldterm.c_cc[VINTR];
+       if (tcsetattr(0, TCSANOW, &newterm) == -1) {
+           cancel_sigs = 2;
+           nperror("tcsetattr");
+       }
+    }
+#endif   /* _POSIX_VDISABLE */
+
+    read_file(fd[0],"stdin",0);
+    set_modified();
+
+    if (wait(NULL) == -1) 
+       nperror("wait");
+
+#ifdef _POSIX_VDISABLE
+    if (!cancel_sigs && tcsetattr(0, TCSANOW, &term) == -1)
+       nperror("tcsetattr");
+#endif   /* _POSIX_VDISABLE */
+
+    if (cancel_sigs!=1 && sigaction(SIGINT, &oldaction, NULL) == -1)
+       nperror("sigaction");
+
+    return 0;
+}
+#endif /* NANO_SMALL */
+
 int do_exit(void)
 {
     int i;
diff --git a/proto.h b/proto.h
index 8a158be7cea195bfb699aa00a82ae79f3ce7bc91..945aa86b2ba6235f2ec22a745467bd407d22cab2 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -116,6 +116,8 @@ int open_file(char *filename, int insert, int quiet);
 int do_insertfile(int loading_file);
 int length_of_list(shortcut *s);
 int num_of_digits(int n);
+int open_pipe(char *command);
+int read_file(int fd, char *filename, int quiet);
 
 #ifdef ENABLE_MULTIBUFFER
 int add_open_file(int update);
@@ -171,6 +173,7 @@ void center_cursor(void);
 void bottombars(shortcut *s);
 void blank_statusbar_refresh(void);
 void *nmalloc (size_t howmuch);
+void nperror(const char *s);
 void *mallocstrcpy(char *dest, char *src);
 void wrap_reset(void);
 void display_main_list(void);
diff --git a/utils.c b/utils.c
index 826c86a4b265b976aff24d8b1af632ca0bb74aad..aa9dc25cdc0e2359dbcfae842d20ddcda1866b52 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 
+#include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
@@ -160,6 +161,18 @@ char *strstrwrapper(char *haystack, char *needle, char *rev_start)
 #endif
 }
 
+/* This is a wrapper for the perror function.  The wrapper takes care of 
+ * ncurses, calls perror (which writes to STDERR), then refreshes the 
+ * screen.  Note that nperror causes the window to flicker once.
+ */
+void nperror(const char *s) {
+       /* leave ncurses mode, go to the terminal */
+    if (endwin() != ERR) {
+       perror(s);              /* print the error */
+       total_refresh();        /* return to ncurses and repaint */
+    }
+}
+
 /* Thanks BG, many ppl have been asking for this... */
 void *nmalloc(size_t howmuch)
 {