- 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:
- 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.
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)
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)
#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;
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);
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);
#include "config.h"
+#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#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)
{