📄 os_dep.c
字号:
/* os_dep.c * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "links.h"#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#if defined(HAVE_LIBGPM) && defined(HAVE_GPM_H)#define USE_GPM#endif#ifdef USE_GPM#include <gpm.h>#endif/* prototypes */int get_e(char *);void sigwinch(void *);void exec_new_links(struct terminal *, unsigned char *, unsigned char *, unsigned char *);void open_in_new_twterm(struct terminal *, unsigned char *, unsigned char *);void open_in_new_xterm(struct terminal *, unsigned char *, unsigned char *);void open_in_new_screen(struct terminal *, unsigned char *, unsigned char *);void open_in_new_vio(struct terminal *, unsigned char *, unsigned char *);void open_in_new_fullscreen(struct terminal *, unsigned char *, unsigned char *);void open_in_new_win32(struct terminal *, unsigned char *, unsigned char *);void open_in_new_be(struct terminal *, unsigned char *, unsigned char *);void open_in_new_g(struct terminal *, unsigned char *, unsigned char *);int is_safe_in_shell(unsigned char c){ return c == '@' || c == '+' || c == '-' || c == '.' || c == ',' || c == '=' || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= 'a' && c <= 'z');}int is_safe_in_url(unsigned char c){ return is_safe_in_shell(c) || c == ':' || c == '/' || c >= 0x80;}void check_shell_security(unsigned char **cmd){ unsigned char *c = *cmd; while (*c) { if (!is_safe_in_shell(*c)) *c = '_'; c++; }}int check_shell_url(unsigned char *url){ while (*url) { if (!is_safe_in_url(*url)) return -1; url++; } return 0;}unsigned char *escape_path(unsigned char *path){ unsigned char *result; size_t i; if (strchr(path, '"')) return stracpy(path); for (i = 0; path[i]; i++) if (!is_safe_in_url(path[i])) goto do_esc; return stracpy(path); do_esc: result = stracpy("\""); add_to_strn(&result, path); add_to_strn(&result, "\""); return result;}int get_e(char *env){ char *v; if ((v = getenv(env))) return atoi(v); return 0;}void ignore_signals(void){ signal(SIGPIPE, SIG_IGN);#ifdef SIGXFSZ signal(SIGXFSZ, SIG_IGN);#endif}char *clipboard = NULL;#if defined(WIN32)#include <windows.h>#endif#if defined(OS2)#define INCL_MOU#define INCL_VIO#define INCL_DOSPROCESS#define INCL_DOSERRORS#define INCL_DOSMODULEMGR#define INCL_WIN#define INCL_WINCLIPBOARD#define INCL_WINSWITCHLIST#include <os2.h>#include <io.h>#include <process.h>#include <sys/video.h>#ifdef HAVE_SYS_FMUTEX_H#include <sys/builtin.h>#include <sys/fmutex.h>#endif#ifdef X2/* from xf86sup - XFree86 OS/2 support driver */#include <pty.h>#endif#endif#if defined(O_SIZE) && defined(__EMX__)int open_prealloc(char *name, int flags, int mode, off_t siz){ return open(name, flags | O_SIZE, mode, (unsigned long)siz);}void prealloc_truncate(int h, off_t siz){ ftruncate(h, siz);}#endif/* Terminal size */#ifdef WIN32/* Cygwin has a bug and loses SIGWINCH sometimes, so poll it */static void winch_thread(void *p, int l){ static int old_xsize, old_ysize; static int cur_xsize, cur_ysize; if (get_terminal_size(0, &old_xsize, &old_ysize)) return; while (1) { if (get_terminal_size(1, &cur_xsize, &cur_ysize)) return; if ((old_xsize != cur_xsize) || (old_ysize != cur_ysize)) { old_xsize = cur_xsize; old_ysize = cur_ysize; raise(SIGWINCH); } sleep(1); }}static void win32_resize_poll(void){ static int winch_thread_running = 0; if (!winch_thread_running) { if (start_thread(winch_thread, NULL, 0) >= 0) winch_thread_running = 1; }}#endif#if defined(UNIX) || defined(BEOS) || defined(RISCOS) || defined(ATHEOS) || defined(WIN32) || defined(SPAD)void sigwinch(void *s){ ((void (*)(void))s)();}void handle_terminal_resize(int fd, void (*fn)(void)){ install_signal_handler(SIGWINCH, sigwinch, fn, 0);#ifdef WIN32 win32_resize_poll();#endif}void unhandle_terminal_resize(int fd){ install_signal_handler(SIGWINCH, NULL, NULL, 0);}int get_terminal_size(int fd, int *x, int *y){ struct winsize ws; if (!x || !y) return -1; if (ioctl(1, TIOCGWINSZ, &ws) != -1) { if (!(*x = ws.ws_col) && !(*x = get_e("COLUMNS"))) *x = 80; if (!(*y = ws.ws_row) && !(*y = get_e("LINES"))) *y = 24; return 0; } else { if (!(*x = get_e("COLUMNS"))) *x = 80; if (!(*y = get_e("LINES"))) *y = 24; } return 0;}#elif defined(OS2)#define A_DECL(type, var) type var##1, var##2, *var = _THUNK_PTR_STRUCT_OK(&var##1) ? &var##1 : &var##2int is_xterm(void){ static int xt = -1; if (xt == -1) xt = !!getenv("WINDOWID"); return xt;}int winch_pipe[2];int winch_thread_running = 0;#define WINCH_SLEEPTIME 500 /* time in ms for winch thread to sleep */static void winch_thread(void){ /* A thread which regularly checks whether the size of window has changed. Then raise SIGWINCH or notifiy the thread responsible to handle this. */ static int old_xsize, old_ysize; static int cur_xsize, cur_ysize; ignore_signals(); if (get_terminal_size(1, &old_xsize, &old_ysize)) return; while (1) { if (get_terminal_size(1, &cur_xsize, &cur_ysize)) return; if ((old_xsize != cur_xsize) || (old_ysize != cur_ysize)) { old_xsize = cur_xsize; old_ysize = cur_ysize; write(winch_pipe[1], "x", 1); /* Resizing may take some time. So don't send a flood of requests?! */ _sleep2(2*WINCH_SLEEPTIME); } else _sleep2(WINCH_SLEEPTIME); }}static void winch(void *s){ char c; while (can_read(winch_pipe[0]) && read(winch_pipe[0], &c, 1) == 1); ((void (*)(void))s)();}void handle_terminal_resize(int fd, void (*fn)(void)){ if (!is_xterm()) return; if (!winch_thread_running) { if (c_pipe(winch_pipe) < 0) return; winch_thread_running = 1; _beginthread((void (*)(void *))winch_thread, NULL, 0x32000, NULL); } set_handlers(winch_pipe[0], winch, NULL, NULL, fn);}void unhandle_terminal_resize(int fd){ set_handlers(winch_pipe[0], NULL, NULL, NULL, NULL);}int get_terminal_size(int fd, int *x, int *y){ if (!x || !y) return -1; if (is_xterm()) {#ifdef X2 /* int fd; */ int arc; struct winsize win; /* fd = STDIN_FILENO; */ arc = ptioctl(1, TIOCGWINSZ, &win); if (arc) { *x = 80; *y = 24; return 0; } *y = win.ws_row; *x = win.ws_col; goto set_default;#else *x = 80; *y = 24; return 0;#endif } else { int a[2] = { 0, 0 }; _scrsize(a); *x = a[0]; *y = a[1]; set_default: if (*x == 0) { *x = get_e("COLUMNS"); if (*x == 0) *x = 80; } if (*y == 0) { *y = get_e("LINES"); if (*y == 0) *y = 24; } } return 0;}#elif defined(WIN32)#endif/* Pipe */#if defined(UNIX) || defined(BEOS) || defined(RISCOS) || defined(ATHEOS) || defined(SPAD)void set_bin(int fd){}int c_pipe(int *fd){ return pipe(fd);}#elif defined(OS2) || defined(WIN32)void set_bin(int fd){ setmode(fd, O_BINARY);}int c_pipe(int *fd){ int r = pipe(fd); if (!r) set_bin(fd[0]), set_bin(fd[1]); return r;}#endif/* Filename */int check_file_name(unsigned char *file){ return 1; /* !!! FIXME */}/* Exec */int can_twterm(void) /* Check if it make sense to call a twterm. */{ static int xt = -1; if (xt == -1) xt = !!getenv("TWDISPLAY"); return xt;}#if defined(UNIX) || defined(SPAD)int is_xterm(void){ static int xt = -1; if (xt == -1) xt = getenv("DISPLAY") && *getenv("DISPLAY"); return xt;}#elif defined(BEOS) || defined(ATHEOS)int is_xterm(void){ return 0;}#elif defined(WIN32)int is_xterm(void){ static int xt = -1; if (xt == -1) xt = !!getenv("WINDOWID"); return xt;}#elif defined(RISCOS)int is_xterm(void){ return 1;}#endiftcount resize_count = 0;void close_fork_tty(void){ struct terminal *t; struct download *d; struct connection *c; struct k_conn *k; foreach (t, terminals) if (t->fdin > 0) close(t->fdin); foreach (d, downloads) if (d->handle > 0) close(d->handle); foreach (c, queue) close_socket(&c->sock1), close_socket(&c->sock2); foreach (k, keepalive_connections) close(k->conn);}#if defined(WIN32)void get_path_to_exe(void){ /* Standard method (argv[0]) doesn't work, if links is executed from symlink --- it returns symlink name and cmd.exe is unable to start it */ unsigned r; static unsigned char path[4096]; r = GetModuleFileName(NULL, path, sizeof path); if (r <= 0 || r >= sizeof path) { path_to_exe = g_argv[0]; return; } path_to_exe = path;}#elif defined(OS2)void get_path_to_exe(void){ /* If you spawn links with quotation marks from cmd.exe, the quotation marks will be present in g_argv[0] ... and will prevent executing it */ static char path[270]; PPIB pib = NULL; path_to_exe = g_argv[0]; /*if (!strchr(path_to_exe, ' ') && !strchr(path_to_exe, '"')) return;*/ DosGetInfoBlocks(NULL, &pib); if (!pib) return; if (DosQueryModuleName(pib->pib_hmte, sizeof path, path)) return; path_to_exe = path;}#elsevoid get_path_to_exe(void){ path_to_exe = g_argv[0];}#endif#if defined(UNIX) || defined(BEOS) || defined(RISCOS) || defined(ATHEOS) || defined(SPAD)#if defined(BEOS) && defined(HAVE_SETPGID)int exe(char *path, int fg){ pid_t p; int s; fg=fg; /* ignore flag */ if (!(p = fork())) { setpgid(0, 0); system(path); _exit(0); } if (p > 0) waitpid(p, &s, 0); else return system(path); return 0;}#else/* UNIX */int exe(char *path, int fg){#ifdef G if (F && drv->exec) return drv->exec(path, fg);#endif#ifdef SIGTSTP signal(SIGTSTP, SIG_DFL);#endif#ifdef SIGCONT signal(SIGCONT, SIG_DFL);#endif#ifdef SIGWINCH signal(SIGWINCH, SIG_DFL);#endif return system(path);}#endif/* clipboard -> links */unsigned char *get_clipboard_text(struct terminal *term){#ifdef GRDRV_X if(term && term->dev && term->dev->drv && !strcmp(term->dev->drv->name,"x")) { return x_get_clipboard_text(); }#endif return stracpy(clipboard);}/* links -> clipboard */void set_clipboard_text(struct terminal *term, unsigned char *data){#ifdef GRDRV_X if(term && term->dev && term->dev->drv && !strcmp(term->dev->drv->name,"x")) { x_set_clipboard_text(term->dev, data); return; }#endif if (clipboard) mem_free(clipboard); clipboard = stracpy(data);}int clipboard_support(struct terminal *term){#ifdef GRDRV_X if(term && term->dev && term->dev->drv && !strcmp(term->dev->drv->name,"x")) { return 1; }#endif return 0;}void set_window_title(unsigned char *title){ /* !!! FIXME */}unsigned char *get_window_title(void){ /* !!! FIXME */ return NULL;}int resize_window(int x, int y){ return -1;}#elif defined(WIN32)static int is_winnt(void){ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof v; if (!GetVersionEx(&v)) return 0; return v.dwPlatformId >= VER_PLATFORM_WIN32_NT;}#define WIN32_START_STRING "start /wait "int exe(char *path, int fg){ /* This is very tricky. We must have exactly 3 arguments, the first one shell and the second one "/c", otherwise Cygwin would quote the arguments and trash them */ int ct; char buffer[1024]; char buffer2[1024]; pid_t pid; unsigned char *x1; char *arg; x1 = GETSHELL; if (!x1) x1 = DEFAULT_SHELL; arg = alloca(strlen(WIN32_START_STRING) + 3 + strlen(path) + 1); strcpy(arg, WIN32_START_STRING); if (*path == '"' && strlen(x1) >= 7 && !strcasecmp(x1 + strlen(x1) - 7, "cmd.exe")) strcat(arg, "\"\" "); strcat(arg, path); ct = GetConsoleTitle(buffer, sizeof buffer); if (!(pid = fork())) { int i; /* Win98 crashes if we spawn command.com and have some sockets open */ for (i = 0; i < FD_SETSIZE; i++) close(i); open("nul", O_RDONLY); open("nul", O_WRONLY); open("nul", O_WRONLY); execlp(x1, x1, "/c", arg, NULL); _exit(1); } if (!is_winnt()) { sleep(1); if (ct && GetConsoleTitle(buffer2, sizeof buffer2) && !casecmp(buffer2, "start", 5)) { SetConsoleTitle(buffer); } } if (pid != -1) waitpid(pid, NULL, 0); return 0;}unsigned char *get_clipboard_text(struct terminal *term){ char buffer[256]; unsigned char *str, *s, *d; int l; int r; int h = open("/dev/clipboard", O_RDONLY); if (h == -1) return stracpy(clipboard); set_bin(h); /* O_TEXT doesn't work on clipboard handle */ str = init_str(); l = 0; while ((r = hard_read(h, buffer, sizeof buffer)) > 0) add_bytes_to_str(&str, &l, buffer, r); close(h); for (s = str, d = str; *s; s++) if (!(s[0] == '\r' && s[1] == '\n')) *d++ = *s; *d = 0; return str;}/* Putting Czech characters to clipboard doesn't work, but it should be fixed rather in Cygwin than here */void set_clipboard_text(struct terminal *term, unsigned char *data){ unsigned char *conv_data; int l; int h; if (clipboard) mem_free(clipboard); clipboard = stracpy(data); h = open("/dev/clipboard", O_WRONLY); if (h == -1) return; set_bin(h); /* O_TEXT doesn't work on clipboard handle */ conv_data = init_str(); l = 0; for (; *data; data++) if (*data == '\n') add_to_str(&conv_data, &l, "\r\n"); else add_chr_to_str(&conv_data, &l, *data); hard_write(h, conv_data, l); mem_free(conv_data); close(h);}int clipboard_support(struct terminal *term){ return 1;}static int get_windows_cp(void){ char str[6]; int cp, idx; static int win_cp_idx = -1; if (win_cp_idx != -1) return win_cp_idx; cp = GetConsoleOutputCP(); if (cp <= 0 || cp >= 100000) return 0; sprintf(str, "%d", cp); if ((idx = get_cp_index(str)) < 0) return 0; win_cp_idx = idx; return idx;}static int get_utf8_cp(void){ static int idx = -1; return idx >= 0 ? idx : (idx = get_cp_index("utf-8"));}void set_window_title(unsigned char *title){ unsigned char *t; struct conv_table *ct; if (is_xterm()) return; ct = get_translation_table(get_utf8_cp(), get_windows_cp()); t = convert_string(ct, title, strlen(title), NULL); SetConsoleTitle(t); mem_free(t);}unsigned char *get_window_title(void){ struct conv_table *ct; int r; char buffer[1024]; if (is_xterm()) return NULL; if (!(r = GetConsoleTitle(buffer, sizeof buffer))) return NULL; ct = get_translation_table(get_windows_cp(), get_utf8_cp()); return convert_string(ct, buffer, r, NULL);}static void call_resize(unsigned char *x1, int x, int y){ pid_t pid; unsigned char arg[40]; sprintf(arg, "mode %d,%d", x, y); if (!(pid = fork())) { int i; /* Win98 crashes if we spawn command.com and have some sockets open */ for (i = 0; i < FD_SETSIZE; i++) if (i != 1 && i != 2) close(i); open("nul", O_WRONLY); execlp(x1, x1, "/c", arg, NULL); _exit(1); } if (pid != -1) waitpid(pid, NULL, 0);}int resize_window(int x, int y){ int old_x, old_y; int ct = 0, fullscreen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -