<div dir="ltr"><div>Here is a simplified 'more' command for Unix V7:</div><div><br></div><div>/*********************************************************************<br> * UNIX pager (v7 compatible)   Chipmaster and KenUnix<br> *<br> * cc -o more more.c<br> *<br> * Usage examples:<br> *   man wall | more<br> *   more xyz<br> *   more abc def xyz<br> *<br> * Started February 15th, 2023 YeOlPiShack.net<br> *<br> * This is the ultimately dumbest version of more I have experienced.<br> * Its main purpose is to illustrate the use of /dev/tty to interact<br> * with the user while in a filter role (stdin -> stdout). This also<br> * leaves stderr clear for actual errors.<br> *<br> *<br> * NOTES on Antiquity:<br> *<br> *   - The early C syntax didn't allow for combining type information<br> *     in the parenthesized argument list only the names were listed.<br> *     Then a "variable" list followed the () and preceded the { that<br> *     declared the types for the argument list.<br> *<br> *   - There is no "void", specifically there is no distinction<br> *     between a function that returns an int or nothing at all.<br> *<br> *   - Many of the modern day header files aren't there.<br> *<br> *   - Apparently "/dev/tty" couldn't be opened for both reading and<br> *     writing on the same FD... at least not in our VM.<br> *<br> *   - Apparently \a wasn't defined yet either. So I use the raw code<br> *     \007.<br> *<br> *   - Modern compilers gripe if you do an assignment and comparison in<br> *     the same statement without enclosing the assignment in (). The<br> *     original compilers did not. So if it looks like there are too<br> *     many ()s it's to appease the modern compiler gods.<br> *<br> *   - I'm not sure where they hid errno if there was one. I'd think<br> *     there had to be. Maybe Kernighan or Pike knows...<br> *<br> *********************************************************************/<br>#include <stdio.h><br><br>/*** Let's make some assumptions about our terminal columns and lines. ***/<br><br>#define T_COLS  80<br>#define T_LINES 24<br><br>/*** Let's set up our global working environment ***/<br><br>FILE *cin;              /* TTY (in) */<br>FILE *cout;             /*  |  (out) */<br>int   ct = 0;<br><br>/*** message to stderr and exit with failure code ***/<br><br>err(msg)<br>  char *msg;<br>{<br>  fputs(msg, stderr);<br>  exit(1);<br>}<br><br>/*** A poor man's CLear Screen ***<br> *<br> * Yup! This is how they used to do it, so says THE Kenrighan & Pike!<br> * termcap?!?! What's that?<br> */<br><br>cls()<br>{<br>  int x;<br>  for(x=0; x<T_LINES; ++x) fputc('\n', cout);<br>  ct = 0; /* reset global line count */<br>}<br><br>/*** The PAUSE prompt & wait ***/<br><br>pause()<br>{<br>  char in[T_COLS+1]; /* TTY input buffer */<br><br>  fflush(stdout); /*JIC*/<br>  fputs("--- [ENTER] to continue --- Ctrl-d exits ", cout);<br>  fflush(cout);<br>  if(!fgets(in, 81, cin)) {<br>    /* ^D / EOF */<br>    fputc('\n', cout); /* cleaner terminal */<br>    exit(0);<br>  }<br>}<br><br>/*** Read and page a "file" ***/<br><br>int pg(f)<br>  FILE *f;<br>{<br>  char  buf[T_COLS+1];   /* input line: usual term width + \0 */<br><br>  /*** read and page stdin ***/<br><br>  while(fgets(buf, sizeof(buf), f)) {<br>    /* page break at T_LINES */<br>    if(++ct==T_LINES) {<br>      pause();<br>      ct = 1;<br>    }<br>    fputs(buf, stdout);<br>  }<br>  return 0;<br>}<br><br>/*** Let's do some paging!! ***/<br><br>int main(argc, argv)<br>  int argc;<br>  char *argv[];<br>{<br>  FILE *in;<br>  int x, er;<br><br>  /*** Grab a direct line to the TTY ***/<br><br>  if(!(cin=fopen("/dev/tty", "r")) || !(cout=fopen("/dev/tty", "w")))<br>    err("\007Couldn't get controlling TTY\n");<br><br>  /*** with CLI args ***/<br><br>  if(argc>1) {<br>    er = 0;<br>    for(x=1; x<argc; ++x) {<br>      if(argc>2) {<br>        if(!er) cls();<br>        er = 0;<br>        /* remember all user interaction is on /dev/tty (cin/cout) */<br>        fprintf(cout, ">>> %s <<<\n", argv[x]);<br>        pause();<br>      }<br><br>      /* - is tradition for stdin */<br>      if(strcmp("-", argv[x])==0) {<br>        pg(stdin);<br><br>      /* it must be a file! */<br>      } else if((in=fopen(argv[x], "r"))) {<br>        pg(in);<br>        fclose(in);<br>      } else {<br>        /* errors go on stderr... JIC someone want to log */<br>        fprintf(stderr, "Could not open '%s'!\n", argv[x]);<br>        fflush(stderr);<br>        er = 1; /* this prevents cls() above. */<br>      }<br><br>    }<br><br>  /*** no args - read and page stdin ***/<br>  } else {<br>    pg(stdin);<br>  }<br><br>  return 0;<br>}<br></div><div><br></div><div>End...<br></div><div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div></div><div>WWL 📚</div><div><br></div><div><br></div></div></div></div></div>