static void failed(const char *s) { int save = errno; IGNORE_RC(write(2, myname, strlen(myname))); IGNORE_RC(write(2, ": ", (size_t) 2)); errno = save; perror(s); exit(EXIT_FAILURE); }
/** * Insert 'ch' at position 'pos' * * Returns 1 if the line needs to be refreshed, 2 if not * and 0 if nothing was inserted (no room) */ static int insert_char(struct current *current, int pos, int ch) { char buf[3]; int n = utf8_getchars(buf, ch); if (has_room(current, n) && pos >= 0 && pos <= current->chars) { int p1, p2; int ret = 1; p1 = utf8_index(current->buf, pos); p2 = p1 + n; #ifdef USE_TERMIOS /* optimise the case where adding a single char to the end and no scrolling is needed */ if (current->pos == pos && current->chars == pos) { if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { IGNORE_RC(write(current->fd, buf, n)); ret = 2; } } #endif memmove(current->buf + p2, current->buf + p1, current->len - p1); memcpy(current->buf + p1, buf, n); current->len += n; current->chars++; if (current->pos >= pos) { current->pos++; } return ret; } return 0; }
int main(int argc, char *argv[]) { int ch; char buffer[80]; attr_t underline; bool i_option = FALSE; setlocale(LC_ALL, ""); while ((ch = getopt(argc, argv, "i")) != -1) { switch (ch) { case 'i': i_option = TRUE; break; default: usage(); } } printf("starting filter program using %s...\n", i_option ? "initscr" : "newterm"); filter(); if (i_option) { initscr(); } else { (void) newterm((char *) 0, stdout, stdin); } cbreak(); keypad(stdscr, TRUE); if (has_colors()) { int background = COLOR_BLACK; start_color(); #if HAVE_USE_DEFAULT_COLORS if (use_default_colors() != ERR) background = -1; #endif init_pair(1, COLOR_CYAN, (short) background); underline = (attr_t) COLOR_PAIR(1); } else { underline = A_UNDERLINE; } while (new_command(buffer, sizeof(buffer) - 1, underline) != ERR && strlen(buffer) != 0) { reset_shell_mode(); printf("\n"); fflush(stdout); IGNORE_RC(system(buffer)); reset_prog_mode(); touchwin(stdscr); erase(); refresh(); } printw("done"); refresh(); endwin(); ExitProgram(EXIT_SUCCESS); }
static void outbuf_flush(Iso2022Ptr is, int fd) { int rc; unsigned i = 0; if (olog >= 0) IGNORE_RC(write(olog, is->outbuf, is->outbuf_count)); while (i < is->outbuf_count) { rc = (int) write(fd, is->outbuf + i, is->outbuf_count - i); if (rc > 0) { i += (unsigned) rc; } else { if (rc < 0 && errno == EINTR) continue; else if ((rc == 0) || ((rc < 0) && (errno == EAGAIN))) { waitForOutput(fd); continue; } else break; } } is->outbuf_count = 0; }
PTR get_pipe(char *name, int type, int *pid_ptr) { int the_pipe[2], local_fd, remote_fd; if (pipe(the_pipe) == -1) return (PTR) 0; /* * If this is an input-pipe then local_fd is reader, remote_fd is writer * If this is an output-pipe then local_fd is writer, remote_fd is reader */ local_fd = the_pipe[type == PIPE_OUT]; remote_fd = the_pipe[type == PIPE_IN]; /* to keep output ordered correctly */ fflush(stdout); fflush(stderr); switch (*pid_ptr = fork()) { case -1: close(local_fd); close(remote_fd); return (PTR) 0; case 0: /* * This is the child process. Close the unused end of the pipe, i.e, * (local_fd) and then close the input/output file descriptor that * corresponds to the direction we want to read/write. * * The dup() call uses the first unused file descriptor, which happens * to be the one that we just closed, e.g., 0 or 1 for stdin and stdout * respectively. */ close(local_fd); close(type == PIPE_IN); IGNORE_RC(dup(remote_fd)); close(remote_fd); execl(shell, shell, "-c", name, (char *) 0); errmsg(errno, "failed to exec %s -c %s", shell, name); fflush(stderr); _exit(128); default: close(remote_fd); /* we could deadlock if future child inherit the local fd , set close on exec flag */ (void) CLOSE_ON_EXEC(local_fd); break; } return ((type == PIPE_IN) ? (PTR) FINdopen(local_fd, 0) : (PTR) fdopen(local_fd, "w")); }
/* This is fdprintf() on some systems, but use a different * name to avoid conflicts */ static void fd_printf(int fd, const char *format, ...) { va_list args; char buf[64]; int n; va_start(args, format); n = vsnprintf(buf, sizeof (buf), format, args); va_end(args); IGNORE_RC(write(fd, buf, n)); }
int system_SHELL(char *cmd) { int cpid; TRACE(("system_SHELL(%s)\n", NONNULL(cmd))); cpid = softfork(); if (cpid < 0) { IGNORE_RC(write(2, "cannot fork\n", (size_t) 13)); return cpid; } if (cpid) { /* parent */ int child; int status; beginDisplay(); while ((child = wait(&status)) != cpid) { if (child < 0 && errno == EINTR) { (void) kill(SIGKILL, cpid); } } endofDisplay(); #if VILE_SOMEDAY shellstatus = process_exit_status(status); #endif return 0; } else { beginDisplay(); exec_sh_c(cmd); IGNORE_RC(write(2, "cannot exec\n", (size_t) 13)); endofDisplay(); return -1; } }
static void exec_sh_c(char *cmd) { static char bin_sh[] = "/bin/sh"; char *sh, *shname; int i; #ifndef NOFILE # define NOFILE 20 #endif /* Make sure there are no upper inherited file descriptors */ for (i = 3; i < NOFILE; i++) (void) close(i); sh = user_SHELL(); if (isEmpty(sh)) { sh = bin_sh; shname = pathleaf(sh); } else { shname = last_slash(sh); if (shname == NULL) { shname = sh; } else { shname++; if (*shname == EOS) shname = sh; } } if (cmd) { #if SYS_OS2_EMX /* * OS/2 EMX accepts forward and backward slashes * interchangeably except in one special case - * invoking the OS/2 cmd.exe program for syntax * filters. That accepts only backslashes if we put a * ".exe" suffix on the pathname. */ for (i = 0; ispath(cmd[i]); i++) if (cmd[i] == '/') cmd[i] = '\\'; #endif (void) execlp(sh, shname, SHELL_C, cmd, (void *) 0); } else { (void) execlp(sh, shname, (void *) 0); } IGNORE_RC(write(2, "exec failed\r\n", (size_t) 14)); exit(-1); }
NCURSES_SP_NAME(unget_wch) (NCURSES_SP_DCLx const wchar_t wch) { int result = OK; mbstate_t state; size_t length; int n; T((T_CALLED("unget_wch(%p, %#lx)"), (void *) SP_PARM, (unsigned long) wch)); init_mb(state); length = _nc_wcrtomb(0, wch, &state); if (length != (size_t) (-1) && length != 0) { char *string; if ((string = (char *) malloc(length)) != 0) { init_mb(state); /* ignore the result, since we already validated the character */ IGNORE_RC((int) wcrtomb(string, wch, &state)); for (n = (int) (length - 1); n >= 0; --n) { if (NCURSES_SP_NAME(ungetch) (NCURSES_SP_ARGx UChar(string[n])) !=OK) { result = ERR; break; } } free(string); } else { result = ERR; } } else { result = ERR; } returnCode(result); }
int inout_popen(FILE **fr, FILE **fw, char *cmd) { int rp[2]; int wp[2]; if (pipe(rp)) return FALSE; if (pipe(wp)) return FALSE; pipe_pid = softfork(); if (pipe_pid < 0) return FALSE; ffstatus = file_is_pipe; fileeof = FALSE; if (pipe_pid) { /* parent */ if (fr) { *fr = fdopen(rp[0], "r"); if (*fr == NULL) { (void) fprintf(stderr, "fdopen r failed\n"); abort(); } } else { (void) close(rp[0]); } (void) close(rp[1]); if (fw) { *fw = fdopen(wp[1], "w"); if (*fw == NULL) { (void) fprintf(stderr, "fdopen w failed\n"); abort(); } } else { (void) close(wp[1]); } (void) close(wp[0]); return TRUE; } else { /* child */ beginDisplay(); append_libdir_to_path(); if (fw) { (void) close(0); if (dup(wp[0]) != 0) { IGNORE_RC(write(2, "dup 0 failed\r\n", (size_t) 15)); exit(-1); } } (void) close(wp[1]); if (fr) { (void) close(1); if (dup(rp[1]) != 1) { IGNORE_RC(write(2, "dup 1 failed\r\n", (size_t) 15)); exit(-1); } (void) close(2); if (dup(rp[1]) != 2) { IGNORE_RC(write(1, "dup 2 failed\r\n", (size_t) 15)); exit(-1); } } else { (void) close(rp[1]); } (void) close(rp[0]); exec_sh_c(cmd); endofDisplay(); } return TRUE; }
static void test_redraw(WINDOW *win) { WINDOW *win1; WINDOW *win2; bool done = FALSE; int ch, y, x; int max_y, max_x; int beg_y, beg_x; assert(win != 0); scrollok(win, TRUE); keypad(win, TRUE); getmaxyx(win, max_y, max_x); getbegyx(win, beg_y, beg_x); while (!done && win != 0) { ch = wgetch(win); getyx(win, y, x); switch (ch) { case 'q': /* FALLTHRU */ case ESCAPE: done = TRUE; break; case 'w': win1 = newwin(max_y, max_x, beg_y, beg_x); win2 = newwin(max_y - 2, max_x - 2, beg_y + 1, beg_x + 1); box(win1, 0, 0); wrefresh(win1); test_redraw(win2); delwin(win2); delwin(win1); touchwin(win); break; case '!': /* * redrawwin() and wredrawln() do not take into account the * possibility that the cursor may have moved. That makes them * cumbersome for using with a shell command. So we simply * trash the current line of the window using backspace/overwrite. */ trash(beg_x, max_x, x + beg_x); break; #ifdef NCURSES_VERSION case '@': /* * For a shell command, we can work around the problem noted above * using mvcur(). It is ifdef'd for NCURSES, since X/Open does * not define the case where the old location is unknown. */ IGNORE_RC(system("date")); mvcur(-1, -1, y, x); break; #endif case CTRL('W'): redrawwin(win); break; case CTRL('L'): wredrawln(win, y, 1); break; case KEY_UP: if (y > 0) wmove(win, y - 1, x); break; case KEY_DOWN: if (y < max_y) wmove(win, y + 1, x); break; case KEY_LEFT: if (x > 0) wmove(win, y, x - 1); break; case KEY_RIGHT: if (x < max_x) wmove(win, y, x + 1); break; default: if (ch > KEY_MIN) { waddstr(win, keyname(ch)); } else { waddstr(win, unctrl(UChar(ch))); } break; } wnoutrefresh(win); doupdate(); } }
static void test_redraw(WINDOW *win) { static const char *help[] = { "Commands:", " ^Q/ESC/q - quit", " w - recur in a new window", " ! - overwrite current line using stdio outside curses.", #ifdef NCURSES_VERSION " @ - run \"date\" command, to put its output on screen.", #endif " ^L - call redrawwin() for current window.", " ^W - call wredrawln() for current line/current window.", " arrow-keys - move cursor on the screen", "", "Other control characters are added to the screen in printable form.", "Other printable characters are added to the screen as is.", 0 }; WINDOW *win1; WINDOW *win2; bool done = FALSE; int ch, y, x; int max_y, max_x; int beg_y, beg_x; assert(win != 0); scrollok(win, TRUE); keypad(win, TRUE); getmaxyx(win, max_y, max_x); getbegyx(win, beg_y, beg_x); while (!done) { ch = wgetch(win); getyx(win, y, x); switch (ch) { case 'q': /* FALLTHRU */ case QUIT: case ESCAPE: done = TRUE; break; case 'w': win1 = newwin(max_y, max_x, beg_y, beg_x); win2 = newwin(max_y - 2, max_x - 2, beg_y + 1, beg_x + 1); box(win1, 0, 0); wrefresh(win1); test_redraw(win2); delwin(win2); delwin(win1); touchwin(win); break; case '!': /* * redrawwin() and wredrawln() do not take into account the * possibility that the cursor may have moved. That makes them * cumbersome for using with a shell command. So we simply * trash the current line of the window using backspace/overwrite. */ trash(beg_x, max_x, x + beg_x); break; #ifdef NCURSES_VERSION case '@': /* * For a shell command, we can work around the problem noted above * using mvcur(). It is ifdef'd for NCURSES, since X/Open does * not define the case where the old location is unknown. */ IGNORE_RC(system("date")); mvcur(-1, -1, y, x); break; #endif case CTRL('W'): redrawwin(win); break; case CTRL('L'): wredrawln(win, y, 1); break; case KEY_UP: if (y > 0) wmove(win, y - 1, x); break; case KEY_DOWN: if (y < max_y) wmove(win, y + 1, x); break; case KEY_LEFT: if (x > 0) wmove(win, y, x - 1); break; case KEY_RIGHT: if (x < max_x) wmove(win, y, x + 1); break; case HELP_KEY_1: popup_msg(win, help); break; default: if (ch > KEY_MIN) { waddstr(win, keyname(ch)); waddch(win, '\n'); } else { waddstr(win, unctrl(UChar(ch))); } break; } wnoutrefresh(win); doupdate(); } }
static int tput(int argc, char *argv[]) { NCURSES_CONST char *name; char *s; int i, j, c; int status; FILE *f; #if !PURE_TERMINFO bool termcap = FALSE; #endif if ((name = argv[0]) == 0) name = ""; check_aliases(name); if (is_reset || is_init) { if (init_prog != 0) { IGNORE_RC(system(init_prog)); } FLUSH; if (is_reset && reset_1string != 0) { PUTS(reset_1string); } else if (init_1string != 0) { PUTS(init_1string); } FLUSH; if (is_reset && reset_2string != 0) { PUTS(reset_2string); } else if (init_2string != 0) { PUTS(init_2string); } FLUSH; #ifdef set_lr_margin if (set_lr_margin != 0) { PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); } else #endif #ifdef set_left_margin_parm if (set_left_margin_parm != 0 && set_right_margin_parm != 0) { PUTS(TPARM_1(set_left_margin_parm, 0)); PUTS(TPARM_1(set_right_margin_parm, columns - 1)); } else #endif if (clear_margins != 0 && set_left_margin != 0 && set_right_margin != 0) { PUTS(clear_margins); if (carriage_return != 0) { PUTS(carriage_return); } else { PUTCHAR('\r'); } PUTS(set_left_margin); if (parm_right_cursor) { PUTS(TPARM_1(parm_right_cursor, columns - 1)); } else { for (i = 0; i < columns - 1; i++) { PUTCHAR(' '); } } PUTS(set_right_margin); if (carriage_return != 0) { PUTS(carriage_return); } else { PUTCHAR('\r'); } } FLUSH; if (init_tabs != 8) { if (clear_all_tabs != 0 && set_tab != 0) { for (i = 0; i < columns - 1; i += 8) { if (parm_right_cursor) { PUTS(TPARM_1(parm_right_cursor, 8)); } else { for (j = 0; j < 8; j++) PUTCHAR(' '); } PUTS(set_tab); } FLUSH; } } if (is_reset && reset_file != 0) { f = fopen(reset_file, "r"); if (f == 0) { quit(4 + errno, "Can't open reset_file: '%s'", reset_file); } while ((c = fgetc(f)) != EOF) { PUTCHAR(c); } fclose(f); } else if (init_file != 0) { f = fopen(init_file, "r"); if (f == 0) { quit(4 + errno, "Can't open init_file: '%s'", init_file); } while ((c = fgetc(f)) != EOF) { PUTCHAR(c); } fclose(f); } FLUSH; if (is_reset && reset_3string != 0) { PUTS(reset_3string); } else if (init_3string != 0) { PUTS(init_3string); } FLUSH; return 0; } if (strcmp(name, "longname") == 0) { PUTS(longname()); return 0; } #if !PURE_TERMINFO retry: #endif if ((status = tigetflag(name)) != -1) { return exit_code(BOOLEAN, status); } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { (void) printf("%d\n", status); return exit_code(NUMBER, 0); } else if ((s = tigetstr(name)) == CANCELLED_STRING) { #if !PURE_TERMINFO if (!termcap) { const struct name_table_entry *np; termcap = TRUE; if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { switch (np->nte_type) { case BOOLEAN: if (bool_from_termcap[np->nte_index]) name = boolnames[np->nte_index]; break; case NUMBER: if (num_from_termcap[np->nte_index]) name = numnames[np->nte_index]; break; case STRING: if (str_from_termcap[np->nte_index]) name = strnames[np->nte_index]; break; } goto retry; } } #endif quit(4, "unknown terminfo capability '%s'", name); } else if (s != ABSENT_STRING) { if (argc > 1) { int k; int ignored; long numbers[1 + NUM_PARM]; char *strings[1 + NUM_PARM]; char *p_is_s[NUM_PARM]; /* Nasty hack time. The tparm function needs to see numeric * parameters as numbers, not as pointers to their string * representations */ for (k = 1; k < argc; k++) { char *tmp = 0; strings[k] = argv[k]; numbers[k] = strtol(argv[k], &tmp, 0); if (tmp == 0 || *tmp != 0) numbers[k] = 0; } for (k = argc; k <= NUM_PARM; k++) { numbers[k] = 0; strings[k] = 0; } switch (tparm_type(name)) { case Num_Str: s = TPARM_2(s, numbers[1], strings[2]); break; case Num_Str_Str: s = TPARM_3(s, numbers[1], strings[2], strings[3]); break; case Numbers: default: (void) _nc_tparm_analyze(s, p_is_s, &ignored); #define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) s = TPARM_9(s, myParam(1), myParam(2), myParam(3), myParam(4), myParam(5), myParam(6), myParam(7), myParam(8), myParam(9)); break; } } /* use putp() in order to perform padding */ putp(s); return exit_code(STRING, 0); } return exit_code(STRING, 1); }
/* Output startup string. */ bool send_init_strings(int fd GCC_UNUSED, TTY * old_settings) { int i; bool need_flush = FALSE; (void) old_settings; #ifdef TAB3 if (old_settings != 0 && old_settings->c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { old_settings->c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); SET_TTY(fd, old_settings); } #endif if (use_reset || use_init) { if (VALID_STRING(init_prog)) { IGNORE_RC(system(init_prog)); } need_flush |= sent_string((use_reset && (reset_1string != 0)) ? reset_1string : init_1string); need_flush |= sent_string((use_reset && (reset_2string != 0)) ? reset_2string : init_2string); #if defined(set_lr_margin) if (VALID_STRING(set_lr_margin)) { need_flush |= sent_string(TPARM_2(set_lr_margin, 0, columns - 1)); } else #endif #if defined(set_left_margin_parm) && defined(set_right_margin_parm) if (VALID_STRING(set_left_margin_parm) && VALID_STRING(set_right_margin_parm)) { need_flush |= sent_string(TPARM_1(set_left_margin_parm, 0)); need_flush |= sent_string(TPARM_1(set_right_margin_parm, columns - 1)); } else #endif if (VALID_STRING(clear_margins) && VALID_STRING(set_left_margin) && VALID_STRING(set_right_margin)) { need_flush |= sent_string(clear_margins); need_flush |= to_left_margin(); need_flush |= sent_string(set_left_margin); if (VALID_STRING(parm_right_cursor)) { need_flush |= sent_string(TPARM_1(parm_right_cursor, columns - 1)); } else { for (i = 0; i < columns - 1; i++) { out_char(' '); need_flush = TRUE; } } need_flush |= sent_string(set_right_margin); need_flush |= to_left_margin(); } need_flush |= reset_tabstops(columns); need_flush |= cat_file((use_reset && reset_file) ? reset_file : init_file); need_flush |= sent_string((use_reset && (reset_3string != 0)) ? reset_3string : init_3string); } return need_flush; }