Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <termios.h>
- #define MAXC 1024 /* if you need a constant, #define one (or more) */
- #define LINES 20
- /* avoid use of global variables, okay when used as flag or in callback functions.
- * you could pass address of both struct termios variables as parameters if desired.
- */
- static struct termios cooked, raw; /* keyboard modes cooked (normal) and raw */
- static int inrawmode;
- static int modesfilled;
- static int linenumbers;
- /** set (toggle) keyboard between cooked (normal buffered mode) and
- * raw (unbuffered / noncanonical) mode each time the function is called.
- * on first call, the termios structs cooked & raw are filled. for all
- * remaining calls, tcsetattr either sets raw mode or restores cooked
- * mode based on the flag 'inrawmode'.
- */
- int kbd_toggle_raw_mode (void)
- {
- if (inrawmode) { /* if in raw mode, switch back to cooked */
- if (tcsetattr (0, TCSANOW, &cooked)) { /* validate change */
- fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);
- return -1;
- }
- inrawmode = 0; /* set in raw mode flag false */
- }
- else { /* in cooked mode, switch to raw mode */
- if (!modesfilled) { /* if first time called */
- if (tcgetattr (0, &cooked)) { /* save orig settings / validate */
- fprintf (stderr, "%s() error: tcgetattr failed.\n", __func__);
- return -1;
- }
- /* copy cooked to raw to initialize raw struct */
- memcpy (&raw, &cooked, sizeof(struct termios));
- raw.c_lflag &= ~(ICANON | ECHO); /* set flags for raw mode */
- raw.c_cc[VTIME] = 0;
- raw.c_cc[VMIN] = 1;
- modesfilled = 1; /* set flag indicating both structs filled */
- }
- if (tcsetattr (0, TCSANOW, &raw)) { /* set raw mode / validate */
- fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);
- return -1;
- }
- inrawmode = 1; /* set in raw mode flag true */
- }
- return 0;
- }
- /** requires filename to page as first argument, any second
- * argument will enable line number of output.
- * pressing any whitespace (space, tab, newline) will page
- * next 20 lines, 'c' will continue to end, 'q' will quit
- * at that point.
- */
- int main (int argc, char **argv) {
- char line[MAXC]; /* buffer to hold each line */
- int n = 0, pager = 1; /* line counter, flag to page/continue to end */
- /* use filename provided as 1st argument (stdin by default)
- * allows piping output or redirecting file to program
- * (no line numbering control in that case of input on stdin)
- */
- FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
- if (!fp) { /* validate file open for reading */
- perror ("file open failed");
- return 1;
- }
- if (argc > 2) /* if addition argument given */
- linenumbers = 1; /* enable line numbers */
- while (fgets (line, MAXC, fp)) { /* read each line into line */
- n += 1; /* increment line number counter */
- if (linenumbers) /* if line number flag set */
- printf ("%3d ", n); /* output line numbers */
- fputs (line, stdout); /* output line */
- if (pager && n % LINES == 0) { /* pager set && LINES no. of lines out */
- int c, quit = 0; /* char to read, quit flag */
- if (kbd_toggle_raw_mode() == -1) /* if error in setting raw mode, warn */
- fputs ("\nerror: unable to change to raw keyboard mode.\n\n", stderr);
- /* read user input, check if not space and not EOF */
- for (c = getchar(); !isspace(c) && c != EOF; c = getchar())
- if (c == 'c') { /* if user input 'c' */
- pager = 0; /* set pager flag false */
- break;
- }
- else if (c == 'q') { /* if user input 'q' */
- quit = 1; /* set quit flag true */
- break;
- }
- if (kbd_toggle_raw_mode() == -1) /* if error switing to cooked, warn */
- fputs ("\nerror: unable to restore keyboard mode.\n\n", stderr);
- if (c == EOF || quit) /* if c is EOF, manual EOF from user */
- break; /* Ctrl+d Unix, (Ctrl+z on windows) */
- }
- }
- if (fp != stdin) /* close file if not stdin */
- fclose (fp);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement