myadm

Simple MySQL client for the terminal
git clone git://git.bitsmanent.org/myadm
Log | Files | Refs | README | LICENSE

commit 8f54c4cc246b253fdc28436f7ffeadcaf3a9a5c2
parent a9c88ec161ce482fe271ea4f16f35014b068a7f0
Author: Claudio Alessi <smoppy@gmail.com>
Date:   Tue, 26 Apr 2016 22:30:20 +0200

Improve how the $EDITOR gets called.

First we call endwin() (which is called by stfl_free() through ui_end()),
then take off all the signal handlers from ncurses. At this point we can
fork the editor and wait or it to exit. By calling ui_init() we restore
ncurses signal handlers and may safely continue execution.

This is quite simple but required me to dig in some code. For curious, give a
look at the mutt's _mutt_system() function.

As a side effect, it was also possible to clean up fget() which was weirdly
removing a newline from the buffer.

Diffstat:
Mmyadm.c | 70++++++++++++++++++++++++++++++++++++----------------------------------
1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/myadm.c b/myadm.c @@ -15,6 +15,7 @@ #include <stdarg.h> #include <string.h> #include <stdlib.h> +#include <signal.h> #include <ctype.h> #include <mysql.h> #include <stfl.h> @@ -119,7 +120,6 @@ void reload(const Arg *arg); void run(void); void setview(const char *name, void (*func)(void)); void setup(void); -void spawn(const Arg *arg); void ui_end(void); struct stfl_form *ui_getform(wchar_t *code); void ui_init(void); @@ -288,27 +288,42 @@ ecalloc(size_t nmemb, size_t size) { char * editbuf(char *in, int len, int *sz) { - Arg a; - char tmp[] = "myadm.XXXXXX", *buf; - int fd; - - fd = mkstemp(tmp); - if(fd == -1) - return NULL; - close(fd); - if(fput(tmp, in, len) == -1) { - unlink(tmp); - return NULL; + pid_t pid; + char tmp[] = "myadm.XXXXXX", *buf; + int fd, rc = -1; + + fd = mkstemp(tmp); + if(fd == -1) + return NULL; + close(fd); + if(fput(tmp, in, len) == -1) { + unlink(tmp); + return NULL; + } + + ui_end(); /* endwin() */ + + /* take off ncurses signal handlers */ + struct sigaction sa = {.sa_flags = 0, .sa_handler = SIG_DFL}; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGTSTP, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); + + if((pid = fork()) == 0) { + execl("/bin/sh", "sh", "-c", "$EDITOR \"$0\"", tmp, NULL); + _exit(127); + } + else if(pid != -1) { + while(!WIFEXITED(rc)) + waitpid(pid, &rc, 0); } - a.v = (const char*[]){"/bin/sh", "-c", "$EDITOR \"$0\"", tmp, NULL}; - ui_end(); - spawn(&a); - while(wait(NULL) == -1); - ui_init(); + ui_init(); /* restore ncurses signal handlers */ ui_redraw(); - buf = fget(tmp, sz); - unlink(tmp); - return buf; + + buf = fget(tmp, sz); + unlink(tmp); + return buf; } void @@ -370,7 +385,7 @@ escape(char *s, char c, int *nc) { char * fget(char *fn, int *sz) { int fd; - char *buf; + char *buf, *p; fd = open(fn, O_RDONLY); if(fd == -1) @@ -379,8 +394,6 @@ fget(char *fn, int *sz) { lseek(fd, 0, SEEK_SET); buf = ecalloc(1, *sz+1); read(fd, buf, *sz); - if(*sz && buf[*sz - 1] == '\n') - --*sz; buf[*sz] = '\0'; close(fd); return buf; @@ -711,17 +724,6 @@ setup(void) { } void -spawn(const Arg *arg) { - if(!fork()) { - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - fprintf(stderr, "myadm: execvp %s", ((char **)arg->v)[0]); - perror(" failed"); - exit(EXIT_SUCCESS); - } -} - -void ui_end(void) { stfl_reset(); stfl_ipool_destroy(ipool);