home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
- # This is a shell script. Feed it to sh.
- echo '
- Hi, and welcome to the pty install script.
- pty is a program for managing pseudo-terminals.
-
- I'\''m not actually going to install anything.
- I'\''ll just guide you through what has to be done,
- from compiling through installation.
-
- One advantage of this hands-off philosophy is that
- you can kill and restart this script at any time.
-
- In the first part of this script, I'\''ll lead you through configuration.
- For the moment, don'\''t actually change anything in your system. Just
- alternate between reading this script and fooling around with the
- Makefile, and I'\''ll remind you later, after compilation, of what has
- to be changed elsewhere.
-
- I need the following programs: echo, tr [-d], man, sed [-n], grep, test.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- The first versions of pty were designed on a BSD 4.2-based system.
- During May 1990 pty 3.0 was written completely from scratch,
- on a BSD 4.3-based system. It has been thoroughly tested on
- several BSD 4.3-based systems, tested with a few Makefile changes
- on several BSD 4.2-based systems, and run on at least one mutant.
-
- If you make it through installation and testing and get pty running,
- please send a note to the author, Dan Bernstein, on the Internet
- at brnstnd@kramden.acf.nyu.edu. Let him know your computer model, OS
- version, and what changes you had to make. If you have any trouble,
- please also get in touch with the author. If you have a different kind
- of system with pseudo-terminal support that could use a pty port, the
- author would love to hear about it.
-
- One note: Like all software, pty comes without warranty, to the extent
- permitted by applicable law. Use it at your own risk.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- I assume that you don'\''t want to make any major changes
- to your computer just to take advantage of pty'\''s capabilities.
- You might not even have a privileged account, for all I know.
-
- The first major decision you have to make is what privileges to give pty.
- Obviously if you don'\''t have privileges then pty won'\''t either;
- this is Case UN.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- There are several good reasons for giving programs privileges.
- Most importantly, privileged programs can precisely control access
- to a shared resource. pty supports an interactive user list in
- /etc/utmp, a login-logout record in /usr/adm/wtmp, and controlled
- access to the pseudo-terminal files themselves, including security and
- mode changing. None of these are possible if pty isn'\''t setuid.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- If you do want pty to have privileges, you have to decide between
- setting up pty as root (Case ROOT) or as some other user, say ``pty'\'\''
- (Case PTY). Staying away from root has the advantage that problems
- can'\''t possibly destroy all security in one blow. However, root has
- several advantages, mainly because of BSD limitations: 1. A process
- can'\''t change ownership of a file between its euid and uid. Only root
- can change ownership. It shouldn'\''t be necessary to change ownership
- of ptys anyway, but that'\''s what many programs assume. 2. MAXUPRC in
- <sys/param.h> limits the number of processes under a given *effective*
- uid. This absolutely idiotic behavior is a serious problem for programs
- setuid to anything other than root. pty tries to work around this
- problem, but there are no true solutions. 3. Despite the documentation
- in kill(2), many machines don'\''t allow non-root processes to send
- CONT to children with a different uid. Unlike almost all other programs,
- pty sensibly handles its child stopping and restarting; but this won'\''t
- work on those machines if pty isn'\''t root.
-
- You should decide now between Case ROOT and Case PTY.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Whether you'\''ve decided on ROOT, PTY, or UN,
- now is the time to check the security of the entire pty package.
- It'\''d be difficult for anything to slip through the checks by the
- author, testers, and source group moderator, but you should take
- at least a moment to look for your pet security peeves.
-
- A couple of security notes: The only open(,O_CREAT) in pty is in
- master.c, at the top of master(), of a file with a very restricted
- form constructed from the filename of a /dev/ttyxx. There are no
- creat()s. The only bind() is in sock.c'\''s pty_readsock(), which is
- called only from master.c'\''s master() to create a socket with a
- similarly restricted name. (fnsty is changed in sigler but not in
- master.) The only exec() is in slave.c, after a forced setreuid()
- to a uid that is only set to getuid(). unlink(), mkdir(), and rename()
- are only used with restricted pathnames.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- In Case PTY, you have to set up a new uid, say ``pty'\'\'' (or whatever
- username you want). pty should not allow logins. Its password should
- be an asterisk; its home directory should be /nonexistent; its shell
- should be /bin/true. In other words, the only access to user pty
- should be through these setuid programs.
-
- In any privileged case you should have group tty,
- which most BSD 4.3 systems have as gid 4.
- '
-
- echo 'Running '\
- '$ ttygroup="`sed -n '\''s/^tty:[^:]*:\(.*\):.*/\1/p'\'' < /etc/group`" ...'
- ttygroup="`sed -n 's/^tty:[^:]*:\(.*\):.*/\1/p' < /etc/group`"
-
- case "$ttygroup" in
- 4) echo '
- I see that you have a tty group, 4 as usual. Good.
- ' ;;
- '') echo '
- You don'\''t have a tty group. Unless you have a suitable group under a
- different name, you should add the line
- tty:*:4:root
- to /etc/group.
- ' ;;
- *) echo '
- I see that you have a tty group, gid '"$ttygroup"' rather than 4. Okay.
- ' ;;
- esac
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Next, we'\''re going to drudge through the config.h file.
-
- In Cases ROOT or PTY, you have to set up a system-wide directory
- for storing information about pty sessions. (A session is a program
- stuck under a pty that you can disconnect and reconnect.) Users can
- get around this directory, storing the information in ~/.pty and
- revoking any privileges, with pty -xS; you can even make this default
- by setting flagxsetuid = 0 in globals.c. However, a single system-wide
- directory is safer.
-
- Anyway, that directory, PTYDIR, should be mode 0700, owner root in case
- ROOT or pty in case PTY, group irrelevant. PTYDIR is defined in config.h
- as /usr/etc/pty by default; if you choose a different directory, add
- -DPTYDIR=\"/what/ever/dir/ect/ory\" to CCOPTS in the Makefile.
-
- In Case UN, you may want to set up a directory ~/PTY inside your home
- directory, and set PTYDIR to that; you may want to set flagxsetuid = 0
- in globals.c; or you may want to just type -xS to pty all the time. I
- recommend the first strategy.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Next come pseudo-terminal pathnames. I assume that your ptys are
- labelled as /dev/ptyxx and /dev/ttyxx, where xx is any two-letter
- extension. pty can support any initial strings instead of these,
- but some of the utilities have /dev/tty hardcoded, and lots of other
- programs running around assume those names. If you'\''re desperate,
- define DEVMTY and DEVSTY in the Makefile, and figure out what has to
- be changed in util/*. (Sorry.)
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- The extension is traditionally [p-za-o][0-9a-f]. The first letter of the
- second string is special: if /dev/ttyq0 doesn'\''t exist, for example, then
- none of /dev/ttyq[0-9a-f] will be used. (That'\''s called a pty bank.)
-
- You can change those strings by defining, e.g., PTY1=\"ABCDEFG\" or
- PTY2=\"02468abfq\" in the Makefile. You have at least four choices here:
- 1. Give pty its own, new, banks of new pseudo-terminals with weird bank
- names not including a through z, and define PTY1 appropriately. pty will
- only use those new ptys, and older programs will just use the old ptys.
- This may require reconfiguring your system for the larger number of
- terminals. 2. Give pty some new banks, and take out some old ones to
- make up for it. 3. Give pty a chunk of the old banks. 4. Give pty all
- the old banks.
-
- Note that pty searches randomly through PTY1 and PTY2 by default; for
- efficiency, PTY1 really should reflect exactly the pty banks you have.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- So now you'\''ve decided on new ptys, or set aside some or all of your
- old ptys, and changed PTY1 and PTY2 appropriately. Because BSD gives a
- process very little control over its controlling terminal, pty has to
- pass a terminal name explicitly when it reconnects. If any of your tty
- (not just pseudo-tty!) filenames are longer than 30 characters, you have
- to set -DTTYNAMELEN=60 or whatever in the Makefile.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- /etc/utmp has traditionally listed all users logged on.
- This nebulous concept has evolved through the years; given the way
- that most programs use utmp, utmp is probably better defined as a
- list of all interactive sessions. Anyway, pty supports this file,
- and will make an entry in it when given -xu. If you have a different
- file, add -DPTYUTMP_FILE=\"/foo/bar/utmp\" to DEFINES in the Makefile.
-
- Note that /etc/utmp is unprotected (mode 666) on Suns. This was Sun'\''s
- attempt to let unprivileged programs manage the file. Unforunately, this
- error in judgment opens up a huge security hole, which even on
- single-user machines is an invitation to make mistakes. I advise you to
- make /etc/utmp owned by root in Case ROOT or pty in Case PTY, mode 644.
- There aren'\''t many unprivileged programs that don'\''t understand the
- pty interface; people on non-Suns have survived so far, and there'\''s
- no reason for you to keep subscribing to an insecure model of resource
- sharing.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Although pty will put an entry into utmp, it doesn'\''t really support
- the remote-host field. There is no logical association between sessions
- and connections; why should a login require a pty, and why should a
- session only stick around for one connection? So pty just puts "pty" in
- the host field. You can change this with -DPTYUTMP_HOST=\"foo\"; you may
- even want to make PTY_UTMPHOST call a function that you define.
-
- (Similar comments apply to PTYWTMP_HOST. There are also PTYUTMP_SWHOST
- and PTYWTMP_SWHOST, defaults PTYUTMP_HOST and "pty-sessuser"
- respectively; see util/sessuser.1 for more information.)
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- /usr/adm/wtmp has traditionally recorded all logins, logouts, reboots,
- ftp sessions, and various other interesting events. (The entry for a
- line in utmp is the last entry for that line in wtmp.) pty supports wtmp
- fully, in the same way as utmp. You should make wtmp mode 644, owner
- root or pty as appropriate. Change PTYWTMP_FILE if /usr/adm/wtmp is
- somewhere else.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- You can turn off utmp support by uncommenting the NO_UTMP line in
- config.h. (Just delete the initial /*.) You can also turn off support
- for wtmp, disconnectable sessions, or changing pseudo-terminal file
- ownership; just uncomment the appropriate line. You can force use of
- each of these features by defining MUST_UTMP, etc., in the same way.
-
- Note that the usual login programs do their own wtmp management, and
- many accounting programs incorrectly equate session time with connect
- time, so users will rarely want wtmp. As more programs appear using the
- pty interface, and as login programs start using a more logical system
- for accounting, MUST_WTMP may become an appropriate way to monitor
- pseudo-terminal usage. For the moment, I do not advise setting any NO
- or MUST.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- pty subscribes (not very willingly) to the BSD 4.3 model of pty
- protection, with a few twists. All ptys are under group tty, at all
- times; if you don'\''t have a tty group, all ptys should be under some
- other protected group at all times. Anyway, pty will change the group of
- each pseudo-terminal file to PTYGROUP, default 4, under -xc.
- '
-
- case "$ttygroup" in
- 4) echo '
- Since you already have a tty group, gid 4, you'\''re fine.
- ' ;;
- '') echo '
- You don'\''t have a tty group. You should pick a gid and define
- -DPTYGROUP=whatever in the Makefile.
- ' ;;
- *) echo '
- You have a tty group, but it'\''s not gid 4. You should define
- -DPTYGROUP='"$ttygroup"' in the Makefile.
- ' ;;
- esac
-
- echo '
- (Under Case UN, don'\''t worry about all this group stuff. Just leave
- PTYGROUP alone.)
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Under -xc, pty changes the pseudo-terminal owner to the current real
- uid. The fact that terminals need to be in the file hierarchy reflects a
- serious failure in the BSD terminal model; but anyway, many programs
- expect to be able to fool around with /dev/tty. After pty is done with
- the terminal, it sets the owner back to its effective uid. You can
- modify this behavior by changing PTYOWNER from euid to something else.
-
- Under Case UN, PTYOWNER is irrelevant.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- While a tty is unused, BSD systems traditionally leave it unprotected.
- Unfortunately, this leaves some huge security holes. Here'\''s one of
- the biggest advantages of a privileged pty manager: unused ttys don'\''t
- have to be left open for any random program to use. After it'\''s done
- with a pseudo-terminal, pty changes it to mode UNUSEDPTYMODE, default
- 0600. (This is another case of a poor model for kludging pty support
- into unprivileged programs. If you haven'\''t set up separate pty banks
- for pty, and you really want to allow unprivileged access to unused
- ptys, try mode 0660 and make those other programs setgid to tty.)
-
- A tty that someone'\''s using can be in many different modes. Typically
- USEDPTYMODE should be 0600, which means user-only access, messages off,
- biff off. If you really, really, really want to make the mistake of
- having messages or biff on by default, try 0620, 0700, or 0720. Note
- that the world protection should always be 0: the point of the tty group
- is that only setgid-tty programs can access ttys.
-
- As usual, you can'\''t do anything about these in Case UN.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Now we'\''re past generic configuration and down to your system'\''s
- nitty-gritty.
-
- For purity, pty has SIGRET_TYPE, default int, as the type returned by a
- signal handler. On Suns and ANSI-compliant machines, you should define
- SIGRET_TYPE=void. Then you can admire the lint -haxc *.c output.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- OUTBUFSIZE, default 16384, is the size of the buffer pty keeps between
- the incoming data and the pseudo-tty, and between the pseudo-tty and the
- outgoing data. If you want to spare less than 32K per pty just for
- buffer space, feel free to change this.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- GENERIC is another concession to ANSI taste. GENERIC * should be a
- pointer type that any other pointer can be safely converted to and back;
- GENERIC is char by default, but on newer machines can be set to void.
- As it'\''ll be at least five years before ANSI manages to outlaw char *,
- and as void * is often invalid, I advise you to leave GENERIC alone.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- pty attempts to forward window-size changes transparently. It also
- supports the auxiliary characters structure, which lets you type a
- single character to get system and tty status.
- '
-
- echo 'Running $ man 4 tty | sed '\''s/_//g'\'' | grep -s winsize'
- if man 4 tty | sed 's/_//g' | grep -s winsize
- then havewin=y; echo '
- I see you have window sizes.
- '
- else havewin=n; echo '
- I see you don'\''t have window sizes.
- You'\''ll have to comment out #define TTY_WINSIZE in config.h.
- (This may be inaccurate on Suns; try grep winsize /usr/include/sys/tt*.h.)
- '
- case "$ttygroup" in
- 4) ;;
- '') echo '(Let me guess: This isn'\''t a BSD 4.3 system.)' ;;
- *) ;;
- esac
- fi
-
- echo 'Running $ man 4 tty | sed '\''s/_//g'\'' | grep -s auxchars'
- if man 4 tty | sed 's/_//g' | grep -s auxchars
- then haveaux=y; echo '
- I see you have auxiliary characters.
- You should uncomment #define TTY_AUXCHARS in config.h.
- '
- else haveaux=n; echo '
- I see you don'\''t have auxiliary characters.
- '
- fi
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- pty also puts siginterrupt() and usleep() to good use in working
- around BSD limitations. Without siginterrupt(), there is absolutely
- no way to get per-process non-blocking I/O, so pty may block when it
- doesn'\''t have to (namely, when it has N bytes to write to the output,
- the output is a pipe with M bytes of space, and N > M > 0). If you
- define SIGINTERRUPT (as default), pty will take some extra effort to
- never, ever, ever block when it doesn'\''t have to.
-
- At one point, pty pauses to kludge around a common bug in UNIX-domain
- sockets. With usleep() it will pause much more briefly. This makes
- reconnects much faster.
- '
-
- echo 'Running terrupt(). Good.
- '
- case "$ttygroup$havewinsize" in
- 4y) echo 'I'\''ll bet you'\''re a BSD 4.3 system.' ;;
- *) echo 'Weird, are you BSD 4.3?' ;;
- esac
- else havesigintr=n; echo '
- I see you don'\''t have siginterrupt(). You have to comment out
- #define SIGINTERRUPT in config.h.
- '
- fi
-
- echo 'Running $ man usleep | sed '\''s/_//g'\'' | grep -s usleep'
- if man usleep | sed 's/_//g' | grep -s usleep
- then haveusleep=y; echo '
- I see you have usleep(). Good.
- '
- else haveusleep=n; echo '
- I see you don'\''t have usleep(). You have to comment out
- #define USLEEP in config.h.
- '
- fi
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Finally (almost done with configuration!), we have to make sure that you
- have UNIX-domain sockets, and check whether you have file descriptor
- passing.
- '
-
- echo 'Running $ test -r /usr/include/sys/un.h'
- if test -r /usr/include/sys/un.h
- then haveunsocks=y; echo '
- I see you have UNIX-domain sockets. Good.
- '
- echo 'Running $ man recvmsg | sed '\''s/_//g'\'' | grep -s rights'
- if man recvmsg | sed 's/_//g' | grep -s rights
- then havefdpass=y; echo '
- I see you have file descriptor passing. Good. (Your fd passing may be
- buggy, as it'\''s a relatively new, powerful, and rarely exploited
- feature. If you have trouble, try defining NO_FDPASSING.)
- '
- else havefdpass=n; echo '
- I see you don'\''t have file descriptor passing. This isn'\''t a
- disaster, though it means that reconnected sessions will be as
- inefficient as they are in programs other than this one, boo hoo hoo.
- Uncomment NO_FDPASSING in config.h.
- '
- fi
- else haveunsocks=n; echo '
- Uh-oh. I don'\''t see <sys/un.h>, which means you probably don'\''t have
- UNIX-domain sockets. Without sockets you can'\''t have disconnectable
- sessions. Sigh. I guess you have to define NO_UNIXSOCKS in config.h.
- '
- fi
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Whew! We'\''ve finally made it through configuration. If you want, try
- running lint -haxc *.c or whatever your favorite code checker is; the
- lint here gives some bogus errors about correct char * casts, an error
- because the SIG_IGN definition is unportable, and a couple of bzero
- complaints because FD_ZERO isn'\''t defined very well.
-
- If you'\''re on an old system without FD_ZERO, FD_SET, and FD_ISSET in
- <sys/types.h>, I recommend you upgrade. Try copying file.h.old to file.h
- (the original version is in file.h.new).
-
- We'\''re nearly at the end. Change CC and CCOPTS in the Makefile for any
- last-minute additions; if you'\''re worried, change -s to -g for debugging.
- Now compile! % (date; make) >>& Makelog & and come back to this script.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- While the program is compiling, let'\''s start providing some support.
- (If the compile finishes or has an error, just ignore it for the
- moment.) These are some real changes, so watch out!
-
- First, in Case PTY, make a new uid, pty, not allowing logins.
-
- /etc/passwd: pty:*:whatever:4:::/bin/true
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Second, make sure you have a tty group set up.
-
- /etc/group: tty:*:4:root
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Third, make PTYDIR.
-
- ROOT: # mkdir /usr/etc/pty; chmod 700 /usr/etc/pty
- PTY: # mkdir /usr/etc/pty; chown pty /usr/etc/pty; chmod 700 /usr/etc/pty
- UN: % mkdir ~/PTY; chmod 700 ~/PTY
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Fourth, make sure you have all the pseudo-terminal files set up and
- appropriately configured.
-
- Change each of them to group tty.
-
- Change each of them to owner pty in case PTY or root in case ROOT.
-
- Change each of them to mode UNUSEDPTYMODE (0600).
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Fifth, make sure /etc/utmp and /usr/adm/wtmp exist, owned by root in
- Case ROOT or pty in Case PTY, each mode 644. (In Case UN, you probably
- want to be working on a Sun with its insecure /etc/utmp, so that pty can
- take advantage of it. Sigh.)
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Sixth, I advise that you make a special directory /usr/local/ptybin for
- pty and its associated utilities, with symbolic links in /usr/local.
- This choice isn'\''t too important, but it'\''s easier if you know a
- place to put programs.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Okay. You'\''ve done about all that can be done before compilation
- finishes, so go do something else.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- The compile should be done now. If all went well, the make should have
- exited normally, Makelog should show no errors, and you should have an
- executable pty program sitting in this directory. Unfortunately, life
- isn'\''t always so generous. Here are a few of the more common errors.
-
- The loader complains about missing getopt(), optarg, and optind: These
- are all in the getopt library, available in the early volumes of
- comp.sources.unix. If you use GNU getopt, please make sure you
- understand the implications of its license.
-
- The loader complains about missing FD_ZERO, FD_SET, and FD_ISSET: Try
- copying file.h.old to file.h and recompiling. If the compiler gives
- various further errors related to these macros, uncomment the
- commented-out lines in file.h.old, copy to file.h, and try once again.
-
- bcopy() isn'\''t defined: In pty.h, change bcopy(src,dst,num) to
- memcpy(dst,src,num). (Note the order.) Try again.
-
- If you still can'\''t get the code to compile, let the author know.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- Next, compile the utilities. There isn'\''t much to say about them;
- they'\''re all public domain, some of them clones of or improvements
- over standard utilities, some of them clones with special features to
- work with pty, some of them entirely new programs for pty'\''s new
- features. Just glance at the top of util/Makefile; then
- % cd util; (date; make) >>& Makelog & and wait.
- '
-
- echo '----- Press return to continue. ' | tr -d '\012'; read contline
-
- echo '
- So now you should have some executables sitting around collecting dust.
- In Cases ROOT and PTY, put {pty,biff,disconnect,mesg,reconnect,sesskill,
- sesslist,sessname,sessuser} into a system-wide directory, owner root or
- pty, mode 4755. Put wall and write into the same place, group tty, mode
- 2755. Put {condom,excloff,exclon,last,lock,script,script.tidy,sess,tiocsti,
- tty,u,who,xdisconnect,xreconnect,xsesskill,xsesslist,xsessname,xsessuser}
- into the same place, mode 755. Make absolutely sure none of the shell
- scripts are setuid.
-
- In Case UN, just put all the programs somewhere in your PATH.
-
- That'\''s it! Try running TESTS now.
-
- (Two other things you have to do at some point: move your old script,
- biff, mesg, and so on to script.old, biff.old, mesg.old, etc., with
- symbolic links to the new versions in their place; and move the old
- /usr/man/{script,biff,mesg,...}.1 somewhere else, copy all the *.1
- here to /usr/man/man1, and run /etc/catman.)
- '
-