📄 shell.c
字号:
/* shell.c - user defined shell commands Copyright (C) 1996-2000 Paul Sheer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include <sys/types.h>#if HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#ifndef WEXITSTATUS#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)#endif#ifndef WIFEXITED#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)#endif#include <errno.h>#ifdef HAVE_SYS_ERRNO_H#include <sys/errno.h>#endif#include "editoptions.h"#include "shell.h"#include "pool.h"#include "mad.h"#define shell_error_dialog(h,t) CErrorDialog(e->widget->winid,20,20,h,"%s",t)#undef gettext_noop#define gettext_noop(x) xextern struct look *look;int save_options_section (const char *file, const char *section, const char *text);extern char *editor_options_file;extern char *init_font;extern Window main_window;/* Here are the default example shells */struct shell_cmd default_scripts[] ={ { " Sed ", "Sed...\tC-M-d", '~', XK_d, Mod1Mask | ControlMask, gettext_noop (" Enter sed arguments (see sed manpage) : "), SHELL_OPTION_SAVE_BLOCK | SHELL_OPTION_REQUEST_ARGUMENTS | SHELL_OPTION_DELETE_BLOCK | SHELL_OPTION_INSERT_STDOUT | SHELL_OPTION_DISPLAY_ERROR_FILE | SHELL_OPTION_CHECK_ERROR_FILE, 0, "#!/bin/sh\n" \ "cat %b | sed %a 2>%e\n" }, { gettext_noop (" Indent "), gettext_noop ("'indent' C Formatter\tS-F9"), '~', XK_F9, ShiftMask, "", SHELL_OPTION_SAVE_BLOCK | SHELL_OPTION_DELETE_BLOCK | SHELL_OPTION_DISPLAY_ERROR_FILE | SHELL_OPTION_CHECK_ERROR_FILE | SHELL_OPTION_INSERT_BLOCK_FILE, 0, "#!/bin/sh\n" \ "indent -kr -pcs %b 2>%e\n" }, { gettext_noop (" Sort "), gettext_noop ("Sort...\tM-t"), '~', XK_t, Mod1Mask, gettext_noop (" Enter sort options (see sort manpage) : "), SHELL_OPTION_SAVE_BLOCK | SHELL_OPTION_REQUEST_ARGUMENTS | SHELL_OPTION_DELETE_BLOCK | SHELL_OPTION_INSERT_STDOUT | SHELL_OPTION_DISPLAY_ERROR_FILE | SHELL_OPTION_CHECK_ERROR_FILE, 0, "#!/bin/sh\n" \ "sort %a %b 2>%e\n" }, { " Ispell ", gettext_noop ("'ispell' Spell Check\tC-p"), '~', XK_p, ControlMask, "", SHELL_OPTION_SAVE_BLOCK | SHELL_OPTION_DELETE_BLOCK | SHELL_OPTION_INSERT_BLOCK_FILE, 0, "#!/bin/sh\n" \ XTERM_CMD " -e ispell %b\n" }, { " Make ", gettext_noop ("Run make in curr. dir\tM-F7"), '~', XK_F7, Mod1Mask, "", SHELL_OPTION_DISPLAY_STDOUT_CONTINUOUS | SHELL_OPTION_DISPLAY_STDERR_CONTINUOUS, 0, "#!/bin/sh\n" \ "cd %d\n" \ "make\n" \ "echo Done\n" }, { " Latex ", "Latex\tC-M-l", '~', XK_l, Mod1Mask | ControlMask, "", SHELL_OPTION_DISPLAY_STDOUT_CONTINUOUS | SHELL_OPTION_DISPLAY_STDERR_CONTINUOUS, 0, "#!/bin/sh\n" \ "cd %p\n" \ "latex %f\n" \ "echo Done\n" }, { " Latex to PS ", "Latex to PS\tC-M-p", '~', XK_p, Mod1Mask | ControlMask, "", SHELL_OPTION_DISPLAY_STDOUT_CONTINUOUS | SHELL_OPTION_DISPLAY_STDERR_CONTINUOUS, 0, "#!/bin/sh\n" \ "cd %p\n" \ "latex %f\n" \ "dvips %n.dvi\n" \ "echo Done\n" }, { " Xdvi ", "Xdvi\tC-M-d", '~', XK_d, Mod1Mask | ControlMask, "", SHELL_OPTION_RUN_IN_BACKGROUND, 0, "#!/bin/sh\n" \ "cd %p\n" \ "xdvi %n.dvi 2>%e\n" }, { " GhostView ", "GhostView\tC-M-g", '~', XK_g, Mod1Mask | ControlMask, "", SHELL_OPTION_RUN_IN_BACKGROUND, 0, "#!/bin/sh\n" \ "cd %p\n" \ "ghostview %n.ps 2>%e\n" }, { gettext_noop (" Run Application "), gettext_noop ("Run Application...\tC-M-a"), '~', XK_a, Mod1Mask | ControlMask, gettext_noop (" Enter command : "), SHELL_OPTION_REQUEST_ARGUMENTS | SHELL_OPTION_RUN_IN_BACKGROUND, 0, "#!/bin/sh\n" \ "%a 2>%e\n" }, { gettext_noop (" Terminal Application "), gettext_noop ("Run Terminal App...\tC-M-e"), '~', XK_e, Mod1Mask | ControlMask, gettext_noop (" Enter command : "), SHELL_OPTION_REQUEST_ARGUMENTS | SHELL_OPTION_RUN_IN_BACKGROUND, 0, "#!/bin/sh\n" \ XTERM_CMD " -e %a\n" }, { " Translate ", "Translate...\tC-M-t", '~', XK_t, Mod1Mask | ControlMask, gettext_noop (" Enter args for tr (See `man tr' for help): "), SHELL_OPTION_SAVE_BLOCK | SHELL_OPTION_REQUEST_ARGUMENTS | SHELL_OPTION_DELETE_BLOCK | SHELL_OPTION_INSERT_STDOUT | SHELL_OPTION_DISPLAY_ERROR_FILE | SHELL_OPTION_CHECK_ERROR_FILE, 0, "#!/bin/sh\n" \ "cat %b | tr %a 2>%e\n" }, { gettext_noop (" C Run "), gettext_noop ("Run this file\tC-M-r"), '~', XK_r, Mod1Mask | ControlMask, "", SHELL_OPTION_RUN_IN_BACKGROUND, 0, "#!/bin/sh\n" \ XTERM_CMD " -e %p/%n\n" }, { gettext_noop (" C Compile "), "Cc\tC-M-c", '~', XK_c, Mod1Mask | ControlMask, "", SHELL_OPTION_DISPLAY_STDOUT_CONTINUOUS | SHELL_OPTION_DISPLAY_STDERR_CONTINUOUS, 0, "#!/bin/sh\n" \ "cd %p\n" \ "cc -g -Wall -o %n %f\n" \ "echo Done\n" }};char *hme (char *text);char *substitute_strings (char *text, char *cmdline_options, char *editor_file, char *dnd_major_type, char *dnd_minor_type, char *dnd_data_file);/* {{{ dynamic display of shell output in a dialog box */#define MAX_RUNNING_SHELLS 32static struct running_shell { pid_t shell_pid; int shell_pipe; POOL *shell_pool; char *shell_name; CWidget *w; int killme;} running_shell[MAX_RUNNING_SHELLS];static void kill_process (pid_t p){ if (p) kill (p, SIGTERM);}/* one of these must be non-zero */static int find_shell (pid_t p, char *name, CWidget * w){ int i; for (i = 0; i < MAX_RUNNING_SHELLS; i++) { if (p) if (running_shell[i].shell_pid == p) return i; if (name && running_shell[i].shell_name) if (*name) if (!strcmp (name, running_shell[i].shell_name)) return i; if (w) if ((unsigned long) w == (unsigned long) running_shell[i].w) return i; } return -1;}static int new_shell (char *name){ int i; i = find_shell (0, name, 0); if (i < 0) { for (i = 0; i < MAX_RUNNING_SHELLS; i++) if (!running_shell[i].shell_name) { memset (&running_shell[i], 0, sizeof (struct running_shell)); running_shell[i].shell_pipe = -1; running_shell[i].shell_name = name; /* FIXME: strdup() then free() later - static is ok for now */ return i; } } return -1;}void text_free (void *x){ if (x) free (x);}static void shell_pool_update (int fd, fd_set * reading, fd_set * writing, fd_set * error, void *data);char *shell_free_pool (int i){ char *s = 0; if (i < 0) return 0; if (running_shell[i].shell_pool) s = (char *) pool_break (running_shell[i].shell_pool); if (running_shell[i].shell_pipe >= 0) { CRemoveWatch (running_shell[i].shell_pipe , shell_pool_update, WATCH_READING); close (running_shell[i].shell_pipe); } memset (&running_shell[i], 0, sizeof (struct running_shell)); running_shell[i].shell_pipe = -1; return s;}/* kills an executing shell whose output is being dynamically displayed */void set_to_kill (pid_t p){ int i; i = find_shell (p, 0, 0); if (i >= 0) running_shell[i].killme = 1;}/* kills an executing shell whose output is being dynamically displayed */static int kill_shell (pid_t p, char *name, CWidget * w){ int i; i = find_shell (p, name, w); if (i < 0) return -1; kill_process (running_shell[i].shell_pid); set_to_kill (running_shell[i].shell_pid); return i;}static int restart_shell (pid_t p, char *name, CWidget * w){ int i; i = find_shell (p, name, w); if (i < 0) return new_shell (name); if (running_shell[i].shell_pipe >= 0) { CRemoveWatch (running_shell[i].shell_pipe, shell_pool_update, WATCH_READING); close (running_shell[i].shell_pipe); } kill_process (running_shell[i].shell_pid); running_shell[i].shell_pid = 0; running_shell[i].shell_pipe = -1; running_shell[i].killme = 0; if (running_shell[i].shell_pool) { pool_break (running_shell[i].shell_pool); running_shell[i].shell_pool = 0; } return i;}void goto_error (char *message, int raise_wm_window);/* if you double click on a line of gcc output, this will take you to the file */static int goto_file_callback (CWidget * w, XEvent * x, CEvent * c){ if (c->double_click || (c->command == CK_Enter && !c->handled)) { int width; char *q; CPushFont ("editor", 0); width = w->options & TEXTBOX_WRAP ? (w->width - TEXTBOX_BDR) / FONT_MEAN_WIDTH : 32000; CPopFont (); q = strline (w->text, strmovelines (w->text, w->current, w->cursor - w->firstline, width)); goto_error (q, 1); } return 0;}static char *nm (int i, char *a, char *b, char *c){ static char id[36]; sprintf (id, "%.3d%s", i, a); if (b) { strcat (id, "."); strcat (id, b); if (c) { strcat (id, "."); strcat (id, c); } } return id;}/* if the dynamic output dialog's tick button is click, then terminate: */static int display_file_callback (CWidget * w, XEvent * x, CEvent * c){ shell_free_pool (kill_shell (0, 0, CIdent (nm (atoi (w->ident), "shelldisplaytext", "text", 0)))); CDestroyWidget (nm (atoi (w->ident), "shelldisplaytext", 0, 0)); return 1;}#if 0 fd_set reading; struct timeval tv; FD_ZERO (&reading); for (i = 0; i < MAX_RUNNING_SHELLS; i++) { if (running_shell[i].shell_pipe >= 0 && running_shell[i].shell_name) { FD_SET (running_shell[i].shell_pipe, &reading); if (n < (int) running_shell[i].shell_pipe) n = running_shell[i].shell_pipe; } } if (n < 0) { CAddCallback ("AlarmCallback", 0); return 0; } tv.tv_sec = 0; tv.tv_usec = 0;#endif#define CHUNK 8192static void shell_pool_update (int fd, fd_set * reading, fd_set * writing, fd_set * error, void *data){ CWidget *w; struct running_shell *r; int i, count = 0, do_redraw = 0; r = &running_shell[i = (int) data]; if (r->shell_pipe != fd) { printf ("huh??\n"); }/* first check if we are still on the screen */ w = CIdent (nm (i, "shelldisplaytext", "text", 0)); if (!w) { shell_free_pool (kill_shell (0, 0, w)); return; }/* is the buffer initialised? : */ if (!r->shell_pool) r->shell_pool = pool_init ();/* read a little */ for (;;) { int c, j; unsigned char *p; if (pool_freespace (r->shell_pool) < CHUNK + 1) { pool_advance (r->shell_pool, CHUNK + 1); do_redraw = 1; /* must redraw cause pool has changed */ } while ((c = read (fd, pool_current (r->shell_pool), CHUNK)) == -1 && errno == EINTR);/* translate unreadables */ for (j = 0, p = (unsigned char *) pool_current (r->shell_pool); j < c; j++, p++) { if (*p == '\t') *p = ' '; else if (*p == '\n') *p = '\n'; else if (!FONT_PER_CHAR(*p)) *p = '?'; } if (c <= 0) break; count += c; pool_current (r->shell_pool) += c; break; } pool_null (r->shell_pool); /* adds a zero to the end *//* do we need to refresh? : */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -