# A program like 'more'

**URL:** <https://boards.straightdope.com/t/a-program-like-more/173766>\
**Category:** Factual Questions\
**Created:** [May 7, 2003, 9:31pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766 "2003-05-07T21:31:35Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![The\_Weak\_Force](https://avatars.discourse-cdn.com/v4/letter/t/9dc877/32.png) [@The\_Weak\_Force](https://boards.straightdope.com/u/The_Weak_Force)\
**Post date:** [May 7, 2003, 9:31pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/1 "2003-05-07T21:31:35Z")

</div>

I’ve been programming (in C) in Unix for a few months, and it occurred to me that nothing I’ve learned so far allows me to write a program that emulates a small part of the functionality of the basic program ‘more’ that lives on every Unix workstation.

Specifically, I don’t know how to handle input and output like more does. If you’re reading this, you probably know that the purpose of more is to display the contents of a text file in a convenient way. There are various ways to call more from a shell. When invoked as

**more \< _sometextfile_**

or

**_someothercommand_ | more**

more will, as one would expect, display the contents of _sometextfile_ or the output of _someothercommand_ in a convenient way. However, unlike the programs I know how to write, more still accepts commands interactively from the keyboard, even in such cases, where its “standard input” is supposedly redirected.

On the other hand,

**more _sometextfile_**

has the exact same effect as

**more \< _sometextfile_**.

Remarkably, more does _not_ read lines of input from the keyboard and display them. However, it does accept commands interactively from the keyboard in the exact same way as it does when its input is redirected. In this way, the way more uses its “standard input” is fundamentally different depending on whether the shell has redirected its standard input or not.

Moreover,

**more _sometextfile_ | _someothercommand_**

is fundamentally different from the above cases: in this case, more does not use keyboard input at all.

The thing that is simply beyond me right now is that the program more is able to respond differently based on where the shell connects its input and output; I don’t even know how to tell, from within a process, whether the process’s input/output have been redirected by the shell. And secondly, no matter where the shell connects the input of more, more retains the ability to accept commands directly from the keyboard.

So how can a program tell where its standard input is coming from and where its standard output is going? And how can a program take commands directly from the keyboard if the shell has redirected its standard input? If anything isn’t clear, I’d be happy to clarify.

(P.S.: Thanks to those who responded to my previous GQ’s, [A Proof of the Riemann Hypothesis?](http://boards.straightdope.com/sdmb/showthread.php?s=&threadid=167318), and [General Animalian Color Vision](http://boards.straightdope.com/sdmb/showthread.php?s=&threadid=160563).)

---

<div class="post-metadata">

**Author:** ![LordVor](https://avatars.discourse-cdn.com/v4/letter/l/90ced4/32.png) [@LordVor](https://boards.straightdope.com/u/LordVor)\
**Post date:** [May 7, 2003, 11:53pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/2 "2003-05-07T23:53:49Z")

</div>

You’re thinking wrong, more isn’t responding differently depending on whether input and output are redirected, it’s responding differently whether or not it’s got a filename for a parameter.

both the \< and the | redirect more’s stdin, the \< from a file and the | from a command. More has no arguements in this case, so it assumes it should start reading from stdin and doing its thing.

When you say “more sometextfile”, more assumes by the arguement count that it should open sometextfile and do its thing on that.

to really blow your mind, just run “more”.

-lv

---

<div class="post-metadata">

**Author:** ![Ms2001](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/ms2001/32/18463_2.png) [@Ms2001](https://boards.straightdope.com/u/Ms2001)\
**Post date:** [May 8, 2003, 1:10am UTC](https://boards.straightdope.com/t/a-program-like-more/173766/3 "2003-05-08T01:10:47Z")

</div>

> [@](#):
>
> The thing that is simply beyond me right now is that the program more is able to respond differently based on where the shell connects its input and output; I don’t even know how to tell, from within a process, whether the process’s input/output have been redirected by the shell.

The **isatty** function will tell you if stdin is connected to a terminal.

---

<div class="post-metadata">

**Author:** ![The\_Weak\_Force](https://avatars.discourse-cdn.com/v4/letter/t/9dc877/32.png) [@The\_Weak\_Force](https://boards.straightdope.com/u/The_Weak_Force)\
**Post date:** [May 8, 2003, 4:14am UTC](https://boards.straightdope.com/t/a-program-like-more/173766/4 "2003-05-08T04:14:35Z")

</div>

LordVor, what you say is _prima facie_ reasonable, but you can’t be right. Sorry, I didn’t mention that the command

**more**

sends an error message to stderr:

Usage: more [-cdflrsuw] [-lines] [+linenumber] [+/pattern] [filename …].

I don’t know if your version of more does the same.

Mr2001, thanks for isatty; it does indeed do what you say. One down, one to go. I don’t suppose you know how to access the keyboard without having to use standard input?

---

<div class="post-metadata">

**Author:** ![Ms2001](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/ms2001/32/18463_2.png) [@Ms2001](https://boards.straightdope.com/u/Ms2001)\
**Post date:** [May 8, 2003, 5:37am UTC](https://boards.straightdope.com/t/a-program-like-more/173766/5 "2003-05-08T05:37:12Z")

</div>

I suggest checking the source code. I couldn’t find the source for ‘more’, though I’m sure it’s out there, so [here](http://www.greenwoodsoftware.com/less/less-381.zip) is the source for ‘less’, which works mostly the same.

---

<div class="post-metadata">

**Author:** ![Mort\_Furd](https://avatars.discourse-cdn.com/v4/letter/m/8e8cbc/32.png) [@Mort\_Furd](https://boards.straightdope.com/u/Mort_Furd)\
**Post date:** [May 8, 2003, 1:07pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/6 "2003-05-08T13:07:21Z")

</div>

Here’s what appears to be a Japanes langauge version of more:  
[http://www.kyoto-su.ac.jp/circle/mics/Docs/unix/command/FILE/more.c](http://www.kyoto-su.ac.jp/circle/mics/Docs/unix/command/FILE/more.c)

I’m still looking for an english version.

---

<div class="post-metadata">

**Author:** ![Desmostylus](https://avatars.discourse-cdn.com/v4/letter/d/c57346/32.png) [@Desmostylus](https://boards.straightdope.com/u/Desmostylus)\
**Post date:** [May 8, 2003, 1:23pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/7 "2003-05-08T13:23:29Z")

</div>

[http://cvs.kerneli.org/util-linux/text-utils/more.c?annotate=1.1](http://cvs.kerneli.org/util-linux/text-utils/more.c?annotate=1.1)

---

<div class="post-metadata">

**Author:** ![Mort\_Furd](https://avatars.discourse-cdn.com/v4/letter/m/8e8cbc/32.png) [@Mort\_Furd](https://boards.straightdope.com/u/Mort_Furd)\
**Post date:** [May 8, 2003, 1:47pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/8 "2003-05-08T13:47:45Z")

</div>

Well, that last would appear to have been crap.  
Here’s the real thing:  
[http://www.mit.edu/afs/athena/astaff/reference/4.4lite/usr/src/old/more/more.c](http://www.mit.edu/afs/athena/astaff/reference/4.4lite/usr/src/old/more/more.c)

---

<div class="post-metadata">

**Author:** ![Desmostylus](https://avatars.discourse-cdn.com/v4/letter/d/c57346/32.png) [@Desmostylus](https://boards.straightdope.com/u/Desmostylus)\
**Post date:** [May 8, 2003, 2:08pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/9 "2003-05-08T14:08:23Z")

</div>

> [@](#):
>
> \*Originally posted by Mort Furd \*  
> **Well, that last would appear to have been crap.**

I’ll assume that you were referring to _your_ earlier post, and not to mine. 🙂

---

<div class="post-metadata">

**Author:** ![Mort\_Furd](https://avatars.discourse-cdn.com/v4/letter/m/8e8cbc/32.png) [@Mort\_Furd](https://boards.straightdope.com/u/Mort_Furd)\
**Post date:** [May 8, 2003, 3:34pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/10 "2003-05-08T15:34:17Z")

</div>

Yup. Sorry. 🙂

---

<div class="post-metadata">

**Author:** ![pestie](https://avatars.discourse-cdn.com/v4/letter/p/e5b9ba/32.png) [@pestie](https://boards.straightdope.com/u/pestie)\
**Post date:** [May 8, 2003, 3:39pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/11 "2003-05-08T15:39:54Z")

</div>

Usually, in any UNIX variant, if a program explicity opens /dev/tty it will read from the current TTY (the “keyboard,” whether that is a physically-connected keyboard at the console, a serial port, a telnet/ssh session, whatever) and allow it to interact with the user directly, regardless of where stdin/stdout are pointing.

Another fun fact is that many UNIX programs will behave differently depending on whether stdin is a tty or not. They’ll check the result of the **isatty()** call and change their buffering mode accordingly. If they’re connected to a TTY they’ll default to “line buffered” mode (asking the kernel to send them a single line of text at a time, which is usually best for interacting with a terminal) whereas they’ll default to either raw (one character at a time) or some sort of buffered mode (a “block” at a time, with the block size being some arbitrarily-sized chunk of data, which is better for dealing with “bulk” data, or data that may be in binary format).

---

<div class="post-metadata">

**Author:** ![LordVor](https://avatars.discourse-cdn.com/v4/letter/l/90ced4/32.png) [@LordVor](https://boards.straightdope.com/u/LordVor)\
**Post date:** [May 8, 2003, 3:55pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/12 "2003-05-08T15:55:46Z")

</div>

> [@](#):
>
> _Originally posted by The Weak Force I don’t know if your version of more does the same._

good point. I tested my theory under HP-UX, which does indeed pipe input from the keyboard into more’s display engine when you just type in “more”, no error message.

Mort’s link to source code seems to use an ioctl instead of the isatty() test, but still uses the argc to see if it should read a file or print the error if there’s no file and no tty input.

opening /dev/tty solves the real question I had, which was “If more’s stdin is redirected, then how can more get commands from the keyboard?”

-lv

---

<div class="post-metadata">

**Author:** ![The\_Weak\_Force](https://avatars.discourse-cdn.com/v4/letter/t/9dc877/32.png) [@The\_Weak\_Force](https://boards.straightdope.com/u/The_Weak_Force)\
**Post date:** [May 8, 2003, 5:52pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/13 "2003-05-08T17:52:54Z")

</div>

Thanks, pestie, that’s exactly what I need. Unfortunately, you were too late; I downloaded the source code for ‘less’ last night and a little while ago I figured out the bit about /dev/tty. Also, apparently you can read input from standard error (the version of less Mr2001 linked to will first try opening /dev/tty and on failure will use standard error for keyboard input). By experimenting, I think that this will work as long as you use the low-level function ‘read’ to do it and standard error is not being redirected. I’m having trouble finding doumentation on using input from stderr, but it seems to work on this machine. Moreover,

**more _sometextfile_ 2\>\> junk**

Does not behave as expected. It displays one screenful of _sometextfile_, up to the point where it would normally say “MORE” and wait for input, but instead it just returns to the shell after the one screenful. This leads me to believe that more is trying to read keyboard input from the standard error stream, but the read is failing because stderr is being redirected.

**less _sometextfile_ 2\>\> junk**

Also doesn’t behave properly. The keyboard input becomes echoed and buffered and the output is messed up, but the program is basically able to display the entire file.

Thanks to everyone who responded. Now I basically know what I wanted to know. The source code for ‘more’ will be useful.

---

<div class="post-metadata">

**Author:** ![Zyada](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/zyada/32/3028_2.png) [@Zyada](https://boards.straightdope.com/u/Zyada)\
**Post date:** [June 20, 2003, 4:12pm UTC](https://boards.straightdope.com/t/a-program-like-more/173766/14 "2003-06-20T16:12:03Z")

</div>

I realize this is an old thread, but I’ve read through it twice and I think there are some basic misconceptions that need to be cleared up(just in case someone searches, you know?).

Redirection is handled by the shell that you are using, not by the program you are calling. All the program needs to do is to read stdin or write to stdout to be able to work with redirection. In the case of “more”, it will read stdin if there is no file argument (although, as **The Weak Force** found out, some versions will not accept input from the terminal)

Check the documentation for the specifics of how redirection works for your shell. I know there are minor variations in implementation; however, here are some basics that work in ksh and csh:

**\> _file_** send standard out to a file  
**\< _file_** Use a file as standard input  
**_command_ | _command_** Take the standard out put from the first command and process it with the second command.

If I understand the last post by **The Weak Force** , _more_ is not the command you want to use. It looks like you are trying to append one file to the end of another one. The command _cat_ will write the contents of desired file to standard output _without interaction_ and can be then be redirected with \>\> to append to another file.
