void resize_terminal(void) { struct interlink_event ev; int width, height; get_terminal_size(ditrm->out.std, &width, &height); set_resize_interlink_event(&ev, width, height); itrm_queue_event(ditrm, (char *) &ev, sizeof(ev)); }
static void send_auth(char *username, char *password) { struct mt_packet data; unsigned short width = 0; unsigned short height = 0; char *terminal = getenv("TERM"); char md5data[100]; unsigned char md5sum[17]; int plen; md5_state_t state; #if defined(__linux__) && defined(_POSIX_MEMLOCK_RANGE) mlock(md5data, sizeof(md5data)); mlock(md5sum, sizeof(md5data)); #endif /* Concat string of 0 + password + encryptionkey */ md5data[0] = 0; strncpy(md5data + 1, password, 82); md5data[83] = '\0'; memcpy(md5data + 1 + strlen(password), encryptionkey, 16); /* Generate md5 sum of md5data with a leading 0 */ md5_init(&state); md5_append(&state, (const md5_byte_t *)md5data, strlen(password) + 17); md5_finish(&state, (md5_byte_t *)md5sum + 1); md5sum[0] = 0; /* Send combined packet to server */ init_packet(&data, MT_PTYPE_DATA, srcmac, dstmac, sessionkey, outcounter); plen = add_control_packet(&data, MT_CPTYPE_PASSWORD, md5sum, 17); plen += add_control_packet(&data, MT_CPTYPE_USERNAME, username, strlen(username)); plen += add_control_packet(&data, MT_CPTYPE_TERM_TYPE, terminal, strlen(terminal)); if (is_a_tty && get_terminal_size(&width, &height) != -1) { width = htole16(width); height = htole16(height); plen += add_control_packet(&data, MT_CPTYPE_TERM_WIDTH, &width, 2); plen += add_control_packet(&data, MT_CPTYPE_TERM_HEIGHT, &height, 2); } outcounter += plen; /* TODO: handle result */ send_udp(&data, 1); }
static void sig_winch(int sig) { unsigned short width,height; struct mt_packet data; int plen; /* terminal height/width has changed, inform server */ if (get_terminal_size(&width, &height) != -1) { init_packet(&data, MT_PTYPE_DATA, srcmac, dstmac, sessionkey, outcounter); width = htole16(width); height = htole16(height); plen = add_control_packet(&data, MT_CPTYPE_TERM_WIDTH, &width, 2); plen += add_control_packet(&data, MT_CPTYPE_TERM_HEIGHT, &height, 2); outcounter += plen; send_udp(&data, 1); } /* reinstate signal handler */ signal(SIGWINCH, sig_winch); }
int pause_screen(t_tetris *game) { char key[20]; init_pause(game); key[0] = '\0'; while (my_strcmp(key, game->pause_key) != 0 && get_terminal_size(game) == 0) { if (my_strcmp(key, game->quit_key) == 0) { game->pause = 1; escape_game(game); return (0); } getstr(key); } werase(game->pause_screen); delwin(game->pause_screen); return (0); }
int main(int argc, char* argv[]) { int is_running = 1; int x_terminal_size, y_terminal_size; int is_lurking = 0; int is_yelling = 0; int in_deepsix = 0; int sending_im = 0; int i; /* josh-note: These need to be uncommented for the client connection to work. */ /* int client_id = init_client("Henry"); create a client. */ /* init_user_list(client_id); init the client size user list. */ log_init(); log_writeln(" --------------------------- "); log_writeln(" > Starting BlackChat"); signal(SIGALRM, scroll_ended_handler); for(i = 0; i < 26; i ++) { /* set our message to null */ memset(yell_messages[i], '\0', MAX_MESSAGE_LENGTH * sizeof(wchar_t)); } transcript_buffer = (wchar_t*)malloc(sizeof(wchar_t)*transcript_buffer_size); f_transcript_buffer = (wchar_t*)malloc(sizeof(wchar_t)*f_transcript_buffer_size); memset(client_buffer, '\0', sizeof(client_buffer)); memset(transcript_buffer, '\0', sizeof(transcript_buffer)); get_terminal_size(&x_terminal_size, &y_terminal_size); log_writeln(" > ... detecting current terminal size xy:(%d,%d)", x_terminal_size, y_terminal_size); log_writeln(" > ... initializing ncurses screen in raw mode"); initscr(); // start_color(); init_pair(0, COLOR_WHITE, COLOR_BLACK); init_pair(1, COLOR_GREEN, COLOR_BLACK); init_pair(2, COLOR_YELLOW, COLOR_BLACK); init_pair(3, COLOR_CYAN, COLOR_BLACK); init_pair(4, COLOR_MAGENTA, COLOR_BLACK); raw(); keypad(stdscr, TRUE); noecho(); color_set(0, NULL); log_writeln(" > ... creating transcript and client window"); transcript_window = newwin(TRANSCRIPT_MAX_ROWS,TRANSCRIPT_MAX_COLUMNS, 0,0); fullscreen_transcript_window = newwin(TRANSCRIPT_MAX_ROWS,TRANSCRIPT_MAX_COLUMNS*2, 0,0); client_chat_window = newwin(MAX_ROWS,MAX_COLUMNS,24,0); lurk_win = newwin(MAX_ROWS,MAX_COLUMNS,24,0); yell_win = newwin(23,40,0,0); deepsix_win = newwin(23,40,0,0); im_win = newwin(TRANSCRIPT_MAX_ROWS,TRANSCRIPT_MAX_COLUMNS, 0,0); status_win = newwin(3,40,21,40); info_win = newwin(3,40,0,40); // box(yell_win, '|', '-'); set_yell_message(0, L"Hello World"); set_yell_message(1, L"Yo dog!"); set_yell_message(2, L"Hey everyone!"); set_yell_message(3, L"Whats up?"); set_yell_message(12,L"I agree."); wcolor_set(lurk_win, 4, NULL); wcolor_set(transcript_window, 3, NULL); wcolor_set(client_chat_window, 4, NULL); wcolor_set(yell_win, 2, NULL); wprintw(lurk_win, "Lurking... Use CTRL-L to unLurk or CTRL-Q to quit."); log_writeln(" > ... creating other 9 windows"); init_other_windows(); log_writeln(" > ... [beginning transcript]"); write_to_transcript_window(L"***************************************"); write_to_transcript_window(L"******** Wecome to BlackChat! *********"); write_to_transcript_window(L"***************************************"); set_window_user_name(0, L"chris"); set_window_user_name(1, L"sue"); set_window_user_name(2, L"dan"); set_window_user_name(3, L"joe"); append_text_to_window(0, L"Sup!"); append_text_to_window(1, L"yo everyone, I'm in love with blackchat!"); append_text_to_window(2, L"hey, my name is Dan!"); append_text_to_window(3, L"Hey!?"); can_deepsix_user(0, 0); set_user_status(1, 'L'); set_user_status(2, 'L'); /* Set our info window text. */ wprintw(info_win, " Black Chat v1.0\n"); wprintw(info_win, "UI: Henry Stratmann|Client: Josh Hartman\n"); wprintw(info_win, "Server: Tyler Reid |Protocol: Tim Rhoads\n"); while(is_running) { int ch = getch(); /* wchar_t buf[512]; //get wchar_ts sprintf(buf, "key pressed: '%c' int value: %d\n", ch, ch); write_to_transcript_window(buf); */ //end get wchar_t /* Check if were in "Lurk" mode. */ if(is_lurking) { switch(ch) { case 12: /* lurk-off */ is_lurking = 0; print_client_chat_buffer(); break; case 17: /* quit */ is_running = 0; break; default: wrefresh(lurk_win); } } /* Check if were in IM mode. */ else if(sending_im) { /* TODO: Display list of users (like deepsix) to send IM to. All IM's will be displayed on the main transcript with some type of "marker" indicating that this was an IM. */ if(ch >= 48 && ch <= 57) { /* josh-note: Have josh send IM based on "ch" */ } /* quit */ if(ch == 17) { is_running = 0; } /* exit IM */ sending_im = 0; window_page_up(transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS, transcript_buffer); window_page_up(fullscreen_transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS*2, f_transcript_buffer); } /* Check if were in deepsix mode. */ else if(in_deepsix) { /* kick user */ if(ch >= 48 && ch <= 57) { /* josh-note: Have josh make a "kick_user(ch-48)" command. Also, have josh keep track of who user voted for and display message on transcript as to how user voted and/or if they already voted for the user. */ } /* quit */ if(ch == 17) { is_running = 0; } /* exit deepsix */ in_deepsix = 0; window_page_up(transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS, transcript_buffer); window_page_up(fullscreen_transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS*2, f_transcript_buffer); } /* Check if were yelling. */ else if(is_yelling) { // redrawwin(yell_win); // wrefresh(yell_win); int index = ch - 97; /* Write our comment to our transcript window. */ if(index >= 0 && index < 26) { if( yell_messages[index][0] != '\0' ) { write_to_transcript_window( yell_messages[index] ); } } is_yelling = 0; redrawwin(client_chat_window); wrefresh(client_chat_window); redrawwin(transcript_window); wrefresh(transcript_window); } else { /* Check what keys we pressed. */ switch(ch) { /* * Check if we pressed a control key. */ if(iscntrl(ch)) { case 7: /* CTRL-G */ gaudy_mode_on = (gaudy_mode_on == 1) ? 0 : 1; if(gaudy_mode_on) { client_buffer[ client_cursor_position++ ] = 2; } else { client_buffer[ client_cursor_position++ ] = 3; } /* Print out updates to the window. */ print_client_chat_buffer(); break; case 127:/* Backsapce Key (grok hack) */ case 8: /* CTRL-H */ client_buffer[ wcslen(client_buffer)-1 ] = '\0'; print_client_chat_buffer(); break; case 9: /* CTRL-I / TAB */ if(!sending_im) { sending_im = 1; draw_im_window(); } break; case 10: /* CTRL-J and CTRL-M */ /* UNCOMMENT ME FOR USE WITH SERVER */ { wchar_t *buf = NULL; /* If we had gaudy mode on, we need to disable it. */ if(gaudy_mode_on) { client_buffer[ client_cursor_position++ ] = 3; client_buffer[ client_cursor_position++ ] = ' '; gaudy_mode_on = 0; } /* Get our buffer togther to write to the transcript window. */ buf = (wchar_t*)malloc( (wcslen(L"[Client Says]: ")+wcslen(client_buffer)+1) * sizeof(wchar_t) ); write_to_transcript_window(L"[Client Says]: "); write_to_transcript_window(client_buffer); // sprintf(buf, "[Client Says]: %ls", client_buffer); // write_to_transcript_window(buf); } clear_text_from_client_typing_window(); /* write_out(client_id); enter key is pressed so send a message to the server. */ break; case 11: /* CTRL-K */ { int i; for(i = client_cursor_position+1; i < wcslen(client_buffer); i ++) { client_buffer[i] = '\0'; } } break; case 12: /* CTRL-L */ if(!is_lurking) { redrawwin(lurk_win); wrefresh(lurk_win); is_lurking = 1; } break; case 14: /* CTRL-N */ alarm(5); user_is_scrolling = 1; transcript_current_line ++; window_page_down( transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS, transcript_buffer ); window_page_down( fullscreen_transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS*2, f_transcript_buffer ); break; case 16: /* CTRL-P */ alarm(5); user_is_scrolling = 1; transcript_current_line --; window_page_up( transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS, transcript_buffer ); window_page_up( fullscreen_transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS*2, f_transcript_buffer ); break; case 17: /* CTRL-Q */ log_writeln(" > ... recived quit signal from client"); is_running = 0; break; case 20: /* CTRL-T */ if(transcript_maxed) { transcript_maxed = 0; window_page_up(transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS, transcript_buffer); wclear(fullscreen_transcript_window); wrefresh(fullscreen_transcript_window); } else { transcript_maxed = 1; window_page_up(fullscreen_transcript_window, &transcript_current_line, TRANSCRIPT_MAX_COLUMNS*2, f_transcript_buffer); wclear(transcript_window); wrefresh(transcript_window); } break; case 21: /* CTRL-U */ client_current_line = 0; client_cursor_position = 0; memset(client_buffer, '\0', wcslen(client_buffer)+1); print_client_chat_buffer(); break; case 23: /* CTRL-W */ delete_last_word_in_buffer(client_buffer); print_client_chat_buffer(); break; case 25: /* CTRL-Y */ { if(!is_yelling) { redrawwin(yell_win); wrefresh(yell_win); is_yelling = 1; } } break; case 29: /* CTRL-] */ alarm(0); user_is_scrolling = 0; print_transcript_chat_buffer(); break; case 30: /* CTRL-6 */ if(!in_deepsix) { draw_deepsix_window(); in_deepsix = 1; } break; /* * If we encountered an unkown escape wchar_tcter, break out of here so we don't * print it. */ break; /* TODO: Fix me! */ } #if 0 /* Scroll the clients typing window down. */ case KEY_DOWN: client_current_line ++; if(client_current_line*MAX_COLUMNS > wcslen(client_buffer)) client_current_line --; wclear(client_chat_window); wprintw(client_chat_window, &client_buffer[client_current_line*MAX_COLUMNS]); break; /* Scroll the clients typing window up. */ case KEY_UP: client_current_line --; if(client_current_line < 0) client_current_line = 0; wclear(client_chat_window); wprintw(client_chat_window, &client_buffer[client_current_line*MAX_COLUMNS]); break; #endif /* Delete the previous chracter. */ case KEY_BACKSPACE: /* Check if were deleting the last wchar_tacter. */ if( client_cursor_position == wcslen(client_buffer) ) { client_buffer[ client_cursor_position-1 ] = '\0'; client_cursor_position --; print_client_chat_buffer(); } else { /* If were here, that means were NOT deleting the last wchar_tacter. */ int i; for(i = client_cursor_position-1; i < wcslen(client_buffer); i ++) { client_buffer[i] = client_buffer[i+1]; } client_cursor_position --; print_client_chat_buffer(); } break; /* If were here, that means we didn't press any "special" keys so that means were * trying to write some generic wchar_tacters to our chat window. */ default: /* Make sure we don't print a control wchar_tacter. */ if(!iscntrl(ch)) { /* Check if were inserting a wchar_tacter before the end of our client * typing buffer. */ if( client_cursor_position != wcslen(client_buffer) ) { /* Move all wchar_tacters in front of the cursor up one. */ int i; for(i = wcslen(client_buffer)+1; i > client_cursor_position; i --) { client_buffer[i] = client_buffer[i-1]; } } /* Add the wchar_tacter to our buffer. */ client_buffer[ client_cursor_position++ ] = ch; /* Print our new/updated buffer. */ print_client_chat_buffer(); break; } } } /* Read from the server. */ /* josh-note Uncomment this! */ /* read_from_server(client_id); */ refresh_all_windows(is_lurking); } log_writeln(" > ... [ending transcript]"); log_writeln(" > ... freeing resources"); free_other_windows(); free(transcript_buffer); delwin(transcript_window); delwin(fullscreen_transcript_window); delwin(client_chat_window); delwin(status_win); delwin(info_win); delwin(im_win); delwin(deepsix_win); delwin(yell_win); endwin(); /* josh-note This should be uncommented to close down the client socket. */ /* close_client(client_id); */ log_writeln(" > ... closing client log"); log_writeln(" > ... bye bye for now!"); log_close(); return 0; }
int main(int argc, char *argv[]) { int optc; int option_differences = 0, option_differences_cumulative = 0, option_help = 0, option_version = 0; double interval = 2; char *command; int command_length = 0; /* not including final \0 */ setlocale(LC_ALL, ""); progname = argv[0]; while ((optc = getopt_long(argc, argv, "+d::hn:vt", longopts, (int *) 0)) != EOF) { switch (optc) { case 'd': option_differences = 1; if (optarg) option_differences_cumulative = 1; break; case 'h': option_help = 1; break; case 't': show_title = 0; break; case 'n': { char *str; interval = strtod(optarg, &str); if (!*optarg || *str) do_usage(); if(interval < 0.1) interval = 0.1; if(interval > ~0u/1000000) interval = ~0u/1000000; } break; case 'v': option_version = 1; break; default: do_usage(); break; } } if (option_version) { fprintf(stderr, "%s\n", VERSION); if (!option_help) exit(0); } if (option_help) { fprintf(stderr, usage, progname); fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr); fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr); fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr); fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr); fputs(" -v, --version\t\t\t\tprint the version number\n", stderr); fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr); exit(0); } if (optind >= argc) do_usage(); command = strdup(argv[optind++]); command_length = strlen(command); for (; optind < argc; optind++) { char *endp; int s = strlen(argv[optind]); command = realloc(command, command_length + s + 2); /* space and \0 */ endp = command + command_length; *endp = ' '; memcpy(endp + 1, argv[optind], s); command_length += 1 + s; /* space then string length */ command[command_length] = '\0'; } get_terminal_size(); /* Catch keyboard interrupts so we can put tty back in a sane state. */ signal(SIGINT, die); signal(SIGTERM, die); signal(SIGHUP, die); signal(SIGWINCH, winch_handler); /* Set up tty for curses use. */ curses_started = 1; initscr(); nonl(); noecho(); cbreak(); for (;;) { time_t t = time(NULL); char *ts = ctime(&t); int tsl = strlen(ts); char *header; FILE *p; int x, y; int oldeolseen = 1; if (screen_size_changed) { get_terminal_size(); resizeterm(height, width); clear(); /* redrawwin(stdscr); */ screen_size_changed = 0; first_screen = 1; } if (show_title) { // left justify interval and command, // right justify time, clipping all to fit window width asprintf(&header, "Every %.1fs: %.*s", interval, min(width - 1, command_length), command); mvaddstr(0, 0, header); if (strlen(header) > (size_t) (width - tsl - 1)) mvaddstr(0, width - tsl - 4, "... "); mvaddstr(0, width - tsl + 1, ts); free(header); } if (!(p = popen(command, "r"))) { perror("popen"); do_exit(2); } for (y = show_title; y < height; y++) { int eolseen = 0, tabpending = 0; for (x = 0; x < width; x++) { int c = ' '; int attr = 0; if (!eolseen) { /* if there is a tab pending, just spit spaces until the next stop instead of reading characters */ if (!tabpending) do c = getc(p); while (c != EOF && !isprint(c) && c != '\n' && c != '\t'); if (c == '\n') if (!oldeolseen && x == 0) { x = -1; continue; } else eolseen = 1; else if (c == '\t') tabpending = 1; if (c == EOF || c == '\n' || c == '\t') c = ' '; if (tabpending && (((x + 1) % 8) == 0)) tabpending = 0; } move(y, x); if (option_differences) { chtype oldch = inch(); char oldc = oldch & A_CHARTEXT; attr = !first_screen && ((char)c != oldc || (option_differences_cumulative && (oldch & A_ATTRIBUTES))); } if (attr) standout(); addch(c); if (attr) standend(); } oldeolseen = eolseen; } pclose(p); first_screen = 0; refresh(); usleep(interval * 1000000); } endwin(); return 0; }
/* Set xterm-like term window's title. */ void set_window_title(unsigned char *title) { unsigned char *s; int xsize, ysize; int j = 0; #ifndef HAVE_SYS_CYGWIN_H /* Check if we're in a xterm-like terminal. */ if (!is_xterm() && !is_gnuscreen()) return; #endif /* Retrieve terminal dimensions. */ get_terminal_size(0, &xsize, &ysize); /* Check if terminal width is reasonnable. */ if (xsize < 1 || xsize > 1024) return; /* Allocate space for title + 3 ending points + null char. */ s = mem_alloc(xsize + 3 + 1); if (!s) return; /* Copy title to s if different from NULL */ if (title) { int i; /* We limit title length to terminal width and ignore control * chars if any. Note that in most cases window decoration * reduces printable width, so it's just a precaution. */ /* Note that this is the right place where to do it, since * potential alternative set_window_title() routines might * want to take different precautions. */ for (i = 0; title[i] && i < xsize; i++) { /* 0x80 .. 0x9f are ISO-8859-* control characters. * In some other encodings they could be used for * legitimate characters, though (ie. in Kamenicky). * We should therefore maybe check for these only * if the terminal is running in an ISO- encoding. */ if (iscntrl(title[i]) || (title[i] & 0x7f) < 0x20 || title[i] == 0x7f) continue; s[j++] = title[i]; } /* If title is truncated, add "..." */ if (i == xsize) { s[j++] = '.'; s[j++] = '.'; s[j++] = '.'; } } s[j] = '\0'; /* Send terminal escape sequence + title string */ printf("\033]0;%s\a", s); #if 0 /* Miciah don't like this so it is disabled because it changes the * default window name. --jonas */ /* Set the GNU screen window name */ if (is_gnuscreen()) printf("\033k%s\033\134", s); #endif fflush(stdout); mem_free(s); }
int main(int argc, char *argv[]) { int optc; int option_differences = 0, option_differences_cumulative = 0, option_exec = 0, option_beep = 0, option_errexit = 0, option_help = 0, option_version = 0; double interval = 2; char *command; char **command_argv; int command_length = 0; /* not including final \0 */ watch_usec_t next_loop; /* next loop time in us, used for precise time keeping only */ int pipefd[2]; int status; pid_t child; setlocale(LC_ALL, ""); progname = argv[0]; while ((optc = getopt_long(argc, argv, "+bed::hn:pvtx", longopts, (int *) 0)) != EOF) { switch (optc) { case 'b': option_beep = 1; break; case 'd': option_differences = 1; if (optarg) option_differences_cumulative = 1; break; case 'e': option_errexit = 1; break; case 'h': option_help = 1; break; case 't': show_title = 0; break; case 'x': option_exec = 1; break; case 'n': { char *str; interval = strtod(optarg, &str); if (!*optarg || *str) do_usage(); if(interval < 0.1) interval = 0.1; if(interval > ~0u/1000000) interval = ~0u/1000000; } break; case 'p': precise_timekeeping = 1; break; case 'v': option_version = 1; break; default: do_usage(); break; } } if (option_version) { fprintf(stderr, "%s\n", VERSION); if (!option_help) exit(0); } if (option_help) { fprintf(stderr, usage, progname); fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr); fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr); fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr); fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr); fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr); fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr); fputs(" -p, --precise\t\t\t\tprecise timing, ignore command run time\n", stderr); fputs(" -v, --version\t\t\t\tprint the version number\n", stderr); fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr); fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr); exit(0); } if (optind >= argc) do_usage(); command_argv=&(argv[optind]); /* save for later */ command = strdup(argv[optind++]); command_length = strlen(command); for (; optind < argc; optind++) { char *endp; int s = strlen(argv[optind]); command = realloc(command, command_length + s + 2); /* space and \0 */ endp = command + command_length; *endp = ' '; memcpy(endp + 1, argv[optind], s); command_length += 1 + s; /* space then string length */ command[command_length] = '\0'; } get_terminal_size(); /* Catch keyboard interrupts so we can put tty back in a sane state. */ signal(SIGINT, die); signal(SIGTERM, die); signal(SIGHUP, die); signal(SIGWINCH, winch_handler); /* Set up tty for curses use. */ curses_started = 1; initscr(); nonl(); noecho(); cbreak(); if (precise_timekeeping) next_loop = get_time_usec(); for (;;) { time_t t = time(NULL); char *ts = ctime(&t); int tsl = strlen(ts); char *header; FILE *p; int x, y; int oldeolseen = 1; if (screen_size_changed) { get_terminal_size(); resizeterm(height, width); clear(); /* redrawwin(stdscr); */ screen_size_changed = 0; first_screen = 1; } if (show_title) { // left justify interval and command, // right justify time, clipping all to fit window width asprintf(&header, "Every %.1fs: %.*s", interval, min(width - 1, command_length), command); mvaddstr(0, 0, header); if (strlen(header) > (size_t) (width - tsl - 1)) mvaddstr(0, width - tsl - 4, "... "); mvaddstr(0, width - tsl + 1, ts); free(header); } /* allocate pipes */ if (pipe(pipefd)<0) { perror("pipe"); do_exit(7); } /* flush stdout and stderr, since we're about to do fd stuff */ fflush(stdout); fflush(stderr); /* fork to prepare to run command */ child=fork(); if (child<0) { /* fork error */ perror("fork"); do_exit(2); } else if (child==0) { /* in child */ close (pipefd[0]); /* child doesn't need read side of pipe */ close (1); /* prepare to replace stdout with pipe */ if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */ perror("dup2"); exit(3); } dup2(1, 2); /* stderr should default to stdout */ if (option_exec) { /* pass command to exec instead of system */ if (execvp(command_argv[0], command_argv)==-1) { perror("exec"); exit(4); } } else { status=system(command); /* watch manpage promises sh quoting */ /* propagate command exit status as child exit status */ if (!WIFEXITED(status)) { /* child exits nonzero if command does */ exit(1); } else { exit(WEXITSTATUS(status)); } } } /* otherwise, we're in parent */ close(pipefd[1]); /* close write side of pipe */ if ((p=fdopen(pipefd[0], "r"))==NULL) { perror("fdopen"); do_exit(5); } for (y = show_title; y < height; y++) { int eolseen = 0, tabpending = 0; for (x = 0; x < width; x++) { int c = ' '; int attr = 0; if (!eolseen) { /* if there is a tab pending, just spit spaces until the next stop instead of reading characters */ if (!tabpending) do c = getc(p); while (c != EOF && !isprint(c) && c != '\n' && c != '\t'); if (c == '\n') if (!oldeolseen && x == 0) { x = -1; continue; } else eolseen = 1; else if (c == '\t') tabpending = 1; if (c == EOF || c == '\n' || c == '\t') c = ' '; if (tabpending && (((x + 1) % 8) == 0)) tabpending = 0; } move(y, x); if (option_differences) { chtype oldch = inch(); unsigned char oldc = oldch & A_CHARTEXT; attr = !first_screen && ((char)c != oldc || (option_differences_cumulative && (oldch & A_ATTRIBUTES))); } if (attr) standout(); addch(c); if (attr) standend(); } oldeolseen = eolseen; } fclose(p); /* harvest child process and get status, propagated from command */ if (waitpid(child, &status, 0)<0) { perror("waitpid"); do_exit(8); }; /* if child process exited in error, beep if option_beep is set */ if ((!WIFEXITED(status) || WEXITSTATUS(status))) { if (option_beep) beep(); if (option_errexit) do_exit(8); } first_screen = 0; refresh(); if (precise_timekeeping) { watch_usec_t cur_time = get_time_usec(); next_loop += USECS_PER_SEC*interval; if (cur_time < next_loop) usleep(next_loop - cur_time); } else usleep(interval * 1000000); } endwin(); return 0; }
int main(int argc, char *argv[]) { int optc; int option_differences = 0, option_differences_cumulative = 0, option_exec = 0, option_beep = 0, option_color = 0, option_errexit = 0, option_help = 0, option_version = 0; double interval = 2; char *command; wchar_t *wcommand = NULL; char **command_argv; int command_length = 0; /* not including final \0 */ int wcommand_columns = 0; /* not including final \0 */ int wcommand_characters = 0; /* not including final \0 */ watch_usec_t next_loop; /* next loop time in us, used for precise time keeping only */ int pipefd[2]; int status; pid_t child; setlocale(LC_ALL, ""); progname = argv[0]; while ((optc = getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *) 0)) != EOF) { switch (optc) { case 'b': option_beep = 1; break; case 'c': option_color = 1; break; case 'd': option_differences = 1; if (optarg) option_differences_cumulative = 1; break; case 'e': option_errexit = 1; break; case 'h': option_help = 1; break; case 't': show_title = 0; break; case 'x': option_exec = 1; break; case 'n': { char *str; interval = strtod(optarg, &str); if (!*optarg || *str) do_usage(); if(interval < 0.1) interval = 0.1; if(interval > ~0u/1000000) interval = ~0u/1000000; } break; case 'p': precise_timekeeping = 1; break; case 'v': option_version = 1; break; default: do_usage(); break; } } if (option_version) { fprintf(stderr, "%s\n", VERSION); if (!option_help) exit(0); } if (option_help) { fprintf(stderr, usage, progname); fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr); fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr); fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr); fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr); fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr); fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr); fputs(" -p, --precise\t\t\t\tprecise timing, ignore command run time\n", stderr); fputs(" -v, --version\t\t\t\tprint the version number\n", stderr); fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr); fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr); exit(0); } if (optind >= argc) do_usage(); command_argv=&(argv[optind]); /* save for later */ command = strdup(argv[optind++]); command_length = strlen(command); for (; optind < argc; optind++) { char *endp; int s = strlen(argv[optind]); command = realloc(command, command_length + s + 2); /* space and \0 */ endp = command + command_length; *endp = ' '; memcpy(endp + 1, argv[optind], s); command_length += 1 + s; /* space then string length */ command[command_length] = '\0'; } // convert to wide for printing purposes //mbstowcs(NULL, NULL, 0); wcommand_characters = mbstowcs(NULL, command, 0); if(wcommand_characters < 0) { fprintf(stderr, "Unicode Handling Error\n"); exit(1); } wcommand = (wchar_t*)malloc((wcommand_characters+1) * sizeof(wcommand)); if(wcommand == NULL) { fprintf(stderr, "Unicode Handling Error (malloc)\n"); exit(1); } mbstowcs(wcommand, command, wcommand_characters+1); wcommand_columns = wcswidth(wcommand, -1); get_terminal_size(); /* Catch keyboard interrupts so we can put tty back in a sane state. */ signal(SIGINT, die); signal(SIGTERM, die); signal(SIGHUP, die); signal(SIGWINCH, winch_handler); /* Set up tty for curses use. */ curses_started = 1; initscr(); if (option_color) { if (has_colors()) { start_color(); use_default_colors(); init_ansi_colors(); } else option_color = 0; } nonl(); noecho(); cbreak(); if (precise_timekeeping) next_loop = get_time_usec(); for (;;) { time_t t = time(NULL); char *ts = ctime(&t); int tsl = strlen(ts); char *header; FILE *p; int x, y; int oldeolseen = 1; if (screen_size_changed) { get_terminal_size(); resizeterm(height, width); clear(); /* redrawwin(stdscr); */ screen_size_changed = 0; first_screen = 1; } if (show_title) { // left justify interval and command, // right justify time, clipping all to fit window width int hlen = asprintf(&header, "Every %.1fs: ", interval); // the rules: // width < tsl : print nothing // width < tsl + hlen + 1: print ts // width = tsl + hlen + 1: print header, ts // width < tsl + hlen + 4: print header, ..., ts // width < tsl + hlen + wcommand_columns: print header, truncated wcommand, ..., ts // width > "": print header, wcomand, ts // this is slightly different from how it used to be if(width >= tsl) { if(width >= tsl + hlen + 1) { mvaddstr(0, 0, header); if(width >= tsl + hlen + 2) { if(width < tsl + hlen + 4) { mvaddstr(0, width - tsl - 4, "... "); }else{ if(width < tsl + hlen + wcommand_columns) { // print truncated int avail_columns = width - tsl - hlen; int using_columns = wcommand_columns; int using_characters = wcommand_characters; while(using_columns > avail_columns - 4) { using_characters--; using_columns = wcswidth(wcommand, using_characters); } mvaddnwstr(0, hlen, wcommand, using_characters); mvaddstr(0, width - tsl - 4, "... "); }else{ mvaddwstr(0, hlen, wcommand); } } } } mvaddstr(0, width - tsl + 1, ts); } free(header); } /* allocate pipes */ if (pipe(pipefd)<0) { perror("pipe"); do_exit(7); } /* flush stdout and stderr, since we're about to do fd stuff */ fflush(stdout); fflush(stderr); /* fork to prepare to run command */ child=fork(); if (child<0) { /* fork error */ perror("fork"); do_exit(2); } else if (child==0) { /* in child */ close (pipefd[0]); /* child doesn't need read side of pipe */ close (1); /* prepare to replace stdout with pipe */ if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */ perror("dup2"); exit(3); } dup2(1, 2); /* stderr should default to stdout */ if (option_exec) { /* pass command to exec instead of system */ if (execvp(command_argv[0], command_argv)==-1) { perror("exec"); exit(4); } } else { status=system(command); /* watch manpage promises sh quoting */ /* propagate command exit status as child exit status */ if (!WIFEXITED(status)) { /* child exits nonzero if command does */ exit(1); } else { exit(WEXITSTATUS(status)); } } } /* otherwise, we're in parent */ close(pipefd[1]); /* close write side of pipe */ if ((p=fdopen(pipefd[0], "r"))==NULL) { perror("fdopen"); do_exit(5); } for (y = show_title; y < height; y++) { int eolseen = 0, tabpending = 0; wint_t carry = WEOF; for (x = 0; x < width; x++) { wint_t c = L' '; int attr = 0; if (!eolseen) { /* if there is a tab pending, just spit spaces until the next stop instead of reading characters */ if (!tabpending) do { if(carry == WEOF) { c = my_getwc(p); }else{ c = carry; carry = WEOF; } }while (c != WEOF && !isprint(c) && c<128 && wcwidth(c) == 0 && c != L'\n' && c != L'\t' && (c != L'\033' || option_color != 1)); if (c == L'\033' && option_color == 1) { x--; process_ansi(p); continue; } if (c == L'\n') if (!oldeolseen && x == 0) { x = -1; continue; } else eolseen = 1; else if (c == L'\t') tabpending = 1; if (x==width-1 && wcwidth(c)==2) { y++; x = -1; //process this double-width carry = c; //character on the next line continue; //because it won't fit here } if (c == WEOF || c == L'\n' || c == L'\t') c = L' '; if (tabpending && (((x + 1) % 8) == 0)) tabpending = 0; } move(y, x); if (option_differences) { cchar_t oldc; in_wch(&oldc); attr = !first_screen && ((wchar_t)c != oldc.chars[0] || (option_differences_cumulative && (oldc.attr & A_ATTRIBUTES))); } if (attr) standout(); addnwstr((wchar_t*)&c,1); if (attr) standend(); if(wcwidth(c) == 0) { x--; } if(wcwidth(c) == 2) { x++; } } oldeolseen = eolseen; } fclose(p); /* harvest child process and get status, propagated from command */ if (waitpid(child, &status, 0)<0) { perror("waitpid"); do_exit(8); }; /* if child process exited in error, beep if option_beep is set */ if ((!WIFEXITED(status) || WEXITSTATUS(status))) { if (option_beep) beep(); if (option_errexit) do_exit(8); } first_screen = 0; refresh(); if (precise_timekeeping) { watch_usec_t cur_time = get_time_usec(); next_loop += USECS_PER_SEC*interval; if (cur_time < next_loop) usleep(next_loop - cur_time); } else usleep(interval * 1000000); } endwin(); return 0; }
static void fb_gpm_in(void *nic) { #ifndef USE_GPM_DX static int lx = -1, ly = -1; #endif struct event ev; Gpm_Event gev; again: if (Gpm_GetEvent(&gev) <= 0) { unhandle_fb_mouse(); return; } /*fprintf(stderr, "%x %x %d %d %d %d\n", gev.type, gev.buttons, gev.dx, gev.dy, gev.wdx, gev.wdy);*/ #ifndef USE_GPM_DX if (gev.x != lx || gev.y != ly) { mouse_x = (gev.x - 1) * fb_xsize / fb_txt_xsize + fb_xsize / fb_txt_xsize / 2 - 1; mouse_y = (gev.y - 1) * fb_ysize / fb_txt_ysize + fb_ysize / fb_txt_ysize / 2 - 1; lx = gev.x, ly = gev.y; } #else if (gev.dx || gev.dy) { if (!((int)gev.type & gpm_smooth)) { mouse_x += gev.dx * 8; mouse_y += gev.dy * 8; } #ifdef GPM_HAVE_SMOOTH else { mouse_x += gev.dx; mouse_y += gev.dy; } #endif } #endif ev.ev = EV_MOUSE; if (mouse_x >= fb_xsize) mouse_x = fb_xsize - 1; if (mouse_y >= fb_ysize) mouse_y = fb_ysize - 1; if (mouse_x < 0) mouse_x = 0; if (mouse_y < 0) mouse_y = 0; if (!((int)gev.type & gpm_smooth) && (gev.dx || gev.dy)) { mouse_x = (mouse_x + 8) / 8 * 8 - 4; mouse_y = (mouse_y + 8) / 8 * 8 - 4; if (mouse_x >= fb_xsize) mouse_x = fb_xsize - 1; if (mouse_y >= fb_ysize) mouse_y = fb_ysize - 1; if (mouse_x < 0) mouse_x = 0; if (mouse_y < 0) mouse_y = 0; } ev.x = mouse_x; ev.y = mouse_y; if (gev.buttons & GPM_B_LEFT) ev.b = B_LEFT; else if (gev.buttons & GPM_B_MIDDLE) ev.b = B_MIDDLE; else if (gev.buttons & GPM_B_RIGHT) ev.b = B_RIGHT; else ev.b = 0; if ((int)gev.type & GPM_DOWN) ev.b |= B_DOWN; else if ((int)gev.type & GPM_UP) ev.b |= B_UP; else if ((int)gev.type & GPM_DRAG) ev.b |= B_DRAG; else ev.b |= B_MOVE; #ifdef HAVE_WDX_WDY if ((ev.b & BM_ACT) == B_DRAG || (ev.b & BM_ACT) == B_MOVE) { if (gev.wdy < 0) { ev.b &= ~BM_BUTT; ev.b |= B_WHEELDOWN; } else if (gev.wdy > 0) { ev.b &= ~BM_BUTT; ev.b |= B_WHEELUP; } #if 0 /* it doesn't work anyway - the exps2 protocol doesn't support it and evdev support in gpm is buggy */ else if (gev.wdx < 0) { ev.b &= ~BM_BUTT; ev.b |= B_WHEELRIGHT; } else if (gev.wdx > 0) { ev.b &= ~BM_BUTT; ev.b |= B_WHEELLEFT; #endif } #endif #ifndef USE_GPM_DX if (fb_msetsize < 0) { } else if (fb_msetsize < 10) { fb_msetsize++; } else if ((ev.b & BM_ACT) == B_MOVE && !(ev.b & BM_BUTT)) { fb_mouse_setsize(); fb_msetsize = -1; } #endif if (((ev.b & BM_ACT) == B_MOVE && !(ev.b & BM_BUTT)) || (ev.b & BM_ACT) == B_DRAG) { if (can_read(fb_hgpm)) goto again; } last_mouse_buttons = (int)ev.b; if (!current_virtual_device) return; if (current_virtual_device->mouse_handler) current_virtual_device->mouse_handler(current_virtual_device, ev.x, ev.y, (int)ev.b); redraw_mouse(); } static int handle_fb_mouse(void) { Gpm_Connect conn; #ifndef USE_GPM_DX int gpm_ver = 0; struct winsize ws; fb_old_ws_v = 0; #endif fb_hgpm = -1; #ifndef USE_GPM_DX Gpm_GetLibVersion(&gpm_ver); fb_msetsize = -1; if (gpm_ver >= 11900) { int rs; EINTRLOOP(rs,ioctl(1, TIOCGWINSZ, &ws)); if (rs != -1) { memcpy(&fb_old_ws, &ws, sizeof(struct winsize)); fb_old_ws_v = 1; ws.ws_row *= 2; EINTRLOOP(rs, ioctl(1, TIOCSWINSZ, &ws)); fb_msetsize = 0; memcpy(&fb_new_ws, &ws, sizeof ws); } } get_terminal_size(1, &fb_txt_xsize, &fb_txt_ysize); #endif conn.eventMask = (unsigned short)~0U; conn.defaultMask = gpm_smooth; conn.minMod = 0; conn.maxMod = (unsigned short)~0U; if ((fb_hgpm = Gpm_Open(&conn, 0)) < 0) { unhandle_fb_mouse(); return -1; } set_handlers(fb_hgpm, fb_gpm_in, (void (*)(void *))NULL, (void (*)(void *))NULL, NULL); #ifdef SIGTSTP install_signal_handler(SIGTSTP, (void (*)(void *))sig_tstp, NULL, 0); #endif #ifdef SIGCONT install_signal_handler(SIGCONT, (void (*)(void *))sig_cont, NULL, 0); #endif #ifdef SIGTTIN install_signal_handler(SIGTTIN, (void (*)(void *))sig_tstp, NULL, 0); #endif return 0; }
/** Construct the struct itrm of this process, make ::ditrm point to it, * set up select() handlers, and send the initial interlink packet. * * The first five parameters are file descriptors that this function * saves in submembers of struct itrm, and for which this function may * set select() handlers. Please see the definitions of struct * itrm_in and struct itrm_out for further explanations. * * @param std_in itrm_in.std: read tty device (or pipe) * @param std_out itrm_out.std: write tty device (or pipe) * @param sock_in itrm_in.sock * - If master: == @a std_out (masterhood flag) * - If slave: read socket from master * @param sock_out itrm_out.sock * - If master: write pipe to same process * - If slave: write socket to master * @param ctl_in itrm_in.ctl: control tty device * * The remaining three parameters control the initial interlink packet. * * @param init_string A string to be passed to the master process. Need * not be null-terminated. If @a remote == 0, this is * a URI. Otherwise, this is a remote command. * @param init_len The length of init_string, in bytes. * @param remote = 0 if asking the master to start a new session * and display it via this process. Otherwise, * enum ::remote_session_flags. */ void handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, void *init_string, int init_len, int remote) { struct itrm *itrm; struct terminal_info info; struct interlink_event_size *size = &info.event.info.size; unsigned char *ts; memset(&info, 0, sizeof(info)); get_terminal_size(ctl_in, &size->width, &size->height); info.event.ev = EVENT_INIT; info.system_env = get_system_env(); info.length = init_len; if (remote) { info.session_info = remote; info.magic = INTERLINK_REMOTE_MAGIC; } else { info.session_info = get_cmd_opt_int("base-session"); info.magic = INTERLINK_NORMAL_MAGIC; } itrm = mem_calloc(1, sizeof(*itrm)); if (!itrm) return; itrm->in.queue.data = mem_calloc(1, ITRM_IN_QUEUE_SIZE); if (!itrm->in.queue.data) { mem_free(itrm); return; } ditrm = itrm; itrm->in.std = std_in; itrm->out.std = std_out; itrm->in.sock = sock_in; itrm->out.sock = sock_out; itrm->in.ctl = ctl_in; itrm->timer = TIMER_ID_UNDEF; itrm->remote = !!remote; /* If the master does not tell which charset it's using in * this terminal, assume it's some ISO 8859. Because that's * what older versions of ELinks did. */ itrm->title_codepage = get_cp_index("ISO-8859-1"); /* FIXME: Combination altscreen + xwin does not work as it should, * mouse clicks are reportedly partially ignored. */ if (info.system_env & (ENV_SCREEN | ENV_XWIN)) itrm->altscreen = 1; if (!remote) { if (ctl_in >= 0) setraw(itrm, 1); send_init_sequence(std_out, itrm->altscreen); handle_terminal_resize(ctl_in, resize_terminal); #ifdef CONFIG_MOUSE enable_mouse(); #endif handle_itrm_stdin(itrm); } else { /* elinks -remote may not have a valid stdin if not run from a tty (bug 938) */ if (std_in >= 0) handle_itrm_stdin(itrm); } if (sock_in != std_out) set_handlers(sock_in, (select_handler_T) in_sock, NULL, (select_handler_T) free_itrm, itrm); get_terminal_name(info.name); ts = get_cwd(); if (ts) { memcpy(info.cwd, ts, int_min(strlen(ts), MAX_CWD_LEN)); mem_free(ts); } itrm_queue_event(itrm, (char *) &info, TERMINAL_INFO_SIZE); itrm_queue_event(itrm, (char *) init_string, init_len); }
int main(int argc, char* argv[]) { int is_running = 1; int x_terminal_size, y_terminal_size; memset(client_buffer, '\0', sizeof(client_buffer)); get_terminal_size(&x_terminal_size, &y_terminal_size); initscr(); raw(); keypad(stdscr, TRUE); noecho(); transcript_window = newwin(23,40,0,0); client_chat_window = newwin(MAX_ROWS,MAX_COLUMNS,20,40); write_to_transcript_window("Hello!\n"); write_to_transcript_window("Hey all!\nI love BlackChat, it's so awesome!\n"); write_to_transcript_window("Press the \'q\' key to quit!"); while(is_running) { int ch = getch(); switch(ch) { case 'q': is_running = 0; break; /* Scroll the clients typing window down. */ case KEY_DOWN: client_current_line ++; if(client_current_line*MAX_COLUMNS > strlen(client_buffer)) client_current_line --; wclear(client_chat_window); wprintw(client_chat_window, &client_buffer[client_current_line*MAX_COLUMNS]); break; /* Scroll the clients typing window up. */ case KEY_UP: client_current_line --; if(client_current_line < 0) client_current_line = 0; wclear(client_chat_window); wprintw(client_chat_window, &client_buffer[client_current_line*MAX_COLUMNS]); break; /* Delete the previous chracter. */ case KEY_BACKSPACE: client_buffer[ strlen(client_buffer)-1 ] = '\0'; print_client_chat_buffer(); break; /* If were here, that means we didn't press any "special" keys so that means were * trying to write some generic characters to our chat window. */ default: /* Store the new char in our buffer. */ client_buffer[ strlen(client_buffer) ] = ch; /* Print our new chat buffer. */ print_client_chat_buffer(); break; } wrefresh(transcript_window); wrefresh(client_chat_window); } delwin(transcript_window); delwin(client_chat_window); endwin(); return 0; }