From 77777d4c0d497b2cac51825425cf444e10d5ade5 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Fri, 29 Mar 2002 16:31:29 +0000 Subject: [PATCH] Add David Benbennick's changes to open_pipe() and move it to nano.c, and add his nperror function git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1159 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 9 +++-- files.c | 51 ++------------------------ nano.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ proto.h | 3 ++ utils.c | 13 +++++++ 5 files changed, 129 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 540ea9f4..edbcf316 100644 --- 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 0df7b24d..5a9a7238 100644 --- 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 cfb666f3..bb75156f 100644 --- 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 8a158be7..945aa86b 100644 --- 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 826c86a4..aa9dc25c 100644 --- a/utils.c +++ b/utils.c @@ -21,6 +21,7 @@ #include "config.h" +#include #include #include #include @@ -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) {