summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2000-04-15 04:41:27 +0000
committerobrien <obrien@FreeBSD.org>2000-04-15 04:41:27 +0000
commit4ad28cefef28ce6bdb44a0532cfe20a2076bc694 (patch)
tree7679c440a91912ee9586cee3ebab24596c0fe1c4 /contrib/tcsh
downloadFreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.zip
FreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.tar.gz
Import the latest version of the 44BSD C-shell -- tcsh-6.09.
Diffstat (limited to 'contrib/tcsh')
-rw-r--r--contrib/tcsh/FAQ211
-rw-r--r--contrib/tcsh/Fixes1435
-rw-r--r--contrib/tcsh/Imakefile622
-rwxr-xr-xcontrib/tcsh/MAKEDIFFS41
-rwxr-xr-xcontrib/tcsh/MAKESHAR121
-rw-r--r--contrib/tcsh/Makefile.in628
-rw-r--r--contrib/tcsh/Makefile.std625
-rw-r--r--contrib/tcsh/Makefile.vms594
-rw-r--r--contrib/tcsh/NewThings169
-rw-r--r--contrib/tcsh/Ported1016
-rw-r--r--contrib/tcsh/README207
-rw-r--r--contrib/tcsh/README.imake9
-rw-r--r--contrib/tcsh/WishList40
-rw-r--r--contrib/tcsh/Y2K10
-rw-r--r--contrib/tcsh/complete.tcsh708
-rw-r--r--contrib/tcsh/config.h.in1
-rw-r--r--contrib/tcsh/config_f.h193
-rw-r--r--contrib/tcsh/csh-mode.el935
-rw-r--r--contrib/tcsh/ed.chared.c4005
-rw-r--r--contrib/tcsh/ed.decls.h274
-rw-r--r--contrib/tcsh/ed.defns.c1949
-rw-r--r--contrib/tcsh/ed.h254
-rw-r--r--contrib/tcsh/ed.init.c736
-rw-r--r--contrib/tcsh/ed.inputl.c903
-rw-r--r--contrib/tcsh/ed.refresh.c1317
-rw-r--r--contrib/tcsh/ed.screen.c1706
-rw-r--r--contrib/tcsh/ed.term.c1150
-rw-r--r--contrib/tcsh/ed.term.h492
-rw-r--r--contrib/tcsh/ed.xmap.c844
-rw-r--r--contrib/tcsh/eight-bit.me143
-rw-r--r--contrib/tcsh/gethost.c344
-rw-r--r--contrib/tcsh/glob.3326
-rw-r--r--contrib/tcsh/glob.c723
-rw-r--r--contrib/tcsh/glob.h71
-rw-r--r--contrib/tcsh/host.defs1121
-rw-r--r--contrib/tcsh/imake.config65
-rwxr-xr-xcontrib/tcsh/install-sh251
-rw-r--r--contrib/tcsh/ma.setp.c618
-rw-r--r--contrib/tcsh/mi.termios.c393
-rw-r--r--contrib/tcsh/mi.varargs.h15
-rw-r--r--contrib/tcsh/mi.wait.h44
-rw-r--r--contrib/tcsh/nls/C/set1140
-rw-r--r--contrib/tcsh/nls/C/set108
-rw-r--r--contrib/tcsh/nls/C/set1110
-rw-r--r--contrib/tcsh/nls/C/set124
-rw-r--r--contrib/tcsh/nls/C/set1313
-rw-r--r--contrib/tcsh/nls/C/set146
-rw-r--r--contrib/tcsh/nls/C/set157
-rw-r--r--contrib/tcsh/nls/C/set1613
-rw-r--r--contrib/tcsh/nls/C/set1716
-rw-r--r--contrib/tcsh/nls/C/set184
-rw-r--r--contrib/tcsh/nls/C/set1915
-rw-r--r--contrib/tcsh/nls/C/set2111
-rw-r--r--contrib/tcsh/nls/C/set2041
-rw-r--r--contrib/tcsh/nls/C/set215
-rw-r--r--contrib/tcsh/nls/C/set2217
-rw-r--r--contrib/tcsh/nls/C/set2334
-rw-r--r--contrib/tcsh/nls/C/set244
-rw-r--r--contrib/tcsh/nls/C/set256
-rw-r--r--contrib/tcsh/nls/C/set2615
-rw-r--r--contrib/tcsh/nls/C/set278
-rw-r--r--contrib/tcsh/nls/C/set294
-rw-r--r--contrib/tcsh/nls/C/set3117
-rw-r--r--contrib/tcsh/nls/C/set3016
-rw-r--r--contrib/tcsh/nls/C/set317
-rw-r--r--contrib/tcsh/nls/C/set445
-rw-r--r--contrib/tcsh/nls/C/set54
-rw-r--r--contrib/tcsh/nls/C/set611
-rw-r--r--contrib/tcsh/nls/C/set730
-rw-r--r--contrib/tcsh/nls/C/set85
-rw-r--r--contrib/tcsh/nls/C/set912
-rw-r--r--contrib/tcsh/nls/Makefile21
-rw-r--r--contrib/tcsh/nls/french/set1140
-rw-r--r--contrib/tcsh/nls/french/set108
-rw-r--r--contrib/tcsh/nls/french/set1110
-rw-r--r--contrib/tcsh/nls/french/set124
-rw-r--r--contrib/tcsh/nls/french/set1313
-rw-r--r--contrib/tcsh/nls/french/set146
-rw-r--r--contrib/tcsh/nls/french/set157
-rw-r--r--contrib/tcsh/nls/french/set1613
-rw-r--r--contrib/tcsh/nls/french/set1716
-rw-r--r--contrib/tcsh/nls/french/set184
-rw-r--r--contrib/tcsh/nls/french/set1915
-rw-r--r--contrib/tcsh/nls/french/set294
-rw-r--r--contrib/tcsh/nls/french/set2041
-rw-r--r--contrib/tcsh/nls/french/set215
-rw-r--r--contrib/tcsh/nls/french/set2217
-rw-r--r--contrib/tcsh/nls/french/set2334
-rw-r--r--contrib/tcsh/nls/french/set244
-rw-r--r--contrib/tcsh/nls/french/set256
-rw-r--r--contrib/tcsh/nls/french/set2615
-rw-r--r--contrib/tcsh/nls/french/set278
-rw-r--r--contrib/tcsh/nls/french/set294
-rw-r--r--contrib/tcsh/nls/french/set3117
-rw-r--r--contrib/tcsh/nls/french/set3016
-rw-r--r--contrib/tcsh/nls/french/set317
-rw-r--r--contrib/tcsh/nls/french/set445
-rw-r--r--contrib/tcsh/nls/french/set54
-rw-r--r--contrib/tcsh/nls/french/set611
-rw-r--r--contrib/tcsh/nls/french/set730
-rw-r--r--contrib/tcsh/nls/french/set85
-rw-r--r--contrib/tcsh/nls/french/set912
-rw-r--r--contrib/tcsh/nls/german/set1140
-rw-r--r--contrib/tcsh/nls/german/set109
-rw-r--r--contrib/tcsh/nls/german/set1110
-rw-r--r--contrib/tcsh/nls/german/set124
-rw-r--r--contrib/tcsh/nls/german/set1313
-rw-r--r--contrib/tcsh/nls/german/set146
-rw-r--r--contrib/tcsh/nls/german/set157
-rw-r--r--contrib/tcsh/nls/german/set1613
-rw-r--r--contrib/tcsh/nls/german/set1716
-rw-r--r--contrib/tcsh/nls/german/set184
-rw-r--r--contrib/tcsh/nls/german/set1915
-rw-r--r--contrib/tcsh/nls/german/set294
-rw-r--r--contrib/tcsh/nls/german/set2041
-rw-r--r--contrib/tcsh/nls/german/set215
-rw-r--r--contrib/tcsh/nls/german/set2217
-rw-r--r--contrib/tcsh/nls/german/set2334
-rw-r--r--contrib/tcsh/nls/german/set244
-rw-r--r--contrib/tcsh/nls/german/set256
-rw-r--r--contrib/tcsh/nls/german/set2615
-rw-r--r--contrib/tcsh/nls/german/set278
-rw-r--r--contrib/tcsh/nls/german/set294
-rw-r--r--contrib/tcsh/nls/german/set3117
-rw-r--r--contrib/tcsh/nls/german/set3016
-rw-r--r--contrib/tcsh/nls/german/set317
-rw-r--r--contrib/tcsh/nls/german/set445
-rw-r--r--contrib/tcsh/nls/german/set54
-rw-r--r--contrib/tcsh/nls/german/set611
-rw-r--r--contrib/tcsh/nls/german/set730
-rw-r--r--contrib/tcsh/nls/german/set85
-rw-r--r--contrib/tcsh/nls/german/set912
-rw-r--r--contrib/tcsh/nls/greek/set1140
-rw-r--r--contrib/tcsh/nls/greek/set108
-rw-r--r--contrib/tcsh/nls/greek/set1110
-rw-r--r--contrib/tcsh/nls/greek/set124
-rw-r--r--contrib/tcsh/nls/greek/set1313
-rw-r--r--contrib/tcsh/nls/greek/set146
-rw-r--r--contrib/tcsh/nls/greek/set157
-rw-r--r--contrib/tcsh/nls/greek/set1613
-rw-r--r--contrib/tcsh/nls/greek/set1716
-rw-r--r--contrib/tcsh/nls/greek/set184
-rw-r--r--contrib/tcsh/nls/greek/set1915
-rw-r--r--contrib/tcsh/nls/greek/set294
-rw-r--r--contrib/tcsh/nls/greek/set2041
-rw-r--r--contrib/tcsh/nls/greek/set215
-rw-r--r--contrib/tcsh/nls/greek/set2218
-rw-r--r--contrib/tcsh/nls/greek/set2331
-rw-r--r--contrib/tcsh/nls/greek/set244
-rw-r--r--contrib/tcsh/nls/greek/set256
-rw-r--r--contrib/tcsh/nls/greek/set2615
-rw-r--r--contrib/tcsh/nls/greek/set278
-rw-r--r--contrib/tcsh/nls/greek/set294
-rw-r--r--contrib/tcsh/nls/greek/set3118
-rw-r--r--contrib/tcsh/nls/greek/set3016
-rw-r--r--contrib/tcsh/nls/greek/set317
-rw-r--r--contrib/tcsh/nls/greek/set445
-rw-r--r--contrib/tcsh/nls/greek/set54
-rw-r--r--contrib/tcsh/nls/greek/set611
-rw-r--r--contrib/tcsh/nls/greek/set730
-rw-r--r--contrib/tcsh/nls/greek/set85
-rw-r--r--contrib/tcsh/nls/greek/set912
-rw-r--r--contrib/tcsh/nls/italian/set1140
-rw-r--r--contrib/tcsh/nls/italian/set108
-rw-r--r--contrib/tcsh/nls/italian/set1110
-rw-r--r--contrib/tcsh/nls/italian/set124
-rw-r--r--contrib/tcsh/nls/italian/set1313
-rw-r--r--contrib/tcsh/nls/italian/set146
-rw-r--r--contrib/tcsh/nls/italian/set157
-rw-r--r--contrib/tcsh/nls/italian/set1613
-rw-r--r--contrib/tcsh/nls/italian/set1716
-rw-r--r--contrib/tcsh/nls/italian/set184
-rw-r--r--contrib/tcsh/nls/italian/set1915
-rw-r--r--contrib/tcsh/nls/italian/set294
-rw-r--r--contrib/tcsh/nls/italian/set2041
-rw-r--r--contrib/tcsh/nls/italian/set215
-rw-r--r--contrib/tcsh/nls/italian/set2217
-rw-r--r--contrib/tcsh/nls/italian/set2334
-rw-r--r--contrib/tcsh/nls/italian/set244
-rw-r--r--contrib/tcsh/nls/italian/set256
-rw-r--r--contrib/tcsh/nls/italian/set2615
-rw-r--r--contrib/tcsh/nls/italian/set278
-rw-r--r--contrib/tcsh/nls/italian/set294
-rw-r--r--contrib/tcsh/nls/italian/set3117
-rw-r--r--contrib/tcsh/nls/italian/set3016
-rw-r--r--contrib/tcsh/nls/italian/set317
-rw-r--r--contrib/tcsh/nls/italian/set445
-rw-r--r--contrib/tcsh/nls/italian/set54
-rw-r--r--contrib/tcsh/nls/italian/set611
-rw-r--r--contrib/tcsh/nls/italian/set730
-rw-r--r--contrib/tcsh/nls/italian/set85
-rw-r--r--contrib/tcsh/nls/italian/set912
-rw-r--r--contrib/tcsh/nls/ja/set1139
-rw-r--r--contrib/tcsh/nls/ja/set108
-rw-r--r--contrib/tcsh/nls/ja/set1110
-rw-r--r--contrib/tcsh/nls/ja/set124
-rw-r--r--contrib/tcsh/nls/ja/set1312
-rw-r--r--contrib/tcsh/nls/ja/set157
-rw-r--r--contrib/tcsh/nls/ja/set1613
-rw-r--r--contrib/tcsh/nls/ja/set1715
-rw-r--r--contrib/tcsh/nls/ja/set184
-rw-r--r--contrib/tcsh/nls/ja/set294
-rw-r--r--contrib/tcsh/nls/ja/set215
-rw-r--r--contrib/tcsh/nls/ja/set244
-rw-r--r--contrib/tcsh/nls/ja/set294
-rw-r--r--contrib/tcsh/nls/ja/set3016
-rw-r--r--contrib/tcsh/nls/ja/set54
-rw-r--r--contrib/tcsh/nls/ja/set611
-rw-r--r--contrib/tcsh/nls/ja/set85
-rw-r--r--contrib/tcsh/nls/spanish/set1140
-rw-r--r--contrib/tcsh/nls/spanish/set108
-rw-r--r--contrib/tcsh/nls/spanish/set1110
-rw-r--r--contrib/tcsh/nls/spanish/set124
-rw-r--r--contrib/tcsh/nls/spanish/set1313
-rw-r--r--contrib/tcsh/nls/spanish/set146
-rw-r--r--contrib/tcsh/nls/spanish/set157
-rw-r--r--contrib/tcsh/nls/spanish/set1613
-rw-r--r--contrib/tcsh/nls/spanish/set1716
-rw-r--r--contrib/tcsh/nls/spanish/set184
-rw-r--r--contrib/tcsh/nls/spanish/set1915
-rw-r--r--contrib/tcsh/nls/spanish/set292
-rw-r--r--contrib/tcsh/nls/spanish/set2042
-rw-r--r--contrib/tcsh/nls/spanish/set215
-rw-r--r--contrib/tcsh/nls/spanish/set2217
-rw-r--r--contrib/tcsh/nls/spanish/set2334
-rw-r--r--contrib/tcsh/nls/spanish/set244
-rw-r--r--contrib/tcsh/nls/spanish/set256
-rw-r--r--contrib/tcsh/nls/spanish/set2615
-rw-r--r--contrib/tcsh/nls/spanish/set278
-rw-r--r--contrib/tcsh/nls/spanish/set294
-rw-r--r--contrib/tcsh/nls/spanish/set3117
-rw-r--r--contrib/tcsh/nls/spanish/set3016
-rw-r--r--contrib/tcsh/nls/spanish/set317
-rw-r--r--contrib/tcsh/nls/spanish/set445
-rw-r--r--contrib/tcsh/nls/spanish/set54
-rw-r--r--contrib/tcsh/nls/spanish/set611
-rw-r--r--contrib/tcsh/nls/spanish/set730
-rw-r--r--contrib/tcsh/nls/spanish/set85
-rw-r--r--contrib/tcsh/nls/spanish/set912
-rw-r--r--contrib/tcsh/patchlevel.h14
-rw-r--r--contrib/tcsh/pathnames.h169
-rw-r--r--contrib/tcsh/sh.c2441
-rw-r--r--contrib/tcsh/sh.char.c1206
-rw-r--r--contrib/tcsh/sh.char.h250
-rw-r--r--contrib/tcsh/sh.decls.h380
-rw-r--r--contrib/tcsh/sh.dir.c1381
-rw-r--r--contrib/tcsh/sh.dir.h61
-rw-r--r--contrib/tcsh/sh.dol.c1150
-rw-r--r--contrib/tcsh/sh.err.c522
-rw-r--r--contrib/tcsh/sh.exec.c1262
-rw-r--r--contrib/tcsh/sh.exp.c1107
-rw-r--r--contrib/tcsh/sh.file.c848
-rw-r--r--contrib/tcsh/sh.func.c2401
-rw-r--r--contrib/tcsh/sh.glob.c1111
-rw-r--r--contrib/tcsh/sh.h1228
-rw-r--r--contrib/tcsh/sh.hist.c477
-rw-r--r--contrib/tcsh/sh.init.c1074
-rw-r--r--contrib/tcsh/sh.lex.c1891
-rw-r--r--contrib/tcsh/sh.misc.c516
-rw-r--r--contrib/tcsh/sh.parse.c706
-rw-r--r--contrib/tcsh/sh.print.c278
-rw-r--r--contrib/tcsh/sh.proc.c2184
-rw-r--r--contrib/tcsh/sh.proc.h137
-rw-r--r--contrib/tcsh/sh.sem.c975
-rw-r--r--contrib/tcsh/sh.set.c1209
-rw-r--r--contrib/tcsh/sh.time.c711
-rw-r--r--contrib/tcsh/sh.types.h608
-rw-r--r--contrib/tcsh/snames.h88
-rw-r--r--contrib/tcsh/src.desc72
-rw-r--r--contrib/tcsh/tc.alloc.c637
-rw-r--r--contrib/tcsh/tc.bind.c1079
-rw-r--r--contrib/tcsh/tc.const.c406
-rw-r--r--contrib/tcsh/tc.decls.h335
-rw-r--r--contrib/tcsh/tc.disc.c200
-rw-r--r--contrib/tcsh/tc.func.c2125
-rw-r--r--contrib/tcsh/tc.h53
-rw-r--r--contrib/tcsh/tc.os.c1474
-rw-r--r--contrib/tcsh/tc.os.h754
-rw-r--r--contrib/tcsh/tc.printf.c415
-rw-r--r--contrib/tcsh/tc.prompt.c614
-rw-r--r--contrib/tcsh/tc.sched.c288
-rw-r--r--contrib/tcsh/tc.sig.c418
-rw-r--r--contrib/tcsh/tc.sig.h226
-rw-r--r--contrib/tcsh/tc.str.c427
-rw-r--r--contrib/tcsh/tc.vers.c169
-rw-r--r--contrib/tcsh/tc.wait.h159
-rw-r--r--contrib/tcsh/tc.who.c679
-rw-r--r--contrib/tcsh/tcsh.man5078
-rw-r--r--contrib/tcsh/tcsh.man2html859
-rw-r--r--contrib/tcsh/termcap.vms51
-rw-r--r--contrib/tcsh/tw.color.c346
-rw-r--r--contrib/tcsh/tw.comp.c626
-rw-r--r--contrib/tcsh/tw.decls.h126
-rw-r--r--contrib/tcsh/tw.h110
-rw-r--r--contrib/tcsh/tw.help.c206
-rw-r--r--contrib/tcsh/tw.init.c1087
-rw-r--r--contrib/tcsh/tw.parse.c2232
-rw-r--r--contrib/tcsh/tw.spell.c168
-rw-r--r--contrib/tcsh/vms.termcap.c337
299 files changed, 78108 insertions, 0 deletions
diff --git a/contrib/tcsh/FAQ b/contrib/tcsh/FAQ
new file mode 100644
index 0000000..86fea4a
--- /dev/null
+++ b/contrib/tcsh/FAQ
@@ -0,0 +1,211 @@
+
+Last Updated:
+Fri Mar 12 12:53:43 EST 1999
+
+This is for people who do not read the manual!
+
+So far people who don't read manuals don't read this either... I may
+call it README.*PLEASE* in the future, but then the same people won't
+be able to get ftp it... :-)
+
+1. Why is the meta key broken in tcsh-5.20 and up?
+
+ On some machines the tty is not set up to pass 8 bit characters by default.
+ Tcsh 5.19 used to try to determine if pass8 should be set by looking at
+ the terminal's meta key. Unfortunately there is no good way of determining
+ if the terminal can really pass 8 characters or not. Consider if you are
+ logged in through a modem line with 7 bits and parity and your terminal
+ has a meta key. Then tcsh 5.19 would set wrongly set pass8.
+
+ If you did like the previous behavior you can add in /etc/csh.login, or
+ in .login:
+
+ if ( $?tcsh && $?prompt ) then
+ if ( "`echotc meta`" == "yes" ) then
+ stty pass8
+ endif
+ endif
+
+ If you don't have pass8, maybe something like
+
+ stty -parity -evenp -oddp cs8 -istrip (rs6000)
+ or
+ stty -parenb -istrip cs8
+
+ would work..
+
+2. I ran 'dbxtool &' and 'shelltool &' from tcsh, and they end up in cbreak
+ and no echo mode?
+
+ These programs are broken. Background jobs should not try to look at the
+ tty. What happens is that dbxtool looks in stderr to inherit the tty
+ setups, but tcsh sets up the tty in cbreak and -echo modes, so that it
+ can do line editing. This cannot be fixed because tcsh cannot give away
+ the tty. A work-around is:
+
+ dbxtool < /dev/null >& /dev/null &
+ or
+ /usr/etc/setsid dbxtool &
+
+ If that does not work, for dbxtool at least you can add "sh stty sane"
+ in your .dbxinit
+
+3. I tried to compile tcsh and it cannot find <locale.h>?
+
+ Your system does not support NLS. Undefine NLS in config_f.h and it
+ should work fine.
+
+4. Where can I get csh sources?
+
+ Csh sources are now available with the 4.4BSD networking distributions.
+ You don't need csh sources to compile tcsh-6.0x.
+
+5. I just made tcsh my login shell, and I cannot ftp any more?
+
+ Newer versions of the ftp daemon check for the validity of the
+ user's shell before they allow logins. The list of valid login
+ shells is either hardcoded or it is usually in a file called
+ /etc/shells. If it is hard-coded, then you are out of luck and
+ your best bet is to get a newer version of ftpd. Otherwise add
+ tcsh to the list of shells. [For AIX this file is called
+ /etc/security/login.cfg]. Remember that the full path is required.
+ If there is no /etc/shells, and you are creating one, remember to
+ add /bin/csh, /bin/sh, and any other valid shells for your system,
+ so that other people can ftp too :-)
+
+6. I am using SunView/OpenWindows and editing is screwed up. In
+ particular my arrow keys and backspace don't work right. What
+ am I doing wrong?
+
+ Well, cmdtool tries to do its own command line editing and the
+ effect you get is one of using an editor inside an editor. Both
+ try to interpret the arrow key sequences and cmdtool wins since
+ it gets them first. The solutions are in my order of preference:
+
+ 1 Don't use suntools
+ 2 Use shelltool instead of cmdtool.
+ 3 Unset edit in tcsh.
+
+6b. On a SPARCstation running Solaris 2.x and OpenWindows 3.1,
+ inside a cmdtool, the short-cut key sequence to clear log
+ (i.e. Meta-e or Diamond-e) doesn't work: it just echos 'e'
+
+6c. On a SPARCstation running Solaris 2.x and OpenWindows 3.1,
+ maketool (within SPARCworks) doesn't work: it just does
+ a `cd' to the working directory then stops.
+
+ The workaround for 6b and 6c is doing "unset edit."
+ Using shelltool instead of cmdtool doesn't fix 6c.
+
+7. I rlogin to another machine, and then no matter what I tell 'stty'
+ I cannot get it to pass 8 bit characters?
+
+ Maybe you need to use 'rlogin -8' to tell rlogin to pass 8
+ bit characters.
+
+8. Where do I get the public domain directory library?
+
+ Anonymous ftp to prep.ai.mit.edu:/pub/gnu/dirent.tar.Z
+
+9. I compiled tcsh using gcc, and when I start up it says:
+ tcsh: Warning no access to tty (Invalid Argument).
+ Thus no job control in this shell
+
+ Your <sys/ioctl.h> file is not ansi compliant. You have one of 3 choices:
+ a. Run fixincludes from the gcc distribution.
+ b. Add -traditional to the gcc flags.
+ c. Compile with cc.
+
+10. I compiled tcsh with the SunOS unbundled compiler and now things
+ get echo'ed twice.
+
+ It is a bug in the unbundled optimizer. Lower the optimization level.
+
+11. How can I use the arrow keys with hpterm?
+ Hp terminals use the arrow keys internally. You can tell hpterm not
+ to do that, by sending it the termcap sequence smkx. Since this
+ has to be done all the time, the easiest thing is to put it as an
+ alias for precmd, or inside the prompt:
+
+ if ($term == "hp") then
+ set prompt="%{`echotc smkx`%}$prompt"
+ endif
+
+ Note that by doing that you cannot use pgup and pgdn to scroll...
+ Also if you are using termcap, replace "smkx" with "ks"...
+
+12. On POSIX machines ^C and ^Z will do not work when tcsh is a login
+ shell?
+ Make sure that the interrupt character is set to ^C and suspend
+ is set to ^Z; 'stty -a' will show you the current stty settings;
+ 'stty intr ^C susp ^Z' will set them to ^C and ^Z respectively.
+
+13. I am trying to compile tcsh and I am getting compile errors that
+ look like:
+
+ >sh.c:???: `STR???' undeclared, outside of functions [gcc]
+ or
+ >"sh.c", line ???: STR??? undefined [cc]
+
+ You interrupted make, while it was making the automatically
+ generated headers. Type 'make clean; make'
+
+14. On the cray, sometimes the CR/LF mapping gets screwed up.
+
+ You are probably logged in to the cray via telnet. Cray's
+ telnetd implements line mode selection the telnet client
+ you are using does not implement telnet line mode.
+ This cause the Cray's telnetd to try to use KLUDGELINEMODE.
+ You can turn off telnet line mode from the cray side by
+ doing a "stty -extproc", or you can get the Cray AIC to build
+ a telnetd without KLUDGELINEMODE, or you can compile
+ a new telnet client (from the BSD net2 tape), or at least
+ on the suns use: 'mode character'.
+
+
+15. On AU/X, I made tcsh my startup shell, but the mac desktop is not
+ starting up (no X11 or Finder), and I only get console emulation.
+
+ This is another manifestation of item 5. Just add the pathname
+ to tcsh in /etc/shells and everything should work fine.
+
+16. On machines that use YP (NIS) tilde expansion might end up in /dev/null
+ If this happens complain to your vendor, to get a new version of NIS.
+ You can fix that in tcsh by defining YPBUGS in config.h
+
+17. Script on SGI 4.0.5 does not give us a tty, so we cannot have job
+ control. Their csh does not have job control either. Try:
+ % script
+ % cat > /dev/tty
+
+18. I start tcsh and it takes a couple of minutes to get the prompt.
+ You have defined REMOTEHOST and your DNS is not responding. Either
+ undefine REMOTEHOST and recompile or fix your DNS.
+
+19. If you need help generating your .cshrc file, check out:
+ http://www.imada.ou.dk/~blackie/dotfile/
+
+20. On POSIX systems the kernel will send hup signals to all the processes
+ in the foreground process group if 'stty hupcl' is set. For example
+ ./tcsh
+ echo $$
+ 591
+ ./tcsh
+ kill -6 591
+
+ Will kill everything, since hup will be sent to all tcsh processes.
+ To avoid that you can set stty -hupcl, but it is not recommended.
+
+21. When I rsh the meta key stops working on the remote machine.
+
+ Try using rsh -8; this option is undocumented on some systems,
+ but it works. If that does not work, get and use ssh/sshd. You'll
+ be better off from a security point of view anyway.
+
+22. Tcsh compiled under hp/ux-10.x does not pass resource limits correctly
+ when ran on hp/ux-11.x systems. This is a problem with lack of ABI
+ compatibility between the two systems. The only solution is to recompile.
+
+christos
+
+Everything else is a bug :-(
diff --git a/contrib/tcsh/Fixes b/contrib/tcsh/Fixes
new file mode 100644
index 0000000..bdaf2cc
--- /dev/null
+++ b/contrib/tcsh/Fixes
@@ -0,0 +1,1435 @@
+ 65. V6.09.00 - 19990816
+ 64. Add csh emacs mode (Dan Harkless)
+ 63. Make sure the the glob buffer matches the word buffer size (Brian Biswas)
+ 62. Fix periodic to work without tperiod set (Kenny McCormack)
+ 61. V6.08.07 - 19990813
+ 60. Fix e_dabbrev_expand (Bjorn Knutsson)
+ 59. Make \builtin work again (by calling the command not the builtin)
+ 58. Add NLS_BUGS for OS's that keep file descriptors open for NLS (Ian Dowse)
+ 57. Make NONLSREBIND work after tcsh starts up.
+ 56. Fix AIX stupid exit bug. (Dan Harkless)
+ 55. More irix fixes (Kaveh)
+ 54. V6.08.06 - 19990701
+ 53. module command completion (Dan Nicolaescu)
+ 52. Man command completion enhancement (Tom)
+ 51. Fixes for irix configuration (Kaveh)
+ 50. Support \a and \e in echo command. From (Keith Thompson)
+ 49. Alpha configure nit from Kaveh
+ 48. V6.08.05 - 19990511
+ 47. In some system, when a builtin fails immediately after we start
+ tcsh and before we print any messages, NLS messages fail (some
+ descriptor might be closed) [FreeBSD, HP/UX?]. So we force reading
+ the NLS catalogs in errinit() (Yoshiyuki Sakakibara)
+ 46. typos in ja/set1 and ja/set29 (Yoshiyuki Sakakibara)
+ 45. "dspmbyte autoset trap" support to HP-UX 10.20. (Yoshiyuki Sakakibara)
+ 44. misnumbered NLS message in tw.help.c (Yoshiyuki Sakakibara)
+ 43. colorcat variable for NLS color messages (Yoshiyuki Sakakibara)
+ 42. autoconf fixes from Kaveh (and if it broke, me)
+ 41. SGI irix fixes from Glenn Coombs.
+ 40. Don't spin writing the history file when quota is exceeded (Rob McMahon)
+ 39. V6.08.04 - 19990419
+ 38. complete additions (John Gotts)
+ 37. Port to amiga with geek gadgets (Arto Huusko)
+ 36. Ignore case in setenv for windows (amol)
+ 35. Bug fixes for NT unc stuff (amol)
+ 34. Hash spell check (amol)
+ 33. V6.08.03 - 19990211
+ 32. Helpcommand documentation (Vladimir Alexiev)
+ 31. small Y2K fix [%y in prompt would be formatted as 10 not 00 at year 2000],
+ and new Itoa() code (Chris Torek)
+ 30. OpenBSD m68k patches (Paul DuBois)
+ 29. Avoid redefinition of getpeername on Solaris-2.7
+ 28. fix problems with savedups=erase, savehist=merge (Randy Gobbel)
+ 27. Don't set $shell to csh, if we were invoked as tcsh (Tomas Persson)
+ 26. added $_
+ 25. added postcmd
+ 24. V6.08.02 - 19981124
+ 23. document continue and continue_args
+ 22. wrong test in slowexec made NT optimization a noop (Amol)
+ 21. Rhapsody fixes + separate CFLAGS/CPPFLAGS (Wilfredo Sanchez)
+ 20. literals in both prompt at rprompt did not work properly (Taga Nayuta)
+ 19. multibyte deletion fixes (Yoshiyuki.Sakakibara)
+ 18. clean up key binding stuff for NT by moving the nt dependent code to
+ the NT source (amol)
+ 17. dspmbyte fixes for AIX, typos in man page and nls (Yoshiyuki Sakakibara)
+ 16. Convex fixes (Ron Echeverri)
+ 15. V6.08.01 - 19981025
+ 14. SX4 port; this adds many casts for machines where ptrdiff_t is 64 bits.
+ (Andreas Schott)
+ 13. U/Win port; does not work properly with U/Win 1.6, wait for the next
+ version (Chris Jones)
+ 12. Sgi does not need gethostname prototype (John Bogan)
+ 11. Logic in sh.dir.c was wrong for NT (Amol)
+ 10. HP_CXD_SPP stat64 fixes (Scott Garee)
+ 9. Documentation spelling fixes (Keith Thompson)
+ 8. Documentation fix for savedirs (Amol)
+ 7. Siemens OSD_POSIX fixes (Martin Kraemer)
+ 6. include <errno.h> for all the BSD's (Trevor Johnson)
+ 5. Multibyte display fixes for gnu ls (Taga Nayuta)
+ 4. Configure/Makefile hesiod and bindir fixes (Dan Winship)
+ 3. Use winnt not win32 in tc.os.h (Amol)
+ 2. Cygwin32 port (Raj Menon)
+ 1. Ported Fixes (Tom)
+
+ 95. V6.08.00 - 19981002
+ 94. where builtin nt fix (Amol)
+ 93. V6.07.13 - 19980926
+ 96. NT multibyte fixes (Amol)
+ 95. NeXT needs getcwd.
+ 94. fix new bug introduced by strncpy'fication in sh.dir.c (Taga Nayuta)
+ 93. V6.07.12 - 19980918
+ 92. add cray in configure script (Tom)
+ 91. nls fixes
+ 90. Avoid buffer overflows in directory code (kim)
+ 89. Add multibyte character display support (Yoshiyuki Sakakibara)
+ 88. Make tcsh use getcwd instead of getwd and supply a getcwd.
+ 87. Fix remotehost again (kim)
+ 86. V6.07.11 - 19980913
+ 85. Leave remotehost ip addresses alone (don't try to resolve them) (Kim)
+ 84. Read vs. force_read fixes (Amol)
+ 83. Make colorls if color is set before the first LS_COLORS setenv
+ (Taga Nayuta)
+ 82. Use _PATH_DEFPATH on BSD4_4 systems. (Jim Bernard)
+ 81. Cursor bounds checks (Michael Schroeder)
+ 80. Syntax error nits (Michael Schroeder)
+ 79. configure fixes (Michael Schroeder)
+ 78. V6.07.10 - 19980904
+ 77. Off by one error in NO_ERRORS...
+ 76. Japanese NLS messages (Yoshiyuki Sakakibara)
+ 75. Add ENXIO and EBADF in the test for write failures for Irix Zombies
+ (Ralf W. Grosse-Kunstleve)
+ 74. Missed a test for NOSTRCOLL in glob.c (Michael Liepelt)
+ 73. Another ABSOLUTEP change (Amol)
+ 72. Italian NLS messages (Massimo Bertozzi)
+ 71. WIN32 fixes for ntslowexec and color_ls literal printing in prompt (Amol)
+ 70. a few missed WIN32 merges (Amol)
+ 69. defined YPBUGS for sgi (Kaveh)
+ 68. V6.07.09 - 19980707
+ 67. Separate the nt builtins (Amol)
+ 66. completion fixes (Tom)
+ 65. color ls fixes (Taga Nayuta)
+ 64. V6.07.08 - 19980629
+ 63. add config.h.in (Kaveh)
+ 62. win32 updates (Amol)
+ 61. warning and portability cleanups on the new changes (Kaveh)
+ 60. V6.07.07 - 19980628
+ 59. Fast execute by-pass for win32 (Amol Deshpande)
+ 58. Clean up const usage a bit, and fix gcc 2.8.1 warnings.
+ 57. Use @bindir@ for DESTBIN in Makefile.in (Edgar Hoch)
+ 56. Avoid overflow in time builtin computation (Nobue Adachi)
+ 55. Color ls additions (Taga Nayuta)
+ 54. unsigned char vs. char warning fixes (Kaveh)
+ 53. Solaris 64 bit fixes (fix directory offset bug) (Thomas-Martin Kruel)
+ 52. More win32 patches (Amol)
+ 51. autoconf lossage from (Kaveh)
+ 50. V6.07.06 - 04/08/98
+ 49. Collation fix for globbing (Andrey A. Chernov)
+ 48. We might have NLS_CATALOGS and not LC_MESSAGES (Andrey A. Chernov)
+ 47. 4.4BSD header fixes (Andrey A. Chernov)
+ 46. Signed char prompt fixes (Andrey A. Chernov)
+ 45. Pattern match fix for directory searches (Mike Patnode)
+ 44. Pentium DGUX fixes (Miko Nahum)
+ 43. Spanish nls message catalogs (Luis Francisco Gonzalez)
+ 42. Fix trailing whitespace parsing in HASHBANG code (Martin Kraemer)
+ 41. Remove stray debuggin message from unmatched substitutions.
+ (from Amol Deshpande)
+ 40. Fix reversed arguments in Usagae message. (from Amol Deshpande)
+ 39. Fix bug introduced at tcsh-7.06.03 [expdollar] that affected %.n prompt
+ format.
+ 38. Fix typos introduced in last batch of changes.
+ 37. Fix interrupted script using onintr, exiting parent shell problem.
+ 36. Cleanup prototypes.
+ 35. V6.07.05 - 10/28/97
+ 34. Integrate Amol Deshpande's WINNT fixes to the tcsh source. Note that
+ this is not complete yet; we are missing the NT glue code and the message
+ catalogs.
+ 33. Fix ^T at the first character in the line (Chuck Silvers)
+ 32. Eliminate xsprintf and xvsprintf
+ 31. Qmail patch from (Matthew Zahorik)
+ 30. Added missing linux signals (Vadim Vygonets)
+ 29. fixed problem where complete complete 'p/*/t:*.txt/' would not honor
+ the pattern.
+ 28. Port to an EBCDIC machine: BS2000 by Siemens Nixdorf that has an
+ IBM/390 compatible processor (Martin.Kraemer)
+ 27. Detect when we have errors writing to stdout (Vadim Vygonets)
+ 26. Ignore quotes in the comparisons for builtins, so that \builtin works
+ (Amol Deshpande).
+ 25. HPUX, portability fixes; make sure that we have the right config file
+ (Jonathan Kamens)
+ 24. Don't do lookups for x displays and figure out ttys properly
+ (Leonard N. Zubkoff)
+ 23. make print_by_columns print in a single column when the output is not a tty
+ 22. use rlim_t for Solaris2 (Casper Dik)
+ 21. V6.07.04 - 05/04/97
+ 20. set -f -l patch (Michael Veksler)
+ 19. SGI patches (Tomasz J. Cholewo). Also fix completion code to take into
+ account aliases that start with a period.
+ 18. SCO patches (Boyd Lynn Gerber)
+ 17. Fujitsu patches (Toshiaki Nomura)
+ 16. autoconf patches (Kaveh Ghazi)
+ 15. BSDI patches (Paul Vixie)
+ 14. %Q formatting character addition.
+ 13. Fix set=#123; echo $i:s/#// (Quoting problem)
+ 12. V6.07.03 - 02/23/97
+ 11. Understand %$variable in the prompt.
+ 10. Quote directory names properly in .cshdirs
+ 9. USE_ACCESS and autoconfig patches from (Larry Schwimmer)
+ 8. Pyramid att config file (Andrew Lister)
+ 7. $rprompt code (Luke Mewburn)
+ 6. Kanji patches (Huw Rogers)
+ 5. Cray T3E port (Jorn Amundsen)
+ 4. Avoid html redirects in tcsh.man2html (from Kimmo)
+ 3. HP/UX 10.0 fix for filesize resource limit; don't scale by 512 anymore.
+ 2. Workaround for TIOCSTAT for NetBSD from lukem@netbsd.org
+ 1. Return exit status from 0..255 not -128...127, as POSIX mandates.
+
+V6.07.02, 10/27/96
+ 58. More configure fixes from Kaveh.
+ 57. Fix histdup=erase again: Don't renumber events, or access uninitialized
+ storage.
+ 56. 6.07.01 - 10/19/96
+ 55. Fix histdup=erase, where after some repetitions, we would get negative
+ history events (kim@gw.com)
+ 54. NLS fixes and typo in sh.err.c (Martin.Kraemer@deejai.mch.sni.de)
+ 53. Output history in raw format in the history file (mveksler@VNET.IBM.COM)
+ 52. Fix possible core dump when !:<tab> in autoexpand mode (rbrown@ERA.COM)
+ 51. 6.07.00 - 10/11/96
+ 50. Avoid stdio.h inclusion problem in SCO (gethost.c).
+ 49. A bit of housekeeping in host.defs
+ 48. 6.06.04 - 10/05/96
+ 47. Fix tellmewhat() code to return true if found.
+ 46. Change register foo to register int foo to avoid compiler warnings.
+ 45. Fix problem with sticky non editing mode from Casper Dik.
+ 44. history lex fix from Martin Kraemer; history events that ended with 0
+ were not properly parsed.
+ 43. SNI fixes from Martin Kraemer.
+ 42. SGI fixes from Ralf W. Grosse-Kunstleve.
+ 41. BSDI2.1 fixes from Paul Vixie.
+ 40. 6.06.03 - 09/24/96
+ 39. undef TIOCGLTC for HP/UX 10.0 from Michael Shroeder
+ 38. Sinix fixes
+ 37. 6.06.02 - 06/22/96
+ 36. Added implicitcd
+ 35. Added configure.in and Makefile.in from Kaveh.
+ 34. unset path, unsetenv PATH, ./foo did not work.
+ 33. Add VAR_NOGLOB, and use it to avoid globbing directory names when
+ cd'ing into them.
+ 32. Fix bug introduced in the new tty parsing code.
+ 31. Avoid pushing string back to the parsing string in ${ errors.
+ 30. Patches for the manual page from Dave.
+ 29. 6.06.01 - 05/24/96
+ 28. Use sysconf to get NCARGS if available Robert Daniel Kennedy
+ <kennedy@b0ru01.fnal.gov>
+ 27. Grab the program name and use that instead of tcsh in error messages.
+ 26. Fix histdup, so that it does not leave gaps in the event sequence.
+ 25. HP/UX v10.0 fixes: Don't use bsdtty.h and avoid clobbering memory
+ since SIGRT??? is defined as -1.
+ 24. Avoid coredumps when $TERMCAP exceeds 1024 characters
+ Michael Schroeder <Michael.Schroeder@informatik.uni-erlangen.de>
+ 23. Fix memory clobbering when SHORT_STRINGS is not defined.
+ Todd J Derr <infidel+@pitt.edu>
+ 22. Only restart stopped editors. Robert Webb <robertw@wormald.com.au>
+ 21. Recognize pts sysv ptys when checking to set autologout Bob Myers
+ <bob@intelenet.net>
+ 20. Magic space incomplete modified core dump fix. Chris Metcalf
+ <metcalf@catfish.lcs.mit.edu>, Bradley White <bww@fore.com>
+ 19. Linux nls fixes Rik Faith <faith@cs.unc.edu>
+ 18. SGI RS8000, Ported notes. Ralf W. Grosse-Kunstleve
+ <rwgk@laplace.csb.yale.edu>
+ 17. Greek nls messages. Aggelos P. Varvitsiotis <avarvit@cc.ece.ntua.gr>
+ 16. Imakefile linux and libcrypt fixes. Jonathan Kamens <jik@cam.ov.com>
+ 15. FreeBSD fixes Jukka Ukkonen <jau@jau.csc.fi>
+ 14. Expand the environment space for path Steve Kelem <steve.kelem@xilinx.com>
+ 13. Don't overwrite the environment randomly Steve Kelem
+ <steve.kelem@xilinx.com>
+ 12. Don't turn the editor on when we have dumb or unknown terminals. This
+ breaks emacs when compiled with terminfo Jonathan Kamens <jik@cam.ov.com>
+ 11. Fix F- parsing in tc.bind.c <bob@intelnet.net> (Bob Meyers)
+ 10. Added -T option in history to force timestamp printing. -h alone does
+ not print timestamps anymore for compatibility with csh.
+ 9. Typo in tc.bind.c [with -DOBSOLETE] (misplaced parenthesis)
+ 8. Recognize convex models properly.
+ 7. suppress the DING! option using the noding variable.
+ 6. negative nice values did not work.
+ 5. Harris CX/UX 7.x support.
+ 4. ERR_DMMODE was used on the crays but not defined. I changed the error
+ messages in tc.os.c to use ERR_STRING instead, and fixed a missing error
+ message in the catalogs. Someone will need to retranslate #30 and #31
+ in set23.
+ 3. Bug setting listflags... Workaround: set listflags=(A /bin/ls)
+ 2. Typo in Imakefile (# comment instead of c comment)
+ 1. Typo in ma.setp.c (missing parenthesis)
+
+
+V6.06.00, 05/13/95
+ 88. Cleanup off-by-one error ed.defns.c.
+ 87. 6.05.09 - 05/06/95
+ 86. Small memory leak in dosetenv()
+ 85. Make sure that the number of editing functions defined is correct
+ and abort otherwise.
+ 84. Completion Fixes from Tom
+ 83. Don't add yp stuff in the tilde cache [names that start with + or -]
+ 82. Don't let children catclose() in xexit(), because the parent will lose
+ access to the nls catalogs. From Michael.
+ 81. 6.05.08 - 04/29/95
+ 80. Update to the newest csh sh.file.c
+ 79. More completions from Tom.
+ 78. Fix the Imakefile to use XCOMM
+ 77. Update for AIX 3.2.
+ 76. French catalog from J.M.Vansteene@frcl.bull.fr (fwd Michael Schmidt)
+ 75. Nls fixes and small typos from Michael
+ 74. PDP11 BSD type fixes.
+ 73. More manual page fixes.
+ 72. 6.05.07 - 04/19/95
+ 71. More NLS catalog fixes.
+ 70. Bruce's jumbo patch.
+ 69. 6.05.06 - 03/15/95
+ 68. make clean does not clobber config.h if Makefile.std is used.
+ make veryclean does.
+ 67. New config define NISPLUS. Reportedly fixes vanishing output of ~expansion
+ on solaris 2.4.
+ 66. showdots has been removed; use listflags instead. [handles -x too]
+ 65. more nls catalog fixes.
+ 64. set histchars=,. did not have any effect in .cshrc
+ 63. fix "-c command" new core dump.
+ 62. more completions from Tom
+ 61. call catclose() before exiting, so that svr4 cleans up the symlinks before
+ exiting.
+ 60. Per's fix for insert-last-word
+ 59. Per's emacs abbreviation mode.
+ 58. Makefile fixes for catalog stuff.
+ 57. fixed again complete-word-raw and list-word-raw
+ 56. 6.05.05 - 03/11/95
+ 55. Made %?str work again
+ 54. IRIX sigalarm problem should be fixed
+ 53. complete-word-raw and list-word-raw should work
+ 52. nls catalogs complete reworking.
+ 51. sh.init.c: Signal complete rewrite.
+ 50. Signal fixes from Bruce.
+ 49. Added promptchars, like histchars; affect %# in the prompt. The first
+ char is for the user and the second is for root.
+ 48. 6.05.04 - 03/03/95
+ 47. Add NODOT config, $command [that holds the command passed with -c]
+ $GROUP and $group
+ 46. AFS fixes from Larry Schwimmer <rosebud@cyclone.Stanford.EDU>
+ 45. Real NLS catalogs from Michael Schmidt <michael@muc.de>
+ 44. patch to allow ^? binding.
+ 43. completion patch from Paul DuBois.
+ 42. Don't spell check in here docs.
+ 41. Incorrect normalization of usec in sh.time.c
+ 40. directory printing and option parsing fixes [from Paul DuBois]
+ 39. realloc_searchlen should be static to avoid conflicts with OS's that
+ use the same malloc package.
+ 38. LOGINFIRST now applies to /etc/csh.login
+ 37. Fixes in bind compatibility code to bindkey.
+ 36. 6.05.03 - 01/17/95
+ 35. Don't print the whole watchlist on startup. One can use explicitly
+ the log builtin for that.
+ 34. Don't display the $watch value in the log command.
+ 33. Don't delete the unmatched portion if we try to complete a spelling error.
+ 32. Solaris 2.4 workaround for isprint('\t') lossage (From Casper)
+ 31. Fixed csh bug: [Reported by Jaap]
+ set test="one\
+ two\
+ three"
+ echo "$test:q"
+ 30. Fixed the lossage in setting the looking mode in tw.parse.c before
+ calling t_search; $x/$y will not append the right suffix.
+ 29. Another attempt at the gethost timeout code.
+ 28. Cray dmmode and filetests -m -k [need documentation!]
+ 27. More manual patches.
+ 26. Don't glob the path; security problem and core-dump. [from beto]
+ 25. Avoid waiting for jobs that failed to restart, thus hanging the shell.
+ eg, run job in background, attach to debugger; kill it inside the
+ debugger. Get out of the debugger and you are stuck if you fg that job.
+ 24. 6.05.02 - 09/04/94
+ 23. remhost code could pass the wrong length to getpeername()
+ 22. too eager sed'ing broke convex getwarpbyvalue() to getwarpbyvarval()
+ 21. Fixed new bindings bug.
+ 20. Fixed bug in newgrp code; execv was called incorrectly.
+ 19. Take into account programmable completion hints when spell checking.
+ 18. Unconditionally change stty modes in Rawmode()
+ 17. Change date in $version to be ISO 8601 per Keith's suggestion
+ 16. Fixed portability problems in the new counted-strings codes (From Kaveh)
+ 15. Fixed binding problem with the new counted-strings code [all key bindings
+ ended up in the extended map]
+ 14. 6.05.01 - 07/08/94
+ 13. Changed key bindings to use counted strings instead of Null terminated
+ strings, so that binding ^@ works.
+ 12. Fix parsing bug, where words that contained keywords caused incorrect
+ word breaks:
+ switch (iftagd)
+ case iftagd:
+ echo It works
+ breaksw
+ default:
+ echo It is broken.
+ endsw
+ 11. Fix sh.c for systems with no job control. [the new hup builtin sends
+ SIGCONT].
+ 10. Don't add the suffix character when all completions fail, from michael
+ 9. Added histdup=erase, that deletes the oldest duplicate instead of
+ the newest.
+ 8. Don't call .logout recursively if we receive more than one hup,
+ and don't process hangups when we execute the .logout.
+ 7. $logout was set to a static string.
+ 6. Non printable binding listing was broken.
+ 5. Recursive sourced scripts would get mangled up because of input buffer
+ confusion (thanks michael)
+ 4. M-space should not be counted as a space. Leads to infinite loop in
+ word splitting.
+ 3. Pyramid fixes.
+ 2. Fixed '\' in sysv echo (from Mika)
+ 1. Missed fix_yp_bugs() when setting REMOTEHOST (From Casper)
+
+
+V6.05.00, 06/19/94
+113. 6.04.17 06/18/94
+112. Realloc debug fix from John.
+111. Completion fixes from Bruce.
+110. Added -b option to bind.
+109. Added tcsh.man2html from Dave. Looks great!
+108. 6.04.16 06/06/94
+107. Allow multi word glob in "`foo`" expressions.
+ > if ("`ls`" == "a b c") then
+106. Michaels lex() buffer patch version 2.
+ the previous version core-dumped with
+ > sleep | echo
+105. Fix seg fault in find_cmd, when path is unset.
+104. 6.04.15 05/28/94
+103. the previous =~ fix, was a bit broken.
+102. 6.04.14 05/25/94
+101. expression parser fix for !~ and =~.
+ if (foo =~ *) echo ok
+ the * was taken for a multiply and parsed as 0 * 0 returning 0.
+ and asked to match "foo" with "0"
+100. Michael's lex() buffer patch.
+ 99. Bruce's Jumbo cleanup
+ 98. fixed Imakefile for X11R6
+ 97. fixed argument parsing in source command.
+ 96. added $sched to format scheduled events.
+ 95. 6.04.13 05/07/94
+ 94. added expand-command
+ 93. Alpha OSF-2.0 fixes
+ 92. 6.04.12 04/28/94
+ 91. Ignoreeof patch from Bruce.
+ 90. Dan's completion fix.
+ 89. 6.04.11 04/12/94
+ 88. Don't source .logout when killed with -HUP unless we are a login shell.
+ [ actually $loginsh controls the behavior now ]
+ 87. ISC-4.0 posix exec() bug workaround
+ (from Jonathan Broome <jon@wilbur.uucp>)
+ 86. Dan's patch for complete=enhance
+ 85. Kaveh's patches for memset, host.defs, _{U,G}ID_T
+ 84. 6.04.10 03/29/94
+ 83. Pathname completion bug fixes...
+ 82. Completion pathname(p) changes: Completion 'C' -> 'X'.
+ Replaced 'p' with 'F' and added D,T,C.
+ 81. Next NLS fixes
+ (From Paul Nevai <nevai@ops.mps.ohio-state.edu>)
+ 80. make spelling correction obey the current histchars setting.
+ 79. Fix rounding in limits so that 0 is a true 0.
+ (From Ken Lalonde <ken@cs.berkeley.edu>)
+ 78. 6.04.09 03/12/94
+ 77. Alarm race with remotehost.
+ 76. If you have in your .cshrc
+ set savehist=(100 merge)
+ and execute
+ #!./tcsh
+ exec ps
+ you get no output; [fixed]
+ 75. setenv SHLVL -1; tcsh = Segmentation fault [fixed]
+ 74. 6.04.08 02/10/94
+ 73. new machtype, ostype, vendor
+ 72. execute .logout on hangup.
+ 71. more man page fixes.
+ 70. 6.04.07 02/04/94
+ 69. Dynamic hash changes, globbing for which command from Michael.
+ 68. INBUFSIZE fixes for history.
+ 67. printenv returns 1 when a variable is not found, like the non builtin one
+ 66. Add quotes to the mismatch array so that:
+ > touch foo
+ > mail "oo bar"
+ does not get corrected. The right fix would be to do correct parsing
+ and quote the space...
+ 65. NULL terminate mismatch[] array in ed.inputl.c, since it is used in
+ Strchr().
+ 64. renamed stat to filetest
+ 63. Afs and Hesiod patches.
+ 62. More manual page patches.
+ 61. 6.04.06 12/19/93
+ 60. Alarm for resolver timeouts (untested)
+ 59. Fixes for Henry Spenser's regex in the Makefiles
+ 58. Modifiers now work with $< and $< does not do :q by default.
+ [incompatibility with csh] and $< can be interrupted.
+ 57. Added $histdup.
+ 56. source /etc/.login for Solaris 2.x
+ 55. don't remove trailing spaces in history searches.
+ 54. dirs -L and dirs -S spurious warning elimination.
+ 53. man page fixes from David.
+ 52. Kimmo's patch [makefile, gcc warning, netdb.h include]
+ 51. 6.04.05 12/12/93
+ 50. rewrote srcunit() to use st_save and st_restore. The code was
+ too messy to be useful before.
+ 49. recdirs and rechist patches again!
+ 48. Harris hck port, and ISC imake update
+ 47. Eliminate the x windows :display.screen before looking for the
+ hostname in REMOTEHOST
+ 46. Patch for CDF filetype() recognition (hpux)
+ 45. 6.04.04 11/12/93
+ 44. Made =x obey nonomatch.
+ 43. Fixed rechist and recdirs not to depend on savehist and savedirs
+ 42. Removed aliases, bind, linedit builtins [ifdef'ed out as OBSOLETE]
+ 41. change REMHOST to REMOTEHOST for compatibility with SGI.
+ 40. $owd was not working correctly.
+ 39. Debugging printf elimination (from Kimmo)
+ 38. Typos in the new hup code in sh.c (from Matt)
+ 37. Imakefile fix for sequent (from Jaap)
+ 36. 6.04.03, 10/30/93
+ 35. New manual page in place.
+ 34. Fixed Makefile sed RE to work with gnu sed.
+ 33. Added hup builtin.
+ 32. Added $REMHOST in config_f.h
+ 31. Fixed random parsing bug in sh.exp.c in isa(). It checked cp[1]
+ without checking cp[0] first... (should propagate to 4.4BSD)
+ 30. More sh.exp.c fixes from Bruce
+ 29. Always exit when the user types exit.
+ cat | tcsh -f -s
+ exit
+ ls
+ 28. savedirs fix and readlink() null termination fix from Peter.
+ 27. Added -p flag (force dirs printing in all directory functions and $owd
+ variable
+ 26. Let $dirstack work by default without needing to be set.
+ 25. Fixed history -h to work with other history flags.
+ 24. Renamed ed-functions more consistently (dcs)
+ 23. Added missing filetests (dcs)
+ 22. Added NEWGRP define in config_f.h (dcs)
+ 21. More fixes for non blocking io recovery from Bruce
+ 20. 6.04.02, 10/08/93
+ 19. changed default prompt to %#
+ 18. New group 'g' completion.
+ 17. removed IIASA defs.
+ 16. fix for history -SL and dirs -SL to work when savedirs and savehist are
+ not set.
+ 15. fix magic-space to understand :p
+ 14. make :u,:l work for history.
+ 13. Fixes for non-blocking i/o recovery. trap all non blocking styles under
+ sunos.
+ 12. 6.04.01, 08/10/93
+ 11. Vi mode word moves [they work like vi and don't obey wordchars anymore].
+ 10. New file operators and stat builtin
+ 9. David's FIONREAD patch for SVR4
+ 8. Bruce's ignoreeof=n patch
+ 7. Dan's complete/correct enhancement
+ 6. Abort corrections patch.
+ 5. Print_by_columns, now does not use the rightmost column.
+ 4. Renamed config/config.$i to $i to avoid once and for all filename length
+ problems.
+ 3. bbn butterfly config
+ 2. Beto's proc fixes
+ 1. Bruce's bug fix for ed.chared.c, signals
+
+
+V6.04.00, 07/03/93
+ 92. Alpha prototypes, for gcc -Wall clean compile.
+ 91. Fixed alpha hashing. Did not work for directories > 31, Thanks to
+ Dan Mosedale <mosedale@genome.Stanford.EDU> for all the help!
+ 90. Added USE(a) for unused parameters, to avoid compiler warnings.
+ 89. 6.03.10, 06/25/93
+ 88. Makefile and lint patches from Bruce.
+ 87. Posixsig patch from Peter for svr4
+ 86. 6.03.09, 06/11/93
+ 85. signal handling broke with the last job control patch...
+ > (does-not-compute;)
+ would hang.
+ 84. don't quit after the first modifier fails:
+ > set i=aabbcc
+ > echo $i:s/a/A/:s/b/B/
+ AaBbcc
+ > echo $i:s/x/A/:s/b/B/
+ aabbcc
+ 83. Imakefile fixes for sequents from Jaap.
+ 82. Move past the bottom of input when we hit ^C, so that multi-line
+ input commands don't get trashed.
+ 81. Look only at the first word in ${EDITOR,VISUAL} to determine the
+ editor name.
+ 80. Last patch broke listmax.
+ 79. Remove extra sandbagging in exitstat(). Not needed anymore as value()
+ will never return NULL.
+ 78. Save $status before calling aliasrun() otherwise:
+ > alias precmd 'cd .'
+ > true
+ > echo $status
+ 0
+ > false
+ > echo $status
+ 0
+ 77. 6.03.08, 06/07/93
+ 76. missing prototypes/unused variables under SYSV4.
+ 75. savedirs should glob the filename argument.
+ 74. 6.03.07, 06/05/93
+ 73. Changed _Q, _Q1 macros in sh.lex.c, sh.dol.c, sh.char.? to _QF and _QB
+ because today 4.4BSD <ctype.h> defined _Q to be ``Phonetics''
+ 72. listmaxrows variable.
+ 71. set -r would not make existing variables readonly.
+ 70. print usernames with ~user where possible in dirs and job cwd's
+ 69. Mika's fixes (missing args in sh.c set(), linux Makefile, SIGCHLD)
+ 68. FIONREAD argument is int everywhere except on SunOS where it is long.
+ Tcsh used to think that it was long, and so it broke on the alpha where
+ sizeof(int) != sizeof(long)
+ 67. 6.03.06 05/16/93
+ 66. Pipeline fixes. This should get rid of the dreaded Stopped tty output
+ message.
+ 65. Michael's fix for history buffer cleanup:
+ > alias foo 'echo \!:1:h'
+ > foo a/b
+ a
+ > ^P [nothing happens]
+ 64. Unsigned long rlimit type for 64 bit machines (alpha)
+ 63. Fixed Imakefile for alpha
+ 62. tilde expansion now obeys $nonomatch
+ 61. readonly veriables. 'set -r x=3' will set x to a very sticky 3...
+ 60. Fixed bug in the new tab'ed completion that interfered with old listing.
+ 59. Fixed entry -> item in tw.parse.c
+ 58. Added -f option to unlimit
+ 57. Define __STDC__ in Imakefile for Irix
+ 56. Static redeclarations in tw.parse.c
+ 55. 6.03.05 04/26/93
+ 54. Don't echo history expansion in loops:
+ > alias junk 'foreach i (\!:2*) \
+ foreach? echo \!:1 $i; \
+ foreach? end'
+ > junk a b c d
+ echo a $i ;
+ a b
+ echo a $i ;
+ a c
+ echo a $i ;
+ a d
+ 53. Added complete-word-fwd and complete-word-back that scroll through
+ the list of possible completions... Neat addition from
+ jfink@csugrad.cs.vt.edu (Jeff "$DOTDIR" Fink)
+ 52. Workaround hpux9.01 broken optimizer in sh.glob.c where 'ls *' breaks.
+ 51. Michael's editor fix. With "magic margins" and 80 char width, try:
+ > set prompt=
+ <ESC>20a<CTRL>a<ESC>76b<CTRL>ac
+ 50. Reverted fix that does not glob the expanded back-quote text again.
+ 49. > cd /., echo $cwd
+ /.
+ Eliminate the . in this case...
+ 48. Matt's optimization in glob.c [retracted]
+ 47. Fixed bug with -S
+ 46. Renamed Makefile Makefile.std, and fixed the readme file
+ 45. 6.03.04 04/07/93
+ 44. Changed -s == !-z and -S == socket
+ 43. Fixed typo in sh.c, in phup [shpgrp != pr->pgrp]
+ 42. Multi-line aliases are not entered into the history when executed.
+ 41. Changed f_seek to a union to avoid gcc warnings on 4.4BSD
+ 40. Fixed 'unset home; dirs' bug
+ 39. fixed $HOME->$home memory problem.
+ 38. $?0 returns false now on interactive shells for csh compatibility.
+ 37. Default watch inteval was 10 hours not 10 minutes as advertized in the
+ manual!
+ 36. Fixed clobbered veriable warning from gcc-1.39 in tw.parse.c
+ 35. Fixed typo with INVPTR in sh.lex.c
+ 34. 6.03.03 03/04/93
+ 33. Eliminate 'Reset tty pgrp error message'. It is normal for the
+ walking process group stuff. Check about the killpg() above?
+ 32. More portability for 64 bit machines.
+ 31. Improved completion error messages.
+ 30. Fix bug with double globbing expansion on mirrored variables:
+ > setenv TERM '?vt100'
+ 29. Avoid hanging when writing to pipes etc. (From Paul Close)
+ 28. Typo in the $HOME->$home mirroring.
+ 27. %p %P 'p'recise time formats that include seconds for prompt strings.
+ 26. Signal list fixes from Paul Close. nsig is now a variable.
+ 25. 6.03.02 02/12/93
+ 24. NEC SX3 "entry" is a reserved word!, changed entry to item...
+ [this is as bad as cray typedefining "word" to int. Next thing I know,
+ I'll have to prefix all the variables with tcsh_!]
+ 23. xxx
+ 22. Protected all include files to avoid warnings from lcc.
+ 21. Finally resolved the job control problems with linux and ISC (from Beto)
+ 20. More HUP,XFSZ,XCPU fixes. (with Beto)
+ 19. Dcanon would not canonicalize correctly in case where dnormalize()
+ failed to find a directory, but the directory existed when not
+ crossing the symbolic link.
+ 18. sh.init.c fixes; give 65 signals for all POSIX machines.
+ 17. AMS mail fixes and cmu wm handling.
+ 16. Setenv would not ignore trim quoted names...
+ > alias foo 'setenv "\!:1" bar'
+ > setenv FOO 123
+ > foo FOO
+ > printenv
+ ...
+ FOO=123
+ FOO=bar
+ ...
+ 15. 6.03.01 08/01/93
+ 14. #undef SHORT_STRINGS gcc warning fixes...
+ 13. csh bug fix in foreach [quoteing problem]
+ > foreach i ("*")
+ > echo $i:q
+ > end
+ Should print *
+ 12. ls-F obeys showdots...
+ 11. After scheduled commands get executed, the editor could stay disabled
+ until the first enter.
+ 10. sigset() bug in ed.init.c; ^C could get disabled sometimes.
+ 9. Don't glob in dowhich(); otherwise \pat does not work if pat is aliased.
+ 8. When completion patterns are used $ and ~ expansion did not work right.
+ 7. Printenv builtin and long backquote expansion fix from Harald.
+ 6. $:-1, $:-0 enhancement from Paul and Michael.
+ 5. Lynx/OS patches
+ 4. Apollo bugs [Setenv -> tsetenv, typedef in pid_t]
+ 3. ^@ did not work correctly in bindkey.
+ 2. Fix vms/posix ifdefs in tc.alloc.c
+ 1. Elide gcc-2.3.1 warnings
+
+
+V6.03.00, 11/20/92
+102. Solaris2 patches, renamed sunosX to sosX to fit in 14 character filenames.
+101. 6.02.12 11/12/92
+100. Decreased BUFSIZE to 1K...
+99. Don't use sbrk() in tc.alloc.c on VMS
+98. EINTR error handling from Michael
+97. Overwrite mode takes effect immediately, not delayed by a command.
+96. Emx fixes.
+95. SIGHUP gain...
+94. Coherent times()/ <sys/file.h> fixes.
+93. 6.02.11 10/27/92
+92. Mach setpath fixes.
+91. Which now globs its arguments
+90. Again POSIX SIGHUP fixes... Maybe we got it right this time...
+89. Increased BUFSIZE to 4K. Smaller machines may want to decrease this.
+ [ Now one can edit up to 4K of buffer! ]. From Harald.
+88. : is now a true builtin that does nothing, instead of being treated like
+ the last character of a label. This is so it can take args. From Harald.
+87. More fixes for hpux limits from Harald.
+86. Login shell if ppid == 1 and argc == 1 for VMS.
+85. Typo in sh.exec.c from Harry.
+84. Per's editor fixes.
+83. 6.02.10 10/17/92
+82. Don't free STRNULL in freelex(). Update linked list in copylex() to
+ do the same insert as in lex().
+81. Fixed spurious tilde printing in %c prompt.
+80. Fixed dumb wild free in AddXKey...
+ (thanks Harald for the complex bindings! :-)
+ > bindkey "\e10z" expand-line # Any editor command will do
+ > bindkey -[cs] "\e10z" "foo" # Any string or command will do
+ Free(%x) ....
+79. coherent additions.
+78. fixes for hpux8 resource limits [Thanks Harald]
+77. 6.02.09 10/10/92
+76. More vms cleanups.
+75. Removed #include CONFIGH from sh.h. There was no way to make it work
+ under VMS/POSIX
+74. Added t completion (Gray Watson)
+73. Memory leaks in sh.dir.c and sh.glob.c [thanks purify :-)]
+72. IRIX 5.0 patches (from Paul Close)
+71. BSD resource limits for hpux8.0 (From Andreas Stolcke)
+70. NGROUPS_MAX fixes (from Matt Day)
+69. 6.02.08 10/04/92
+68. VMS port additions.
+67. Added $%var, which == strlen(var)
+66. Added ^X^I and ^X^D to override programmable listing+completion
+65. Added case insensitive globbing for OS/2
+64. FIOCLEX and FIONCLEX are only used if we don't have FD_CLOEXEC.
+63. Added emx termio support, and emx pathsep support; emx compiles and runs:
+ needs job-debugging and finishing touches.
+62. Horrible bug with the lex linked list; from Loic Grenie, grenie@ens.fr
+ > echo a !#
+ echoed 'echo a echo a echo'!
+61. Shell -w,-x were incompatible with the same for test [POSIX] (beto)
+60. builtin newgrp did not accept the - argument.
+59. FIOCLEX for the masses (POSIX FD_CLOEXEC addition)
+58. Old style csh completion bug fix [not used] (beto)
+57. A background process waiting for input from tty
+ blocks when being foregrounded doesn't read its input and
+ doesn't get <cntl-c> and <cntl-z> signals.
+ It can only be killed from another session. (beto)
+ > cat > foo
+ #!/bin/csh -f
+ echo ">>>>>>"
+ set x = $<
+ echo $x
+ ^D
+ > chmod +x foo
+ > foo &
+ > fg
+ ^Z,^C # Nothing happens
+56. history > 1000 fix (beto)
+55. 6.02.07 9/18/92
+54. Added e_stuff_char() to put back a character in cooked mode in
+ the input stream... Useful for status (^T)
+53. $? == $status and $# == $#argv like in the bourne shell.
+52. Added $dirstack. Problems: off by one since =0 == $cwd, but
+ $dirstack[1] == $cwd... Suggestions welcome.
+51. Leading spaces would confuse the run-help function.
+50. Don't expand imported environment variables:
+ > setenv HOME \*
+ > tcsh
+ > echo "$home"
+ > echo "$HOME"
+49. %C0n displays the number of directories omitted as /usr/local/bin /<2>bin/
+48. Added POSIXSIGS as a configuration option.
+47. Per's fixes for history format and arrow key binding.
+46. Expand-variables expands array variables too
+45. 6.02.06 8/14/92
+44. Separated limit stuff from BSDTIMES and added BSDLIMIT
+43. History searching inconsistent with HistLit:
+ > echo foo
+ foo
+ > ^foo^bar
+ bar
+ > ec[M-p]
+ echo foo
+42. 6.02.05 8/8/92
+41. sourcing a script that contains 'onintr -; onintr' would disable
+ interrupts on the command line
+40. cd ../... with symlinks=ignore would work !@#!@
+39. No more BACKPIPE for POSIX machines...
+38. SUNOS NLS bug workarounds...
+37. New HASHBANG define for #! emulation... even 386BSD does not have it
+ yet...
+36. Added new -b -c file operators from SGI csh.
+35. 6.02.04 7/23/92
+34. Walking process group fixes.
+33. $0 contains now argv[0] when we are not executing a shell script.
+32. New Getwd() was broken.
+31. 6.02.03 7/17/92
+30. We kill our last foreground process group on HUP, for POSIX systems.
+29. Walking process group fix.
+28. $shlvl gets reset to 1 for login shells.
+27. Macros can now involve multiple commands, i.e.
+ bindkey -s "^[OP" "ls\n^P"
+26. 6.02.02 7/6/92
+25. nostat accepts now a list shell patterns.
+24. Avoid print_exit_value in if ( { foo } )
+23. Symbolic key names for bindkey [arrow keys].
+22. Smarter getwd() that avoids some of the NFS hangs...
+21. Use memmove() where possible.
+20. 6.02.01 6/16/92
+19. Fix automatic correction to work with the new completion.
+18. Globbing bug with brace expansion, when arguments need to be realloced...
+ e.g. echo 134{6,7}{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}
+17. shift and left operators update variables correcly ('shift path' did not
+ work)
+16. apollo fixes for cd.
+15. STRNULL <-> NULL bug fixes.
+14. %S in xprintf for short strings.
+13. history -LSc, dirs -LSc additions, builtins builtin [oxymoron]
+12. history formatting string, who formatting string, prompt formatting
+ all use tprintf() now.
+11. $history accepts a second formatting argument..
+10. History timestamps preserved in .history
+9. Backquotes were broken: echo hi | cat > `echo foo`
+8. SGI -t operator problem.
+7. Dnix fixes.
+6. Fix history file writing bug when autologout.
+5. Change from TCSETA to TCSETAW, since we affect the output.
+4. Per's fixes for display margin bugs.
+3. Linux fixes.
+2. Collapse adjacent stars in glob.c to avoid exponential behavior.
+1. Fixed parseescape to put ^ literally if not followed by alpha.
+
+
+V6.02.00, 5/15/92
+94. Default echo_style was not being set correctly.
+93. $< did not work correctly with NLS chars.
+92. 6.01.15 (5/11/92)
+91. Minor cleanups in refresh code.
+90. 6.01.14 (5/8/92)
+89. Print \n in the right margin always to be consistent.
+88. Linux patches.
+87. 6.01.13 (5/2/92)
+86. Fixes in listing and completion of non-unique commands.
+85. Fix =stack entries > 9... from Bill Petro
+84. Fix for last character at margin. [on terminals that have am & xm move
+ the cursor manually to the next line]
+83. Fix for complete completions
+82. small typo in tc.alloc.c from Mark Moraes.
+81. small typo in tw.parse.c from Richard.
+80. Man page fixes from Per.
+79. 6.01.12 (4/24/92) [release version for 6.02]
+78. Autosuffix was not getting reset all the time.
+77. Don't limit completion patterns to 1K.
+76. Naming changes in ed.screen.c from Justin.
+75. 6.01.11 (4/10/92)
+74. Fixed magic-space ! expand bug:
+ > echo a b123 45.{6,7}
+ > echo !:2!:3[magic-space]
+73. Work-around for apollo optimizer in tc.bind.c
+72. Problem with setjmp in tw.parse.c
+71. symlinks=expand from Yumin.
+70. tenematch() fixes from Michael;
+69. 6.01.10 (4/3/92)
+68. Fixed Gnmatch.
+67. Removed ignore_symlinks and chase_symlinks. Replaced by symlinks variable.
+66. Backquote from completion was broken for machines with no dup2()
+65. No $printexitvalue for `` jobs.
+64. Added ultrix stuff for PW_AUTH [from Mike Potter mpotter@lampf.lanl.gov]
+63. Fixed bug in Gnmatch(), added 'N' command 'x' completion.
+62. Fixed fg_proc_entry() so autologout gets disabled when a process
+ is foregrounded.
+61. 6.01.09 (3/26/92)
+60. source builtin takes arguments now that are passed in the script e.g.:
+ > ./tcsh -i a b c
+ > cat test
+ echo $argv
+ > echo $argv
+ a b c
+ > source test 1 2 3
+ 1 2 3
+ > echo $argv
+ a b c
+59. Eliminate $margin_bug, add more intelligent margin code [from Justin]
+58. expand_symlinks variable Urgh...
+57. SGI CONTROL() fixes...
+56. new dnormalize(), expand_symlinks flag.
+55. interrupting completion restores the current line. [from Marc]
+54. 6.01.08 (3/20/92)
+53. inputmode affects the first line too.
+52. Searches in vi do not destroy the current line.
+51. -drwX test enhancement.
+50. Generalized completion syntax and added more completion builtins.
+49. Don't print '\n' on the right margin if we can avoid it.
+48. 6.01.07 (3/9/92)
+47. New completion style. [[<pattern>[ ]],=<completion action>]
+46. 6.01.06 (3/7/92)
+45. complete styles are ignored after shell metachars eg.
+ > complete mail =u
+ > mail christos < [tab]
+ completes filenames.
+44. $echo_style is initialized to the default style of the machine.
+43. SGI 4.0 CTRL() macro is busted. So we ignore it.
+42. Fixed bug with the new margin code (thanks justin)
+41. Fixed mirroring of variables. Now set and setenv affect
+ HOME, TERM, PATH, SHLVL, USER and their csh counterparts. Unset affects
+ affects only the csh copies of the variables, and unsetenv only the
+ environment variables.
+40. Fixed gcc-2.0 warnings in sh.sem.c (needed for vfork() -O2 optimization)
+39. 6.01.05 (2/21/92)
+38. signal masking for BSD machines was still wrong in tw.init.c
+37. Added $margin_bug, and now the editor outputs on the rightmost
+ column by default. This should fix the xterm cut-n-paste problem.
+36. AU/X 2.0 and SGI compiles with POSIX as a default now.
+35. sysv_echo is gone too. Now we have a variable called echo_style
+ which can be set to "none", "bsd", "sysv", "both" that defines
+ the builtin echo_style. The default is "bsd" for systems with
+ SYSVREL == 0, "sysv" otherwise. This can be overriden in config.h
+ by defining ECHO_STYLE ro be BSD_ECHO, SYSV_ECHO, BOTH_ECHO,
+ or NONE_ECHO.
+34. asynchronous notification in run-fg-editor would try to change the
+ tty settings and print an extra prompt.
+ > set notify
+ > sleep 10 &
+ > vi^Z
+ > ^[^Z
+33. alias x /bin/true
+ x<esc>?
+ reported .//bin/true instead of /bin/true
+32. 6.01.04 (2/12/92)
+31. fixed vi_substitute_line
+30. binding completion addition.
+29. showdots=-A addition
+28. sysv_echo addition; deleted bsd_echo which is now the default.
+27. dunique could crash.
+26. Don't clear lines after an asynchronous notification, because it
+ might erase the message.
+25. 6.01.03 (1/29/92)
+24. `` were not working correctly when tcsh is started with 0,1,2 closed.
+23. Correction was picking up the wrong thing in cases like .rhosts hosts
+22. Correction with names with quoted spaces was broken.
+21. Added sysv_echo and bsd_echo.
+20. Added and documented the complete builtin.
+19. Added dunique and cd -.
+18. Per's fix for alarm functions. Things would break if time went backwards.
+17. Realloc bug fix (copy min of old and new size)
+16. Fix for csh compatible braces.
+15. Brace globbing and negation globbing for Gmatch.
+14. 6.01.02 (1/16/92)
+13. Completion builtin, new tw* files.
+12. 6.01.01 (1/6/92)
+11. Changed w_ fields in tc.who.c to who_ to avoid redefinitions in
+ <sys/wait.h> in some os's.
+10. Setting savehist to an empty string makes savehist use the value
+ in $history.
+9. echotc did not use the internal termcap descriptions.
+8. echotc did not work right for single argument termcap strings.
+7. DGUX needs SAVESIGVEC, updated type protection, and disabled CSWTCH.
+6. Changed SVID to SYSVREL, since there is no SVID == 4 (yet).
+5. Typo in tc.sig.h: UNRELSIGS was not getting defined.
+4. Globbing bug fix. tglob() should ignore globbing characters inside
+ backquotes otherwise things get expanded twice:
+ % echo 'bar?' > 'foo?'
+ % echo `cat foo\?`
+ echo: No match.
+3. Mach setpath fix.
+2. Alliant process group fix.
+1. Xenix fixes for broken vi and help path with no suffixes.
+
+
+V6.01.00, 12/19/91 [for comp.sources.unix]
+22. Restore the original prompt in automatic correction when the user
+ asks to re-edit the command.
+21. Better error for unreadable files in tw.parse.c
+20. Sequent patches.
+19. (V6.00.08 beta 12/14/91)
+18. Filenames containing # were spelled/expanded incorrectly.
+17. Stellar/stellix port.
+16. Hpux 8.0 has SIGWINDOW but we cannot get the window size. Protect
+ against window changes updating $LINES and $COLUMNS.
+15. Mach setpath did not work right.
+14. Mach does not need setenv in lib; in fact that does not work right.
+13. shell level gets decremented when we exec.
+12. restart_fg_editor picked the wrong editor if arg contained a slash.
+ e.g vi ~/.cshrc
+11. (V6.00.07 beta 12/08/91)
+10. Allow use of vfork() on systems that do not have job control.
+9. Avoid NUMCC from being defined twice.
+8. (V6.00.06 beta 12/05/91)
+7. SunOS3's FIOCLEX dups...
+6. Yet another globbing bug fix from Michael (echo .[^.])
+5. Ultrix now wants __ before cpp symbols.
+4. Workaround sun's header files inconsistency so tcsh can be compiled
+ with #undef POSIX
+3. Fixed limit stuff so that large values don't cause errors.
+2. Fixed =1 and ~user error messages (Per)
+1. (beta-5 6.00.04 == 6.00.05)
+
+$#*
+$#* New numbering scheme (The last 2 digits are reserved for beta releases
+$#* from now on. So we start at 6.00.06 which is 6.00.04 beta 6, and we are
+$#* going to release 6.01.00...
+$#*
+
+V6.00.04, (never released)
+34. (beta-5 11/25/91)
+33. Simplify code in BindArrowKeys()
+32. Get rid of the PNULL's
+31. Support for shadow password in locking code. (From Kimmo)
+30. Normalize-path editor function.
+29. (beta-4 11/21/91)
+28. minix additions
+27. bindkey fixes (-c addition, casting cleanups)
+26. (beta-3 11/16/91)
+25. Prompt length checking.
+24. Michael's fixes for the watching code. Tcsh could core dump when using
+ a corrupted utmp.
+23. overwrite mode flag, and autologout locking code.
+22. overwrite mode would still insert digits!
+21. Get the value of _POSIX_VDISABLE from pathconf...
+20. Hpux 8.0 fixes. Sigstack botches with shared libraries. Ansi mode
+ static initialization of structures with prototyped function pointers
+ gives spurious warnings...
+19. Onintr in /etc rc files is disabled.
+18. (beta-2 11/03/91)
+17. Multi-line aliases with `` bug fix.
+16. Sticky emacs overwrite mode.
+15. Autolist option.
+14. Fix for redirection with wildcard filanames.
+13. No error correction for multi-line commands.
+12. Esix-4 re-defines p_pid. Argh...
+11. (beta-1 10/28/91)
+10. Foreach loops were broken again.
+9. SUNOS localtime() bug does not only happen on the 8th byte. [Michael]
+8. sh.dir.c, memory corruption in dinit(). Thanks Michael.
+7. uts broken <sys/stat.h> work-around, and has a wait3()
+6. SGI (-t filename) extension, returns true when filename is a tty.
+5. 'default:' addition in all switch() statements.
+4. oflag was not being updated correctly in Rawmode()
+3. missing 'break;' in prompt code '%y'.
+2. infinite loop in :a<mod> code.
+1. hashstat was not reporting hits+misses
+
+
+V6.00.03, 10/21/91
+31. watch code now accepts shell patterns.
+30. new hashing code portability fixes.
+29. $foo:gs/:/ / fix and 'a' modifier addition.
+28. Added $! (the pid of the last background job forked)
+27. exec does not kill the shell when it fails.
+26. Irix4.0 decls.
+25. SVR4 uthost fixes from Kimmo Suominen
+24. Imake addition from marc
+23. New i-search from Per.
+22. ibmesa fixes
+21. convex fixes.
+20. t command for vi.
+19. SVR4 fixes (reverse pipeline and sigaction()) from David Dawes.
+18. New hashing from Marc
+17. Added : to the ~name separators so ~foo:~bar works.
+16. New ed.init.c. Added ed.term.c
+15. Still can't get the history exactly csh-like... !-2$ was broken...
+14. vi character searches.
+13. -Dvar=name command line option for the apollos.
+12. Prompt format changes for date/directory.
+11. Vi searches.
+10. Emacs i-search. [currently not bound]
+9. Vi additions ([dc]-{w,$,f<c>},Undo)
+8. tcsh -n parses now builtin structures.
+7. seek to the end on errors in loops.
+6. echotc -s was broken
+5. Better !event parsing. !foo;!bar was broken.
+4. foreach loops and if statements in aliases.
+3. .cshdirs would corrupt the heap if some directories were not there.
+2. System V echo was broken with \
+1. Fixed echo '!-1', history would eat the quote.
+
+V6.00.02, 08/05/91 [For comp.sources.unix]
+8. tcsh will always set $LOGNAME and $USER if not already set in the
+ environment.
+7. added $histfile.
+6. echo `echo` * and echo ~ {} were broken
+5. setty builtin addition
+4. Multiple : modifiers [experimental, disabled with -DCOMPAT]
+3. 7 bit fixes, and hp9000s500.
+2. #undef DEBUG in tc.alloc.c, so we continue if we get a bad free()
+1. getn() is now protected against NULL strings.
+
+V6.00.01, 07/16/91
+17. added beepcmd, and fixed small tenematch bugs.
+16. Renamed DUP2 flag to HAVEDUP2 cause AIXPS2 defines DUP2 already.
+15. More ANSI fixes, and mit additions (load-average)
+14. don't clear ECHOE, background programs might need it.
+13. Refresh bug fix...
+12. getpwent() should not be interrupted (yellow pages), cause it might
+ leave dangling pointers, that endpwent() will trash.
+11. ChangeSize is now responsible to set the screen size to something
+ sane, but it should not affect the environment if the information
+ it received is not valid
+10. Find out if we are running under emacs using $TERM. It is more
+ reliable.
+9. tcsh was broken if SHORT_STRINGS was not defined (glob() problem)
+8. If GetSize() fails it should always return reasonable screen sizes.
+7. globbing should not fail if one or more patterns match.
+6. increased the number of aliases in the loop detection code.
+5. DGUX has size_t and pid_t defined now...
+4. ESIX does not have EWOULDBLOCK or EAGAIN & POSIX... That was not handled
+ correctly.
+3. rs6000 needs BSDWAIT.
+2. Hpux susp key could not be changed.
+1. Apollo fixes.
+
+V6.00.00, 07/04/91
+45. Fixed quoting of VSTART/VSTOP on termios
+44. Memory leak every time you pipe in or out.
+43. echo {foo bar.[ch]}. Did not check for end of word.
+42. ANSI prototypes
+41. dmove() would leave the source descriptor open when using dup2()
+ e.g.
+ while (1)
+ echo foo >>! bar
+ end
+ runs out of file descriptors
+40. recursive `` expanded via aliases would abort.
+39. set home=../relative-path-name was broken.
+ e.g.
+ set home=../..; cd ..;
+ <abort>
+38. Incorrect error when changing to directory:
+ e.g.
+ mkdir not-in-cd-path; chmod -x not-in-cd-path; cd not-in-cd-path;
+ echoed:
+ not-in-cd-path: No such file or directory.
+ it should have said
+ not-in-cd-path: Permission denied.
+37. if ( \! =~ [\!] ) echo ok, did not echo ok. Quoting inside [] pattern.
+36. More than 127 jobs caused job # to go negative
+35. unsetenv <pattern> ... Added support for more than one pattern.
+34. More background process status report fixes.
+33. Apollo builtin support.
+32. Glob fix. echo '*' * was not handled properly.
+31. Glob fix. setenv FOO `sleep 1` would either cause a segmentation fault.
+ or print ambiguous.
+30. Glob fix. Quoted characters inside [] were not handled properly.
+29. Removed TELL and VMUNIX defines. I think we cannot compile on V6 anyway
+28. Overflow check for expansions.
+27. Added matchbeep, shell pattern history searching.
+26. Added code to handle /dev/std{in,out,err}
+25. Fixed POSIX speed handling in raw mode.
+24. Fixed a flushing bug in the filec code in sh.file.c
+23. Compiled and added hp9000s700 to the list of hosts.
+22. Fixed horrible bug in gmatch()
+ switch (4)
+ case [a-z]:
+ echo bug;
+ breaksw;
+ case 4:
+ echo ok;
+ breaksw;
+ endsw
+21. Fixes for _SEQUENT_ ut_host.
+20. FLUSHO added
+19. mkdir foo\`bar; cd foo\`bar; was broken
+18. EWOULDBLOCK == EAGAIN on RENO check for that too.
+17. Dword() simplified and removed the gotos.
+16. Hpux now compiles with POSIX. Moved the local chars modes in ed.init.c
+ after the tty modes.
+15. Process group fixes for POSIX
+14. We need <sys/filio.h> on the suns for FIOCLEX!!! We did not close
+ our file descriptors before...
+13. A/UX fixes.
+12. History events that start with a number are not necessarily numeric:
+ > !3d
+ 3d: Event not fount
+11. History loop detection added.
+ > alias a \!#
+ > b; a
+10. Alias loop detection code was ineffective on eager optimizers.
+ 9. All errors should now go through our table. Next step we should
+ add nls error messages.
+ 8. Unsetenv now globs its arguments! Before it did not...
+ 7. Added tilde cache and -l flag.
+ 6. Added autocorrect
+ 5. Fixed for so that background jobs in scripts get process groups
+ 4. Fixed amazing memory leak in setenv()...
+ 3. Added short2qstr() so that we can form quoted strings to be used with glob()
+ 2. str2short and short2str allocate space dynamically.
+ 1. Fixed bug related to the is*() routines called with shorts.
+ [only if NLS and SHORT_STRINGS are defined].
+ (The _ctype_ was getting indexed with shorts...)
+ 0. Complete overhaul. Brought in the 4.4 csh stuff. Separated most
+ tcsh and csh code except where I would have to add more global
+ variables. Compiled correctly with both lint and gcc -Wall on
+ a sparc running 4.1
+
+V5.20.03, 03/20/91. - Never released
+25. Kanji, SXA additions.
+24. (exec foo) should not fail if they are suspended jobs.
+23. Support kernel paging stuff on aix 370.
+22. Now we handle correctly the environment variables LINES, COLUMNS,
+ TERMCAP for window size changes...
+21. Tcsh 5.18c+ had broken NULL chars on scripts.
+ > cat > foo
+ #!/usr/local/bin/tcsh -f
+ echo "foo"
+ echo "^V^@"
+ echo "bar"
+ ^D
+ > chmod +x foo; foo
+ foo
+20. Posix has EAGAIN and not EWOULDBLOCK
+19. Don't set ECHOK; makes kill ^U ugly.
+18. $shell is SHELLPATH and not $SHELL any more.
+17. Added -n flag to cd, pushd, popd and dirs. Documented -l and -v
+ flags.
+16. Documented and fixed chase_symlinks and ignore_symlinks.
+15. Call endpwent() when you get interrupted...
+ cd ~chri<tab>^C
+ cd ~christos/<enter>
+ <stuck>
+14. Exec when you have suspended jobs asks for verification.
+13. Variable length fixes:
+ >set abcdefghijklmnopqrstuvwxyz=1
+ >echo $abcdefghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrs: Undefined variable
+ Now we have better messages too...
+12. Icon fixes...
+11. Quote expanded glob and history chars too.
+10. If someone sets SHIN to O_NDELAY we died... Now we set it back...
+ 9. unset path; unsetenv PATH; ls-F; (poof) fixed...
+ 8. Patches for masscomp, and ${var123} lexical analysis fix...
+ 7. Patch for sunview bug: A partially covered suntool sends SIGWINCH every
+ time the text is scrolled, causing annoying redraw effects. Now tcsh
+ checks if the size really changed before doing anything.
+ 6. Interrupt in the middle of cwdcmd, and periodic does not remove the
+ aliases.
+ 5. prompt2 and prompt3 fixes:
+ Prompt2 now prints the status of the parser by default.
+ Prompt3 can now have the standard prompt escape sequences.
+ 4. eval file descriptor re-direction fix.
+ >set p='w | tail +3'
+ >eval $p
+ (originally | tail +3 was ignored)
+ 3. $edit != emacs anymore; it was misleading, 'set edit' enables editing
+ 'unset edit' disables it.
+ 2. PERROR define fix.
+ 1. irix3.3.1 line discipline fix.
+
+V5.20.02, 12/15/90.
+32. /etc/Logout added and merged with /etc/Login flag.
+31. Fixed tty chars in ed.init.c. Some of them were not handled correctly.
+30. Command execution does not leak memory any more, and doing
+ ~ four times does not core-dump.
+29. Fixed the notorious csh 'if(' bug (part of the convex fixes)
+28. Intelligent getwd() on startup, and canonicalization.
+27. Intelligent directory stack. Gets updated when $HOME changes.
+26. Directory stack/save-restore additions
+25. Convex Fixes.
+24. Fixed onlret, and echonl getting stuck on svid.
+23. Shouldn't leave tty in raw mode at auto-logout (e.g. when su'ing from a
+ csh, this is annoying).
+22. Some users had environment EMACS set to something, and with my bad fix
+ at pl 1 found that they didn't have echo... (of course, even before my
+ "fix", they didn't have editing...). Anyway, refined the check to be
+ for EMACS=t, which is what emacs sets when running a subshell.
+21. kill -CONT %job, would not update the status of the job, but it would
+ just restart it.
+20. Sequent fixes.
+19. AIX370 signal and TCF fixes.
+18. fixed ls-F -l, SIGINT problem.
+17. aix on the ps2 does not have strcoll() either.
+16. Bind [A - [D and OA to OD in vi mode to the arrow key functions
+ so that they work from insert mode.
+15. %~ was not working correctly for /home/news and /home/newsbin...
+14. Removed Rcs Log
+13. ISC unix fixes.
+12. sunos3.x wants <sys/dir.h> not <dirent.h>
+11. Remove precmd's, cwdcmd's and periodic cmds that had errors.
+10. Compile sunos4.1 using termio.
+ 9. Rs6000 line discipline fixes.
+ 8. T_Tabs was wrong for termio machines.
+ 7. Don't bind single keystroke arrow keys, when they are already bound!
+ 6. Test for newline and tab before deciding not to send shell scripts
+ to the bourne shell.
+ 5. Added LITERAL prompt stuff.
+ 4. Fixed gethostname() in sh.rest.c to return the nodename.
+ 3. Do not quote spell checked stuff. This is not very intelligent but
+ works better than before.
+ 2. Fixes for relative path components. (paths that start with a .)
+ 1. Fixed so that Rawmode() is not called when we are not editing
+ (breaks running under emacs)
+
+V5.20.01, 11/15/90.
+12. Recognize environment variables too.
+11. Always start in Rawmode()
+10. don't try to execute binary files using the bourne shell.
+ 9. Vi change to end of line updates correctly now.
+ 8. Prompt in continuation lines.
+ 7. Prompt in if statements fix.
+ 6. System V ^C works right now.
+ 5. ^Z works correctly in bindings
+ 4. Better error messages for variables.
+ 3. dinit() now is more robust.
+ 2. Added aux2.0 patches.
+ 1. Fixed bug with arrow key bindings in ed.screen.c. All the keys
+ were bound to up-history!
+
+V5.20.00, 11/10/90.
+26. Fixed system V and POSIX time reporting.
+25. Fixed ed.screen.c so that it does not use malloc().
+24. Fixed SIGWINCH on the iris
+23. Fixed ed.screen.c, so that settc works correcly. It used to set
+ the termcap with a string that was allocated from the stack!
+22. Fixed listing of commands, where the last command was not checked.
+21. Fixed which command. It did not work for
+ \<command>, if command was aliased.
+20. Eliminated CSH4.3 define. You've had enough time to upgrade from 4.2
+19. Fixed GotTermCaps to be called only once.
+18. Added bindkey -r
+17. Attributes were not getting reset correctly.
+16. history -t does not print the time-stamp.
+15. AddXkey, works now for single character xkeys.
+14. filetype() knows better about symlinks.
+13. ls-F works with filenames that have metachars
+12. Completion/spelling works with quoted things.
+11. Fixed refresh bug. Repeat by:
+ On an intelligent terminal that has insert and delete chars (xterm)
+ > orphan
+ > vi orphan.c
+ > ^P^P
+10. Fixed so that if we don't have a tty on stdin editing is disabled.
+ 9. Check for nested process forking, to avoid loops such as:
+ > alias foo 'set bar=`foo`'
+ > foo
+ 8. Fix setting of AsciiOnly (Per)
+ 7. tw.spell.c, defined F_OK for systems that don't have it.
+ 6. ourwait.h had typo in ifdef.
+ 5. BSD compilers need a cast to int for enums used in
+ switches (Matthew Day)
+ 4. Found the cause for the core-dump in long backquote
+ expansions (Mark Davies)
+ 3. Some externs in ed.h needed to be truly externs...
+ reported by Mark Davies, bug appeared only on hp9000s800.
+ 2. Changed $tcsh, and $version strings.
+ 1. Added internal sprintf function, renamed putchar to CSHputchar,
+ printf to CSHprintf, sprintf to CSHsprintf.
+
+V5.19.02, 10/23/90.
+36. Added /etc/cshrc for the SGI irises.
+35. Added expand-variables function.
+34. Documented $time in tcsh.man
+33. Shell variables are now 'recognized' when expanding/listing things.
+32. ls-F does not eat the last slash on the / directory!
+31. Strings bound to keys are printed inside double quotes.
+30. History now remembers the exact line, not just an unparsed version of
+ the tokens.
+29. Renamed itoa to Itoa(), so things in libc that use itoa() don't break.
+28. Ported to IBM aix/ps2.
+27. Fixed eval so that it forks when the output is piped
+ Repeat by:
+ > who | grep $user
+ > eval who | grep $user
+26. Fixed so that 'nice <builtin changing the working directory>' does not
+ nice or fork.
+ Consider doing:
+ nice cd /tmp && rm *.c (don't try it!!!)
+ [what actually happens is that nice has to fork, then the child executes
+ chdir, and the parent stays where it was]
+25. Added Dan's patches (nls, builtin bindkey, fixes to the editor).
+24. Added aix370, migrate, getspath, getspath, getxvers, setxvers
+23. Added builtin echotc, removed sl and el.
+22. Ported to 4.4 BSD. This involved changing the way lots of flags worked,
+ cleanup of the SVID stuff, and addition of more compilation flags.
+ Now POSIX can work whed BSD is defined...
+21. Fixed so that el, sl work. Actually they are to be removed soon and
+ be replaced with echotc.
+20. Avoid the Quoted Space hack for alias when printing jobs!
+ [aliases to the same name avoid further alias expansion, by
+ inserting a quoted space in front of the command. In SHORT_STRINGS
+ QUOTE is the 15th bit so print ignores it thinking it is the
+ end of the string. So we just skip the Quoted Space....]
+ Repeat by:
+ > set notify
+ > alias ls ls -F
+ > (ls) &
+ Prints Exit 0 (
+ Should print: Exit 0 ( ls -F )
+19. Fixed so that "", '', ``, all produce ': Command not found',
+ and not the spurious messages.
+ Repeat by:
+ > set path = (/bin /usr/bin .... .)
+ > ""
+ /some/path/name/: Command not found
+18. Enable the use of <ctype.h> macros if they exist and NLS is defined.
+ NLS code is not ready yet.
+17. Fixed rmstar and continue_jobs code, so that they are not compile
+ options, but shell variables. Now you need to 'set rmstar' to get
+ enable rmstar.
+16. Fixed SIGWINCH, SIGWINDOW, and setting of li, co, that broke
+ suntools, and others.
+ Repeat by:
+ Start a shelltool of size other than 80x34
+ > telltc
+ > stty -a
+ do not report the same number of lines and columns.
+15. More fixes to tw.parse.c, and tw.spell.c.
+14. More fixes to sh.char.c.
+13. Fixed coredump caused by ``.
+12. Fixed spell-line code..
+11. Trapped SIGCHLD in sh.sem.c, while forking. Still there is a small
+ race, but the probability of happening is smaller!
+10. Fixed sh.char.c to be ISO compliant.
+ 9. Added expand-glob
+ 8. Fixed ourwait.h for little endians.
+ 7. Fixed that foreach i (^D expands correctly.
+ 6. Fixed so that listmax is ignored in ls-F.
+ 5. Fixed spelling correction so that single letter words and words that
+ contain globbing chars do not get spell checked.
+ 4. Changed NeXT HOSTTYPE to next, since all HOSTTYPE's are lower case.
+ 3. Fixed symmetry, and changed symmetry HOSTTYPE from sequent to symmetry.
+ 2. Added boldfacing, underlining chars.
+ 1. Added IRIX3.3.1 support.
+
+V5.19.01, 9/26/90.
+ 7. Brought the README file up-to-date, and changed the bug report
+ address to point to me.
+ 6. sh.lex.c. In addla(), overflow computation was wrong.
+ 5. Fixed SHELLPATH, to be set correctly when $SHELL is not set.
+ 4. Fixed print statement in sh.proc.c that contained \215.
+ 3. Fixed the Makefile and MAKEDIFFS so that a tahoe diff can be made.
+ 2. RS6000: hacked around execv bug, and ed.init.c warning.
+ 1. Editor should not be enabled when we don't have a tty.
diff --git a/contrib/tcsh/Imakefile b/contrib/tcsh/Imakefile
new file mode 100644
index 0000000..bb79bf5
--- /dev/null
+++ b/contrib/tcsh/Imakefile
@@ -0,0 +1,622 @@
+XCOMM
+XCOMM $Id: Imakefile,v 1.76 1999/06/09 19:26:36 christos Exp $
+XCOMM
+XCOMM Imakefile for tcsh 6.08
+XCOMM Marc Horowitz, MIT SIPB
+XCOMM
+
+#ifdef DestDir
+#undef DestDir
+#endif
+#ifdef ManSuffix
+#undef ManSuffix
+#endif
+
+/* All config options go in a separate file. */
+
+#include "imake.config"
+
+#ifndef HasGcc
+# define HasGcc 0
+#endif
+
+#ifndef HasGcc2
+# define HasGcc2 0
+#endif
+
+/* This is a giant conditional block. It should be set up right for
+platforms which are in here, but it may need to be changed for new
+ones. Please send in your fixes and additions! */
+
+/**** tcsh configuration defines ****/
+
+/* specific platforms */
+
+#ifndef ConfigH
+# ifdef UltrixArchitecture
+# define ConfigH ultrix
+# endif
+
+# ifdef UxpArchitecture
+# define ConfigH sysv4
+# endif
+
+# ifdef LinuxArchitecture
+# define ConfigH linux
+# endif
+
+# ifdef AlphaArchitecture
+# ifndef LinuxArchitecture
+# define ConfigH decosf1
+# endif
+# if !HasGcc
+# define MyCflags -std1 -Olimit 2000
+# else
+# define NoCombineRegs
+# endif
+# endif
+
+# if defined(VaxArchitecture) && !defined(UltrixArchitecture)
+# define ConfigH bsd
+# endif
+
+# ifdef NeXTArchitecture
+# define ConfigH mach
+# endif
+
+# if defined(SunArchitecture)
+# if (OSMajorVersion == 3)
+# define ConfigH sunos35
+# else
+# if (OSMajorVersion == 4)
+# if (OSMinorVersion == 0)
+# define ConfigH sunos40
+# else /* OSMinorVersion == 1 */
+# if (OSTeenyVersion == 3)
+# define ConfigH sunos413
+# else /* OsTeenyVersion in [0,1,2] */
+# define ConfigH sunos41
+# endif
+# endif
+# define NoCombineRegs
+# else /* OSMajorVersion == 5 */
+# if (OSMinorVersion < 3)
+# if (OSMinorVersion < 2)
+# define ConfigH sol2
+# else
+# define ConfigH sol22
+# endif
+# else
+# if (OSMinorVersion < 4)
+# define ConfigH sol23
+# else
+# if (OSMinorVersion < 6)
+# define ConfigH sol24
+# else
+# define ConfigH sol26
+# endif
+# endif
+# endif
+# define NoCombineRegs
+# endif
+# endif
+# endif
+
+# ifdef HPArchitecture
+/* For some stupid reason makedepend on HP requires this */
+DEPENDFLAGS = -o.o
+# if (OSMajorVersion >= 8)
+# define ConfigH hpux8
+# else
+# define ConfigH hpux7
+# endif
+# endif
+
+# ifdef CrayArchitecture
+# define ConfigH cray
+# endif
+
+# ifdef SGIArchitecture
+# define ConfigH irix
+# define UseLibBSD
+# if (OSMajorVersion < 5)
+# ifdef you_are_using_yp
+# define UseSunLib
+# endif
+# if !HasGCC
+# define MyStdc -D__STDC__
+# if SGICompilerMajorVersion < 4
+CCOPTIONS=-float # We don't want -cckr and -prototypes
+# endif
+# endif
+# endif
+# if (OSMajorVersion == 6)
+# if (OSMinorVersion >= 2)
+# undef UseLibBSD
+# define ConfigH irix62
+# endif
+# endif
+# endif
+
+# ifdef IBMArchitecture
+# undef UseLibBSD
+# if (SystemV == YES)
+# define ConfigH aix
+# if OSMajorVersion < 3
+# if OSMinorVersion < 2
+# define UseLibBSD
+# endif
+# endif
+# else
+# define ConfigH bsd
+# define AOSArchitecture
+# endif
+# endif
+
+
+#ifdef AOSArchitecture
+#define MyStdc -U__STDC__
+#endif
+
+# if defined(MipsBsdArchitecture) || defined(MipsSysvArchitecture)
+# define ConfigH mips
+# endif
+
+# ifdef DguxArchitecture
+# define ConfigH dgux
+# endif
+
+# ifdef ConvexArchitecture
+# define ConfigH convex
+# endif
+
+# if defined(SQNTArchitecture) || defined(SequentArchitecture)
+# define ConfigH sequent
+# endif
+
+# ifdef MacIIArchitecture
+# define ConfigH mac2
+# endif
+
+# ifdef MinixArchitecture
+/* Maybe conditional on MACH? */
+SYSSRCS=mi.termios.c mi.wait.h mi.varargs.h
+SYSOBJS=mi.termios.${SUF}
+EXTF=ma.setp.c vms.termcap.c
+# else
+/* Maybe conditional on MACH? */
+SYSSRCS=ma.setp.c
+SYSOBJS=ma.setp.${SUF}
+EXTF=mi.termios.c mi.wait.h mi.varargs.h vms.termcap.c
+# endif
+
+# ifdef i386Isc
+# if IscVersion != 202
+# define ConfigH isc
+# define UseLibCposix
+# else
+# define ConfigH isc202
+# endif
+# endif /* i386Isc */
+
+# ifdef OpenBSDArchitecture
+# define ConfigH bsd4.4
+# endif /* OpenBsdArchitecture */
+
+# ifdef NetBSDArchitecture
+# define ConfigH bsd4.4
+# endif /* NetBsdArchitecture */
+
+# ifdef FreeBSDArchitecture
+# define ConfigH bsd4.4
+# endif /* FreeBsdArchitecture */
+
+# ifdef i386SVR4Architecture
+# define ConfigH sysv4
+# ifdef DELL
+# define NoCombineRegs
+# endif
+# endif
+
+#endif /* !ConfigH */
+
+/* generic os's */
+
+#ifndef ConfigH
+
+#if (SystemV == YES)
+#define ConfigH sysv3
+#else
+/* why this as a default? Why not? */
+#define ConfigH bsd
+#endif
+
+#endif /* !ConfigH */
+
+/**** libraries ****/
+
+#if (SystemV == NO) || defined(HPArchitecture) || \
+ defined(SQNTArchitecture) || defined(SequentArchitecture) || \
+ defined(MacIIArchitecture) || defined(UseLibTermcap)
+LIBTERMCAP = -ltermcap
+#else
+LIBTERMCAP =
+#endif
+
+#if defined(SQNTArchitecture) || defined(SequentArchitecture)
+LIBSQNT=-lsocket -linet -lnsl -lseq
+#endif
+
+/* This may not be good enough - I don't have access to enough systems
+to really test it. */
+#if (SystemV == YES) || defined(UseLibCurses) && !defined(HPArchitecture)
+LIBCURSES = -lcurses
+#else
+LIBCURSES =
+#endif
+
+#if defined(UseLibNet)
+LIBNET = -lnet
+#else
+LIBNET =
+#endif
+
+#if defined(UseLibSocket)
+LIBSOCKET = -lsocket
+#else
+LIBSOCKET =
+#endif
+
+#if defined(UseLibBSD)
+LIBBSD = -lbsd
+#else
+LIBBSD =
+#endif
+
+#if (defined(SGIArchitecture) && \
+ (OSMajorVersion == 3) && (OSMinorVersion == 3)) || \
+ defined(UseLibC_S)
+LIBC_S = -lc_s
+#else
+LIBC_S =
+#endif
+
+#if defined(UseLibSun)
+LIBSUN = -lsun
+#else
+LIBSUN =
+#endif
+
+#if defined(UseLibCposix)
+LIBCPOSIX = -lcposix
+#else
+LIBCPOSIX =
+#endif
+
+#if defined(UseLibInet)
+LIBINET = -linet
+#else
+LIBINET =
+#endif
+
+#if defined(UseLibDir)
+LIBDIRECT = -ldir
+#else
+LIBDIRECT =
+#endif
+
+#if defined(UseLibX)
+LIBX = -lx
+#else
+LIBX =
+#endif
+
+#if defined(UseLibIntl)
+LIBINTL = -lintl
+#else
+LIBINTL =
+#endif
+
+#if (HasLibCrypt == YES)
+LIBCRYPT = -lcrypt
+#else
+LIBCRYPT =
+#endif
+
+#if defined(MacIIArchitecture) || defined(UseLibPosix)
+LIBPOSIX = -lposix
+#else
+LIBPOSIX =
+#endif
+
+#if defined(ATTArchitecture) || defined(UseLibDirent)
+LIBDIRECTENT = -ldirent
+#else
+LIBDIRECTENT =
+#endif
+
+/* The order here is significant. Although nothing uses all of these,
+some platforms which use more than one do care about the order. */
+
+SYSLIBS = $(LIBPOSIX) $(LIBDIRECTENT) $(LIBTERMCAP) $(LIBCURSES) \
+ $(LIBNET) $(LIBINTL) $(LIBSOCKET) $(LIBSUN) $(LIBBSD) $(LIBCPOSIX) \
+ $(LIBINET) $(LIBDIRECT) $(LIBX) $(LIBC_S) $(LIBSQNT) $(LIBCRYPT)
+
+/* Past here, nothing should need to be changed to compile on a different
+platform, unless you have a really weird architecture. */
+
+#ifdef MyCC
+CC = MyCC
+#else
+# if HasGcc
+# if HasGcc2
+CC = gcc
+# else
+# ifdef NoCombineRegs
+CC = gcc -finline-functions -fstrength-reduce
+# else
+CC = gcc -fcombine-regs -finline-functions -fstrength-reduce
+# endif
+# endif
+# else
+CC = cc
+# endif
+#endif
+
+#ifdef HESIOD
+HESLIB = -L/usr/athena/lib -lhesiod
+/* it seems to me that the -I shouldn't be necessary, but there seems
+to be a bug in the Imake stuff, so here it is. */
+HESDEF = -DHESIOD -I/usr/athena/include
+#else
+HESLIB =
+HESDEF =
+#endif
+
+#ifdef AFS
+#ifndef AFSDIR
+AFSDIR = /usr/afsws
+#endif
+#ifdef AFS33
+#define AFS33LIB -laudit
+#else
+#define AFS33LIB
+#endif
+/* Auxilliary libs needed for AFS */
+/* Both HPUX and Solaris need the BSD libraries. We need -lc before
+ * the bsd library to avoid using any more of it than is necessary.
+ */
+#if defined(HPArchitecture)
+#define AFSAUXLIB -lc -lBSD
+/* This is probably a kludge, but so is imake. */
+#else
+#if defined(SunArchitecture) && (OSMajorVersion == 5)
+#define AFSAUXLIB -lsocket -lnsl -lc -lucb
+#else
+#define AFSAUXLIB
+#endif
+#endif /* AFSAUXLIB */
+AFSLIB = -L$(AFSDIR)/lib -L$(AFSDIR)/lib/afs -lkauth -lprot -lubik\
+ -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err\
+ $(AFSDIR)/lib/afs/util.a AFS33LIB AFSAUXLIB
+AFSDEF = -DAFS -I$(AFSDIR)/include
+#else
+AFSLIB =
+AFSDEF =
+#endif
+
+/* This is encore specific, but I don't know what encore's #define is,
+and it shouldn't hurt to have it here, so here it is */
+PARALLEL=12 # Make the multi-max run fast.
+
+#ifndef TcshTop
+#define TcshTop /usr/local
+#endif
+TCSHTOP = TcshTop
+
+#ifndef ManSuffix
+#define ManSuffix 1
+#endif
+MANSUFFIX = ManSuffix
+
+#ifdef TcshPath
+PATH_TCSHELL = TcshPath
+TCSHPATH = -D_PATH_TCSHELL='"$(PATH_TCSHELL)"'
+#else
+TCSHPATH =
+#endif
+
+#ifdef DestBin
+TCSH_BINDIR = DestBin
+#else
+TCSH_BINDIR = $(TCSHTOP)/bin
+#endif
+#ifdef DestMan
+TCSH_MANDIR = DestMan
+#else
+TCSH_MANDIR = $(TCSHTOP)/man/man$(MANSUFFIX)
+#endif
+
+LOCALLIBS =
+
+#ifndef MyCflags
+#define MyCflags
+#endif
+
+#ifndef MyDefines
+#define MyDefines
+#endif
+
+#ifndef MyIncludes
+#define MyIncludes
+#endif
+
+#ifndef MyStdc
+#define MyStdc
+#endif
+
+#ifdef CDebugFlags
+CDEBUGFLAGS = CDebugFlags
+#else
+# if HasGcc2
+CDEBUGFLAGS = -O2
+# else
+CDEBUGFLAGS = -O
+# endif
+#endif
+
+
+#ifdef HostType
+HOSTTYPE=HostType
+HTDEF = -DHOSTTYPE='"$(HOSTTYPE)"'
+#else
+HTDEF =
+#endif
+
+DEFINES = $(TCSHPATH) $(HESDEF) $(AFSDEF) $(HTDEF) MyDefines MyCflags MyStdc
+INCLUDES = -I. MyIncludes
+#ifdef MyLibs
+LDLIBS = MyLibs
+#endif
+
+SUF = o
+VERSION = 6.08
+
+SHSRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
+ sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
+ sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
+ sh.set.c sh.time.c sh.char.h sh.dir.h sh.proc.h sh.h \
+ sh.decls.h glob.c glob.h ${SYSSRCS}
+SHOBJS= sh.${SUF} sh.dir.${SUF} sh.dol.${SUF} sh.err.${SUF} sh.exec.${SUF} \
+ sh.char.${SUF} sh.exp.${SUF} sh.func.${SUF} sh.glob.${SUF} \
+ sh.hist.${SUF} sh.init.${SUF} sh.lex.${SUF} sh.misc.${SUF} \
+ sh.parse.${SUF} sh.print.${SUF} sh.proc.${SUF} sh.sem.${SUF} \
+ sh.set.${SUF} sh.time.${SUF} glob.${SUF} ${SYSOBJS}
+
+TWSRCS= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \
+ tw.comp.c tw.color.c
+TWOBJS= tw.help.${SUF} tw.init.${SUF} tw.parse.${SUF} tw.spell.${SUF} \
+ tw.comp.${SUF} tw.color.${SUF}
+
+EDSRCS= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \
+ ed.refresh.c ed.screen.c ed.xmap.c ed.term.c ed.term.h
+EDOBJS= ed.chared.${SUF} ed.refresh.${SUF} ed.screen.${SUF} ed.init.${SUF} \
+ ed.inputl.${SUF} ed.defns.${SUF} ed.xmap.${SUF} ed.term.${SUF}
+
+TCSRCS= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \
+ tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c \
+ tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \
+ tc.who.c tc.h
+TCOBJS= tc.alloc.${SUF} tc.bind.${SUF} tc.const.${SUF} tc.defs.${SUF} \
+ tc.disc.${SUF} tc.func.${SUF} tc.os.${SUF} tc.printf.${SUF} \
+ tc.prompt.${SUF} tc.sched.${SUF} tc.sig.${SUF} tc.str.${SUF} \
+ tc.vers.${SUF} tc.who.${SUF}
+
+MISCF = Makefile.std Fixes MAKEDIFFS MAKESHAR NewThings README FAQ \
+ WishList config_f.h eight-bit.me glob.3 patchlevel.h \
+ pathnames.h tcsh.man Ported src.desc Imakefile imake.config \
+ README.imake complete.tcsh vmsreadme.txt Makefile.vms termcap.vms \
+ snames.h host.defs gethost.c tcsh.man2html Makefile.in configure.in \
+ Makefile.win32
+CONFSRCS=config/[a-z]*
+
+
+SRCS = $(SHSRCS) $(TWSRCS) $(EDSRCS) $(TCSRCS)
+OBJS = $(SHOBJS) $(TWOBJS) $(EDOBJS) $(TCOBJS)
+
+ALLSRCS= $(MISCF) $(SRCS) $(EXTF)
+
+AllTarget(tcsh)
+
+ed.defns.h: config.h ed.defns.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_ed_defns' >> $@
+ @echo '#define _h_ed_defns' >> $@
+ egrep '[FV]_' ed.defns.c | egrep '^#define' >> $@
+ @echo '#endif /* _h_ed_defns */' >> $@
+
+sh.err.h: config.h sh.err.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_sh_err' >> $@
+ @echo '#define _h_sh_err' >> $@
+ egrep 'ERR_' sh.err.c | egrep '^#define' >> $@
+ @echo '#endif /* _h_sh_err */' >> $@
+
+tc.const.h: config.h tc.const.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_tc_const' >> $@
+ @echo '#define _h_tc_const' >> $@
+ ${CC} -E $(INCLUDES) ${DEFINES} -D_h_tc_const tc.const.c | \
+ grep 'Char STR' | \
+ sed -e 's/Char \([a-zA-Z0-9_]*\)\[\].*/extern Char \1[];/' | \
+ sort >> $@
+ @echo '#endif /* _h_tc_const */' >> $@
+
+config.h: config_f.h
+ cp config/ConfigH config.h
+
+$(OBJS): sh.err.h tc.const.h ed.defns.h
+
+tar.Z:
+ rm -f tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tar.gz:
+ rm -f tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | gzip > tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+
+shar:
+ rm -f tcsh-*.shar
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ MAKESHAR -v -n tcsh-${VERSION} tcsh-${VERSION} \
+ tcsh-${VERSION}/?* tcsh-${VERSION}/config/?* \
+ tcsh-${VERSION}/?*/set?*
+ rm -rf tcsh-${VERSION}
+
+catalogs:
+ @(cd nls; make catalogs)
+
+world:
+ $(MAKE) clean ; $(MAKE) depend ; $(MAKE) tcsh ; $(MAKE) install
+
+clean::
+ rm -f ed.defns.h sh.err.h tc.const.h config.h tc.defs.*
+ rm -f tcsh.*.m tcsh.*.cat
+
+depend:: config.h ed.defns.h sh.err.h tc.const.h $(SRCS) tc.defs.c
+
+tc.defs.${SUF}: tc.defs.c sh.h
+
+tc.defs.c: gethost host.defs
+ @rm -f $@
+ @echo "/* Do not edit this file, make creates it */" > $@
+ ./gethost host.defs >> $@
+
+ALIB=$(HESLIB) $(AFSLIB) $(SYSLIBS)
+AINC=ed.defns.h sh.err.h tc.const.h sh.h
+
+NormalProgramTarget(tcsh, $(OBJS), $(AINC), $(LOCALLIBS), $(ALIB))
+NormalProgramTarget(gethost, gethost.${SUF}, $(AINC), $(LOCALLIBS), $(ALIB))
+
+InstallProgram(tcsh,$(TCSH_BINDIR))
+InstallManPage(tcsh,$(TCSH_MANDIR))
+DependTarget()
diff --git a/contrib/tcsh/MAKEDIFFS b/contrib/tcsh/MAKEDIFFS
new file mode 100755
index 0000000..3b87683
--- /dev/null
+++ b/contrib/tcsh/MAKEDIFFS
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# MAKEDIFFS.sh: Make context diffs for the csh sources
+#
+# $Id: MAKEDIFFS,v 3.0 1991/07/04 21:57:47 christos Exp $
+XINUDIR=/usr/share/src/mtXinu/bin/csh
+BSDDIR=/usr/share/src/mtXinu/BSD/bin/csh
+TAHOEDIR=/usr/share/src/mtXinu/TAHOE/bin/csh
+RENODIR=/usr/share/src/mtXinu/RENO/bin/csh
+TCSHDIR=`pwd`
+case "x$1" in
+xxinu)
+ CSHDIR=$XINUDIR;;
+xbsd)
+ CSHDIR=$BSDDIR;;
+xtahoe)
+ CSHDIR=$TAHOEDIR;;
+xreno)
+ CSHDIR=$RENODIR;;
+x*)
+ echo "Usage: `basename $0` [bsd|tahoe|xinu|reno]";exit 1;;
+esac
+DIFF1='sh.c sh.char.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.exp.c sh.file.c'
+DIFF2='sh.func.c sh.glob.c sh.hist.c sh.init.c sh.lex.c sh.misc.c sh.parse.c sh.print.c'
+DIFF3='sh.proc.c sh.sem.c sh.set.c sh.time.c sh.char.h sh.dir.h sh.h sh.local.h sh.proc.h'
+
+for i in $DIFF1
+do
+ diff -c $CSHDIR/$i $TCSHDIR/$i
+done > DIFFS.1
+
+for i in $DIFF2
+do
+ diff -c $CSHDIR/$i $TCSHDIR/$i
+done > DIFFS.2
+
+for i in $DIFF3
+do
+ diff -c $CSHDIR/$i $TCSHDIR/$i
+done > DIFFS.3
+exit 0
diff --git a/contrib/tcsh/MAKESHAR b/contrib/tcsh/MAKESHAR
new file mode 100755
index 0000000..691690f
--- /dev/null
+++ b/contrib/tcsh/MAKESHAR
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# MAKESHAR.sh: Make a shar file for the sources
+#
+# $Id: MAKESHAR,v 3.1 1992/05/09 04:03:53 christos Exp $
+
+AWK=/usr/bin/nawk # Must be nawk or gawk cause of 2D arrays
+WC=/usr/ucb/wc
+GREP=/usr/bin/egrep
+SORT=/usr/bin/sort
+SH=/bin/sh
+
+dirs=
+name=kit
+files=
+verbose=0
+size=45000
+
+for i
+do
+ case $i in
+ -n)
+ name=;;
+ -v)
+ verbose=1;;
+ -d)
+ SH=/bin/cat;;
+ -s)
+ size=$1;;
+ *)
+ if [ -z "$name" ]
+ then
+ name=$i
+ elif [ -d $i ]
+ then
+ dirs="$dirs $i"
+ elif [ -f $i ]
+ then
+ files="$files $i"
+ else
+ echo "$0: File `$i' not found." 1>&2
+ exit 1
+ fi;;
+ esac
+done
+
+if [ \( -z "$files" \) -a \( -z "$dirs" \) ]
+then
+ echo "Usage: $0 [-n name] [-s size] [-vd] <files>." 1>&2
+ exit 1
+fi
+
+$WC $files | $GREP -v total | $SORT +2 | $AWK '
+ BEGIN {
+ i = 0;
+ seq = 1;
+ size = 0;
+ name = 1;
+ used = 2;
+ verbose='"$verbose"';
+ tty = "/dev/tty";
+ maxsize = '"$size"';
+ dirs = "'"$dirs"'";
+ };
+ {
+ a[i, size] = $3;
+ a[i, name] = $4;
+ a[i, used] = 0;
+ i++;
+ };
+ END {
+ for (maxi = i--; i >= 0; i--) {
+ idx = 0;
+ if (a[i, used] == 0) {
+ if (verbose && a[i, size] > maxsize)
+ printf("Warning: File %s is %d > %d\n",
+ a[i, name], a[i, size], maxsize) > tty;
+ s = a[i, size];
+ a[i, used] = 1;
+ kit[seq, idx++] = i;
+ j = 0;
+ while (j < maxi) {
+ # Find the greatest file we can add
+ j = maxi;
+ for (k = 0; k < maxi; k++)
+ if (a[k, used] == 0 && a[k, size] + s < maxsize)
+ j = k;
+ if (j < maxi) {
+ s += a[j, size];
+ a[j, used] = 1;
+ kit[seq, idx++] = j;
+ }
+ }
+ sizes[seq] = s;
+ kit[seq++, idx] = -1;
+ }
+ }
+ for (i = 1; i < seq; i++) {
+ printf("shar -n%d -e%d %s ", i, seq - 1, dirs);
+ if (verbose) {
+ printf("%3d of %3d: ", i, seq - 1) > tty;
+ len = 12;
+ }
+ for (j = 0; kit[i, j] != -1; j++) {
+ s = a[kit[i, j], name];
+ if (verbose) {
+ clen = length(s) + 1;
+ len += clen;
+ if (len > 70) {
+ printf("\n ") > tty;
+ len = 12 + clen;
+ }
+ printf("%s ", s) > tty;
+ }
+ printf("%s ", s);
+ }
+ printf("> '"$name"'-%d.shar;", i);
+ if (verbose)
+ printf("= %5d\n", sizes[i]) > tty;
+ }
+ }' | $SH
diff --git a/contrib/tcsh/Makefile.in b/contrib/tcsh/Makefile.in
new file mode 100644
index 0000000..f752763
--- /dev/null
+++ b/contrib/tcsh/Makefile.in
@@ -0,0 +1,628 @@
+# $Id: Makefile.in,v 3.12 1998/11/24 18:17:08 christos Exp $
+# Makefile.in 4.3 6/11/83
+#
+# C Shell with process control; VM/UNIX VAX Makefile
+# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
+#
+# With an input editor, command completion, etc. and ported to all sorts of
+# things; Paul Placeway, CIS Dept., Ohio State University
+#
+SHELL=/bin/sh
+VERSION=6.08
+BUILD=tcsh
+VPATH=@srcdir@
+srcdir=@srcdir@
+
+################################################################
+## CFLAGS. For various -D things, see config.h
+################################################################
+#
+# These are the default suffixes from .c to .o and -c to get there
+# but to use the global optimizer on the mips boxes, see below
+#
+SUF=o
+CF=-c
+
+CPPFLAGS=-I. -I$(srcdir)
+
+LFLAGS=
+#LFLAGS= -Zn10000 # hpux lint
+
+
+CFLAGS = @CFLAGS@ # This is set by autoconf.
+#CFLAGS= -g # debug
+#CFLAGS= -O # production
+#CFLAGS= # Broken optimizers....
+
+#CFLAGS= -g -pg -DPROF
+#CFLAGS= -O -pg -DPROF
+
+# gcc 1.00-1.37
+#CFLAGS= -O -finline-functions -fstrength-reduce
+
+# gcc 1.37-1.40
+#CFLAGS= -O -fcombine-regs -finline-functions -fstrength-reduce
+# add -msoft-float for 68881 machines.
+
+# gcc 2.0
+# On the sparc, don't use -O2; it breaks setjmp() and vfork()
+#CFLAGS= -O
+
+# gcc-2.1+
+#CFLAGS= -O2
+
+# lucid c on suns
+#CFLAGS= -O5
+
+# gcc 2.1 on linux
+#CFLAGS= -O6 -fomit-frame-pointer
+
+# HP/UX 8.0, 9.0
+#CFLAGS= +O3 -Aa
+
+# Ultrix 4.2a
+#CFLAGS= -O -Olimit 2000
+
+# Intel Paragon OSF/1 with PGI compilers
+#CFLAGS= -O -Mnodebug -Mnoperfmon
+
+# DEC Alpha OSF/1
+#CFLAGS= -O2 -Olimit 2000 ## Normal Optimization
+#CFLAGS= -O3 -Olimit 2000 ## Full Optimization - may not work
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u
+
+# for silicon graphics (and other mips compilers) -- use the
+# global optimizer! (-O3).
+# On SGI 4.0+ you need to add -D__STDC__ too.
+#CFLAGS= -O3
+#CFLAGS= -O3 -Olimit 2000 ## Ultrix 4.2a
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u ## Ultrix and gnu-make need that
+
+# mips systems
+# CFLAGS= -O -systype bsd43 -Wf,-XNd5000 -Wf,-XNp6000 -Olimit 2000
+
+# for at&t machines
+#CFLAGS= -O -Ksd
+
+# Stardent Titan
+#CFLAGS = -O -43
+
+# Stardent Stellar or sunos4 /bin/cc or Solaris2.1 /opt/SUNWspro/bin/cc
+#CFLAGS = -O4
+
+# Intergraph clipper CLIX 3.1
+#CFLAGS= -w -O2
+
+# Dnix 5.3
+#CFLAGS = -O -X7
+
+# Pyramid OS/x
+#CFLAGS = -OG
+
+# Multiflow (5M binary... if you choose -O5!)
+#CFLAGS = -O5 -sb_trace 0
+
+# DDE Supermax Unix SYSV Rel III.
+# CFLAGS= -O3
+
+# SINIX RMx00
+#CFLAGS= -O # -D_POSIX_SOURCE # -kansi
+
+# Apollo's with cc [apollo builtins don't work with gcc]
+# and apollo should not define __STDC__ if it does not have
+# the standard header files. RT's (aos4.3) need that too;
+# you might want to skip the -O on the rt's... Not very wise.
+# AIX/ESA needs -D_IBMESA on command line (this may disappear by GA)
+#DFLAGS=-U__STDC__
+#DFLAGS=-D_IBMESA
+# On aix2.2.1 we need more compiler space.
+#DFLAGS=-Nd4000 -Nn3000
+# AU/X 2.0 needs a flag for POSIX (read the config file)
+#DFLAGS=-Zp
+# Tektronix 4300 running UTek 4.0 (BSD 4.2) needs:
+#DFLAGS = -DUTek -DBSD
+# VMS_POSIX needs:
+#DFLAGS=-D_VMS_POSIX
+# Multiflow and PCC compilers don't like void typedefs.
+# You may also need -U__STDC__ if you use pcc (i.e. ibmrt aos4.3).
+#DFLAGS=-DMULTIFLOW
+#DFLAGS=-DPCC
+# DELL SVR4
+#DFLAGS=-DDELL
+#DFLAGS=
+#DFLAGS=-D_PATH_TCSHELL='"${DESTBIN}/tcsh"'
+## The following is set by autoconf.
+DFLAGS = -D_PATH_TCSHELL='"${DESTBIN}/tcsh"' @DFLAGS@ @CPPFLAGS@
+
+
+################################################################
+## LDFLAGS. Define something here if you need to
+################################################################
+LDFLAGS= @LDFLAGS@ ## This is set by autoconf.
+#LDFLAGS= ## The simplest, suitable for all.
+#LDFLAGS= -s ## Stripped. Takes less space on disk.
+#LDFLAGS= -s -n ## Pure executable. Spares paging over
+# ## the network for machines with local
+# ## swap but external /usr/local/bin .
+#LDFLAGS= -s -n -Bstatic ## Without dynamic linking. (SunOS/cc)
+#LDFLAGS= -s -n -static ## Without dynamic linking. (SunOS/gcc)
+#LDFLAGS= -Wl,-s,-n ## Stripped, shared text (Unicos)
+#LDFLAGS= -s -static ## Link statically. (linux)
+#LDFLAGS= -s -N ## Impure executable (linux)
+
+################################################################
+## LIBES. Pick one, or roll your own.
+################################################################
+LIBES= @LIBS@ ## This is set by autoconf.
+#LIBES= -ltermcap ## BSD style things
+#LIBES= -ltermcap ## SunOS, HP-UX, pyramid
+#LIBES= -ltermcap ## Linux
+#LIBES= -ltermcap -lshadow ## Linux with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Tek XD88/10 (UTekV) with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Motorola MPC (sysV88) with PW_SHADOW
+#LIBES= -ltermcap -lcs ## Mach
+#LIBES= -ltermcap -lbsd ## DEC osf1 on the alpha
+#LIBES= -ltermcap -lbsd ## Intel paragon
+#LIBES= -ltermcap -lbsd ## Clipper intergraph
+#LIBES= -ltermcap -lseq ## Sequent's Dynix
+#LIBES= -ltermcap -lauth ## Ultrix with Enhanced Security
+#LIBES= -ltermcap -ldir -lx ## Xenix 386 style things
+#LIBES= -ltermcap -lndir -lsocket -ljobs ## masscomp RTU6.0
+#LIBES= -lcurses ## AIX on the rt
+#LIBES= -lcurses ## TitanOS on the stellar
+#LIBES= -ltermlib -lsocket -lnsl ## SysV4 w/o BSDTIMES or Solaris 2
+#LIBES= -lcurses ## SysV3 w/o networking
+#LIBES= -lcurses -lnet ## SysV3 with networking
+#LIBES= -lcurses -ldir ## SysV2 w/o networking & dirlib
+#LIBES= -lcurses -ldir -lnet ## SysV2 with networking & dirlib
+#LIBES= -lcurses -lbsd ## AIX on the IBM 370 or rs6000 or ps2
+#LIBES= -lcurses -lbsd ## ETA10
+#LIBES= -lcurses -lbsd ## Irix3.1 on the SGI-IRIS4D
+#LIBES= -lcurses -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D w/o yp
+#LIBES= -lcurses -lsun -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D with yp
+#LIBES= -lcurses -lsocket -lbsd ## Amdahl UTS 2.1
+#LIBES= -lcurses -lsocket ## Intel's hypercube.
+#LIBES= -lcurses -lsocket ## ns32000 based Opus.
+#LIBES= -lcurses -lcposix ## ISC 2.2 without networking
+#LIBES= -lcposix -lc_s -lcurses -linet ## ISC 2.2 with networking
+#LIBES= -lcurses -lsec -lc_s ## ISC 2.0.2 without networking
+#LIBES= -lcurses -linet -lsec -lc_s ## ISC 2.0.2 with networking
+#LIBES= -lcurses -lintl -lcrypt ## SCO SysVR3.2v2.0
+#LIBES= -lcurses -lintl -lsocket -lcrypt ## SCO+ODT1.1
+#LIBES= -lposix -ltermcap ## A/UX 2.0
+#LIBES= -lposix -ltermcap -lc_s ## A/UX 3.0
+#LIBES= -ldirent -lcurses ## att3b1 cc w/o shared lib & dirlib
+#LIBES= -shlib -ldirent -lcurses ## att3b1 gcc with shared lib & dirlib
+#LIBES= -ltermlib -lsocket -lnsl -lc /usr/ucblib/libucb.a ## SysV4 with BSDTIMES
+#LIBES= -lcurses -lnsl -lsocket -lc /usr/ucblib/libucb.a ## Stardent Vistra
+#LIBES= -ltermc ## emx under OS/2
+#LIBES= ## Minix, VMS_POSIX
+#LIBES= -ltermcap -lcrypt ## Multiflow
+#LIBES= -ltermcap -lcrypt ## NetBSD
+#LIBES= -lcurses ## DDE Supermax
+
+################################################################
+## EXTRAFLAGS and EXTRALIBS
+################################################################
+# Compiling for AFS with kerberos authentication
+#AFSLIBDIR = /usr/afsws/lib
+#AFSDEF = -DAFS -I/usr/afsws/include
+#AFS33LIB = -laudit
+#
+#Solaris and HPUX require the BSD libraries with AFS.
+#We use -lc to use only what we require.
+#AFSAUXLIB = -lsocket -lnsl -lc -lucb # Solaris
+#AFSAUXLIB = -lc -lBSD # HPUX
+#
+#AFSLIB = -L$(AFSLIBDIR) -L$(AFSLIBDIR)/afs -lkauth -lprot -lubik\
+# -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err\
+# $(AFSLIBDIR)/afs/util.a $(AFS33LIB) $(AFSAUXLIB)
+#
+
+EXTRAFLAGS = @HESDEF@ $(AFSDEF)
+EXTRALIBS = @HESLIB@ $(AFSLIB)
+
+
+# The difficult choice of a c-compiler...
+# First, you should try your own c-compiler.
+# Gcc -traditional is also a safe choice.
+# If you think that you have good include files try gcc -Wall...
+# If you want to take out -traditional, make sure that your sys/ioctl.h
+# is fixed correctly, otherwise you'll be stopped for tty input, or you
+# will lose the editor and job control.
+
+# This is for setting your C preprocessor value.
+CPP = @CPP@ # This is set by autoconf.
+# The -B tells gcc to use /bin/ld. This is to avoid using the gnu ld, which
+# on the suns does not know how to make dynamically linked binaries.
+CC = @CC@ # This is set by autoconf.
+#CC= gcc -Wall -pipe -B/bin/ # -ansi -pedantic
+#CC= gcc -m486 -pipe -Wall # Generate code for Intel 486 (linux)
+#CC= shlicc # BSDI2.1 w/ shared libraries
+#CC= cc
+#CC= occ
+#CC= acc
+#CC= pcc
+#CC= hc -w
+#CC= c89 # For VMS/POSIX
+#CC= /bin/cc # For suns, w/o gcc and SVR4
+#CC= /usr/lib/sun.compile/cc # FPS 500 (+FPX) with Sun C compiler
+#CC= /opt/SUNWspro/bin/cc # Solaris 2.1
+#CC= scc # Alliant fx2800
+#CC= cc -h0,ansi,novector,float0 # for NEC SX-4
+#CC= lcc -wa
+ED= ed
+AS= as
+RM= rm
+CXREF= /usr/ucb/cxref
+VGRIND= csh /usr/ucb/vgrind
+CTAGS= /usr/ucb/ctags
+#XSTR= /usr/ucb/xstr
+SCCS= /usr/local/sccs
+PARALLEL=12 # Make the multi-max run fast.
+#P=& # Use Sequent's parallel make
+P=
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+mandir=@mandir@
+MANSECT=1
+DESTBIN=${DESTDIR}${bindir}
+DESTMAN=${DESTDIR}${mandir}/man${MANSECT}
+# DESTMAN=${DESTDIR}/catman/man${MANSECT} # A/UX
+# DESTMAN=${DESTDIR}/usr/share/man/man${MANSECT} # Stardent Vistra (SysVR4)
+# DESTMAN=/usr/catman/1l # Amiga unix (SysVR4)
+FTPAREA=/usr/spool/ftp
+
+ASSRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
+ sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
+ sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
+ sh.set.c sh.time.c sh.char.h sh.dir.h sh.proc.h sh.h \
+ tw.color.c
+PSSRCS= sh.decls.h glob.c glob.h mi.termios.c mi.wait.h mi.varargs.h ma.setp.c \
+ vms.termcap.c
+SHSRCS= ${ASSRCS} ${PSSRCS}
+SHOBJS= sh.${SUF} sh.dir.${SUF} sh.dol.${SUF} sh.err.${SUF} sh.exec.${SUF} \
+ sh.char.${SUF} sh.exp.${SUF} sh.func.${SUF} sh.glob.${SUF} \
+ sh.hist.${SUF} sh.init.${SUF} sh.lex.${SUF} sh.misc.${SUF} \
+ sh.parse.${SUF} sh.print.${SUF} sh.proc.${SUF} sh.sem.${SUF} \
+ sh.set.${SUF} sh.time.${SUF} glob.${SUF} mi.termios.${SUF} \
+ ma.setp.${SUF} vms.termcap.${SUF}
+
+TWSRCS= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \
+ tw.comp.c tw.color.c
+TWOBJS= tw.help.${SUF} tw.init.${SUF} tw.parse.${SUF} tw.spell.${SUF} \
+ tw.comp.${SUF} tw.color.${SUF}
+
+EDSRCS= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \
+ ed.refresh.c ed.screen.c ed.xmap.c ed.term.c ed.term.h
+EDOBJS= ed.chared.${SUF} ed.refresh.${SUF} ed.screen.${SUF} ed.init.${SUF} \
+ ed.inputl.${SUF} ed.defns.${SUF} ed.xmap.${SUF} ed.term.${SUF}
+
+TCSRCS= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \
+ tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c \
+ tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \
+ tc.who.c tc.h
+TCOBJS= tc.alloc.${SUF} tc.bind.${SUF} tc.const.${SUF} tc.defs.${SUF} \
+ tc.disc.${SUF} tc.func.${SUF} tc.os.${SUF} tc.printf.${SUF} \
+ tc.prompt.${SUF} tc.sched.${SUF} tc.sig.${SUF} tc.str.${SUF} \
+ tc.vers.${SUF} tc.who.${SUF}
+
+PVSRCS= Makefile.std Makefile.vms Makefile.in Makefile.win32
+AVSRCS= Fixes MAKEDIFFS MAKESHAR NewThings README FAQ \
+ WishList config_f.h eight-bit.me glob.3 patchlevel.h \
+ pathnames.h tcsh.man Ported src.desc Imakefile imake.config \
+ README.imake complete.tcsh vmsreadme.txt termcap.vms snames.h \
+ host.defs gethost.c tcsh.man2html configure.in configure config.h.in
+
+VHSRCS=${PVSRCS} ${AVSRCS}
+
+CONFSRCS=config/*
+
+ALLSRCS= ${SHSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${VHSRCS}
+DISTSRCS= ${PSSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${AVSRCS}
+
+
+OBJS= ${SHOBJS} ${TWOBJS} ${EDOBJS} ${TCOBJS}
+
+
+all: ${BUILD}
+
+tcsh:$(P) ${OBJS}
+ rm -f tcsh core
+ ${CC} -o tcsh ${LDFLAGS} ${CFLAGS} ${CPPFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+
+# Purify
+pure:$(P) ${OBJS}
+ rm -f tcsh core
+ purify `echo ${CC} | sed -e s,-B/bin/,,` -o tcsh ${LDFLAGS} ${CFLAGS} ${CPPFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+# OS/2
+tcsh.exe: tcsh
+ emxbind tcsh
+
+gethost: gethost.c sh.err.h tc.const.h sh.h
+ rm -f gethost
+ ${CC} -o gethost ${LDFLAGS} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} $(srcdir)/gethost.c ${LIBES} ${EXTRALIBS}
+
+tc.defs.c: gethost host.defs
+ @rm -f $@
+ @echo "/* Do not edit this file, make creates it */" > $@
+ ./gethost $(srcdir)/host.defs >> $@
+
+tcsh.ps: tcsh.man
+ rm -f tcsh.ps
+ -ptroff -t -man $(srcdir)/tcsh.man > tcsh.ps
+
+
+.c.${SUF}:
+ ${CC} ${CF} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${EXTRAFLAGS} $<
+
+# _VMS_POSIX #module addition
+#.c.${SUF}:
+# @(echo '#module '`echo $< | sed -e 's/\./_/g'`; cat $<) > $*..c
+# @echo ${CC} ${CF} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*.c
+# @${CC} ${CF} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*..c
+# @mv $*..o $*.o
+# @rm -f $*..c
+
+
+# Don't do any special massaging of C files for sharing of strings!!
+# it causes weird segmentation faults on some systems.
+#.c.o:
+# ${CPP} ${CFLAGS} ${CPPFLAGS} $*.c | ${XSTR} -c -
+# ${CC} ${CF} ${CFLAGS} ${CPPFLAGS} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#ed.init.o: ed.init.c
+# ${CPP} ${CFLAGS} ${CPPFLAGS} $*.c | ${XSTR} -c -
+# ${CC} -R ${CF} ${CFLAGS} ${CPPFLAGS} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#strings.o: strings
+# ${XSTR}
+# ${CC} -c -R xs.c
+# mv -f xs.o strings.o
+# rm -f xs.c
+
+##.DEFAULT:
+## ${SCCS} get $<
+
+##.DEFAULT:
+## co $<
+
+ed.defns.h: ed.defns.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_ed_defns' >> $@
+ @echo '#define _h_ed_defns' >> $@
+ grep '[FV]_' $(srcdir)/ed.defns.c | grep '^#define' >> $@
+ @echo '#endif /* _h_ed_defns */' >> $@
+
+sh.err.h: sh.err.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_sh_err' >> $@
+ @echo '#define _h_sh_err' >> $@
+ grep 'ERR_' $(srcdir)/sh.err.c | grep '^#define' >> $@
+ @echo '#endif /* _h_sh_err */' >> $@
+
+tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_tc_const' >> $@
+ @echo '#define _h_tc_const' >> $@
+ ${CPP} $(CPPFLAGS) ${DFLAGS} ${EXTRAFLAGS} -D_h_tc_const\
+ $(srcdir)/tc.const.c | grep 'Char STR' | \
+ sed -e 's/Char \([a-zA-Z0-9_]*\)\[\].*/extern Char \1[];/' | \
+ sort >> $@
+ @echo '#endif /* _h_tc_const */' >> $@
+
+csh.prof: ${OBJS} sh.prof.${SUF} mcrt0.${SUF}
+ rm -f csh.prof
+ ld -X mcrt0.${SUF} ${OBJS} -o csh.prof ${LIBES} -lc
+
+sh.prof.${SUF}:
+ cp sh.c sh.prof.c
+ ${CC} ${CF} ${CFLAGS} ${CPPFLAGS} -DPROF sh.prof.c
+
+lint: tc.const.h ed.defns.h
+ lint ${DFLAGS} ${CPPFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+alint: tc.const.h ed.defns.h
+ alint ${DFLAGS} ${CPPFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+print:
+ @pr READ_ME
+ @pr makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -h SIZES
+ @${CXREF} sh*.c | pr -h XREF
+ @ls -l | pr
+ @pr sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vprint:
+ @pr -l84 READ_ME TODO
+ @pr -l84 makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -l84 -h SIZES
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @ls -l | pr -l84
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @pr -l84 sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vgrind:
+ @cp /dev/null index
+ @for i in *.h; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @for i in *.c; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @vgrind -t -x -h Index index >/crp/bill/csh/index.t
+
+install-strip: install
+
+install: tcsh
+ mkdir -p ${DESTBIN}
+ -mv -f ${DESTBIN}/tcsh ${DESTBIN}/tcsh.old
+ cp tcsh ${DESTBIN}/tcsh
+ -strip ${DESTBIN}/tcsh
+ chmod 555 ${DESTBIN}/tcsh
+
+install.man: tcsh.man
+ mkdir -p ${DESTMAN}
+ -rm -f ${DESTMAN}/tcsh.${MANSECT}
+ cp $(srcdir)/tcsh.man ${DESTMAN}/tcsh.${MANSECT}
+ chmod 444 ${DESTMAN}/tcsh.${MANSECT}
+
+# Amiga Unix
+#install.man: tcsh.man
+# compress tcsh.man
+# cp tcsh.man.Z ${DESTMAN}/tcsh.Z
+# chmod 444 ${DESTMAN}/tcsh.Z
+
+# Apple A/UX
+#install.man: tcsh.man
+# -rm -f ${DESTMAN}/tcsh.${MANSECT}.Z
+# nroff -man tcsh.man | compress > ${DESTMAN}/tcsh.${MANSECT}.Z
+# chmod 444 ${DESTMAN}/tcsh.${MANSECT}.Z
+
+clean:
+ ${RM} -f a.out strings x.c xs.c tcsh tcsh.a _MAKE_LOG core gethost
+ ${RM} -f *.${SUF} sh.prof.c ed.defns.h tc.const.h sh.err.h tc.defs.c
+ ${RM} -f tcsh.*.m tcsh.*.cat
+
+veryclean: clean
+ ${RM} -f config.h config.status config.cache config.log Makefile tcsh.ps
+ ${RM} -f *~ #*
+
+distclean: veryclean
+
+tags: /tmp
+ ${CTAGS} sh*.c
+
+tar.Z:
+ rm -f tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tar.gz:
+ rm -f tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | gzip > tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+
+shar:
+ rm -f tcsh-*.shar
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ MAKESHAR -v -n tcsh-${VERSION} tcsh-${VERSION} \
+ tcsh-${VERSION}/?* tcsh-${VERSION}/config/?* \
+ tcsh-${VERSION}/?*/set?*
+ rm -rf tcsh-${VERSION}
+
+catalogs:
+ @(cd nls; make catalogs)
+
+tcsh-${VERSION}.tar.Z:
+ rm -rf tcsh-${VERSION}
+ rm -f tcsh-${VERSION}.tar tcsh-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh-${VERSION}
+ ./MAKEDIFFS bsd
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh-${VERSION}
+ cp ${DISTSRCS} tcsh-${VERSION}
+ mkdir tcsh-${VERSION}/config
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ cp Makefile tcsh-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tcsh.tahoe-${VERSION}.tar.Z:
+ rm -rf tcsh.tahoe-${VERSION}
+ rm -f tcsh.tahoe-${VERSION}.tar tcsh.tahoe-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.tahoe-${VERSION}
+ ./MAKEDIFFS tahoe
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.tahoe-${VERSION}
+ cp ${DISTSRCS} tcsh.tahoe-${VERSION}
+ mkdir tcsh.tahoe-${VERSION}/config
+ cp ${CONFSRCS} tcsh.tahoe-${VERSION}/config
+ cp Makefile tcsh.tahoe-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.tahoe-${VERSION} | compress > tcsh.tahoe-${VERSION}.tar.Z
+ rm -rf tcsh.tahoe-${VERSION}
+
+tcsh.reno-${VERSION}.tar.Z:
+ rm -rf tcsh.reno-${VERSION}
+ rm -f tcsh.reno-${VERSION}.tar tcsh.reno-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.reno-${VERSION}
+ ./MAKEDIFFS reno
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.reno-${VERSION}
+ cp ${DISTSRCS} tcsh.reno-${VERSION}
+ mkdir tcsh.reno-${VERSION}/config
+ cp ${CONFSRCS} tcsh.reno-${VERSION}/config
+ cp Makefile tcsh.reno-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.reno-${VERSION} | compress > tcsh.reno-${VERSION}.tar.Z
+ rm -rf tcsh.reno-${VERSION}
+
+ftp: tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z
+ cp tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z ${FTPAREA}
+ cp tcsh.man ${FTPAREA}
+
+autoconfigure: $(srcdir)/configure $(srcdir)/config.h.in
+
+$(srcdir)/configure: $(srcdir)/configure.in
+ cd $(srcdir) && autoconf
+
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+$(srcdir)/stamp-h.in: $(srcdir)/configure.in
+ cd $(srcdir) && autoheader
+ @echo timestamp > $(srcdir)/stamp-h.in
+
+#
+# Dependencies
+#
+config.h: config_f.h
+
+TCH=tc.h tc.const.h tc.decls.h tc.os.h tc.sig.h
+SHH=sh.h sh.types.h sh.char.h sh.err.h sh.dir.h sh.proc.h pathnames.h \
+ sh.decls.h ${TCH}
+TWH=tw.h tw.decls.h
+EDH=ed.h ed.decls.h
+
+# EDH
+EDINC=sh.${SUF} sh.func.${SUF} sh.lex.${SUF} sh.print.${SUF} sh.proc.${SUF} \
+ sh.set.${SUF} tc.bind.${SUF} tc.os.${SUF} tc.prompt.${SUF} \
+ tc.sched.${SUF} tw.parse.${SUF} tw.color.${SUF}
+${EDOBJS} ${EDINC} : ${EDH}
+
+# SHH
+${OBJS}: config.h ${SHH}
+
+# TWH
+TWINC=ed.chared.${SUF} ed.inputl.${SUF} sh.exec.${SUF} sh.func.${SUF} \
+ sh.set.${SUF} tc.func.${SUF} tw.color.${SUF}
+${TWOBJS} ${TWINC}: ${TWH}
+
+# glob.h
+glob.${SUF} sh.glob.${SUF}: glob.h
+
+# ed.defns.h
+EDDINC=tc.bind.${SUF} tc.func.${SUF} tc.os.${SUF}
+${EDOBJS} ${EDDINC}: ed.defns.h
+
+# tc.defs.o
+tc.defs.${SUF}: tc.defs.c sh.h
diff --git a/contrib/tcsh/Makefile.std b/contrib/tcsh/Makefile.std
new file mode 100644
index 0000000..2e676be
--- /dev/null
+++ b/contrib/tcsh/Makefile.std
@@ -0,0 +1,625 @@
+# $Id: Makefile.std,v 1.88 1998/10/02 10:56:47 christos Exp $
+# Makefile.std 4.3 6/11/83
+#
+# C Shell with process control; VM/UNIX VAX Makefile
+# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
+#
+# With an input editor, command completion, etc. and ported to all sorts of
+# things; Paul Placeway, CIS Dept., Ohio State University
+#
+SHELL=/bin/sh
+VERSION=6.08
+BUILD=tcsh
+srcdir=.
+
+################################################################
+## CFLAGS. For various -D things, see config.h
+################################################################
+#
+# These are the default suffixes from .c to .o and -c to get there
+# but to use the global optimizer on the mips boxes, see below
+#
+SUF=o
+CF=-c
+
+INCLUDES=-I. -I$(srcdir)
+
+LFLAGS=$(INCLUDES)
+#LFLAGS=$(INCLUDES) -Zn10000 # hpux lint
+
+
+#CFLAGS= $(INCLUDES) -g # debug
+#CFLAGS= $(INCLUDES) -O # production
+#CFLAGS= $(INCLUDES) # Broken optimizers....
+
+#CFLAGS= -g -pg $(INCLUDES) -DPROF
+#CFLAGS= -O -pg $(INCLUDES) -DPROF
+
+# gcc 1.00-1.37
+#CFLAGS=-O $(INCLUDES) -finline-functions -fstrength-reduce
+
+# gcc 1.37-1.40
+#CFLAGS=-O $(INCLUDES) -fcombine-regs -finline-functions -fstrength-reduce
+# add -msoft-float for 68881 machines.
+
+# gcc 2.0
+# On the sparc, don't use -O2; it breaks setjmp() and vfork()
+#CFLAGS=-O $(INCLUDES)
+
+# gcc-2.1+
+CFLAGS=-O2 $(INCLUDES)
+
+# lucid c on suns
+#CFLAGS=-O5 $(INCLUDES)
+
+# gcc 2.1 on linux
+#CFLAGS=-O6 -fomit-frame-pointer $(INCLUDES)
+
+# HP/UX 8.0, 9.0
+#CFLAGS= $(INCLUDES) +O3 -Aa
+
+# Ultrix 4.2a
+#CFLAGS= $(INCLUDES) -O -Olimit 2000
+
+# Intel Paragon OSF/1 with PGI compilers
+#CFLAGS=-O -Mnodebug -Mnoperfmon $(INCLUDES)
+
+# DEC Alpha OSF/1
+#CFLAGS= -O2 $(INCLUDES) -Olimit 2000 ## Normal Optimization
+#CFLAGS= -O3 $(INCLUDES) -Olimit 2000 ## Full Optimization - may not work
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u
+
+# for silicon graphics (and other mips compilers) -- use the
+# global optimizer! (-O3).
+# On SGI 4.0+ you need to add -D__STDC__ too.
+#CFLAGS= -O3 $(INCLUDES)
+#CFLAGS= -O3 $(INCLUDES) -Olimit 2000 ## Ultrix 4.2a
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u ## Ultrix and gnu-make need that
+
+# mips systems
+# CFLAGS= $(INCLUDES) -O -systype bsd43 -Wf,-XNd5000 -Wf,-XNp6000 -Olimit 2000
+
+# for at&t machines
+#CFLAGS= -O -Ksd $(INCLUDES)
+
+# Stardent Titan
+#CFLAGS = $(INCLUDES) -O -43
+
+# Stardent Stellar or sunos4 /bin/cc or Solaris2.1 /opt/SUNWspro/bin/cc
+#CFLAGS = $(INCLUDES) -O4
+
+# Intergraph clipper CLIX 3.1
+#CFLAGS= -w -O2 $(INCLUDES)
+
+# Dnix 5.3
+#CFLAGS = -O -X7
+
+# Pyramid OS/x
+#CFLAGS = -OG
+
+# Multiflow (5M binary... if you choose -O5!)
+#CFLAGS = -O5 -sb_trace 0
+
+# DDE Supermax Unix SYSV Rel III.
+# CFLAGS= -O3
+
+# SINIX RMx00
+#CFLAGS= -O # -D_POSIX_SOURCE # -kansi
+
+# Apollo's with cc [apollo builtins don't work with gcc]
+# and apollo should not define __STDC__ if it does not have
+# the standard header files. RT's (aos4.3) need that too;
+# you might want to skip the -O on the rt's... Not very wise.
+# AIX/ESA needs -D_IBMESA on command line (this may disappear by GA)
+#DFLAGS=-U__STDC__
+#DFLAGS=-D_IBMESA
+# On aix2.2.1 we need more compiler space.
+#DFLAGS=-Nd4000 -Nn3000
+# AU/X 2.0 needs a flag for POSIX (read the config file)
+#DFLAGS=-Zp
+# Tektronix 4300 running UTek 4.0 (BSD 4.2) needs:
+#DFLAGS = -DUTek -DBSD
+# VMS_POSIX needs:
+#DFLAGS=-D_VMS_POSIX
+# Multiflow and PCC compilers don't like void typedefs.
+# You may also need -U__STDC__ if you use pcc (i.e. ibmrt aos4.3).
+#DFLAGS=-DMULTIFLOW
+#DFLAGS=-DPCC
+# DELL SVR4
+#DFLAGS=-DDELL
+# SCO_SV
+#DFLAGS=-D_SPEED_T -DSCO
+DFLAGS=
+#DFLAGS=-D_PATH_TCSHELL='"${DESTBIN}/tcsh"'
+
+
+################################################################
+## LDFLAGS. Define something here if you need to
+################################################################
+LDFLAGS= ## The simplest, suitable for all.
+#LDFLAGS= -s ## Stripped. Takes less space on disk.
+#LDFLAGS= -s -n ## Pure executable. Spares paging over
+# ## the network for machines with local
+# ## swap but external /usr/local/bin .
+#LDFLAGS= -s -n -Bstatic ## Without dynamic linking. (SunOS/cc)
+#LDFLAGS= -s -n -static ## Without dynamic linking. (SunOS/gcc)
+#LDFLAGS= -Wl,-s,-n ## Stripped, shared text (Unicos)
+#LDFLAGS= -s -static ## Link statically. (linux)
+#LDFLAGS= -s -N ## Impure executable (linux)
+#LDFLAGS= -Bdynamic -dy ## SCO_SV
+
+################################################################
+## LIBES. Pick one, or roll your own.
+################################################################
+LIBES= -ltermcap ## BSD style things
+#LIBES= -ltermcap ## SunOS, HP-UX, pyramid
+#LIBES= -ltermcap ## Linux
+#LIBES= -ltermcap -lshadow ## Linux with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Tek XD88/10 (UTekV) with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Motorola MPC (sysV88) with PW_SHADOW
+#LIBES= -ltermcap -lcs ## Mach
+#LIBES= -ltermcap -lbsd ## DEC osf1 on the alpha
+#LIBES= -ltermcap -lbsd ## Intel paragon
+#LIBES= -ltermcap -lbsd ## Clipper intergraph
+#LIBES= -ltermcap -lseq ## Sequent's Dynix
+#LIBES= -ltermcap -lauth ## Ultrix with Enhanced Security
+#LIBES= -ltermcap -ldir -lx ## Xenix 386 style things
+#LIBES= -ltermcap -lndir -lsocket -ljobs ## masscomp RTU6.0
+#LIBES= -lcurses ## AIX on the rt
+#LIBES= -lcurses ## TitanOS on the stellar
+#LIBES= -ltermlib -lsocket -lnsl ## SysV4 w/o BSDTIMES or Solaris 2
+#LIBES= -lcurses ## SysV3 w/o networking
+#LIBES= -lcurses -lnet ## SysV3 with networking
+#LIBES= -lcurses -ldir ## SysV2 w/o networking & dirlib
+#LIBES= -lcurses -ldir -lnet ## SysV2 with networking & dirlib
+#LIBES= -lcurses -lbsd ## AIX on the IBM 370 or rs6000 or ps2
+#LIBES= -lcurses -lbsd ## ETA10
+#LIBES= -lcurses -lbsd ## Irix3.1 on the SGI-IRIS4D
+#LIBES= -lcurses -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D w/o yp
+#LIBES= -lcurses -lsun -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D with yp
+#LIBES= -lcurses -lsocket -lbsd ## Amdahl UTS 2.1
+#LIBES= -lcurses -lsocket ## Intel's hypercube.
+#LIBES= -lcurses -lsocket ## ns32000 based Opus.
+#LIBES= -lcurses -lcposix ## ISC 2.2 without networking
+#LIBES= -lcposix -lc_s -lcurses -linet ## ISC 2.2 with networking
+#LIBES= -lcurses -lsec -lc_s ## ISC 2.0.2 without networking
+#LIBES= -lcurses -linet -lsec -lc_s ## ISC 2.0.2 with networking
+#LIBES= -lcurses -lintl -lcrypt ## SCO SysVR3.2v2.0
+#LIBES= -lcurses -lintl -lsocket -lcrypt ## SCO+ODT1.1
+#LIBES= -lcurses -lsocket -lcrypt ## SCO_SV
+#LIBES= -lposix -ltermcap ## A/UX 2.0
+#LIBES= -lposix -ltermcap -lc_s ## A/UX 3.0
+#LIBES= -ldirent -lcurses ## att3b1 cc w/o shared lib & dirlib
+#LIBES= -shlib -ldirent -lcurses ## att3b1 gcc with shared lib & dirlib
+#LIBES= -ltermlib -lsocket -lnsl -lc /usr/ucblib/libucb.a ## SysV4 with BSDTIMES
+#LIBES= -lcurses -lnsl -lsocket -lc /usr/ucblib/libucb.a ## Stardent Vistra
+#LIBES= -ltermc ## emx under OS/2
+#LIBES= ## Minix, VMS_POSIX
+#LIBES= -ltermcap -lcrypt ## Multiflow
+#LIBES= -ltermcap -lcrypt ## NetBSD
+#LIBES= -lcurses ## DDE Supermax
+
+################################################################
+## EXTRAFLAGS and EXTRALIBS
+################################################################
+# Compiling for HESIOD
+#HESDEF = -DHESIOD -I/usr/athena/include
+#HESLIB = -L/usr/athena/lib -lhesiod
+#
+# Compiling for AFS with kerberos authentication
+#AFSLIBDIR = /usr/afsws/lib
+#AFSDEF = -DAFS -I/usr/afsws/include
+#AFS33LIB = -laudit
+#
+#Solaris and HPUX require the BSD libraries with AFS.
+#We use -lc to use only what we require.
+#AFSAUXLIB = -lsocket -lnsl -lc -lucb # Solaris
+#AFSAUXLIB = -lc -lBSD # HPUX
+#
+#AFSLIB = -L$(AFSLIBDIR) -L$(AFSLIBDIR)/afs -lkauth -lprot -lubik\
+# -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err\
+# $(AFSLIBDIR)/afs/util.a $(AFS33LIB) $(AFSAUXLIB)
+#
+
+EXTRAFLAGS = $(HESDEF) $(AFSDEF)
+EXTRALIBS = $(HESLIB) $(AFSLIB)
+
+
+# The difficult choice of a c-compiler...
+# First, you should try your own c-compiler.
+# Gcc -traditional is also a safe choice.
+# If you think that you have good include files try gcc -Wall...
+# If you want to take out -traditional, make sure that your sys/ioctl.h
+# is fixed correctly, otherwise you'll be stopped for tty input, or you
+# will lose the editor and job control.
+
+# This is for setting your C preprocessor value.
+CPP = ${CC} -E
+# The -B tells gcc to use /bin/ld. This is to avoid using the gnu ld, which
+# on the suns does not know how to make dynamically linked binaries.
+CC= gcc -Wall -pipe -B/bin/ # -ansi -pedantic
+#CC= gcc -m486 -pipe -Wall # Generate code for Intel 486 (linux)
+#CC= shlicc # BSDI2.1 w/ shared libraries
+#CC= cc
+#CC= occ
+#CC= acc
+#CC= pcc
+#CC= hc -w
+#CC= c89 # For VMS/POSIX
+#CC= /bin/cc # For suns, w/o gcc and SVR4
+#CC= /usr/lib/sun.compile/cc # FPS 500 (+FPX) with Sun C compiler
+#CC= /opt/SUNWspro/bin/cc # Solaris 2.1
+#CC= scc # Alliant fx2800
+#CC= lcc -wa
+#CC= cc -b elf -Kpic # SCO_SV
+ED= ed
+AS= as
+RM= rm
+CXREF= /usr/ucb/cxref
+#CXREF= /bin/cxref # SCO_SV
+VGRIND= csh /usr/ucb/vgrind
+CTAGS= /usr/ucb/ctags
+#CTAGS= /usr/bin/ctags # SCO_SV
+#XSTR= /usr/ucb/xstr
+#XSTR= /usr/bin/xstr # SCO_SV
+SCCS= /usr/local/sccs
+PARALLEL=12 # Make the multi-max run fast.
+#P=& # Use Sequent's parallel make
+P=
+DESTDIR=/usr/local
+#DESTDIR=/usr/contrib
+MANSECT=1
+DESTBIN=${DESTDIR}/bin
+DESTMAN=${DESTDIR}/man/man${MANSECT}
+# DESTMAN=${DESTDIR}/catman/man${MANSECT} # A/UX
+# DESTMAN=${DESTDIR}/usr/share/man/man${MANSECT} # Stardent Vistra (SysVR4)
+# DESTMAN=/usr/catman/1l # Amiga unix (SysVR4)
+FTPAREA=/usr/spool/ftp
+
+ASSRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
+ sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
+ sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
+ sh.set.c sh.time.c sh.char.h sh.dir.h sh.proc.h sh.h
+PSSRCS= sh.decls.h glob.c glob.h mi.termios.c mi.wait.h mi.varargs.h ma.setp.c \
+ vms.termcap.c
+SHSRCS= ${ASSRCS} ${PSSRCS}
+SHOBJS= sh.${SUF} sh.dir.${SUF} sh.dol.${SUF} sh.err.${SUF} sh.exec.${SUF} \
+ sh.char.${SUF} sh.exp.${SUF} sh.func.${SUF} sh.glob.${SUF} \
+ sh.hist.${SUF} sh.init.${SUF} sh.lex.${SUF} sh.misc.${SUF} \
+ sh.parse.${SUF} sh.print.${SUF} sh.proc.${SUF} sh.sem.${SUF} \
+ sh.set.${SUF} sh.time.${SUF} glob.${SUF} mi.termios.${SUF} \
+ ma.setp.${SUF} vms.termcap.${SUF}
+
+TWSRCS= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \
+ tw.comp.c tw.color.c
+TWOBJS= tw.help.${SUF} tw.init.${SUF} tw.parse.${SUF} tw.spell.${SUF} \
+ tw.comp.${SUF} tw.color.${SUF}
+
+EDSRCS= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \
+ ed.refresh.c ed.screen.c ed.xmap.c ed.term.c ed.term.h
+EDOBJS= ed.chared.${SUF} ed.refresh.${SUF} ed.screen.${SUF} ed.init.${SUF} \
+ ed.inputl.${SUF} ed.defns.${SUF} ed.xmap.${SUF} ed.term.${SUF}
+
+TCSRCS= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \
+ tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c \
+ tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \
+ tc.who.c tc.h
+TCOBJS= tc.alloc.${SUF} tc.bind.${SUF} tc.const.${SUF} tc.defs.${SUF} \
+ tc.disc.${SUF} tc.func.${SUF} tc.os.${SUF} tc.printf.${SUF} \
+ tc.prompt.${SUF} tc.sched.${SUF} tc.sig.${SUF} tc.str.${SUF} \
+ tc.vers.${SUF} tc.who.${SUF}
+
+PVSRCS= Makefile.std Makefile.vms Makefile.in Makefile.win32
+AVSRCS= Fixes MAKEDIFFS MAKESHAR NewThings README FAQ \
+ WishList config_f.h eight-bit.me glob.3 patchlevel.h \
+ pathnames.h tcsh.man Ported src.desc Imakefile imake.config \
+ README.imake complete.tcsh vmsreadme.txt termcap.vms snames.h \
+ host.defs gethost.c tcsh.man2html configure.in configure config.h.in
+
+VHSRCS=${PVSRCS} ${AVSRCS}
+
+CONFSRCS=config/*
+
+ALLSRCS= ${SHSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${VHSRCS}
+DISTSRCS= ${PSSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${AVSRCS}
+
+
+OBJS= ${SHOBJS} ${TWOBJS} ${EDOBJS} ${TCOBJS}
+
+
+all: ${BUILD}
+
+tcsh:$(P) ${OBJS}
+ rm -f tcsh core
+ ${CC} -o tcsh ${LDFLAGS} ${CFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+
+# Purify
+pure:$(P) ${OBJS}
+ rm -f tcsh core
+ purify `echo ${CC} | sed -e s,-B/bin/,,` -o tcsh ${LDFLAGS} ${CFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+# OS/2
+tcsh.exe: tcsh
+ emxbind tcsh
+
+gethost: gethost.c sh.err.h tc.const.h sh.h
+ rm -f gethost
+ ${CC} -o gethost ${LDFLAGS} ${CFLAGS} ${DFLAGS} $(srcdir)/gethost.c ${LIBES} ${EXTRALIBS}
+
+tc.defs.c: gethost host.defs
+ @rm -f $@
+ @echo "/* Do not edit this file, make creates it */" > $@
+ ./gethost $(srcdir)/host.defs >> $@
+
+tcsh.ps: tcsh.man
+ rm -f tcsh.ps
+ -ptroff -t -man $(srcdir)/tcsh.man > tcsh.ps
+
+
+.c.${SUF}:
+ ${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $<
+
+# _VMS_POSIX #module addition
+#.c.${SUF}:
+# @(echo '#module '`echo $< | sed -e 's/\./_/g'`; cat $<) > $*..c
+# @echo ${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*.c
+# @${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*..c
+# @mv $*..o $*.o
+# @rm -f $*..c
+
+
+# Don't do any special massaging of C files for sharing of strings!!
+# it causes weird segmentation faults on some systems.
+#.c.o:
+# ${CPP} ${CFLAGS} $*.c | ${XSTR} -c -
+# ${CC} ${CF} ${CFLAGS} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#ed.init.o: ed.init.c
+# ${CPP} ${CFLAGS} $*.c | ${XSTR} -c -
+# ${CC} -R ${CF} ${CF} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#strings.o: strings
+# ${XSTR}
+# ${CC} -c -R xs.c
+# mv -f xs.o strings.o
+# rm -f xs.c
+
+##.DEFAULT:
+## ${SCCS} get $<
+
+##.DEFAULT:
+## co $<
+
+ed.defns.h: ed.defns.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_ed_defns' >> $@
+ @echo '#define _h_ed_defns' >> $@
+ grep '[FV]_' $(srcdir)/ed.defns.c | grep '^#define' >> $@
+ @echo '#endif /* _h_ed_defns */' >> $@
+
+sh.err.h: sh.err.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_sh_err' >> $@
+ @echo '#define _h_sh_err' >> $@
+ grep 'ERR_' $(srcdir)/sh.err.c | grep '^#define' >> $@
+ @echo '#endif /* _h_sh_err */' >> $@
+
+tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '#ifndef _h_tc_const' >> $@
+ @echo '#define _h_tc_const' >> $@
+ ${CPP} $(INCLUDES) ${DFLAGS} ${EXTRAFLAGS} -D_h_tc_const\
+ $(srcdir)/tc.const.c | grep 'Char STR' | \
+ sed -e 's/Char \([a-zA-Z0-9_]*\)\[\].*/extern Char \1[];/' | \
+ sort >> $@
+ @echo '#endif /* _h_tc_const */' >> $@
+
+csh.prof: ${OBJS} sh.prof.${SUF} mcrt0.${SUF}
+ rm -f csh.prof
+ ld -X mcrt0.${SUF} ${OBJS} -o csh.prof ${LIBES} -lc
+
+sh.prof.${SUF}:
+ cp sh.c sh.prof.c
+ ${CC} ${CF} ${CFLAGS} -DPROF sh.prof.c
+
+lint: tc.const.h ed.defns.h
+ lint ${DFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+alint: tc.const.h ed.defns.h
+ alint ${DFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+print:
+ @pr READ_ME
+ @pr makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -h SIZES
+ @${CXREF} sh*.c | pr -h XREF
+ @ls -l | pr
+ @pr sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vprint:
+ @pr -l84 READ_ME TODO
+ @pr -l84 makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -l84 -h SIZES
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @ls -l | pr -l84
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @pr -l84 sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vgrind:
+ @cp /dev/null index
+ @for i in *.h; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @for i in *.c; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @vgrind -t -x -h Index index >/crp/bill/csh/index.t
+
+install: tcsh
+ -mv -f ${DESTBIN}/tcsh ${DESTBIN}/tcsh.old
+ cp tcsh ${DESTBIN}/tcsh
+ -strip ${DESTBIN}/tcsh
+ chmod 555 ${DESTBIN}/tcsh
+
+install.man: tcsh.man
+ -rm -f ${DESTMAN}/tcsh.${MANSECT}
+ cp $(srcdir)/tcsh.man ${DESTMAN}/tcsh.${MANSECT}
+ chmod 444 ${DESTMAN}/tcsh.${MANSECT}
+
+# Amiga Unix
+#install.man: tcsh.man
+# compress tcsh.man
+# cp tcsh.man.Z ${DESTMAN}/tcsh.Z
+# chmod 444 ${DESTMAN}/tcsh.Z
+
+# Apple A/UX
+#install.man: tcsh.man
+# -rm -f ${DESTMAN}/tcsh.${MANSECT}.Z
+# nroff -man tcsh.man | compress > ${DESTMAN}/tcsh.${MANSECT}.Z
+# chmod 444 ${DESTMAN}/tcsh.${MANSECT}.Z
+
+clean:
+ ${RM} -f a.out strings x.c xs.c tcsh tcsh.a _MAKE_LOG core gethost
+ ${RM} -f *.${SUF} sh.prof.c ed.defns.h tc.const.h sh.err.h tc.defs.c
+ ${RM} -f tcsh.*.m tcsh.*.cat
+
+veryclean: clean
+ ${RM} -f config.h config.status config.cache config.log Makefile tcsh.ps
+ ${RM} -f *~ #*
+
+distclean: veryclean
+
+tags: /tmp
+ ${CTAGS} sh*.c
+
+tar.Z:
+ rm -f tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tar.gz:
+ rm -f tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | gzip > tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+
+shar:
+ rm -f tcsh-*.shar
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ MAKESHAR -v -n tcsh-${VERSION} tcsh-${VERSION} \
+ tcsh-${VERSION}/?* tcsh-${VERSION}/config/?* \
+ tcsh-${VERSION}/?*/set?*
+ rm -rf tcsh-${VERSION}
+
+catalogs:
+ @(cd nls; make catalogs)
+
+tcsh-${VERSION}.tar.Z:
+ rm -rf tcsh-${VERSION}
+ rm -f tcsh-${VERSION}.tar tcsh-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh-${VERSION}
+ ./MAKEDIFFS bsd
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh-${VERSION}
+ cp ${DISTSRCS} tcsh-${VERSION}
+ mkdir tcsh-${VERSION}/config
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ cp Makefile tcsh-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tcsh.tahoe-${VERSION}.tar.Z:
+ rm -rf tcsh.tahoe-${VERSION}
+ rm -f tcsh.tahoe-${VERSION}.tar tcsh.tahoe-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.tahoe-${VERSION}
+ ./MAKEDIFFS tahoe
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.tahoe-${VERSION}
+ cp ${DISTSRCS} tcsh.tahoe-${VERSION}
+ mkdir tcsh.tahoe-${VERSION}/config
+ cp ${CONFSRCS} tcsh.tahoe-${VERSION}/config
+ cp Makefile tcsh.tahoe-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.tahoe-${VERSION} | compress > tcsh.tahoe-${VERSION}.tar.Z
+ rm -rf tcsh.tahoe-${VERSION}
+
+tcsh.reno-${VERSION}.tar.Z:
+ rm -rf tcsh.reno-${VERSION}
+ rm -f tcsh.reno-${VERSION}.tar tcsh.reno-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.reno-${VERSION}
+ ./MAKEDIFFS reno
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.reno-${VERSION}
+ cp ${DISTSRCS} tcsh.reno-${VERSION}
+ mkdir tcsh.reno-${VERSION}/config
+ cp ${CONFSRCS} tcsh.reno-${VERSION}/config
+ cp Makefile tcsh.reno-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.reno-${VERSION} | compress > tcsh.reno-${VERSION}.tar.Z
+ rm -rf tcsh.reno-${VERSION}
+
+ftp: tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z
+ cp tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z ${FTPAREA}
+ cp tcsh.man ${FTPAREA}
+
+autoconfigure: $(srcdir)/configure $(srcdir)/config.h.in
+
+$(srcdir)/configure: $(srcdir)/configure.in
+ cd $(srcdir) && autoconf
+
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+$(srcdir)/stamp-h.in: $(srcdir)/configure.in
+ cd $(srcdir) && autoheader
+ @echo timestamp > $(srcdir)/stamp-h.in
+
+#
+# Dependencies
+#
+config.h: config_f.h
+
+TCH=tc.h tc.const.h tc.decls.h tc.os.h tc.sig.h
+SHH=sh.h sh.types.h sh.char.h sh.err.h sh.dir.h sh.proc.h pathnames.h \
+ sh.decls.h ${TCH}
+TWH=tw.h tw.decls.h
+EDH=ed.h ed.decls.h
+
+# EDH
+EDINC=sh.${SUF} sh.func.${SUF} sh.lex.${SUF} sh.print.${SUF} sh.proc.${SUF} \
+ sh.set.${SUF} tc.bind.${SUF} tc.os.${SUF} tc.prompt.${SUF} \
+ tc.sched.${SUF} tw.parse.${SUF} tw.color.${SUF}
+${EDOBJS} ${EDINC} : ${EDH}
+
+# SHH
+${OBJS}: config.h ${SHH}
+
+# TWH
+TWINC=ed.chared.${SUF} ed.inputl.${SUF} sh.exec.${SUF} sh.func.${SUF} \
+ sh.set.${SUF} tc.func.${SUF} tw.color.${SUF}
+${TWOBJS} ${TWINC}: ${TWH}
+
+# glob.h
+glob.${SUF} sh.glob.${SUF}: glob.h
+
+# ed.defns.h
+EDDINC=tc.bind.${SUF} tc.func.${SUF} tc.os.${SUF}
+${EDOBJS} ${EDDINC}: ed.defns.h
+
+# tc.defs.o
+tc.defs.${SUF}: tc.defs.c sh.h
diff --git a/contrib/tcsh/Makefile.vms b/contrib/tcsh/Makefile.vms
new file mode 100644
index 0000000..e225ee8
--- /dev/null
+++ b/contrib/tcsh/Makefile.vms
@@ -0,0 +1,594 @@
+# $Id: Makefile.vms,v 1.32 1998/10/02 10:56:49 christos Exp $
+# Makefile.vms 4.3 6/11/83
+#
+# C Shell with process control; VM/UNIX VAX Makefile
+# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
+#
+# With an input editor, command completion, etc. and ported to all sorts of
+# things; Paul Placeway, CIS Dept., Ohio State University
+#
+SHELL=/bin/sh
+VERSION=6.08
+BUILD=tcsh
+
+################################################################
+## CFLAGS. For various -D things, see config.h
+################################################################
+#
+# These are the default suffixes from .c to .o and -c to get there
+# but to use the global optimizer on the mips boxes, see below
+#
+SUF=o
+CF=-c
+
+INCLUDES=-I. -I..
+
+LFLAGS=$(INCLUDES)
+#LFLAGS=$(INCLUDES) -Zn10000 # hpux lint
+
+
+#CFLAGS= $(INCLUDES) -g # debug
+#CFLAGS= $(INCLUDES) -O # production
+#CFLAGS= $(INCLUDES) # Broken optimizers....
+
+#CFLAGS= -g -pg $(INCLUDES) -DPROF
+#CFLAGS= -O -pg $(INCLUDES) -DPROF
+
+# gcc 1.00-1.37
+#CFLAGS=-O $(INCLUDES) -finline-functions -fstrength-reduce
+
+# gcc 1.37-1.40
+#CFLAGS=-O $(INCLUDES) -fcombine-regs -finline-functions -fstrength-reduce
+# add -msoft-float for 68881 machines.
+
+# gcc 2.0
+# On the sparc, don't use -O2; it breaks setjmp() and vfork()
+#CFLAGS=-O $(INCLUDES)
+
+# gcc-2.1+
+#CFLAGS=-O2 $(INCLUDES)
+
+# lucid c on suns
+#CFLAGS=-O5 $(INCLUDES)
+
+# gcc 2.1 on linux
+#CFLAGS=-O6 -fomit-frame-pointer $(INCLUDES)
+
+# HP/UX 8.0, 9.0
+#CFLAGS= $(INCLUDES) +O3 -Aa
+
+# Ultrix 4.2a
+#CFLAGS= $(INCLUDES) -O -Olimit 2000
+
+# Intel Paragon OSF/1 with PGI compilers
+#CFLAGS=-O -Mnodebug -Mnoperfmon $(INCLUDES)
+
+# DEC Alpha OSF/1
+#CFLAGS= -O2 $(INCLUDES) -Olimit 2000 ## Normal Optimization
+#CFLAGS= -O3 $(INCLUDES) -Olimit 2000 ## Full Optimization - may not work
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u
+
+# for silicon graphics (and other mips compilers) -- use the
+# global optimizer! (-O3).
+# On SGI 4.0+ you need to add -D__STDC__ too.
+#CFLAGS= -O3 $(INCLUDES)
+#CFLAGS= -O3 $(INCLUDES) -Olimit 2000 ## Ultrix 4.2a
+#CF=-j
+#SUF=u
+#.SUFFIXES: .u ## Ultrix and gnu-make need that
+
+# mips systems
+# CFLAGS= $(INCLUDES) -O -systype bsd43 -Wf,-XNd5000 -Wf,-XNp6000 -Olimit 2000
+
+# for at&t machines
+#CFLAGS= -O -Ksd $(INCLUDES)
+
+# Stardent Titan
+#CFLAGS = $(INCLUDES) -O -43
+
+# Stardent Stellar or sunos4 /bin/cc or Solaris2.1 /opt/SUNWspro/bin/cc
+#CFLAGS = $(INCLUDES) -O4
+
+# Intergraph clipper CLIX 3.1
+#CFLAGS= -w -O2 $(INCLUDES)
+
+# Dnix 5.3
+#CFLAGS = -O -X7
+
+# Pyramid OS/x
+#CFLAGS = -OG
+
+# Multiflow (5M binary... if you choose -O5!)
+#CFLAGS = -O5 -sb_trace 0
+
+# DDE Supermax Unix SYSV Rel III.
+# CFLAGS= -O3
+
+# Apollo's with cc [apollo builtins don't work with gcc]
+# and apollo should not define __STDC__ if it does not have
+# the standard header files. RT's (aos4.3) need that too;
+# you might want to skip the -O on the rt's... Not very wise.
+# AIX/ESA needs -D_IBMESA on command line (this may disappear by GA)
+#DFLAGS=-U__STDC__
+#DFLAGS=-D_IBMESA
+# On aix2.2.1 we need more compiler space.
+#DFLAGS=-Nd4000 -Nn3000
+# AU/X 2.0 needs a flag for POSIX (read the config file)
+#DFLAGS=-Zp
+# Tektronix 4300 running UTek 4.0 (BSD 4.2) needs:
+#DFLAGS = -DUTek -DBSD
+# VMS_POSIX needs:
+#DFLAGS=-D_VMS_POSIX
+# Multiflow
+#DFLAGS=-DMULTIFLOW
+# DELL SVR4
+#DFLAGS=-DDELL
+DFLAGS=
+#DFLAGS=-D_PATH_TCSHELL='"${DESTBIN}/tcsh"'
+
+
+################################################################
+## LDFLAGS. Define something here if you need to
+################################################################
+LDFLAGS= ## The simplest, suitable for all.
+#LDFLAGS= -s ## Stripped. Takes less space on disk.
+#LDFLAGS= -s -n ## Pure executable. Spares paging over
+# ## the network for machines with local
+# ## swap but external /usr/local/bin .
+#LDFLAGS= -s -n -Bstatic ## Without dynamic links. (SunOS)
+#LDFLAGS= -Wl,-s,-n ## Stripped, shared text (Unicos)
+#LDFLAGS= -s -static ## Link statically. (linux)
+#LDFLAGS= -s -N ## Impure executable (linux)
+
+################################################################
+## LIBES. Pick one, or roll your own.
+################################################################
+#LIBES= -ltermcap ## BSD style things
+#LIBES= -ltermcap ## SunOS, HP-UX, pyramid
+#LIBES= -ltermcap ## Linux
+#LIBES= -ltermcap -lshadow ## Linux with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Tek XD88/10 (UTekV) with PW_SHADOW
+#LIBES= -ltermcap -lsec ## Motorola MPC (sysV88) with PW_SHADOW
+#LIBES= -ltermcap -lcs ## Mach
+#LIBES= -ltermcap -lbsd ## DEC osf1 on the alpha
+#LIBES= -ltermcap -lbsd ## Intel paragon
+#LIBES= -ltermcap -lbsd ## Clipper intergraph
+#LIBES= -ltermcap -lseq ## Sequent's Dynix
+#LIBES= -ltermcap -lauth ## Ultrix with Enhanced Security
+#LIBES= -ltermcap -ldir -lx ## Xenix 386 style things
+#LIBES= -ltermcap -lndir -lsocket -ljobs ## masscomp RTU6.0
+#LIBES= -lcurses ## AIX on the rt
+#LIBES= -lcurses ## TitanOS on the stellar
+#LIBES= -ltermlib -lsocket -lnsl ## SysV4 w/o BSDTIMES or Solaris 2
+#LIBES= -lcurses ## SysV3 w/o networking
+#LIBES= -lcurses -lnet ## SysV3 with networking
+#LIBES= -lcurses -ldir ## SysV2 w/o networking & dirlib
+#LIBES= -lcurses -ldir -lnet ## SysV2 with networking & dirlib
+#LIBES= -lcurses -lbsd ## AIX on the IBM 370 or rs6000 or ps2
+#LIBES= -lcurses -lbsd ## ETA10
+#LIBES= -lcurses -lbsd ## Irix3.1 on the SGI-IRIS4D
+#LIBES= -lcurses -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D w/o yp
+#LIBES= -lcurses -lsun -lbsd -lc_s ## Irix3.3 on the SGI-IRIS4D with yp
+#LIBES= -lcurses -lsocket -lbsd ## Amdahl UTS 2.1
+#LIBES= -lcurses -lsocket ## Intel's hypercube.
+#LIBES= -lcurses -lsocket ## ns32000 based Opus.
+#LIBES= -lcurses -lcposix ## ISC 2.2 without networking
+#LIBES= -lcposix -lc_s -lcurses -linet ## ISC 2.2 with networking
+#LIBES= -lcurses -lsec -lc_s ## ISC 2.0.2 without networking
+#LIBES= -lcurses -linet -lsec -lc_s ## ISC 2.0.2 with networking
+#LIBES= -lcurses -lintl -lcrypt ## SCO SysVR3.2v2.0
+#LIBES= -lcurses -lintl -lsocket -lcrypt ## SCO+ODT1.1
+#LIBES= -lposix -ltermcap ## A/UX 2.0
+#LIBES= -lposix -ltermcap -lc_s ## A/UX 3.0
+#LIBES= -ldirent -lcurses ## att3b1 cc w/o shared lib & dirlib
+#LIBES= -shlib -ldirent -lcurses ## att3b1 gcc with shared lib & dirlib
+#LIBES= -ltermlib -lsocket -lnsl -lc /usr/ucblib/libucb.a ## SysV4 with BSDTIMES
+#LIBES= -lcurses -lnsl -lsocket -lc /usr/ucblib/libucb.a ## Stardent Vistra
+#LIBES= -ltermc ## emx under OS/2
+LIBES= ## Minix, VMS_POSIX
+#LIBES= -ltermcap -lcrypt ## Multiflow
+#LIBES= -ltermcap -lcrypt ## NetBSD
+#LIBES= -lcurses ## DDE Supermax
+
+################################################################
+## EXTRAFLAGS and EXTRALIBS
+################################################################
+# Compiling for HESIOD
+#HESDEF = -DHESIOD -I/usr/athena/include
+#HESLIB = -L/usr/athena/lib -lhesiod
+#
+# Compiling for AFS with kerberos authentication
+#AFSLIBDIR = /usr/afsws/lib
+#AFSDEF = -DAFS -I/usr/afsws/include
+#AFS33LIB = -laudit
+#
+#Solaris and HPUX require the BSD libraries with AFS.
+#We use -lc to use only what we require.
+#AFSAUXLIB = -lsocket -lnsl -lc -lucb # Solaris
+#AFSAUXLIB = -lc -lBSD # HPUX
+#
+#AFSLIB = -L$(AFSLIBDIR) -L$(AFSLIBDIR)/afs -lkauth -lprot -lubik\
+# -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err\
+# $(AFSLIBDIR)/afs/util.a $(AFS33LIB) $(AFSAUXLIB)
+#
+
+EXTRAFLAGS = $(HESDEF) $(AFSDEF)
+EXTRALIBS = $(HESLIB) $(AFSLIB)
+
+
+# The difficult choice of a c-compiler...
+# First, you should try your own c-compiler.
+# Gcc -traditional is also a safe choice.
+# If you think that you have good include files try gcc -Wall...
+# If you want to take out -traditional, make sure that your sys/ioctl.h
+# is fixed correctly, otherwise you'll be stopped for tty input, or you
+# will lose the editor and job control.
+
+# The -B tells gcc to use /bin/ld. This is to avoid using the gnu ld, which
+# on the suns does not know how to make dynamically linked binaries.
+#CC= gcc -Wall -pipe -B/bin/ # -ansi -pedantic
+#CC= gcc -m486 -pipe -Wall # Generate code for Intel 486 (linux)
+#CC= cc
+#CC= occ
+#CC= acc
+#CC= pcc
+#CC= hc -w
+CC= c89 # For VMS/POSIX
+#CC= /bin/cc # For suns, w/o gcc and SVR4
+#CC= /usr/lib/sun.compile/cc # FPS 500 (+FPX) with Sun C compiler
+#CC= /opt/SUNWspro/bin/cc # Solaris 2.1
+#CC= scc # Alliant fx2800
+#CC= lcc -wa
+ED= ed
+AS= as
+RM= rm
+CXREF= /usr/ucb/cxref
+VGRIND= csh /usr/ucb/vgrind
+CTAGS= /usr/ucb/ctags
+#XSTR= /usr/ucb/xstr
+SCCS= /usr/local/sccs
+PARALLEL=12 # Make the multi-max run fast.
+#P=& # Use Sequent's parallel make
+P=
+DESTDIR=/usr/local
+MANSECT=1
+DESTBIN=${DESTDIR}/bin
+DESTMAN=${DESTDIR}/man/man${MANSECT}
+# DESTMAN=${DESTDIR}/catman/man${MANSECT} # A/UX
+# DESTMAN=${DESTDIR}/usr/share/man/man${MANSECT} # Stardent Vistra (SysVR4)
+# DESTMAN=/usr/catman/1l # Amiga unix (SysVR4)
+FTPAREA=/usr/spool/ftp
+
+ASSRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
+ sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
+ sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
+ sh.set.c sh.time.c sh.char.h sh.dir.h sh.proc.h sh.h
+PSSRCS= sh.decls.h glob.c glob.h mi.termios.c mi.wait.h mi.varargs.h ma.setp.c \
+ vms.termcap.c
+SHSRCS= ${ASSRCS} ${PSSRCS}
+SHOBJS= sh.${SUF} sh.dir.${SUF} sh.dol.${SUF} sh.err.${SUF} sh.exec.${SUF} \
+ sh.char.${SUF} sh.exp.${SUF} sh.func.${SUF} sh.glob.${SUF} \
+ sh.hist.${SUF} sh.init.${SUF} sh.lex.${SUF} sh.misc.${SUF} \
+ sh.parse.${SUF} sh.print.${SUF} sh.proc.${SUF} sh.sem.${SUF} \
+ sh.set.${SUF} sh.time.${SUF} glob.${SUF} mi.termios.${SUF} \
+ ma.setp.${SUF} vms.termcap.${SUF}
+
+TWSRCS= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \
+ tw.comp.c tw.color.c
+TWOBJS= tw.help.${SUF} tw.init.${SUF} tw.parse.${SUF} tw.spell.${SUF} \
+ tw.comp.${SUF} tw.color.${SUF}
+
+EDSRCS= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \
+ ed.refresh.c ed.screen.c ed.xmap.c ed.term.c ed.term.h
+EDOBJS= ed.chared.${SUF} ed.refresh.${SUF} ed.screen.${SUF} ed.init.${SUF} \
+ ed.inputl.${SUF} ed.defns.${SUF} ed.xmap.${SUF} ed.term.${SUF}
+
+TCSRCS= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \
+ tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c \
+ tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \
+ tc.who.c tc.h
+TCOBJS= tc.alloc.${SUF} tc.bind.${SUF} tc.const.${SUF} tc.defs.${SUF} \
+ tc.disc.${SUF} tc.func.${SUF} tc.os.${SUF} tc.printf.${SUF} \
+ tc.prompt.${SUF} tc.sched.${SUF} tc.sig.${SUF} tc.str.${SUF} \
+ tc.vers.${SUF} tc.who.${SUF}
+
+PVSRCS= Makefile.std Makefile.vms Makefile.in Makefile.win32
+AVSRCS= Fixes MAKEDIFFS MAKESHAR NewThings README FAQ \
+ WishList config_f.h eight-bit.me glob.3 patchlevel.h \
+ pathnames.h tcsh.man Ported src.desc Imakefile imake.config \
+ README.imake complete.tcsh vmsreadme.txt termcap.vms snames.h \
+ host.defs gethost.c tcsh.man2html configure.in
+
+VHSRCS=${PVSRCS} ${AVSRCS}
+
+CONFSRCS=config/*
+
+ALLSRCS= ${SHSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${VHSRCS}
+DISTSRCS= ${PSSRCS} ${TWSRCS} ${EDSRCS} ${TCSRCS} ${AVSRCS}
+
+
+OBJS= ${SHOBJS} ${TWOBJS} ${EDOBJS} ${TCOBJS}
+
+
+all: ${BUILD}
+
+tcsh:$(P) ${OBJS}
+ rm -f tcsh core
+ ${CC} -o tcsh ${LDFLAGS} ${CFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+
+# Purify
+pure:$(P) ${OBJS}
+ rm -f tcsh core
+ purify `echo ${CC} | sed -e s,-B/bin/,,` -o tcsh ${LDFLAGS} ${CFLAGS} ${OBJS} ${LIBES} ${EXTRALIBS}
+# OS/2
+tcsh.exe: tcsh
+ emxbind tcsh
+
+gethost: gethost.c sh.err.h tc.const.h sh.h
+ rm -f gethost
+ ${CC} -o gethost ${LDFLAGS} ${CFLAGS} ${DFLAGS} gethost.c ${LIBES} ${EXTRALIBS}
+
+tc.defs.c: gethost host.defs
+ @rm -f $@
+ @echo "/* Do not edit this file, make creates it */" > $@
+ ./gethost host.defs >> $@
+
+tcsh.ps: tcsh.man
+ rm -f tcsh.ps
+ -ptroff -man tcsh.man > tcsh.ps
+
+
+#.c.${SUF}:
+# ${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $<
+
+# _VMS_POSIX #module addition
+.c.${SUF}:
+ @(echo '\#module '`echo $< | sed -e 's/\./_/g'`; cat $<) > $*..c
+ @echo ${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*.c
+ @${CC} ${CF} ${CFLAGS} ${DFLAGS} ${EXTRAFLAGS} $*..c
+ @mv $*..o $*.o
+ @rm -f $*..c
+
+
+# Don't do any special massaging of C files for sharing of strings!!
+# it causes weird segmentation faults on some systems.
+#.c.o:
+# ${CC} -E ${CFLAGS} $*.c | ${XSTR} -c -
+# ${CC} ${CF} ${CFLAGS} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#ed.init.o: ed.init.c
+# ${CC} -E ${CFLAGS} $*.c | ${XSTR} -c -
+# ${CC} -R ${CF} ${CF} x.c
+# mv -f x.o $*.o
+# rm -f x.c
+
+#strings.o: strings
+# ${XSTR}
+# ${CC} -c -R xs.c
+# mv -f xs.o strings.o
+# rm -f xs.c
+
+##.DEFAULT:
+## ${SCCS} get $<
+
+##.DEFAULT:
+## co $<
+
+ed.defns.h: ed.defns.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '\#ifndef _h_ed_defns' >> $@
+ @echo '\#define _h_ed_defns' >> $@
+ grep '[FV]_' ed.defns.c | grep '^\#define' >> $@
+ @echo '\#endif /* _h_ed_defns */' >> $@
+
+sh.err.h: sh.err.c
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '\#ifndef _h_sh_err' >> $@
+ @echo '\#define _h_sh_err' >> $@
+ grep 'ERR_' sh.err.c | grep '^#define' >> $@
+ @echo '\#endif /* _h_sh_err */' >> $@
+
+tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h
+ @rm -f $@
+ @echo '/* Do not edit this file, make creates it. */' > $@
+ @echo '\#ifndef _h_tc_const' >> $@
+ @echo '\#define _h_tc_const' >> $@
+ ${CC} -E $(INCLUDES) ${DFLAGS} -D_h_tc_const tc.const.c | \
+ grep 'Char STR' | \
+ sed -e 's/Char \([a-zA-Z0-9_]*\)\[\].*/extern Char \1[];/' | \
+ sort >> $@
+ @echo '\#endif /* _h_tc_const */' >> $@
+
+csh.prof: ${OBJS} sh.prof.${SUF} mcrt0.${SUF}
+ rm -f csh.prof
+ ld -X mcrt0.${SUF} ${OBJS} -o csh.prof ${LIBES} -lc
+
+sh.prof.${SUF}:
+ cp sh.c sh.prof.c
+ ${CC} ${CF} ${CFLAGS} -DPROF sh.prof.c
+
+lint: tc.const.h ed.defns.h
+ lint ${DFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+alint: tc.const.h ed.defns.h
+ alint ${DFLAGS} ${LFLAGS} sh*.c tw*.c ed*.c tc.*.c ${LIBES}
+
+print:
+ @pr READ_ME
+ @pr makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -h SIZES
+ @${CXREF} sh*.c | pr -h XREF
+ @ls -l | pr
+ @pr sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vprint:
+ @pr -l84 READ_ME TODO
+ @pr -l84 makefile makefile.*
+ @(size -l a.out; size *.${SUF}) | pr -l84 -h SIZES
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @ls -l | pr -l84
+ @${CXREF} sh*.c | pr -l84 -h XREF
+ @pr -l84 sh*.h [a-rt-z]*.h sh*.c alloc.c
+
+vgrind:
+ @cp /dev/null index
+ @for i in *.h; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @for i in *.c; do vgrind -t -h "C Shell" $$i >/crp/bill/csh/$$i.t; done
+ @vgrind -t -x -h Index index >/crp/bill/csh/index.t
+
+install: tcsh
+ -mv -f ${DESTBIN}/tcsh ${DESTBIN}/tcsh.old
+ cp tcsh ${DESTBIN}/tcsh
+ -strip ${DESTBIN}/tcsh
+ chmod 555 ${DESTBIN}/tcsh
+
+install.man: tcsh.man
+ -rm -f ${DESTMAN}/tcsh.${MANSECT}
+ cp tcsh.man ${DESTMAN}/tcsh.${MANSECT}
+ chmod 444 ${DESTMAN}/tcsh.${MANSECT}
+
+# Amiga Unix
+#install.man: tcsh.man
+# compress tcsh.man
+# cp tcsh.man.Z ${DESTMAN}/tcsh.Z
+# chmod 444 ${DESTMAN}/tcsh.Z
+
+# Apple A/UX
+#install.man: tcsh.man
+# -rm -f ${DESTMAN}/tcsh.${MANSECT}.Z
+# nroff -man tcsh.man | compress > ${DESTMAN}/tcsh.${MANSECT}.Z
+# chmod 444 ${DESTMAN}/tcsh.${MANSECT}.Z
+
+clean:
+ ${RM} -f a.out strings x.c xs.c tcsh tcsh.a _MAKE_LOG core gethost
+ ${RM} -f *.${SUF} sh.prof.c ed.defns.h tc.const.h sh.err.h tc.defs.c
+ ${RM} -f tcsh.*.m tcsh.*.cat
+
+veryclean: clean
+ ${RM} -f config.h
+ ${RM} -f *~ #*
+
+tags: /tmp
+ ${CTAGS} sh*.c
+
+tar.Z:
+ rm -f tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tar.gz:
+ rm -f tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | gzip > tcsh-${VERSION}.tar.gz
+ rm -rf tcsh-${VERSION}
+
+shar:
+ rm -f tcsh-*.shar
+ rm -rf tcsh-${VERSION}
+ mkdir tcsh-${VERSION} tcsh-${VERSION}/config
+ cp ${ALLSRCS} tcsh-${VERSION}
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ MAKESHAR -v -n tcsh-${VERSION} tcsh-${VERSION} \
+ tcsh-${VERSION}/?* tcsh-${VERSION}/config/?* \
+ tcsh-${VERSION}/?*/set?*
+ rm -rf tcsh-${VERSION}
+
+catalogs:
+ @(cd nls; make catalogs)
+
+tcsh-${VERSION}.tar.Z:
+ rm -rf tcsh-${VERSION}
+ rm -f tcsh-${VERSION}.tar tcsh-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh-${VERSION}
+ ./MAKEDIFFS bsd
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh-${VERSION}
+ cp ${DISTSRCS} tcsh-${VERSION}
+ mkdir tcsh-${VERSION}/config
+ cp ${CONFSRCS} tcsh-${VERSION}/config
+ cp Makefile tcsh-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh-${VERSION} | compress > tcsh-${VERSION}.tar.Z
+ rm -rf tcsh-${VERSION}
+
+tcsh.tahoe-${VERSION}.tar.Z:
+ rm -rf tcsh.tahoe-${VERSION}
+ rm -f tcsh.tahoe-${VERSION}.tar tcsh.tahoe-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.tahoe-${VERSION}
+ ./MAKEDIFFS tahoe
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.tahoe-${VERSION}
+ cp ${DISTSRCS} tcsh.tahoe-${VERSION}
+ mkdir tcsh.tahoe-${VERSION}/config
+ cp ${CONFSRCS} tcsh.tahoe-${VERSION}/config
+ cp Makefile tcsh.tahoe-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.tahoe-${VERSION} | compress > tcsh.tahoe-${VERSION}.tar.Z
+ rm -rf tcsh.tahoe-${VERSION}
+
+tcsh.reno-${VERSION}.tar.Z:
+ rm -rf tcsh.reno-${VERSION}
+ rm -f tcsh.reno-${VERSION}.tar tcsh.reno-${VERSION}.tar.Z DIFFS.[123]
+ mkdir tcsh.reno-${VERSION}
+ ./MAKEDIFFS reno
+ mv DIFFS.1 DIFFS.2 DIFFS.3 tcsh.reno-${VERSION}
+ cp ${DISTSRCS} tcsh.reno-${VERSION}
+ mkdir tcsh.reno-${VERSION}/config
+ cp ${CONFSRCS} tcsh.reno-${VERSION}/config
+ cp Makefile tcsh.reno-${VERSION}/Makefile.new
+ tar cf - nls/Makefile nls/?*/set?* | (cd tcsh-${VERSION}; tar xpf -)
+ tar cvf - tcsh.reno-${VERSION} | compress > tcsh.reno-${VERSION}.tar.Z
+ rm -rf tcsh.reno-${VERSION}
+
+ftp: tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z
+ cp tcsh-${VERSION}.tar.Z tcsh.tahoe-${VERSION}.tar.Z ${FTPAREA}
+ cp tcsh.man ${FTPAREA}
+
+#
+# Dependencies
+#
+config.h: config_f.h
+
+TCH=tc.h tc.const.h tc.decls.h tc.os.h tc.sig.h
+SHH=sh.h sh.types.h sh.char.h sh.err.h sh.dir.h sh.proc.h pathnames.h \
+ sh.decls.h ${TCH}
+TWH=tw.h tw.decls.h
+EDH=ed.h ed.decls.h
+
+# EDH
+EDINC=sh.${SUF} sh.func.${SUF} sh.lex.${SUF} sh.print.${SUF} sh.proc.${SUF} \
+ sh.set.${SUF} tc.bind.${SUF} tc.os.${SUF} tc.prompt.${SUF} \
+ tc.sched.${SUF} tw.parse.${SUF}
+${EDOBJS} ${EDINC} : ${EDH}
+
+# SHH
+${OBJS}: config.h ${SHH}
+
+# TWH
+TWINC=ed.chared.${SUF} ed.inputl.${SUF} sh.exec.${SUF} sh.func.${SUF} \
+ sh.set.${SUF} tc.func.${SUF}
+${TWOBJS} ${TWINC}: ${TWH}
+
+# glob.h
+glob.${SUF} sh.glob.${SUF}: glob.h
+
+# ed.defns.h
+EDDINC=tc.bind.${SUF} tc.func.${SUF} tc.os.${SUF}
+${EDOBJS} ${EDDINC}: ed.defns.h
+
+# tc.defs.o
+tc.defs.${SUF}: tc.defs.c sh.h
diff --git a/contrib/tcsh/NewThings b/contrib/tcsh/NewThings
new file mode 100644
index 0000000..a372fbb
--- /dev/null
+++ b/contrib/tcsh/NewThings
@@ -0,0 +1,169 @@
+This file contains visible (incompatible) changes to the users.
+This version of tcsh has the following new things:
+
+6.08
+* %$variables are now expanded in the prompt.
+* print_by_columns prints in a single column if the output is not a tty.
+* REMOTEHOST contains only the IP address, not the host name of the machine.
+* names in .cshdirs are quoted.
+* exit value from 0..255 not -128..127 as posix mandates.
+
+6.07
+* Implicit cd when the variable implicitcd is set or set to verbose
+
+6.06
+* NLS Message Catalog support.
+
+6.05
+* The bind, aliases, linedit builtins are not used anymore; they are
+ #ifdef'ed OBSOLETE and will be really removed in the next version
+* new filetest builtin
+* new hup builtin
+* =x obeys nonomatch
+* tcsh.man2html nroff to HTML converter for the tcsh manpage
+* prompt is now %# by default.
+* $REMOTEHOST contains the name of the remote host (optional)
+* $HOSTTYPE is going away. New variables $OSTYPE, $MACHTYPE, $VENDOR similar
+ to the gnu ones.
+* $< can be interrupted and takes modifiers. Does not quote args by default
+ like csh.
+
+6.04
+* Variable modifiers do not stop processing after the first one fails
+ > set i=aabbcc
+ > echo $i:s/a/A/:s/b/B/
+ AaBbcc
+ > echo $i:s/x/A/:s/b/B/
+ aabbcc
+* set -r makes variables readonly
+* set nonomatch, echo ~notaser returns ~notauser instead of an error
+* file operators: Changed -s == !-z and -S == socket
+* $?0 returns false now on interactive shells for csh compatibility.
+* %p%P include seconds in prompt strings.
+
+6.03
+* $%var contains the number of characters in $var.
+* Shell -w -x are now POSIX compliant on POSIX machines.
+* Imported environment variables are not globbed.
+* $dirstack can be used to set and examine the directory stack.
+* $? == $status and $# == $#argv like in the bourne shell.
+* expand variables expands arrays too (but not array elements yet).
+* $0 contains argv[0] on interactive shells.
+* new -b -c etc file operators from SGI csh.
+* nostat takes a list of shell patterns.
+* symbolic names for arrow key bindings [left, right, up, down]
+* shift, left operators update variables correctly.
+* builtins builtin.
+* history and dirs accept now -LSc flags.
+* $history accepts an optional second argument, that can change the
+ history builtin output similar to the $time format.
+* History timestamps preserved in .history. The history file contains
+ now the timestamps as csh comments.
+
+
+6.02
+* ignore_symlinks and chase_symlinks are replaced with symlinks=ignore
+ and symlinks=chase; symlinks=expand addition
+* complete and uncomplete builtins; user-programmable completion additions.
+* Tcsh now uses the rightmost column of the terminal, allowing cut-and-paste
+ operations in terminal emulators that work [xterm R5 not R4]
+* echo_style controls now the behaviour of the builtin echo; the default
+ should match the builtin echo of /bin/csh; if your system does not
+ come with csh, then the default echo should match /bin/echo.
+* cd -; changes to the previous directory.
+* setting dunique variable pushes only unique directories on the directory
+ stack.
+* source builtin allows additional arguments that get passed in $argv in
+ the sourced script.
+* tcsh now mirrors correctly all exported csh variables [term=TERM,path=PATH
+ etc.]
+* showdots=-A makes listing behave like ls -A.
+* directory stack access =<num> allows for entries > 9.
+* $a:u uppercase the first character in $a, $a:l downcases the first
+ character in $a.
+* Shorthand for file tests in 'if' expressions ( -dx file ) is the
+ same as ( -d file && -x file )
+
+6.01
+* Nothing new.
+
+6.00 PL3
+* %d in the prompt is the week-day and no longer $cwd; use %/ instead.
+* changes in the prompt format. Date changes to accomodate people from
+ down under.
+* vi insert mode to command mode transition does not move the cursor.
+
+6.00 PL2
+* setty builtin
+ This is used to specify what tcsh modes can be altered using stty,
+ Modes that should be set are specified as +<mode>, modes that should
+ be cleared are specified as -<mode>, and the ones that should be
+ untouched are specified as <mode>. setty with no arguments prints
+ the modes that are affected by tcsh, and setty -a prints all modes.
+* multiple : modifiers in variables and ! escapes. Things like:
+ > set prompt="$host:r:$cwd>"
+ don't work any more, they should be replaced with
+ > set prompt="${host:r}:$cwd>"
+ or
+ > set prompt="$host:r"":$cwd>"
+ the reason is that now you can
+ > set foo=/usr/local/a.b.c
+ > echo $foo:t:r:e
+ b
+ If for some reason you don't like this change you can disable it with
+ -DCOMPAT. -DCOMPAT may go away in future tcsh versions and the way tcsh
+ works now is the way the 4.4BSD csh works.
+
+6.00 PL1
+* There is no more config.iris4d, use config.sgi instead
+
+6.00
+* History searching searches using shell patterns too.
+* The autolist values that controlled beeping are not supported any more;
+ used matchbeep instead.
+* /etc/Login and /etc/Logout were renamed to /etc/csh.login /etc/csh.logout
+ and /etc/csh.cshrc was added
+* prompt2 and prompt3 can have prompt escapes.
+* eval pipes work
+* ignore_symlinks works
+
+5.20 PL2
+* %{..%} escapes in prompt
+
+5.20 PL0
+* bindkey -r
+* history -t
+* shell variables in paths expand correctly.
+* variable expansion
+* quoted expansions now work.
+* new version and tcsh variable format
+
+5.19 PL2
+* NLS support
+* New bindkey and echotc builtins
+* Underline and Bold in the prompt; additions and changes to the prompt and
+ who syntax (%u is now %n, so that %u can be used to turn undeline off,
+ and %n is now \n).
+* rmstar needs to be set to protect from accidental removal
+* Fixed editor, and spell line.
+* Glob-expand, on arguments.
+* Added process migration builtins for aix370
+
+5.19 PL1
+* Maintainance release for mainly the rs6000
+
+5.19 PL0
+* 8 bit clean code, by using 16 bit strings.
+* Mostly shared strings (a side-effect)
+* Highlights everywhere (and in ls-F) filenames that contain characters
+ with the eighth bit set (or passes them unchanged depending on the
+ variable 'nometa')
+* Newline in the prompt via %n.
+* dirs takes also a -v flag for `vertical display'
+* There is a new variable `listjobs' which controls if and how jobs
+ are displayed when a new job is suspended. [Idea from the mtXinu
+ code, very useful for novice users who hit control-Z 10 times on
+ the same job!]
+ set listjobs=long, jobs -l is executed every time a job is suspended.
+ set listjobs=short, jobs is executed every time a job is suspended.
+* Passes lint... At least on a sun.
diff --git a/contrib/tcsh/Ported b/contrib/tcsh/Ported
new file mode 100644
index 0000000..769f407
--- /dev/null
+++ b/contrib/tcsh/Ported
@@ -0,0 +1,1016 @@
+
+Hello,
+
+This file contains a list of machines used, libraries compiler etc. If you
+find it out-of-date, or you have additions or changes, please let me know.
+
+christos
+
+
+VENDOR : sun
+MODELS : sun3, sun4, sun386i
+COMPILER: cc, gcc, acc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : sunos 3.5, 4.0, 4.1, 4.1.1, 4.1.2, 4.1.3, 4.1.4
+CONFIG : sunos*
+ENVIRON : n/a
+NOTES : Don't compile with /usr/5bin/cc
+VERSION : 6.08
+
+VENDOR : sun
+MODELS : sun4, ultra
+COMPILER: cc, gcc
+CFLAGS : normal
+LIBES : -lcurses -lsocket -lnsl
+OS : solaris 2.1, 2.2, 2.3, 2.4, 2.5, 2.5.1
+CONFIG : sol*
+ENVIRON : n/a
+NOTES : The sunpro compiler cannot compile tcsh with -O, it crashes
+ : on some files. In any case do not use -O with any of the
+ : tcsh files, because the optimized code assumes that the
+ : floating point is already initialized and does not do the
+ : necessary initializations. This results in weird floating
+ : point failures of programs exec'ed from tcsh.
+VERSION : 6.08
+
+VENDOR : sun
+MODELS : ultra
+COMPILER: WorkShop cc
+CFLAGS : normal
+LIBES : -lcurses -lsocket -lnsl
+OS : solaris 2.6
+CONFIG : sol26
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.08
+
+VENDOR : sun
+MODELS : i386
+COMPILER: cc, gcc
+CFLAGS : -D__STDC__=0
+LIBES : -lcurses -lsocket -lnsl
+OS : solaris 2.1
+CONFIG : sol2
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.04.13
+
+VENDOR : sun
+MODELS : sun4
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : linux 2.0.x, 2.1.x
+CONFIG : linux
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.07.03
+
+VENDOR : hp
+MODELS : apollo
+COMPILER: cc
+CFLAGS : -U__STDC__ -I. -O
+LIBES : -ltermcap
+OS : domain 10.4.3
+CONFIG : bsd
+ENVIRON : bsd4.3
+NOTES : Don't use gcc; breaks tc.os.c
+VERSION : 6.01.00
+
+VENDOR : hp
+MODELS : hp9000s300, hp9000s700, hp9000s800
+COMPILER: cc, gcc
+CFLAGS : normal (-Aa -O3 hpux 8.0, 8.07, 9.05)
+LIBES : -ltermcap
+OS : hpux 6.5, 7.0.x, 8.0, 9.05
+CONFIG : hpux{7,8}
+ENVIRON : n/a
+NOTES : Don't use -lBSD; breaks getpgrp(). Config.hp-3.2 obsolete?
+ : Some versions of the compiler are broken with -O3. Try 'ls *'
+ : If it does not work, lower the optimization level...
+VERSION : 6.05.06
+
+VENDOR : hp
+MODELS : hp9000s700
+COMPILER: cc, c89, gcc
+CFLAGS : +O3 -Aa (cc), +O3 (c89), normal (gcc)
+LIBES : -ltermcap
+OS : hpux 10.00, 10.01
+CONFIG : hpux8
+ENVIRON : n/a
+NOTES : Carl-Olof Almbladh (coa@teorfys.lu.se)
+ : To make a statically linked version: in config_f.h, #undef NLS
+ : and use these LDFLAGS in the Makefile: LDFLAGS= -Wl,-a,archive
+ : [orban@kato.den.csci.csc.com (Tom Orban)
+VERSION : 6.08
+
+VENDOR : hp
+MODELS : SPP-1200 SPP-1600 S-2X00 X-2X00
+COMPILER: cc
+CFLAGS : -Ae
+LIBES : -ltermcap
+OS : SPP-UX 5.X
+CONFIG : hpux8
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.07.02
+
+VENDOR : hp
+MODELS : hp9000s500
+COMPILER: cc
+CFLAGS : -I. -O
+LIBES : -ltermcap
+OS : hpux 5.2
+CONFIG : hp-5.2
+ENVIRON : n/a
+NOTES : very slow in executing commands (I think the reason is
+NOTES : a very slow fork)
+VERSION : 6.00.01
+
+VENDOR : digital
+MODELS : vax
+COMPILER: cc, gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : bsd4.3, bsd4.4
+CONFIG : bsd*
+ENVIRON : n/a
+NOTES : cc broken: typedef void sigret_t; typedef void pret_t;
+VERSION : 6.00.03
+
+VENDOR : digital
+MODELS : vax
+COMPILER: cc, gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : mtXinu 4.3
+CONFIG : mtxinu
+ENVIRON : n/a
+NOTES : cc broken: typedef void sigret_t; typedef void pret_t;
+VERSION : 6.03.09
+
+VENDOR : digital
+MODELS : vax, DECstation
+COMPILER: cc, gcc
+CFLAGS : -O -Olimit 2000 (cc), normal (gcc)
+LIBES : -ltermcap
+OS : ultrix 3.0 (vax), 4.0, 4.1, 4.2, 4.3, 4.4
+CONFIG : ultrix
+ENVIRON : n/a
+NOTES : pcc broken: typedef void sigret_t (vax);
+NOTES : mips compiler on ultrix 3.5 needs -Dvoid=int
+NOTES : vax compiler on ultrix 3.0 needs -Dvoid=int
+NOTES : Does Ultrix 4.x still need YPBUGS?
+NOTES : Ultrix4.2 may need NAMEI_BUG
+VERSION : 6.07.11
+
+VENDOR : apple
+MODELS : macII
+COMPILER: cc
+CFLAGS : normal (-ZP)
+LIBES : -ltermcap (-lposix -ltermcap)
+OS : aux 2.0
+CONFIG : mac2 (-DPOSIX -DPOSIXJOBS)
+ENVIRON : n/a
+NOTES : Tcsh can compile both in non POSIX and POSIX mode. The
+NOTES : default configuration is non POSIX. The flags in parentheses
+NOTES : are the changes that are needed to compile in POSIX mode
+VERSION : 6.00.01
+
+VENDOR : ibm
+MODELS : ps/2, rs6000, ibm370, ibmESA
+COMPILER: cc
+CFLAGS : normal
+LIBES : -lcurses -lbsd [No -lbsd for 4.1]
+OS : aix 3.1,3.2,4.1 (rs6000) aix 1.1 (ps/2) aix G9.9 (ibm370)
+ : aix (ibmESA)
+CONFIG : aix
+ENVIRON : n/a
+NOTES : aix G9.9 sfname() frees bad pointers. Use TCF with care!
+NOTES : aix 3.2 may need NAMEI_BUG
+NOTES : aix 3.2 may need _BSD_INCLUDES defined in h
+NOTES : aix 4.1 does not need -lbsd anymore.
+VERSION : 6.06.00 (rs6000)
+
+VENDOR : ibm
+MODELS : rt
+COMPILER: hc, gcc
+CFLAGS : -I. -U__STDC__
+LIBES : -ltermcap
+OS : aos 4.3
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Old versions of the compiler break with -O. No ansi include
+NOTES : files so we have to undef __STDC__
+VERSION : 6.05.06
+
+VENDOR : ibm
+MODELS : rt
+COMPILER: pcc
+CFLAGS : -I. -U__STDC__ -DPCC
+LIBES : -ltermcap
+OS : aos 4.3
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Old versions of the compiler break with -O. No ansi include
+NOTES : files so we have to undef __STDC__
+NOTES : pcc broken: typedef void sigret_t; typedef void pret_t;
+VERSION : 6.05.06
+
+VENDOR : ibm
+MODELS : rt
+COMPILER: cc
+CFLAGS : -I. -Nd4000 -Nn3000
+LIBES : -lcurses
+OS : aix 2.2.1
+CONFIG : aix
+ENVIRON : n/a
+NOTES : Stacksize limit is 1K off?
+VERSION : 6.00.03
+
+VENDOR : sequent
+MODELS : balance, symmetry
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap -lseq
+OS : Dynix 3.1, 3.2, ptx 1.2
+CONFIG : sequent
+ENVIRON : universe on Dynix 3.1, 3.2: ucb
+NOTES : none
+VERSION : 6.04.00
+
+VENDOR : sequent
+MODELS : symmetry
+COMPILER: gcc 2.6.2
+CFLAGS : -m486
+LIBES : -ltermcap -lseq -lsocket -linet -lnsl
+OS : DYNIX/ptx 2.1.0, 4.1.3
+CONFIG : sequent
+ENVIRON :
+NOTES : Didn't work for me with Sequent's /bin/cc
+NOTES : 4.1.3 does not need libinet anymore.
+VERSION : 6.05.00
+
+VENDOR : encore
+MODELS : multimax
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : umax 4.2
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.00.00
+
+VENDOR : sony
+MODELS : news 1850, 1750
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : bsd 4.3, news-os 3.3,4.1C
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.05.06
+
+VENDOR : ibm + compatibles
+MODELS : i386,i286
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap -ldir -lx
+OS : xenix
+CONFIG : xenix
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.00.01
+
+VENDOR : hp
+MODELS : hp300
+COMPILER: cc, gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : MORE/bsd 4.3+
+CONFIG : mtxinu
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.05.06
+
+VENDOR : hp, motorola
+MODELS : hp300, m68k
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap -lcrypt
+OS : NetBSD 1.0A
+CONFIG : bsd4.4
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.05.06
+
+VENDOR : digital
+MODELS : vax
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : bsd 4.3reno
+CONFIG : bsdreno
+NOTES : ttyname() is buggy. calls closedir() twice. See README
+ENVIRON : n/a
+VERSION : 6.00.04
+
+VENDOR : Cray Research
+MODELS : Y-MP
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Unicos 6.0
+CONFIG : cray
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.00.01
+
+VENDOR : Cray Research
+MODELS : C90
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Unicos 9.0.2.1
+CONFIG : cray
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.08
+
+VENDOR : pyramid
+MODELS : MIS4/2T
+COMPILER: cc
+CFLAGS : -OG
+LIBES : -ltermcap
+OS : OSx5.1,6.4
+CONFIG : pyr
+ENVIRON : n/a
+NOTES : If there are problems with the global optimizer, use -OP
+NOTES : If you only have the AT&T universe, use the pyratt config
+NOTES : file and define -D_PID_T -Dpyr.
+VERSION : 6.06.00
+
+VENDOR : next
+MODELS : any
+COMPILER: gcc or cc -arch m68k -arch i386
+CFLAGS : -O2 -g
+LIBES : -ltermcap # [-lcs 2.0]
+OS : next os 2.x, 3.x
+CONFIG : mach
+ENVIRON : n/a
+NOTES : NeXTSTeP 3.3 on intel defines speed_t so compile with -D_SPEED_T
+NOTES : NeXT's cc -E adds spaces before and after array brackets!
+NOTES : You'll need to change the sed expression in the Makefile to
+NOTES : something like:
+NOTES : 's/Char \([a-zA-Z0-9_]*\) *\[ *\].*/extern Char \1[];/'
+VERSION : 6.04.00
+
+VENDOR : Apple
+MODELS : any
+COMPILER: cc
+CFLAGS : -O3 -pipe -g -arch ppc -arch i386 -UNeXT
+OS : Rhapsody 5
+CONFIG : rhapsody
+ENVIRON : n/a
+NOTES : CFLAGS="-O3 -pipe -g -arch ppc -arch i386 -UNeXT" configure && make
+VERSION : 6.08.00
+
+VENDOR : Heurikon
+MODELS : HK68
+COMPILER: gcc (Green Hills C-68000)
+CFLAGS : -ga -X138 -X25 -I.
+LDFLAGS : -n
+LIBES : -lcurses -ltermcap -ldirent
+OS : UniPlus+ 5.0
+CONFIG : hk68
+ENVIRON : n/a
+NOTES : Need Doug Gwyn's POSIX directory library (libdirent.a)
+VERSION : 6.00.01
+
+VENDOR : Amdahl
+MODELS : n/a
+COMPILER: cc/gcc
+CFLAGS : normal
+LIBES : -lcurses -lsocket -lbsd
+CONFIG : amdahl
+ENVIRON : n/a
+VERSION : 6.00.01
+
+VENDOR : prime
+MODELS : exl 300 series
+COMPILER: cc
+CFLAGS : -O -s -I.
+LIBES : -lcurses -lstcp
+OS : system v.3.1.2
+CONFIG : sysv
+ENVIRON : sysv
+NOTES : Is libstcp.a on all exl 300s?
+VERSION : 6.00.01
+
+VENDOR : convex
+MODELS : c220
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : 9.0.6 (bsd 4.3)
+CONFIG : convex
+ENVIRON : n/a
+NOTES : Dont use the -pcc flag.
+ : Use setty to fix the default tty settings.
+VERSION : 6.00.01
+
+VENDOR : Norsk Data
+MODELS : nd5000
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Ndix Version C
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : The -O option makes the compiler run for ages!
+VERSION : 6.00.03
+
+VENDOR : SGI
+MODELS : 4D, 3000
+COMPILER: cc
+CFLAGS : -D__STDC__
+LIBES : -lcurses -lsun -lbsd -lc_s
+OS : IRIX (3.?) 3.2 3.3 4.0
+CONFIG : sgi
+ENVIRON : n/a
+NOTES : AUTOLOGOUT is probably best undef'ed
+NOTES : For 4.0, the NLS define in h can be enabled.
+NOTES : 4.0.5a cc does not have -O3 anymore.
+NOTES : If you don't like -lbsd, you can define POSIXJOBS in
+NOTES : config.h and omit it.
+VERSION : 6.06.00
+
+VENDOR : SGI
+MODELS : R8000 PowerIndigo2
+COMPILER: cc -n32
+CFLAGS : -D__STDC__
+LIBES : -lcurses -lsun -lbsd -lc_s
+OS : IRIX 6.2
+CONFIG : sgi
+ENVIRON : n/a
+NOTES : CCOPTIONS=-OPT:fold_arith_limit=4000
+NOTES : SHLIBDIR=/usr/lib32
+NOTES : LDPOSTLIB = -nostdlib -L$(ROOT)$(SHLIBDIR)/mips3 \
+NOTES : -L$(ROOT)$(SHLIBDIR)
+NOTES : In config.h #undef NLS and #undef NLS_CATALOGS
+VERSION : 6.06.00
+
+VENDOR : SGI
+MODELS : Onyx R10000
+COMPILER: gcc-2.7.2.1 configured for mips-sgi-irix5.3
+CFLAGS : none
+LIBES : -ltermcap -lbsd
+OS : IRIX 6.2
+CONFIG : sgi
+ENVIRON : n/a
+VERSION : 6.07.02
+
+VENDOR : ibm + compatibles
+MODELS : i386,i486
+COMPILER: /bin/cc
+CFLAGS : normal
+LIBES : -ltermlib -lsocket -lnsl (without BSDTIMES)
+LIBES : -ltermlib -lsocket -lnsl -lc /usr/ucblib/libucb.a (BSDTIMES)
+OS : SVR4 (DELL, ESIX, ISC, UHC)
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.05.06
+
+VENDOR : ibm + compatibles
+MODELS : i386,i486
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : linux 0.8x, 0.9x, 1.x
+CONFIG : linux
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.05.06
+
+VENDOR : ibm + compatibles
+MODELS : i386,i486
+COMPILER: gcc
+CFLAGS : normal
+LIBES : -lcurses -lc_s [for crypt]
+OS : SVR3.2.2 [SCO]
+CONFIG : sco32v2
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.03.00
+
+VENDOR : stardent
+MODELS : gs2600
+COMPILER: /bin/cc
+CFLAGS : -O
+LIBES : -lcurses
+OS : stellix
+CONFIG : stellar
+ENVIRON : n/a
+NOTES : works but not worth compiling with -O4...
+NOTES : setpgrp() and SIGCHLD work the BSD way, not the way documented.
+NOTES : we need to define BACKPIPE
+VERSION : 6.00.04
+
+VENDOR : stardent
+MODELS : titan 3000 series
+COMPILER: /bin/cc
+CFLAGS : -O -43
+LIBES : -ltermcap
+OS : OS 3.0.3
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Kernel bug with SIGTTIN, Try vi, ^Z, bg, fg....
+VERSION : 6.01.01
+
+VENDOR : stardent
+MODELS : titan 1500 series
+COMPILER: cc
+CFLAGS : -O -43
+LIBES : -ltermcap
+OS : OS 2.5
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Kernel bug with SIGTTIN, Try vi, ^Z, bg, fg....
+NOTES : You can add -w to the CFLAGS to suppress the warnings.
+VERSION : 6.02.07
+
+VENDOR : SGI
+MODELS : INDIGO
+COMPILER: cc
+CFLAGS : -D__STDC__
+LIBES : -lcurses -lsun -lbsd -lc_s
+OS : IRIX (3.?) 3.2 3.3 4.0
+CONFIG : sgi
+ENVIRON : n/a
+NOTES : AUTOLOGOUT is probably best undef'ed
+NOTES : For 4.0, the NLS define in h can be enabled.
+VERSION : 6.01
+
+VENDOR : SGI
+MODELS : INDY
+COMPILER: cc
+CFLAGS :
+LIBES : -lcurses -lbsd
+OS : IRIX 5.1
+CONFIG : sgi
+ENVIRON : n/a
+NOTES : it will build without -lbsd but then job control
+NOTES : won't actually work.
+VERSION : 6.04.00
+
+VENDOR : alliant
+MODELS : FX/2800 series
+COMPILER: scc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Alliant Concentrix 2800 2.2.00
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : For a newer version of the operating system try defining
+ : NEW_OS in alliant [or better find a way to tell
+ : them apart.
+VERSION : 6.03.00
+
+VENDOR : stardent
+MODELS : Vistra 800
+COMPILER: /bin/cc
+CFLAGS : -O
+LIBES : -lcurses -lnsl -lsocket -lc /usr/ucblib/libucb.a
+OS : SYSVR4
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : Works like a charm
+VERSION : 6.01
+
+VENDOR : Evans & Sutherland
+MODELS : ESV
+COMPILER: cc
+CFLAGS : mips systems
+LIBES : -ltermcap
+OS : ES/os 2.2 (UMIPS mips ATT_V3_0)
+CONFIG : mips
+ENVIRON : bsd4.3
+NOTES : would it be preferable to have HOSTTYPE of
+NOTES : "esv" instead of "mips"?
+VERSION : 6.01.00
+
+VENDOR : masscomp
+MODELS : Masscomp 6000
+COMPILER: cc
+CFLAGS : production
+LIBES : -ltermcap
+OS : RTU 5.0
+CONFIG : masscomp
+ENVIRON : Link in the "bsd" universe as opposed to "att".
+NOTES : For pre RTU 6.0, remember to remove the #define RTU6 in the
+NOTES : masscomp file.
+NOTES : As of tcsh v6.02.07, try putting "bindkey ^t stuff-char"
+NOTES : in your /etc/csh.cshrc for masscomp kernel (ctrl-t) status.
+VERSION : 6.02.07
+
+VENDOR : masscomp
+MODELS : Masscomp 5400
+COMPILER: cc
+CFLAGS : normal
+LIBES : -ltermcap -lndir -lsocket -ljobs
+OS : RTU 6.0
+CONFIG : masscomp
+ENVIRON : Link in the "bsd" universe as opposed to "att".
+NOTES : n/a
+VERSION : 6.01.00
+
+VENDOR : Cray Computer
+MODELS : CRAY-2 & CRAY-3
+COMPILER: cc
+CFLAGS : normal
+LIBES : -lcurses -lnet
+OS : CSOS 1.0
+CONFIG : csos
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.02
+
+VENDOR : Motorola
+MODELS : Delta 3000/Delta 4000
+COMPILER: cc
+CFLAGS : normal
+LIBES : -lcurses
+OS : System V/68 R3V6.2, R3V7
+CONFIG : sysV68
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.01.00, 6.02.00
+
+VENDOR : Motorola
+MODELS : MPC 3062
+COMPILER: cc
+CFLAGS : Broken optimizers...
+LIBES : -lcurses -lsec
+OS : System V/88 R32V2
+CONFIG : sysV88
+ENVIRON : n/a
+NOTES : If you're using the bundled Greenhills compiler, don't use -O.
+NOTES : One error -O causes is failure to exec scripts with /bin/sh
+NOTES : if they don't have a #! header on top.
+VERSION : 6.02.07
+
+VENDOR : alliant
+MODELS : FX/8X series
+COMPILER: pcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Concentrix 6.0.00 beta
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Needs to define DIRENT in h
+VERSION : 6.02.00
+
+VENDOR : alliant
+MODELS : FX/8X series
+COMPILER: pcc
+CFLAGS : normal
+LIBES : -ltermcap
+OS : Concentrix 5.7.00
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.00.01
+
+VENDOR : gould (encore)
+MODELS : NP1
+COMPILER: cc
+CFLAGS : production
+LIBES : -ltermcap
+OS : UTX/32 3.1A
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : gould (encore)
+MODELS : 9050
+COMPILER: cc
+CFLAGS : production
+LIBES : -ltermcap
+OS : UTX/32 2.1A
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : ibm & compatible
+MODELS : i386
+COMPILER: cc
+CFLAGS : production
+LIBES : -lcurses -lcposix
+OS : 3.2
+CONFIG : isc
+ENVIRON : ISC386
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : att
+MODELS : 3b2-600GR (RISC)
+COMPILER: cc
+CFLAGS : production
+LIBES : -lcurses
+OS : SystemV R4.0
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : att
+MODELS : 3b2-600G
+COMPILER: cc
+CFLAGS : production
+LIBES : -lcurses
+OS : SystemV R3.2.3
+CONFIG : sysv3
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : tektronix
+MODELS : XD88/10
+COMPILER: cc
+CFLAGS : Broken optimizers...
+LIBES : -ltermcap -lsec
+OS : UTekV 3.2e
+CONFIG : tekXD88
+ENVIRON : n/a
+NOTES : If you're using the bundled Greenhills compiler, don't use -O.
+NOTES : One error -O causes is failure to exec scripts with /bin/sh
+NOTES : if they don't have a #! header on top.
+VERSION : 6.02.07
+
+VENDOR : tektronix
+MODELS : 4300
+COMPILER: cc
+CFLAGS : production
+LIBES : -ltermcap
+OS : UTek 4.0 (BSD 4.2)
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : set DFLAGS = -DUTek -DBSD in the Makefile
+VERSION : 6.02.07
+
+VENDOR : BBN
+MODELS : butterfly gp1000
+COMPILER: cc
+CFLAGS : production
+LIBES : -ltermcap
+OS : Mach 1000 version 2.5
+CONFIG : mach
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.02.07
+
+VENDOR : sony
+MODELS : news 3700
+COMPILER: cc
+CFLAGS : -O -Wf,-XNp15000,-XNd15000,-XNh15000
+LIBES : -lcurses -lc /usr/ucblib/libucb.a
+OS : sysvr4, news-os 5.02
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : Use /usr/bin/cc, not /usr/ucb/cc.
+VERSION : 6.00.03
+
+VENDOR : ibm & compatible
+MODELS : i386, i486
+COMPILER: cc
+CFLAGS : production
+LIBES : -lterm
+OS : Coherent 4.0
+CONFIG : coh3
+ENVIRON : gnu tools (see below)
+NOTES : The standard make, /bin/sh and sed that come with Coherent are
+NOTES : not quite up to the makefile. Either use gnu make or change
+NOTES : occurances of '# to '\# since Coherent's make takes all '#'s to
+NOTES : be a comment, even when quoted, except when escaped by '\'.
+NOTES : Coherent's /bin/sh does not allow you to set VERSION, etc.
+NOTES : since they are hard-wired internal variables. Either use
+NOTES : /usr/bin/ksh, another sh or change the name of the offending
+NOTES : variables. Coherent's sed, unfortunately, is broken beyond a
+NOTES : workaround. Either get gnu sed or run that portion of the
+NOTES : makefile on a machine with a full sed and import the output.
+VERSION : 6.02.08
+
+VENDOR : Control Data Systems
+MODELS : CD4680
+COMPILER: cc, cc2.20 (mips)
+CFLAGS : mips systems, DFLAGS=-DCDC
+LIBES : -ltermcap
+OS : EP/IX 1.4.3 (RiscOS based)
+CONFIG : mips
+ENVIRON : bsd4.3 (if sysv, need "set path=(/usr/bsd43/bin $path)" )
+NOTES : n/a
+VERSION : 6.02.00
+
+VENDOR : alliant
+MODELS : FX/8X series
+COMPILER: pcc
+CFLAGS : normal
+LIBES : -ltermcap -lresolv
+OS : Concentrix 6.0.00 beta
+CONFIG : alliant (see NOTES)
+ENVIRON : n/a
+NOTES : Needs to define DIRENT and BSDLIMIT in h. The
+NOTES : beta release of the Concentrix 6.0.00 has some errors
+NOTES : in the system header files, namely, /usr/include/sys/dir.h.
+VERSION : 6.03.00
+
+VENDOR : hp
+MODELS : hp9000s700
+COMPILER: cc
+CFLAGS : No -O here!!! Breaks quoting! Try echo 'foo | bar'...
+LIBES : -ltermcap
+OS : HP OSF/1 1.0
+CONFIG : hposf1
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.03.00
+
+VENDOR : digital
+MODELS : DEC 3000/400 (alpha)
+COMPILER: cc
+CFLAGS : -call_shared -I. -I.. -O -Olimit 2000 -std1
+LIBES : -lcurses
+OS : OSF1 1.2
+CONFIG : decosf1
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.03
+
+VENDOR : digital
+MODELS : DEC 3000/400 (alpha)
+COMPILER: cc
+CFLAGS : -O2 -I. -I.. -Olimit 2000
+LIBES : -lcurses
+OS : OSF1 (Digital Unix) 1.3, 2.0, 3.0, 3.2, 4.0
+CONFIG : decosf1
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.07.11
+
+VENDOR : Intel
+MODELS : Paragon
+COMPILER: icc
+CFLAGS : -O2
+LIBES : -ltermcap
+OS : Paragon OSF/1 Release 1.0.1 Server 1.0 R1.0
+CONFIG : parosf1
+ENVIRON : n/a
+NOTES : I have gotten two different config files that both seem to
+ : work!
+VERSION : 6.03.00
+
+VENDOR : Data General
+MODELS : AViiON mc88000
+COMPILER: cc
+CFLAGS : -O2
+LIBES : -lcurses
+OS : DGUX 5.4R2.01
+CONFIG : dgux5.4
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.04.00
+
+VENDOR : Data General
+MODELS : Aviion
+COMPILER: gcc 2.5.8
+CFLAGS : -g -O2 -msvr4
+LIBES : -ltermcap
+OS : DGUX 5.4.1
+CONFIG : dgux5.4
+ENVIRON : sde m88kdguxelf
+VERSION : 6.05.00
+
+VENDOR : Harris
+MODELS : Tahoe
+COMPILER: cc, gcc 1.42
+CFLAGS : -O
+LIBES : -ltermcap
+OS : CX/UX 5.1 CX/UX 7.1
+CONFIG : hcx
+ENVIRON : universe bsd
+NOTES : n/a
+VERSION : 6.06.01
+
+VENDOR : Multiflow
+MODELS : multiflow
+COMPILER: cc
+CFLAGS : -O5 -sb_trace 0 -DMULTIFLOW
+LIBES : -ltermcap -lcrypt
+OS : 4.3 BSD TRACE/UNIX
+CONFIG : bsd
+ENVIRON : n/a
+NOTES : Lower the optimization or you'll get a 5M binary!
+NOTES : cc broken: typedef void sigret_t; typedef void pret_t;
+VERSION : 6.04.00
+
+VENDOR : Unixware
+MODELS : all
+COMPILER: cc
+CFLAGS : normal
+LIBES : -lcrypt -ltermlib -lsocket -lnsl -lgen
+OS : Unixware 2.03 (4.2MP)
+CONFIG : svr4
+ENVIRON : n/a
+NOTES : Remove PW_SHADOW from config file, or add -lgen for getspnam
+VERSION : 6.07.00
+
+VENDOR : Intergraph
+MODELS : clipper
+COMPILER: cc
+CFLAGS : n/a
+LIBES : -ltermcap -lbsd
+OS : clix 7.1.3
+CONFIG : clipper
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.05.00
+
+VENDOR : SNI (Siemens Nixdorf Information Systems)
+MODELS : rm400 (R4000 mips)
+COMPILER: /usr/bin/cc
+CFLAGS : -kansi; xmkmf (=> -DSVR4 -DSNI -DSMSINFO -DR3000)
+LIBES : -ltermcap -lc -L/usr/ucblib -lucb
+OS : SINIX 5.42
+CONFIG : sysv4
+ENVIRON :
+NOTES : This is a POSIX (XPG-4) system.
+NOTES : Make sure that -lucb is included _last_ (even after -lc)
+NOTES : so use: -ltermcap -lc -L/usr/ucblib -lucb
+NOTES : In config.h, set HAVEUTMPX und unset BSDSIGS and BSDTIMES
+NOTES :
+VERSION : 6.06.03
+
+VENDOR : U/WIN
+MODELS : i386
+COMPILER: cc
+CFLAGS : -O
+LIBES : -lcurses
+OS : Windows NT with U/WIN
+CONFIG : uwin
+ENVIRON :
+NOTES : Needs POSIX.DLL from U/WIN version later than 1.6
+NOTES : Did not function correctly when using #define SYSMALLOC
+VERSION : 6.07.02
+
+VENDOR : SNI (Siemens Nixdorf Information Systems)
+MODELS : rm600 (R4000 mips)
+COMPILER: /usr/bin/cc
+CFLAGS : -kansi -DSVR4 -DSNI -DSMSINFO -DR3000
+LIBES : -ltermcap -lsocket -lxnet -lc -L/usr/ucblib -lucb
+OS : SINIX 5.43
+CONFIG : sysv4
+ENVIRON :
+NOTES : In config.h, set HAVEUTMPX und unset BSDSIGS,
+NOTES : BSDTIMES, and BSDLIMIT, since otherwise resource.h
+NOTES : is falsely searched in /usr/ucbinclude/sys/
+NOTES :
+VERSION : 6.07.02
+
+VENDOR : FUJITSU
+MODELS : ds90
+COMPILER: cc
+CFLAGS : -O -I. -DSVR4 -DANSICPP
+LIBES : -lsocket -lnsl -ltermcap
+OS : UXP/DS V20L10(SVR4.2)
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : n/a
+VERSION : 6.07.02
+
+VENDOR : Fujitsu ICL
+MODELS : SuperServer Intel based
+COMPILER: gcc 2.7.2
+CFLAGS : normal for gcc 2.1+ .... -O2 $(INCLUDES)
+LIBES : -ltermlib -lsocket -lnsl -lcrypt -lgen
+OS : SCO UnixWare 2.1 SysVR4.2 i386 x86at
+CONFIG : sysv4
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.06.00
+
+VENDOR : NEC
+MODELS : SX-4, SX-5
+COMPILER: cc
+CFLAGS : -h0,ansi,novector,float0 # for NEC SX-4
+LIBES : -Gsmall
+OS : NEC's
+CONFIG : superux8
+ENVIRON : n/a
+NOTES : none
+VERSION : 6.08.01
diff --git a/contrib/tcsh/README b/contrib/tcsh/README
new file mode 100644
index 0000000..fb17faf
--- /dev/null
+++ b/contrib/tcsh/README
@@ -0,0 +1,207 @@
+This is tcsh version 6.08. Tcsh is a version of the Berkeley
+C-Shell, with the addition of: a command line editor, command and file
+name completion, listing, etc. and a bunch of small additions to the
+shell itself.
+
+Tcsh has been ported to most unix variants, and can be tinkered to work
+in unix systems that it has not ported yet. See the Ported file for
+a more complete list of ported systems and in the config directory for
+a configuration file that matches your system.
+Tcsh also runs under VMS/POSIX and OS/2+emx; the OS/2 port is not
+complete yet.
+
+Feel free to use it. These changes to csh may only be included in a
+commercial product if the inclusion or exclusion does not change the
+purchase price, level of support, etc. Please respect the individual
+authors by giving credit where credit is due (in other words, don't
+claim that you wrote portions that you haven't, and don't delete the
+names of the authors from the source code or documentation).
+
+To install tcsh:
+
+0) Try running "configure". If that works, goto step 6.
+ If you are using imake, try xmkmf and goto step 3.
+ If imake does not work, copy Makefile.std to Makefile.
+
+1) Look at the Makefile and make sure that you are using the right
+ compilation flags.
+
+2) Copy the appropriate for your machine and OS config file from the
+ config subdirectory into config.h. Consult the file "Ported" for
+ settings known to work on various machines. If you are trying to
+ compile tcsh on a machine for which there is no config file yet,
+ you will need to create a config file using as a template one of
+ the supplied ones. If you get tcsh working on a new machine, I'd
+ appreciate a copy of the config file plus additional information
+ about the architecture/OS. If you are creating a new config file,
+ look very hard at BSDJOBS, BSDSIGS, and BSDTIMES if you are running
+ a non-BSD machine. For vanila SysV, these would all be #undef-ed,
+ but others may vary (such as A/UX or HPUX). On a pyramid, compile
+ in the UCB universe even if you are running under the ATT universe
+ usually; it will work anyway, and you get job control for free.
+
+3) Look at config_f.h, and enable or disable any features you want.
+ It is configured the way I like it, but you may disagree.
+ If you do not have NLS, then locale.h will not be found. Undefine it
+ and things should work ok. On the other hand, if you have NLS you
+ might as well use it...
+
+4) Look at host.defs to make sure that you have the right defines to set
+ the environment variables "HOSTTYPE", "MACHTYPE", "OSTYPE" and
+ "VENDOR" correctly. If you need to make changes, PLEASE SEND THEM
+ BACK TO ME.
+
+5) You may want to adjust the TCSH_BINDIR and TCSH_MANDIR entries in
+ the Makefile. These are the directories that tcsh, and the tcsh.1
+ man entry will be placed in when you do a "make install" and "make
+ install.man" respectively. If you decide to install tcsh somewhere
+ other than in /usr/local/bin/tcsh, you should #define _PATH_TCSHELL
+ "/your/installation/directory/tcsh" in pathnames.h.
+
+6) make
+
+7) Read the documentation while you are waiting. The file tcsh.man
+ is in standard [nt]roff -man format. If you like, you can run the
+ tcsh.man2html script (requires Perl) to generate an HTML version of
+ the manpage which you can read with Mosaic, lynx or other HTML browser.
+
+8) Test tcsh by typing ./tcsh to see that it has compiled correctly.
+ The history command should give a time stamp on every entry.
+ Typing normal characters should echo each exactly once. Control-A
+ should put the cursor at the beginning of the input line, but after
+ the prompt. Typing characters after that should insert them into
+ the line. If you have job control make sure that stopping and
+ restarting jobs works. Make sure you can ^C in the middle of the
+ input line. Also make sure that pipelines work correctly and there
+ are no races. Try 'echo | cat | cat | cat | cat | more' a couple of
+ times. If you have job control, try this command in the background
+ and bring it in the foreground when it stops for tty output. Also
+ make sure that the ioctl() modes are preserved. Get into vi, enter
+ and exit input mode and suspend it, background it and foreground it
+ again. After all that, lastly make sure that the tty process group
+ manipulation is happening correctly. Try ftp to some host. If your
+ passwd appears on the screen, you have lost /dev/tty. Otherwise
+ everything is fine.
+
+9) Once satisfied that tcsh is working correctly, complete the installation
+ by typing "make install" to install the binary, and "make install.man" to
+ install the documentation. Don't forget to look at complete.tcsh for
+ useful completions...
+
+10) Enjoy.
+
+11) PLEASE send any bug reports (and fixes), code for new features,
+ comments, questions, etc. (even flames) to:
+
+ The tcsh mailing list
+ tcsh@mx.gw.com
+
+Various:
+
+***************************************************************************
+
+On sysv versions < 3.0 (not hpux) Doug Gwyn's public domain directory
+manipulation library has to be installed. This library is available
+for anonymous ftp from prep.ai.mit.edu:/pub/gnu/dirent.tar.Z
+If the network is not installed, then there is a gethostname()
+routine is tc.os.c, enabled by defining NEEDgethostname
+
+***************************************************************************
+
+On BSDreno, in ttyname() closedir() is called twice and so the same
+pointer gets free'd twice. tcsh's malloc is picky and it prints an
+error message to that effect. If you don't like the message:
+
+1. Apply the following patch:
+
+*** /usr/src/lib/libc/gen/ttyname.c.orig Fri Jun 1 17:17:15 1990
+--- /usr/src/lib/libc/gen/ttyname.c Tue Oct 29 16:33:12 1991
+***************
+*** 51,57 ****
+ if (stat(buf, &sb2) < 0 || sb1.st_dev != sb2.st_dev ||
+ sb1.st_ino != sb2.st_ino)
+ continue;
+- closedir(dp);
+ rval = buf;
+ break;
+ }
+--- 51,56 ----
+
+Or: Comment the error printing out in tc.alloc.c
+Or: Compile -DSYSMALLOC
+
+
+***************************************************************************
+
+From: Scott Krotz <krotz@honey.rtsg.mot.com>
+
+Tcsh has been ported to minix by Scott Krotz (krotz@honey.rtsg.mot.com).
+Unfortunately the minix sed is broken, so you'll have to find a way to
+make tc.const.h, sh.err.h, ed.defns.h which are automatically generated.
+The easiest way to create them is to make a copy from unix, copying
+minix to config.h, and then 'make sh.err.h tc.const.h ed.defns.h'
+
+The OS/dependent files are in mi.termios.h, mi.wait.h, mi.varargs.h
+
+You will get some warnings, but dont worry about them, just ignore
+them. After tcsh has compiled and the gcc binary is converted to a
+minix binary, remember to chmem it to give it more memory - it will
+need it! How much you need depends on how many aliases you have, etc..
+Add at least 50000 to it.
+
+One last thing. You might have to make some links for include files so
+that they are in the directories that tcsh is expecting while compiling.
+I forget if I had to do this or not, but it should be fairly easy to sort
+out. If it cant find any include files this is probably the reason.
+
+If you have any problems, please tell me. I can be contacted through
+e-mail at:
+
+krotz@honey.rtsg.mot.com
+
+I also read comp.os.minix on a regular basis, so a note there will get
+my attention also.
+
+Have fun!
+
+ps. The termios functions are provided by Magnus Doell and Bruce Evans.
+ Thanks, guys!
+
+
+From: Bob Byrnes <byrnes@ee.cornell.edu>
+
+This is for minix 1.5 (straight out of the box from P-H) plus the i386
+patches from Bruce Evans.
+
+I cross-compiled on a Sun using gcc 2.1 with a target of i386-bsd
+(using the minix include files instead of the bsd versions), and then
+linked the resulting object files with similarly compiled crtso.o and
+libc.a on vax (little endian) using a hacked version of ld which I put
+together to generate minix executables instead of bsd a.out format.
+What a kludge ...
+
+I compiled with -O2 -Wall ... So far I haven't noticed any problems
+with the optimizer.
+
+In case anyone is contemplating compiling tcsh with bcc (Bruce Evan's
+i386 compiler that comes with the minix386 upgrade package), don't bother.
+It is some serious bugs that kill tcsh when compiled for 16-bit characters.
+I can provide more details of bugs that I noticed for brave souls who want
+to try, but it would be hard (and why bother if you can get gcc?).
+
+I can make the binary available to anyone who wants it (for example people
+who can't get access to a cross-compiling environment, and who don't yet
+have gcc running under minix).
+
+
+***************************************************************************
+
+If your compiler cannot handle long symbol names, add
+
+#include "snames.h"
+
+to your config.h file
+
+ -- Christos Zoulas
+ christos@zoulas.com
+
diff --git a/contrib/tcsh/README.imake b/contrib/tcsh/README.imake
new file mode 100644
index 0000000..dfe2e2f
--- /dev/null
+++ b/contrib/tcsh/README.imake
@@ -0,0 +1,9 @@
+
+If you have imake running on your machine, you may skip steps 1 and 2
+described in the README file and try instead the process described here.
+Note that imake is not supported for all the platforms yet, so this
+might not work on your machine. If that is the case please let us know.
+If you can send a patch that fixes the problem we would appreciate it.
+
+1. edit imake.config and modify the configurable parameters to your liking.
+2. 'xmkmf; make depend; make'
diff --git a/contrib/tcsh/WishList b/contrib/tcsh/WishList
new file mode 100644
index 0000000..a849b18
--- /dev/null
+++ b/contrib/tcsh/WishList
@@ -0,0 +1,40 @@
+* Fix memory leak related to aliasrun(). Precmd, Cwdcmd etc. leak memory.
+
+* Fix migrate -site $$... Seems to hang... (aix370)
+
+* Fix history in loops.
+
+* New idea.
+ Lots of people seem to like the idea to be able to do sed type
+ operations on shell variables. Maybe we can extend the syntax
+ of the variable editing to understand string operations.
+ So I would like to be able to use:
+ > set a="this is a STRING"
+ > echo $a:[3-]
+ is is a STRING
+ > echo $a:[#]
+ 16
+ > echo $a:[6-7]
+ is
+ > echo $a:[-2]
+ ng
+ > echo $a:[-20]
+ Subscript out of bounds.
+ > echo $a:[2-20]
+ Subscript out of bounds.
+ > echo $a:[1-1]:u$a:[2-].
+ This is a string.
+
+* Fix pipelines that contain builtins so that they behave correctly.
+ I tried to fix that (most of the code is in sh.sem.c, but it works
+ only for non POSIX machines cause otherwise the setpgid() I added
+ fails).
+
+* Fix the correct code... How to do that involves A.I....
+
+* Rewrite the whole thing. It has taken to much beating over the years...
+
+* Add another hook like precmd to be executed after the prompt but before the
+ command.
+
+* Add instructions for using configure in the README file.
diff --git a/contrib/tcsh/Y2K b/contrib/tcsh/Y2K
new file mode 100644
index 0000000..daf6cd0
--- /dev/null
+++ b/contrib/tcsh/Y2K
@@ -0,0 +1,10 @@
+The tcsh code has been tested on a solaris-2.6 machine and a
+NetBSD-1.3H machine running before, and after the year 2000. The
+code has been also visually inspected for Y2K compliance problems.
+Tcsh does not use time functions for anything but display purposes,
+so its operation should not be affected assuming that the time
+related functions of the c library work properly.
+
+Note: Since the last audit, tcsh-6.08.00 has been found to have
+a minor problem with %y in the prompt (it will print 10 instead
+of 00 in y2k). This has been fixed in tcsh-6.09.00.
diff --git a/contrib/tcsh/complete.tcsh b/contrib/tcsh/complete.tcsh
new file mode 100644
index 0000000..f8e0ab9
--- /dev/null
+++ b/contrib/tcsh/complete.tcsh
@@ -0,0 +1,708 @@
+#
+# $Id: complete.tcsh,v 1.32 1999/06/09 19:09:12 christos Exp $
+# example file using the new completion code
+#
+
+onintr -
+if (! $?prompt) goto end
+
+if ($?tcsh) then
+ if ($tcsh != 1) then
+ set rev=$tcsh:r
+ set rel=$rev:e
+ set pat=$tcsh:e
+ set rev=$rev:r
+ endif
+ if ($rev > 5 && $rel > 1) then
+ set complete=1
+ endif
+ unset rev rel pat
+endif
+
+if ($?complete) then
+ set noglob
+ set hosts
+ foreach f ($HOME/.hosts /usr/local/etc/csh.hosts $HOME/.rhosts /etc/hosts.equiv)
+ if ( -r $f ) then
+ set hosts = ($hosts `grep -v "+" $f | tr -s " " " " | cut -f 1`)
+ endif
+ end
+ if ( -r $HOME/.netrc ) then
+ set f=`awk '/machine/ { print $2 }' < $HOME/.netrc` >& /dev/null
+ set hosts=($hosts $f)
+ endif
+ unset f
+ if ( ! $?hosts ) then
+ set hosts=(hyperion.ee.cornell.edu phaeton.ee.cornell.edu \
+ guillemin.ee.cornell.edu vangogh.cs.berkeley.edu \
+ ftp.uu.net prep.ai.mit.edu export.lcs.mit.edu \
+ labrea.stanford.edu sumex-aim.stanford.edu \
+ tut.cis.ohio-state.edu)
+ endif
+
+ complete ywho n/*/\$hosts/ # argument from list in $hosts
+ complete rsh p/1/\$hosts/ c/-/"(l n)"/ n/-l/u/ N/-l/c/ n/-/c/ p/2/c/ p/*/f/
+ complete ssh p/1/\$hosts/ c/-/"(l n)"/ n/-l/u/ N/-l/c/ n/-/c/ p/2/c/ p/*/f/
+ complete xrsh p/1/\$hosts/ c/-/"(l 8 e)"/ n/-l/u/ N/-l/c/ n/-/c/ p/2/c/ p/*/f/
+ complete rlogin p/1/\$hosts/ c/-/"(l 8 e)"/ n/-l/u/
+ complete telnet p/1/\$hosts/ p/2/x:'<port>'/ n/*/n/
+
+ complete cd p/1/d/ # Directories only
+ complete chdir p/1/d/
+ complete pushd p/1/d/
+ complete popd p/1/d/
+ complete pu p/1/d/
+ complete po p/1/d/
+ complete complete p/1/X/ # Completions only
+ complete uncomplete n/*/X/
+ complete exec p/1/c/ # Commands only
+ complete trace p/1/c/
+ complete strace p/1/c/
+ complete which n/*/c/
+ complete where n/*/c/
+ complete skill p/1/c/
+ complete dde p/1/c/
+ complete adb c/-I/d/ n/-/c/ N/-/"(core)"/ p/1/c/ p/2/"(core)"/
+ complete sdb p/1/c/
+ complete dbx c/-I/d/ n/-/c/ N/-/"(core)"/ p/1/c/ p/2/"(core)"/
+ complete xdb p/1/c/
+ complete gdb n/-d/d/ n/*/c/
+ complete ups p/1/c/
+ complete set 'c/*=/f/' 'p/1/s/=' 'n/=/f/'
+ complete unset n/*/s/
+ complete alias p/1/a/ # only aliases are valid
+ complete unalias n/*/a/
+ complete xdvi n/*/f:*.dvi/ # Only files that match *.dvi
+ complete dvips n/*/f:*.dvi/
+ complete tex n/*/f:*.tex/ # Only files that match *.tex
+ complete latex n/*/f:*.{tex,ltx}/
+ complete su c/--/"(login fast preserve-environment command shell \
+ help version)"/ c/-/"(f l m p c s -)"/ \
+ n/{-c,--command}/c/ \
+ n@{-s,--shell}@'`cat /etc/shells`'@ n/*/u/
+ complete cc c/-[IL]/d/ \
+ c@-l@'`\ls -1 /usr/lib/lib*.a | sed s%^.\*/lib%%\;s%\\.a\$%%`'@ \
+ c/-/"(o l c g L I D U)"/ n/*/f:*.[coasi]/
+ complete acc c/-[IL]/d/ \
+ c@-l@'`\ls -1 /usr/lang/SC1.0/lib*.a | sed s%^.\*/lib%%\;s%\\.a\$%%`'@ \
+ c/-/"(o l c g L I D U)"/ n/*/f:*.[coasi]/
+ complete gcc c/-[IL]/d/ \
+ c/-f/"(caller-saves cse-follow-jumps delayed-branch \
+ elide-constructors expensive-optimizations \
+ float-store force-addr force-mem inline \
+ inline-functions keep-inline-functions \
+ memoize-lookups no-default-inline \
+ no-defer-pop no-function-cse omit-frame-pointer \
+ rerun-cse-after-loop schedule-insns \
+ schedule-insns2 strength-reduce \
+ thread-jumps unroll-all-loops \
+ unroll-loops syntax-only all-virtual \
+ cond-mismatch dollars-in-identifiers \
+ enum-int-equiv no-asm no-builtin \
+ no-strict-prototype signed-bitfields \
+ signed-char this-is-variable unsigned-bitfields \
+ unsigned-char writable-strings call-saved-reg \
+ call-used-reg fixed-reg no-common \
+ no-gnu-binutils nonnull-objects \
+ pcc-struct-return pic PIC shared-data \
+ short-enums short-double volatile)"/ \
+ c/-W/"(all aggregate-return cast-align cast-qual \
+ comment conversion enum-clash error format \
+ id-clash-len implicit missing-prototypes \
+ no-parentheses pointer-arith return-type shadow \
+ strict-prototypes switch uninitialized unused \
+ write-strings)"/ \
+ c/-m/"(68000 68020 68881 bitfield fpa nobitfield rtd \
+ short c68000 c68020 soft-float g gnu unix fpu \
+ no-epilogue)"/ \
+ c/-d/"(D M N)"/ \
+ c/-/"(f W vspec v vpath ansi traditional \
+ traditional-cpp trigraphs pedantic x o l c g L \
+ I D U O O2 C E H B b V M MD MM i dynamic \
+ nodtdlib static nostdinc undef)"/ \
+ c/-l/f:*.a/ \
+ n/*/f:*.{c,C,cc,o,a,s,i}/
+ complete g++ n/*/f:*.{C,cc,o,s,i}/
+ complete CC n/*/f:*.{C,cc,o,s,i}/
+ complete rm c/--/"(directory force interactive verbose \
+ recursive help version)"/ c/-/"(d f i v r R -)"/ \
+ n/*/f:^*.{c,cc,C,h,in}/ # Protect precious files
+ complete vi n/*/f:^*.[oa]/
+ complete bindkey N/-a/b/ N/-c/c/ n/-[ascr]/'x:<key-sequence>'/ \
+ n/-[svedlr]/n/ c/-[vedl]/n/ c/-/"(a s k c v e d l r)"/\
+ n/-k/"(left right up down)"/ p/2-/b/ \
+ p/1/'x:<key-sequence or option>'/
+
+ complete find n/-fstype/"(nfs 4.2)"/ n/-name/f/ \
+ n/-type/"(c b d f p l s)"/ n/-user/u/ n/-group/g/ \
+ n/-exec/c/ n/-ok/c/ n/-cpio/f/ n/-ncpio/f/ n/-newer/f/ \
+ c/-/"(fstype name perm prune type user nouser \
+ group nogroup size inum atime mtime ctime exec \
+ ok print ls cpio ncpio newer xdev depth \
+ daystart follow maxdepth mindepth noleaf version \
+ anewer cnewer amin cmin mmin true false uid gid \
+ ilname iname ipath iregex links lname empty path \
+ regex used xtype fprint fprint0 fprintf \
+ print0 printf not a and o or)"/ \
+ n/*/d/
+
+ complete -%* c/%/j/ # fill in the jobs builtin
+ complete {fg,bg,stop} c/%/j/ p/1/"(%)"//
+
+ complete limit c/-/"(h)"/ n/*/l/
+ complete unlimit c/-/"(h)"/ n/*/l/
+
+ complete -co* p/0/"(compress)"/ # make compress completion
+ # not ambiguous
+ complete zcat n/*/f:*.Z/
+ complete nm n/*/f:^*.{h,C,c,cc}/
+
+ complete finger c/*@/\$hosts/ n/*/u/@
+ complete ping p/1/\$hosts/
+ complete traceroute p/1/\$hosts/
+
+ complete {talk,ntalk,phone} p/1/'`users | tr " " "\012" | uniq`'/ \
+ n/*/\`who\ \|\ grep\ \$:1\ \|\ awk\ \'\{\ print\ \$2\ \}\'\`/
+
+ complete ftp c/-/"(d i g n v)"/ n/-/\$hosts/ p/1/\$hosts/ n/*/n/
+
+ # this one is simple...
+ #complete rcp c/*:/f/ C@[./\$~]*@f@ n/*/\$hosts/:
+ # From Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ # This one will rsh to the file to fetch the list of files!
+ complete rcp 'c%*@*:%`set q=$:-0;set q="$q:s/@/ /";set q="$q:s/:/ /";set q=($q " ");rsh $q[2] -l $q[1] ls -dp $q[3]\*`%' 'c%*:%`set q=$:-0;set q="$q:s/:/ /";set q=($q " ");rsh $q[1] ls -dp $q[2]\*`%' 'c%*@%$hosts%:' 'C@[./$~]*@f@' 'n/*/$hosts/:'
+
+ complete dd c/--/"(help version)"/ c/[io]f=/f/ \
+ c/conv=*,/"(ascii ebcdic ibm block unblock \
+ lcase notrunc ucase swab noerror sync)"/,\
+ c/conv=/"(ascii ebcdic ibm block unblock \
+ lcase notrunc ucase swab noerror sync)"/,\
+ c/*=/x:'<number>'/ \
+ n/*/"(if of conv ibs obs bs cbs files skip file seek count)"/=
+
+ complete nslookup p/1/x:'<host>'/ p/2/\$hosts/
+
+ complete ar c/[dmpqrtx]/"(c l o u v a b i)"/ p/1/"(d m p q r t x)"// \
+ p/2/f:*.a/ p/*/f:*.o/
+
+ # these should be merged with the MH completion hacks below - jgotts
+ complete {sprev,snext} \
+ c@+@F:$HOME/Mail/@
+
+ # these and interrupt handling from Jaap Vermeulen <jaap@sequent.com>
+ complete {rexec,rxexec,rxterm,rmterm} \
+ 'p/1/$hosts/' 'c/-/(l L E)/' 'n/-l/u/' 'n/-L/f/' \
+ 'n/-E/e/' 'n/*/c/'
+ complete kill 'c/-/S/' 'c/%/j/' \
+ 'n/*/`ps -u $LOGNAME | awk '"'"'{print $1}'"'"'`/'
+
+ # these from Marc Horowitz <marc@cam.ov.com>
+ complete attach 'n/-mountpoint/d/' 'n/-m/d/' 'n/-type/(afs nfs rvd ufs)/' \
+ 'n/-t/(afs nfs rvd ufs)/' 'n/-user/u/' 'n/-U/u/' \
+ 'c/-/(verbose quiet force printpath lookup debug map \
+ nomap remap zephyr nozephyr readonly write \
+ mountpoint noexplicit explicit type mountoptions \
+ nosetuid setuid override skipfsck lock user host)/' \
+ 'n/-e/f/' 'n/*/()/'
+ complete hesinfo 'p/1/u/' \
+ 'p/2/(passwd group uid grplist pcap pobox cluster \
+ filsys sloc service)/'
+
+ # these from E. Jay Berkenbilt <ejb@ERA.COM>
+ # = isn't always followed by a filename or a path anymore - jgotts
+ complete ./configure 'c/--*=/f/' 'c/--{cache-file,prefix,exec-prefix,\
+ bindir,sbindir,libexecdir,datadir,\
+ sysconfdir,sharedstatedir,localstatedir,\
+ libdir,includedir,oldincludedir,infodir,\
+ mandir,srcdir}/(=)//' \
+ 'c/--/(cache-file verbose prefix exec-prefix bindir \
+ sbindir libexecdir datadir sysconfdir \
+ sharedstatedir localstatedir libdir \
+ includedir oldincludedir infodir mandir \
+ srcdir)//'
+ complete gs 'c/-sDEVICE=/(x11 cdjmono cdj550 epson eps9high epsonc \
+ dfaxhigh dfaxlow laserjet ljet4 sparc pbm \
+ pbmraw pgm pgmraw ppm ppmraw bit)/' \
+ 'c/-sOutputFile=/f/' 'c/-s/(DEVICE OutputFile)/=' \
+ 'c/-d/(NODISPLAY NOPLATFONTS NOPAUSE)/' 'n/*/f/'
+ complete perl 'n/-S/c/'
+ complete printenv 'n/*/e/'
+ complete sccs p/1/"(admin cdc check clean comb deledit delget \
+ delta diffs edit enter fix get help info \
+ print prs prt rmdel sccsdiff tell unedit \
+ unget val what)"/
+ complete setenv 'p/1/e/' 'c/*:/f/'
+
+ # these and method of setting hosts from Kimmo Suominen <kim@tac.nyc.ny.us>
+ if ( -f $HOME/.mh_profile && -x "`which folders`" ) then
+
+ if ( ! $?FOLDERS ) setenv FOLDERS "`folders -fast -recurse`"
+ if ( ! $?MHA ) setenv MHA "`ali | sed -e '/^ /d' -e 's/:.*//'`"
+
+ set folders = ( $FOLDERS )
+ set mha = ( $MHA )
+
+ complete ali \
+ 'c/-/(alias nolist list nonormalize normalize nouser user help)/' \
+ 'n,-alias,f,'
+
+ complete anno \
+ 'c/-/(component noinplace inplace nodate date text help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete burst \
+ 'c/-/(noinplace inplace noquiet quiet noverbose verbose help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete comp \
+ 'c/-/(draftfolder draftmessage nodraftfolder editor noedit file form nouse use whatnowproc nowhatnowproc help)/' \
+ 'c,+,$folders,' \
+ 'n,-whatnowproc,c,' \
+ 'n,-file,f,'\
+ 'n,-form,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete dist \
+ 'c/-/(noannotate annotate draftfolder draftmessage nodraftfolder editor noedit form noinplace inplace whatnowproc nowhatnowproc help)/' \
+ 'c,+,$folders,' \
+ 'n,-whatnowproc,c,' \
+ 'n,-form,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete folder \
+ 'c/-/(all nofast fast noheader header nopack pack noverbose verbose norecurse recurse nototal total noprint print nolist list push pop help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete folders \
+ 'c/-/(all nofast fast noheader header nopack pack noverbose verbose norecurse recurse nototal total noprint print nolist list push pop help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete forw \
+ 'c/-/(noannotate annotate draftfolder draftmessage nodraftfolder editor noedit filter form noformat format noinplace inplace digest issue volume whatnowproc nowhatnowproc help)/' \
+ 'c,+,$folders,' \
+ 'n,-whatnowproc,c,' \
+ 'n,-filter,f,'\
+ 'n,-form,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete inc \
+ 'c/-/(audit file noaudit nochangecur changecur file form format nosilent silent notruncate truncate width help)/' \
+ 'c,+,$folders,' \
+ 'n,-audit,f,'\
+ 'n,-form,f,'
+
+ complete mark \
+ 'c/-/(add delete list sequence nopublic public nozero zero help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete mhmail \
+ 'c/-/(body cc from subject help)/' \
+ 'n,-cc,$mha,' \
+ 'n,-from,$mha,' \
+ 'n/*/$mha/'
+
+ complete mhpath \
+ 'c/-/(help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete msgchk \
+ 'c/-/(nodate date nonotify notify help)/'
+
+ complete msh \
+ 'c/-/(prompt noscan scan notopcur topcur help)/'
+
+ complete next \
+ 'c/-/(draft form moreproc nomoreproc length width showproc noshowproc header noheader help)/' \
+ 'c,+,$folders,' \
+ 'n,-moreproc,c,' \
+ 'n,-showproc,c,' \
+ 'n,-form,f,'
+
+ complete packf \
+ 'c/-/(file help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete pick \
+ 'c/-/(and or not lbrace rbrace cc date from search subject to othercomponent after before datefield sequence nopublic public nozero zero nolist list help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete prev \
+ 'c/-/(draft form moreproc nomoreproc length width showproc noshowproc header noheader help)/' \
+ 'c,+,$folders,' \
+ 'n,-moreproc,c,' \
+ 'n,-showproc,c,' \
+ 'n,-form,f,'
+
+ complete prompter \
+ 'c/-/(erase kill noprepend prepend norapid rapid nodoteof doteof help)/'
+
+ complete refile \
+ 'c/-/(draft nolink link nopreserve preserve src file help)/' \
+ 'c,+,$folders,' \
+ 'n,-file,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete rmf \
+ 'c/-/(nointeractive interactive help)/' \
+ 'c,+,$folders,'
+
+ complete rmm \
+ 'c/-/(help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete scan \
+ 'c/-/(noclear clear form format noheader header width noreverse reverse file help)/' \
+ 'c,+,$folders,' \
+ 'n,-form,f,'\
+ 'n,-file,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete send \
+ 'c/-/(alias draft draftfolder draftmessage nodraftfolder filter nofilter noformat format noforward forward nomsgid msgid nopush push noverbose verbose nowatch watch width help)/' \
+ 'n,-alias,f,'\
+ 'n,-filter,f,'
+
+ complete show \
+ 'c/-/(draft form moreproc nomoreproc length width showproc noshowproc header noheader help)/' \
+ 'c,+,$folders,' \
+ 'n,-moreproc,c,' \
+ 'n,-showproc,c,' \
+ 'n,-form,f,'\
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete sortm \
+ 'c/-/(datefield textfield notextfield limit nolimit noverbose verbose help)/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete vmh \
+ 'c/-/(prompt vmhproc novmhproc help)/' \
+ 'n,-vmhproc,c,'
+
+ complete whatnow \
+ 'c/-/(draftfolder draftmessage nodraftfolder editor noedit prompt help)/'
+
+ complete whom \
+ 'c/-/(alias nocheck check draft draftfolder draftmessage nodraftfolder help)/' \
+ 'n,-alias,f,'
+
+ complete plum \
+ 'c/-/()/' \
+ 'c,+,$folders,' \
+ 'n,*,`(mark | sed "s/:.*//";echo next cur prev first last)|tr " " "\12" | sort -u`,'
+
+ complete mail \
+ 'c/-/()/' \
+ 'n/*/$mha/'
+
+ endif
+
+ #from Dan Nicolaescu <dann@ics.uci.edu>
+ if ( $?MODULESHOME ) then
+
+ alias Compl_module ' set q = "$MODULEPATH:as/:/ /" ; find $q -name .version -o -name .modulea\* -prune -o -print | sed `echo "-e s@"$MODULEPATH:as%:%/\*@@g -e s@%"/\*@@g"`'
+
+ complete module 'p%1%(add load unload switch display avail use unuse update purge list clear help initadd initrm initswitch initlist initclear)%' \
+ 'n%unload%`echo "$LOADEDMODULES:as/:/ /"`%' \
+ 'n%{lo*,sw*,di*,he*,inita*,initr*,inits*}%`eval Compl_module`%' \
+ 'N%{sw*,initsw*}%`eval Compl_module`%' 'C%-%(-append)%' 'n%{use,unu*,av*}%d%' 'n%-append%d%' \
+ 'C%[^-]*%`eval Compl_module`%'
+ endif
+
+ # these from Tom Warzeka <waz@quahog.npt.nuwc.navy.mil>
+ # you may need to set the following variables for your host
+ set _elispdir = /usr/local/share/emacs/20.2/lisp # GNU Emacs lisp directory
+ set _maildir = /var/spool/mail # Post Office: /var/spool/mail or /usr/mail
+ set _ypdir = /var/yp # directory where NIS (YP) maps are kept
+ set _domain = "`domainname`"
+
+ # this one works but is slow and doesn't descend into subdirectories
+ # complete cd C@[./\$~]*@d@ \
+ # p@1@'`\ls -1F . $cdpath | grep /\$ | sort -u`'@ n@*@n@
+
+ if ( -r /etc/shells ) then
+ complete setenv p@1@e@ n@DISPLAY@\$hosts@: n@SHELL@'`cat /etc/shells`'@
+ else
+ complete setenv p@1@e@ n@DISPLAY@\$hosts@:
+ endif
+ complete unsetenv n/*/e/
+
+ if (-r $HOME/.mailrc) then
+ complete mail c/-/"(e i f n s u v)"/ c/*@/\$hosts/ \
+ c@+@F:$HOME/Mail@ C@[./\$~]@f@ n/-s/x:'<subject>'/ \
+ n@-u@T:$_maildir@ n/-f/f/ \
+ n@*@'`sed -n s/alias//p $HOME/.mailrc | tr -s " " " " | cut -f 2`'@
+ else
+ complete mail c/-/"(e i f n s u v)"/ c/*@/\$hosts/ \
+ c@+@F:$HOME/Mail@ C@[./\$~]@f@ n/-s/x:'<subject>'/ \
+ n@-u@T:$_maildir@ n/-f/f/ n/*/u/
+ endif
+
+ complete man n@1@'`\ls -1 /usr/man/man1 | sed s%\\.1.\*\$%%`'@ \
+ n@2@'`\ls -1 /usr/man/man2 | sed s%\\.2.\*\$%%`'@ \
+ n@3@'`\ls -1 /usr/man/man3 | sed s%\\.3.\*\$%%`'@ \
+ n@4@'`\ls -1 /usr/man/man4 | sed s%\\.4.\*\$%%`'@ \
+ n@5@'`\ls -1 /usr/man/man5 | sed s%\\.5.\*\$%%`'@ \
+ n@6@'`\ls -1 /usr/man/man6 | sed s%\\.6.\*\$%%`'@ \
+ n@7@'`\ls -1 /usr/man/man7 | sed s%\\.7.\*\$%%`'@ \
+ n@8@'`\ls -1 /usr/man/man8 | sed s%\\.8.\*\$%%`'@ \
+ n@9@'`[ -r /usr/man/man9 ] && \ls -1 /usr/man/man9 | sed s%\\.9.\*\$%%`'@ \
+ n@0@'`[ -r /usr/man/man0 ] && \ls -1 /usr/man/man0 | sed s%\\.0.\*\$%%`'@ \
+ n@new@'`[ -r /usr/man/mann ] && \ls -1 /usr/man/mann | sed s%\\.n.\*\$%%`'@ \
+ n@old@'`[ -r /usr/man/mano ] && \ls -1 /usr/man/mano | sed s%\\.o.\*\$%%`'@ \
+n@local@'`[ -r /usr/man/manl ] && \ls -1 /usr/man/manl | sed s%\\.l.\*\$%%`'@ \
+n@public@'`[ -r /usr/man/manp ]&& \ls -1 /usr/man/manp | sed s%\\.p.\*\$%%`'@ \
+ c/-/"(- f k M P s t)"/ n/-f/c/ n/-k/x:'<keyword>'/ n/-[MP]/d/ \
+ N@-[MP]@'`\ls -1 $:-1/man? | sed s%\\..\*\$%%`'@ n/*/c/
+
+ complete ps c/-t/x:'<tty>'/ c/-/"(a c C e g k l S t u v w x)"/ \
+ n/-k/x:'<kernel>'/ N/-k/x:'<core_file>'/ n/*/x:'<PID>'/
+ complete compress c/-/"(c f v b)"/ n/-b/x:'<max_bits>'/ n/*/f:^*.Z/
+ complete uncompress c/-/"(c f v)"/ n/*/f:*.Z/
+
+ complete xhost c/[+-]/\$hosts/ n/*/\$hosts/
+
+ # these conform to the latest GNU versions available at press time ...
+ # updates by John Gotts <jgotts@engin.umich.edu>
+
+ complete emacs c/-/"(batch d f funcall i insert kill l load \
+ no-init-file nw q t u user)"/ c/+/x:'<line_number>'/ \
+ n/-d/x:'<display>'/ n/-f/x:'<lisp_function>'/ n/-i/f/ \
+ n@-l@F:$_elispdir@ n/-t/x:'<terminal>'/ \
+ n/-u/u/ n/*/f:^*[\#~]/
+
+ complete gzcat c/--/"(force help license quiet version)"/ \
+ c/-/"(f h L q V -)"/ n/*/f:*.{gz,Z,z,zip}/
+ complete gzip c/--/"(stdout to-stdout decompress uncompress \
+ force help list license no-name quiet recurse \
+ suffix test verbose version fast best)"/ \
+ c/-/"(c d f h l L n q r S t v V 1 2 3 4 5 6 7 8 9 -)"/\
+ n/{-S,--suffix}/x:'<file_name_suffix>'/ \
+ n/{-d,--{de,un}compress}/f:*.{gz,Z,z,zip,taz,tgz}/ \
+ N/{-d,--{de,un}compress}/f:*.{gz,Z,z,zip,taz,tgz}/ \
+ n/*/f:^*.{gz,Z,z,zip,taz,tgz}/
+ complete {gunzip,ungzip} c/--/"(stdout to-stdout force help list license \
+ no-name quiet recurse suffix test verbose version)"/ \
+ c/-/"(c f h l L n q r S t v V -)"/ \
+ n/{-S,--suffix}/x:'<file_name_suffix>'/ \
+ n/*/f:*.{gz,Z,z,zip,taz,tgz}/
+ complete zgrep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/-/"(A b B c C e f h i l n s v V w x)"/ \
+ p/1/x:'<limited_regular_expression>'/ N/-*e/f/ \
+ n/-*e/x:'<limited_regular_expression>'/ n/-*f/f/ n/*/f/
+ complete zegrep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/-/"(A b B c C e f h i l n s v V w x)"/ \
+ p/1/x:'<full_regular_expression>'/ N/-*e/f/ \
+ n/-*e/x:'<full_regular_expression>'/ n/-*f/f/ n/*/f/
+ complete zfgrep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/-/"(A b B c C e f h i l n s v V w x)"/ \
+ p/1/x:'<fixed_string>'/ N/-*e/f/ \
+ n/-*e/x:'<fixed_string>'/ n/-*f/f/ n/*/f/
+ complete znew c/-/"(f t v 9 P K)"/ n/*/f:*.Z/
+ complete zmore n/*/f:*.{gz,Z,z,zip}/
+ complete zfile n/*/f:*.{gz,Z,z,zip,taz,tgz}/
+ complete ztouch n/*/f:*.{gz,Z,z,zip,taz,tgz}/
+ complete zforce n/*/f:^*.{gz,tgz}/
+
+ complete grep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/--/"(extended-regexp fixed-regexp basic-regexp \
+ regexp file ignore-case word-regexp line-regexp \
+ no-messages revert-match version help byte-offset \
+ line-number with-filename no-filename quiet silent \
+ text directories recursive files-without-match \
+ files-with-matches count before-context after-context \
+ context binary unix-byte-offsets)"/ \
+ c/-/"(A a B b C c d E e F f G H h i L l n q r s U u V \
+ v w x)"/ \
+ p/1/x:'<limited_regular_expression>'/ N/-*e/f/ \
+ n/-*e/x:'<limited_regular_expression>'/ n/-*f/f/ n/*/f/
+ complete egrep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/--/"(extended-regexp fixed-regexp basic-regexp \
+ regexp file ignore-case word-regexp line-regexp \
+ no-messages revert-match version help byte-offset \
+ line-number with-filename no-filename quiet silent \
+ text directories recursive files-without-match \
+ files-with-matches count before-context after-context \
+ context binary unix-byte-offsets)"/ \
+ c/-/"(A a B b C c d E e F f G H h i L l n q r s U u V \
+ v w x)"/ \
+ p/1/x:'<full_regular_expression>'/ N/-*e/f/ \
+ n/-*e/x:'<full_regular_expression>'/ n/-*f/f/ n/*/f/
+ complete fgrep c/-*A/x:'<#_lines_after>'/ c/-*B/x:'<#_lines_before>'/\
+ c/--/"(extended-regexp fixed-regexp basic-regexp \
+ regexp file ignore-case word-regexp line-regexp \
+ no-messages revert-match version help byte-offset \
+ line-number with-filename no-filename quiet silent \
+ text directories recursive files-without-match \
+ files-with-matches count before-context after-context \
+ context binary unix-byte-offsets)"/ \
+ c/-/"(A a B b C c d E e F f G H h i L l n q r s U u V \
+ v w x)"/ \
+ p/1/x:'<fixed_string>'/ N/-*e/f/ \
+ n/-*e/x:'<fixed_string>'/ n/-*f/f/ n/*/f/
+
+ complete users c/--/"(help version)"/ p/1/x:'<accounting_file>'/
+ complete who c/--/"(heading idle count mesg message writable help \
+ version)"/ c/-/"(H i m q s T w u -)"/ \
+ p/1/x:'<accounting_file>'/ n/am/"(i)"/ n/are/"(you)"/
+
+ complete chown c/--/"(changes dereference no-dereference silent \
+ quiet reference recursive verbose help version)"/ \
+ c/-/"(c f h R v -)"/ C@[./\$~]@f@ c/*[.:]/g/ \
+ n/-/u/. p/1/u/. n/*/f/
+ complete chgrp c/--/"(changes no-dereference silent quiet reference \
+ recursive verbose help version)"/ \
+ c/-/"(c f h R v -)"/ n/-/g/ p/1/g/ n/*/f/
+ complete chmod c/--/"(changes silent quiet verbose reference \
+ recursive help version)"/ c/-/"(c f R v)"/
+ complete df c/--/"(all block-size human-readable si inodes \
+ kilobytes local megabytes no-sync portability sync \
+ type print-type exclude-type help version)"/ \
+ c/-/"(a H h i k l m P T t v x)"/
+ complete du c/--/"(all block-size bytes total dereference-args \
+ human-readable si kilobytes count-links dereference \
+ megabytes separate-dirs summarize one-file-system \
+ exclude-from exclude max-depth help version"/ \
+ c/-/"(a b c D H h k L l m S s X x)"/
+
+ complete cat c/--/"(number-nonblank number squeeze-blank show-all \
+ show-nonprinting show-ends show-tabs help version)"/ \
+ c/-/"(A b E e n s T t u v -)"/ n/*/f/
+ complete mv c/--/"(backup force interactive update verbose suffix \
+ version-control help version)"/ \
+ c/-/"(b f i S u V v -)"/ \
+ n/{-S,--suffix}/x:'<suffix>'/ \
+ n/{-V,--version-control}/"(t numbered nil existing \
+ never simple)"/ n/-/f/ N/-/d/ p/1/f/ p/2/d/ n/*/f/
+ complete cp c/--/"(archive backup no-dereference force \
+ interactive link preserve parents sparse recursive \
+ symbolic-link suffix update verbose version-control \
+ one-file-system help version)"/ \
+ c/-/"(a b d f i l P p R r S s u V v x -)"/ \
+ n/-*r/d/ n/{-S,--suffix}/x:'<suffix>'/ \
+ n/{-V,--version-control}/"(t numbered nil existing \
+ never simple)"/ n/-/f/ N/-/d/ p/1/f/ p/2/d/ n/*/f/
+ complete ln c/--/"(backup directory force no-dereference \
+ interactive symbolic suffix verbose version-control \
+ help version)"/ \
+ c/-/"(b d F f i n S s V v -)"/ \
+ n/{-S,--suffix}/x:'<suffix>'/ \
+ n/{-V,--version-control}/"(t numbered nil existing \
+ never simple)"/ n/-/f/ N/-/x:'<link_name>'/ \
+ p/1/f/ p/2/x:'<link_name>'/
+ complete touch c/--/"(date reference time help version)"/ \
+ c/-/"(a c d f m r t -)"/ \
+ n/{-d,--date}/x:'<date_string>'/ \
+ c/--time/"(access atime mtime modify use)"/ \
+ n/{-r,--file}/f/ n/-t/x:'<time_stamp>'/ n/*/f/
+ complete mkdir c/--/"(mode parents verbose help version)"/ \
+ c/-/"(p m -)"/ \
+ n/{-m,--mode}/x:'<mode>'/ n/*/d/
+ complete rmdir c/--/"(ignore-fail-on-non-empty parents verbose help \
+ version)"/ c/-/"(p -)"/ n/*/d/
+
+ complete tar c/-[Acru]*/"(b B C f F g G h i l L M N o P \
+ R S T v V w W X z Z)"/ \
+ c/-[dtx]*/"( B C f F g G i k K m M O p P \
+ R s S T v w x X z Z)"/ \
+ p/1/"(A c d r t u x -A -c -d -r -t -u -x \
+ --catenate --concatenate --create --diff --compare \
+ --delete --append --list --update --extract --get \
+ --help --version)"/ \
+ c/--/"(catenate concatenate create diff compare \
+ delete append list update extract get atime-preserve \
+ block-size read-full-blocks directory checkpoint file \
+ force-local info-script new-volume-script incremental \
+ listed-incremental dereference ignore-zeros \
+ ignore-failed-read keep-old-files starting-file \
+ one-file-system tape-length modification-time \
+ multi-volume after-date newer old-archive portability \
+ to-stdout same-permissions preserve-permissions \
+ absolute-paths preserve record-number remove-files \
+ same-order preserve-order same-owner sparse \
+ files-from null totals verbose label version \
+ interactive confirmation verify exclude exclude-from \
+ compress uncompress gzip ungzip use-compress-program \
+ block-compress help version)"/ \
+ c/-/"(b B C f F g G h i k K l L m M N o O p P R s S \
+ T v V w W X z Z 0 1 2 3 4 5 6 7 -)"/ \
+ n/-c*f/x:'<new_tar_file, device_file, or "-">'/ \
+ n/{-[Adrtux]*f,--file}/f:*.tar/ \
+ N/{-x*f,--file}/'`tar -tf $:-1`'/ \
+ n/--use-compress-program/c/ \
+ n/{-b,--block-size}/x:'<block_size>'/ \
+ n/{-V,--label}/x:'<volume_label>'/ \
+ n/{-N,--{after-date,newer}}/x:'<date>'/ \
+ n/{-L,--tape-length}/x:'<tape_length_in_kB>'/ \
+ n/{-C,--directory}/d/ \
+ N/{-C,--directory}/'`\ls $:-1`'/ \
+ n/-[0-7]/"(l m h)"/
+
+ # SVR4 filesystems
+ #complete mount c/-/"(a F m o O p r v V)"/ n/-p/n/ n/-v/n/ \
+ # n/-o/x:'<FSType_options>'/ \
+ # n@-F@'`\ls -1 /usr/lib/fs`'@ \
+ # n@*@'`grep -v "^#" /etc/vfstab | tr -s " " " " | cut -f 3`'@
+ #complete umount c/-/"(a o V)"/ n/-o/x:'<FSType_options>'/ \
+ # n/*/'`mount | cut -d " " -f 1`'/
+ #complete mountall c/-/"(F l r)"/ n@-F@'`\ls -1 /usr/lib/fs`'@
+ #complete umountall c/-/"(F h k l r s)"/ n@-F@'`\ls -1 /usr/lib/fs`'@ \
+ # n/-h/'`df -k | cut -s -d ":" -f 1 | sort -u`'/
+ # BSD 4.3 filesystems
+ complete mount c/-/"(a r t v)"/ n/-t/"(4.2 nfs)"/ \
+ n@*@'`grep -v "^#" /etc/fstab | tr -s " " " " | cut -f 2`'@
+ complete umount c/-/"(a h t v)"/ n/-t/"(4.2 nfs)"/ \
+ n/-h/'`df | cut -s -d ":" -f 1 | sort -u`'/ \
+ n/*/'`mount | cut -d " " -f 3`'/
+ # BSD 4.2 filesystems
+ #complete mount c/-/"(a r t v)"/ n/-t/"(ufs nfs)"/ \
+ # n@*@'`cut -d ":" -f 2 /etc/fstab`'@
+ #complete umount c/-/"(a h t v)"/ n/-t/"(ufs nfs)"/ \
+ # n/-h/'`df | cut -s -d ":" -f 1 | sort -u`'/ \
+ # n/*/'`mount | cut -d " " -f 3`'/
+
+ # these deal with NIS (formerly YP); if it's not running you don't need 'em
+ complete domainname p@1@D:$_ypdir@" " n@*@n@
+ complete ypcat c@-@"(d k t x)"@ n@-x@n@ n@-d@D:$_ypdir@" " \
+ N@-d@\`\\ls\ -1\ $_ypdir/\$:-1\ \|\ sed\ -n\ s%\\\\.pag\\\$%%p\`@ \
+ n@*@\`\\ls\ -1\ $_ypdir/$_domain\ \|\ sed\ -n\ s%\\\\.pag\\\$%%p\`@
+ complete ypmatch c@-@"(d k t x)"@ n@-x@n@ n@-d@D:$_ypdir@" " \
+ N@-d@x:'<key ...>'@ n@-@x:'<key ...>'@ p@1@x:'<key ...>'@ \
+ n@*@\`\\ls\ -1\ $_ypdir/$_domain\ \|\ sed\ -n\ s%\\\\.pag\\\$%%p\`@
+ complete ypwhich c@-@"(d m t x V1 V2)"@ n@-x@n@ n@-d@D:$_ypdir@" " \
+ n@-m@\`\\ls\ -1\ $_ypdir/$_domain\ \|\ sed\ -n\ s%\\\\.pag\\\$%%p\`@ \
+ N@-m@n@ n@*@\$hosts@
+
+ # there's no need to clutter the user's shell with these
+ unset _elispdir _maildir _ypdir _domain
+
+ complete make \
+ 'n/-f/f/' \
+ 'c/*=/f/' \
+ 'n@*@`cat -s GNUmakefile Makefile makefile |& sed -n -e "/No such file/d" -e "/^[^ #].*:/s/:.*//p"`@'
+
+ if ( -f /etc/printcap ) then
+ set printers=(`sed -n -e "/^[^ #].*:/s/:.*//p" /etc/printcap`)
+
+ complete lpr 'c/-P/$printers/'
+ complete lpq 'c/-P/$printers/'
+ complete lprm 'c/-P/$printers/'
+ complete lpquota 'p/1/(-Qprlogger)/' 'c/-P/$printers/'
+ complete dvips 'c/-P/$printers/' 'n/-o/f:*.{ps,PS}/' 'n/*/f:*.dvi/'
+ endif
+
+ unset noglob
+ unset complete
+endif
+
+end:
+ onintr
diff --git a/contrib/tcsh/config.h.in b/contrib/tcsh/config.h.in
new file mode 100644
index 0000000..61025bc
--- /dev/null
+++ b/contrib/tcsh/config.h.in
@@ -0,0 +1 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
diff --git a/contrib/tcsh/config_f.h b/contrib/tcsh/config_f.h
new file mode 100644
index 0000000..4a8401c
--- /dev/null
+++ b/contrib/tcsh/config_f.h
@@ -0,0 +1,193 @@
+/* $Header: /src/pub/tcsh/config_f.h,v 3.22 1999/05/11 13:07:42 christos Exp $ */
+/*
+ * config_f.h -- configure various defines for tcsh
+ *
+ * This is included by config.h.
+ *
+ * Edit this to match your particular feelings; this is set up to the
+ * way I like it.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_config_f
+#define _h_config_f
+
+/*
+ * SHORT_STRINGS Use 16 bit characters instead of 8 bit chars
+ * This fixes up quoting problems and eases implementation
+ * of nls...
+ *
+ */
+#define SHORT_STRINGS
+
+/*
+ * NLS: Use Native Language System
+ * Routines like setlocale() are needed
+ * if you don't have <locale.h>, you don't want
+ * to define this.
+ */
+#define NLS
+
+/*
+ * NLS_CATALOGS:Use Native Language System catalogs for
+ * international messages.
+ * Routines like catopen() are needed
+ * if you don't have <nl_types.h>, you don't want
+ * to define this.
+ */
+#undef NLS_CATALOGS
+
+/*
+ * LOGINFIRST Source ~/.login before ~/.cshrc
+ */
+#undef LOGINFIRST
+
+/*
+ * VIDEFAULT Make the VI mode editor the default
+ */
+#undef VIDEFAULT
+
+/*
+ * KAI use "bye" command and rename "log" to "watchlog"
+ */
+#undef KAI
+
+/*
+ * TESLA drops DTR on logout. Historical note:
+ * tesla.ee.cornell.edu was a vax11/780 with a develcon
+ * switch that sometimes would not hang up.
+ */
+#undef TESLA
+
+/*
+ * DOTLAST put "." last in the default path, for security reasons
+ */
+#define DOTLAST
+
+/*
+ * NODOT Don't put "." in the default path, for security reasons
+ */
+#undef NODOT
+
+/*
+ * AUTOLOGOUT tries to determine if it should set autologout depending
+ * on the name of the tty, and environment.
+ * Does not make sense in the modern window systems!
+ */
+#define AUTOLOGOUT
+
+/*
+ * SUSPENDED Newer shells say 'Suspended' instead of 'Stopped'.
+ * Define to get the same type of messages.
+ */
+#define SUSPENDED
+
+/*
+ * KANJI Ignore meta-next, and the ISO character set. Should
+ * be used with SHORT_STRINGS
+ *
+ */
+#undef KANJI
+
+/*
+ * DSPMBYTE add variable "dspmbyte" and display multi-byte string at
+ * only output, when "dspmbyte" is set. Should be used with
+ * KANJI
+ */
+#undef DSPMBYTE
+
+/*
+ * MBYTEDEBUG when "dspmbyte" is changed, set multi-byte checktable to
+ * variable "mbytemap".
+ * (use for multi-byte table check)
+ */
+#undef MBYTEDEBUG
+
+/*
+ * NEWGRP Provide a newgrp builtin.
+ */
+#undef NEWGRP
+
+/*
+ * SYSMALLOC Use the system provided version of malloc and friends.
+ * This can be much slower and no memory statistics will be
+ * provided.
+ */
+#if defined(__MACHTEN__) || defined(PURIFY) || defined(MALLOC_TRACE) || defined(_OSD_POSIX)
+# define SYSMALLOC
+#else
+# undef SYSMALLOC
+#endif
+
+/*
+ * USE_ACCESS Use access(2) rather than stat(2) when POSIX is defined.
+ * POSIX says to use stat, but stat(2) is less accurate
+ * than access(2) for determining file access.
+ */
+#undef USE_ACCESS
+
+/*
+ * REMOTEHOST Try to determine the remote host that we logged in from
+ * using first getpeername, and then the utmp file. If
+ * successful, set $REMOTEHOST to the name or address of the
+ * host
+ */
+#define REMOTEHOST
+
+/*
+ * COLOR_LS_F Do you want to use builtin color ls-F ?
+ *
+ */
+#define COLOR_LS_F
+
+/*
+ * COLORCAT Do you want to colorful message ?
+ *
+ */
+#undef COLORCAT
+
+/*
+ * RCSID This defines if we want rcs strings in the binary or not
+ *
+ */
+#if !defined(lint) && !defined(SABER) && !defined(__CLCC__)
+# ifndef __GNUC__
+# define RCSID(id) static char *rcsid = (id);
+# else
+# define RCSID(id) static char *rcsid(const char *a) { return rcsid(a = id); }
+# endif /* !__GNUC__ */
+#else
+# define RCSID(id) /* Nothing */
+#endif /* !lint && !SABER */
+
+#endif /* _h_config_f */
diff --git a/contrib/tcsh/csh-mode.el b/contrib/tcsh/csh-mode.el
new file mode 100644
index 0000000..20fee71
--- /dev/null
+++ b/contrib/tcsh/csh-mode.el
@@ -0,0 +1,935 @@
+;; csh-mode.el --- csh (and tcsh) script editing mode for Emacs.
+;;
+;; Version: 1.2
+;; Date: April 2, 1999
+;; Maintainer: Dan Harkless <dan@wave.eng.uci.edu>
+;;
+;; Description:
+;; csh and tcsh script editing mode for Emacs.
+;;
+;; Installation:
+;; Put csh-mode.el in some directory in your load-path and load it.
+;;
+;; Usage:
+;; This major mode assists shell script writers with indentation
+;; control and control structure construct matching in much the same
+;; fashion as other programming language modes. Invoke describe-mode
+;; for more information.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Author key:
+;; DH - Dan Harkless <dan@wave.eng.uci.edu>
+;; CM - Carlo Migliorini <migliorini@sodalia.it>
+;; JR - Jack Repenning <jackr@sgi.com>
+;; GE - Gary Ellison <Gary.F.Ellison@att.com>
+;;
+;; *** REVISION HISTORY ***
+;;
+;; DATE MOD. BY REASON FOR MODIFICATION
+;; --------- -- --------------------------------------------------------------
+;; 2 Apr 99 DH 1.2: Noticed an out-of-date comment referencing .bashrc etc.
+;; 11 Dec 96 DH 1.1: ksh-mode just indented continuation lines by 1 space.
+;; csh-mode looks at the first line and indents properly to line
+;; up under the open-paren, quote, or command.
+;; 11 Dec 96 DH Added fontification for history substitutions.
+;; 10 Dec 96 DH Added indentation and fontification for labels. Added
+;; fontification for variables and backquoted strings.
+;; 9 Dec 96 DH 1.0: Brought csh-mode up to the level of functionality of
+;; the original ksh-mode.
+;; 7 Oct 96 CM 0.1: Hacked ksh-mode.el into minimally functional csh-mode.el
+;; by doing search-and-replace and some keyword changes.
+;; 8 Aug 96 JR (Last modification to ksh-mode 2.6.)
+;; [...]
+;; 19 Jun 92 GE (Conception of ksh-mode.)
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defconst csh-mode-version "1.2"
+ "*Version number of this version of csh-mode")
+
+(defvar csh-mode-hook
+ '(lambda ()
+ (auto-fill-mode 1))
+ "Hook to run each time csh-mode is entered.")
+
+
+;;
+;; -------------------------------------------> Variables controlling completion
+;;
+(defvar csh-completion-list '())
+(make-variable-buffer-local 'csh-completion-list)
+(set-default 'csh-completion-list '())
+;;
+;; -type- : type number, 0:misc, 1:variable, 2:function
+;; -regexp-: regexp used to parse the script
+;; -match- : used by match-beginning/end to pickup target
+;;
+(defvar csh-completion-type-misc 0)
+(defvar csh-completion-regexp-var "\\([A-Za-z_0-9]+\\)=")
+(defvar csh-completion-type-var 1)
+(defvar csh-completion-match-var 1)
+(defvar csh-completion-regexp-var2 "\\$\\({\\|{#\\)?\\([A-Za-z_0-9]+\\)[#%:}]?")
+(defvar csh-completion-match-var2 2)
+(defvar csh-completion-regexp-function
+ "\\(function\\)?[ \t]*\\([A-Za-z_0-9]+\\)[ \t]*([ \t]*)")
+(defvar csh-completion-type-function 2)
+(defvar csh-completion-match-function 2)
+
+
+;;
+;; ------------------------------------> Variables controlling indentation style
+;;
+(defvar csh-indent 4
+ "*Indentation of csh statements with respect to containing block. A value
+of nil indicates compound list keyword \(\"do\" and \"then\"\) alignment.")
+
+(defvar csh-case-item-offset csh-indent
+ "*Additional indentation for case items within a case statement.")
+(defvar csh-case-indent nil
+ "*Additional indentation for statements under case items.")
+(defvar csh-comment-regexp "^\\s *#"
+ "*Regular expression used to recognize comments. Customize to support
+csh-like languages.")
+(defvar csh-match-and-tell t
+ "*If non-nil echo in the minibuffer the matching compound command
+for the \"breaksw\", \"end\", or \"endif\".")
+(defvar csh-tab-always-indent t
+ "*Controls the operation of the TAB key. If t (the default), always
+reindent the current line. If nil, indent the current line only if
+point is at the left margin or in the line's indentation; otherwise
+insert a tab.")
+
+
+;;
+;; ----------------------------------------> Constants containing syntax regexps
+;;
+(defconst csh-case-default-re
+ "^\\s *\\(case\\|default\\)\\b"
+ "Regexp used to locate grouping keywords case and default" )
+
+(defconst csh-case-item-re "^\\s *\\(case .*\\|default\\):"
+ "Regexp used to match case-items")
+
+(defconst csh-end-re "^\\s *end\\b"
+ "Regexp used to match keyword: end")
+
+(defconst csh-endif-re "^\\s *endif\\b"
+ "Regexp used to match keyword: endif")
+
+(defconst csh-endsw-re "^\\s *endsw\\b"
+ "Regexp used to match keyword: endsw")
+
+(defconst csh-else-re "^\\s *\\belse\\(\\b\\|$\\)"
+ "Regexp used to match keyword: else")
+
+(defconst csh-else-if-re "^\\s *\\belse if\\(\\b\\|$\\)"
+ "Regexp used to match keyword pair: else if")
+
+(defconst csh-if-re "^\\s *if\\b.+\\(\\\\\\|\\bthen\\b\\)"
+ "Regexp used to match non-one-line if statements")
+
+(defconst csh-iteration-keywords-re "^[^#\n]*\\s\"*\\b\\(while\\|foreach\\)\\b"
+ "Match one of the keywords: while, foreach")
+
+(defconst csh-keywords-re
+ "^\\s *\\(else\\b\\|foreach\\b\\|if\\b.+\\(\\\\\\|\\bthen\\b\\)\\|switch\\b\\|while\\b\\)"
+ "Regexp used to detect compound command keywords: else, if, foreach, while")
+
+(defconst csh-label-re "^\\s *[^!#$\n ]+:"
+ "Regexp used to match flow-control labels")
+
+(defconst csh-multiline-re "^.*\\\\$"
+ "Regexp used to match a line with a statement using more lines.")
+
+(defconst csh-switch-re "^\\s *switch\\b"
+ "Regexp used to match keyword: switch")
+
+
+;;
+;; ----------------------------------------> Variables controlling fontification
+;;
+(defvar csh-keywords '("@" "alias" "bg" "break" "breaksw" "case" "cd" "chdir"
+ "continue" "default" "dirs" "echo" "else" "end" "endif"
+ "endsw" "eval" "exec" "exit" "fg" "foreach" "glob" "goto"
+ "hashstat" "history" "if" "jobs" "kill" "limit" "login"
+ "logout" "limit" "notify" "onintr" "popd" "printenv"
+ "pushd" "rehash" "repeat" "set" "setenv" "shift" "source"
+ "stop" "suspend" "switch" "then" "time" "umask" "unalias"
+ "unhash" "unlimit" "unset" "unsetenv" "wait" "while"
+ ;; tcsh-keywords
+ "alloc" "bindkey" "builtins" "complete" "echotc"
+ "filetest" "hup" "log" "ls-F" "nice" "nohup" "sched"
+ "settc" "setty" "telltc" "uncomplete" "where" "which"))
+
+(require 'font-lock) ; need to do this before referring to font-lock-* below
+
+(defconst csh-font-lock-keywords
+ ;; NOTE: The order of some of the items in this list is significant. Do not
+ ;; alphabetize or otherwise blindly rearrange.
+ (list
+ ;; Comments on line 1, which are missed by syntactic fontification.
+ '("^#.*" 0 font-lock-comment-face)
+
+ ;; Label definitions (1 means first parenthesized exp in regexp).
+ '("^\\s *\\([^!#$\n ]+\\):" 1 font-lock-function-name-face)
+
+ ;; Label references.
+ '("\\b\\(goto\\|onintr\\)\\b\\s +\\([^!#$ \n\t]+\\)"
+ 2 font-lock-function-name-face)
+
+ ;; Variable settings.
+ '("\\(@\\|set\\|setenv\\)\\s +\\([0-9A-Za-z_]+\\b\\)"
+ 2 font-lock-variable-name-face)
+
+ ;; Variable references not inside of strings.
+ '("\\$[][0-9A-Za-z_#:?]+" 0 font-lock-variable-name-face)
+
+ ;; Backquoted strings. 'keep' means to just fontify non-fontified text.
+ '("`\\(.*\\)`" 1 font-lock-reference-face keep)
+
+ ;; NOTE: The following variables need to be anchored to the beginning of
+ ;; line to prevent re-fontifying text in comments. Due to this, we
+ ;; can only catch a finite number of occurrences. More can be added.
+ ;; The 't' means to override previous fontification.
+ ;;
+ ;; Variable references inside of " strings.
+ '("^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*\""
+ 1 font-lock-variable-name-face t) ; 1
+ '("^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*\\$[][0-9A-Za-z_#:?]+.*\""
+ 1 font-lock-variable-name-face t) ; 2
+ (cons (concat "^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*"
+ "\\$[][0-9A-Za-z_#:?]+.*\\$[][0-9A-Za-z_#:?]+.*\"")
+ (list 1 font-lock-variable-name-face t)) ; 3
+ ;;
+ ;; History substitutions.
+ '("^![^~= \n\t]+" 0 font-lock-reference-face t) ; BOL
+ '("^[^#\n]*[^#\\\n]\\(![^~= \n\t]+\\)" 1 font-lock-reference-face t) ; 1
+ '("^[^#\n]*[^#\\\n]\\(![^~= \n\t]+\\).*![^~= \n\t]+"
+ 1 font-lock-reference-face t) ; 2
+
+ ;; Keywords.
+ (cons (concat
+ "\\(\\<"
+ (mapconcat 'identity csh-keywords "\\>\\|\\<")
+ "\\>\\)")
+ 1)
+ ))
+
+(put 'csh-mode 'font-lock-keywords 'csh-font-lock-keywords)
+
+
+;;
+;; -------------------------------------------------------> Mode-specific tables
+;;
+(defvar csh-mode-abbrev-table nil
+ "Abbrev table used while in csh mode.")
+(define-abbrev-table 'csh-mode-abbrev-table ())
+
+(defvar csh-mode-map nil
+ "Keymap used in csh mode")
+(if csh-mode-map
+ ()
+ (setq csh-mode-map (make-sparse-keymap))
+;;(define-key csh-mode-map "\177" 'backward-delete-char-untabify)
+ (define-key csh-mode-map "\C-c\t" 'csh-completion-init-and-pickup)
+ (define-key csh-mode-map "\C-j" 'reindent-then-newline-and-indent)
+ (define-key csh-mode-map "\e\t" 'csh-complete-symbol)
+ (define-key csh-mode-map "\n" 'reindent-then-newline-and-indent)
+ (define-key csh-mode-map '[return] 'reindent-then-newline-and-indent)
+ (define-key csh-mode-map "\t" 'csh-indent-command)
+;;(define-key csh-mode-map "\t" 'csh-indent-line)
+ )
+
+(defvar csh-mode-syntax-table nil
+ "Syntax table used while in csh mode.")
+(if csh-mode-syntax-table
+ ;; If it's already set up, don't change it.
+ ()
+ ;; Else, create it from the standard table and modify entries that need to be.
+ (setq csh-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?& "." csh-mode-syntax-table) ; & -punctuation
+ (modify-syntax-entry ?* "." csh-mode-syntax-table) ; * -punctuation
+ (modify-syntax-entry ?- "." csh-mode-syntax-table) ; - -punctuation
+ (modify-syntax-entry ?= "." csh-mode-syntax-table) ; = -punctuation
+ (modify-syntax-entry ?+ "." csh-mode-syntax-table) ; + -punctuation
+ (modify-syntax-entry ?| "." csh-mode-syntax-table) ; | -punctuation
+ (modify-syntax-entry ?< "." csh-mode-syntax-table) ; < -punctuation
+ (modify-syntax-entry ?> "." csh-mode-syntax-table) ; > -punctuation
+ (modify-syntax-entry ?/ "." csh-mode-syntax-table) ; / -punctuation
+ (modify-syntax-entry ?\' "\"" csh-mode-syntax-table) ; ' -string quote
+ (modify-syntax-entry ?. "w" csh-mode-syntax-table) ; . -word constituent
+ (modify-syntax-entry ?? "w" csh-mode-syntax-table) ; ? -word constituent
+
+ ;; \n - comment ender, first character of 2-char comment sequence
+ (modify-syntax-entry ?\n "> 1" csh-mode-syntax-table) ; # -word constituent
+
+ ;; - whitespace, first character of 2-char comment sequence
+ (modify-syntax-entry ? " 1" csh-mode-syntax-table) ;
+
+ ;; \t - whitespace, first character of 2-char comment sequence
+ (modify-syntax-entry ?\t " 1" csh-mode-syntax-table) ; # -word constituent
+
+ ;; # - word constituent, second character of 2-char comment sequence
+ (modify-syntax-entry ?# "w 2" csh-mode-syntax-table) ; # -word constituent
+ )
+
+
+;;
+;; ------------------------------------------------------------------> Functions
+;;
+(defun csh-current-line ()
+ "Return the vertical position of point in the buffer.
+Top line is 1."
+ (+ (count-lines (point-min) (point))
+ (if (= (current-column) 0) 1 0))
+ )
+
+(defun csh-get-compound-level
+ (begin-re end-re anchor-point &optional balance-list)
+ "Determine how much to indent this structure. Return a list (level line)
+of the matching compound command or nil if no match found."
+ (let*
+ (;; Locate the next compound begin keyword bounded by point-min
+ (match-point (if (re-search-backward begin-re (point-min) t)
+ (match-beginning 0) 0))
+ (nest-column (if (zerop match-point)
+ 1
+ (progn
+ (goto-char match-point)
+ (current-indentation))))
+ (nest-list (cons 0 0)) ;; sentinel cons since cdr is >= 1
+ )
+ (if (zerop match-point)
+ nil ;; graceful exit from recursion
+ (progn
+ (if (nlistp balance-list)
+ (setq balance-list (list)))
+ ;; Now search forward from matching start keyword for end keyword
+ (while (and (consp nest-list) (zerop (cdr nest-list))
+ (re-search-forward end-re anchor-point t))
+ (if (not (memq (point) balance-list))
+ (progn
+ (setq balance-list (cons (point) balance-list))
+ (goto-char match-point) ;; beginning of compound cmd
+ (setq nest-list
+ (csh-get-compound-level begin-re end-re
+ anchor-point balance-list))
+ )))
+
+ (cond ((consp nest-list)
+ (if (zerop (cdr nest-list))
+ (progn
+ (goto-char match-point)
+ (cons nest-column (csh-current-line)))
+ nest-list))
+ (t nil)
+ )
+ )
+ )
+ )
+ )
+
+(defun csh-get-nest-level ()
+ "Return a 2 element list (nest-level nest-line) describing where the
+current line should nest."
+ (let ((case-fold-search)
+ (level))
+ (save-excursion
+ (forward-line -1)
+ (while (and (not (bobp))
+ (null level))
+ (if (and (not (looking-at "^\\s *$"))
+ (not (save-excursion
+ (forward-line -1)
+ (beginning-of-line)
+ (looking-at csh-multiline-re)))
+ (not (looking-at csh-comment-regexp)))
+ (setq level (cons (current-indentation)
+ (csh-current-line)))
+ (forward-line -1)
+ );; if
+ );; while
+ (if (null level)
+ (cons (current-indentation) (csh-current-line))
+ level)
+ )
+ )
+ )
+
+(defun csh-get-nester-column (nest-line)
+ "Return the column to indent to with respect to nest-line taking
+into consideration keywords and other nesting constructs."
+ (save-excursion
+ (let ((fence-post)
+ (case-fold-search)
+ (start-line (csh-current-line)))
+ ;;
+ ;; Handle case item indentation constructs for this line
+ (cond ((looking-at csh-case-item-re)
+ ;; This line is a case item...
+ (save-excursion
+ (goto-line nest-line)
+ (let ((fence-post (save-excursion (end-of-line) (point))))
+ (cond ((re-search-forward csh-switch-re fence-post t)
+ ;; If this is the first case under the switch, indent.
+ (goto-char (match-beginning 0))
+ (+ (current-indentation) csh-case-item-offset))
+
+ ((re-search-forward csh-case-item-re fence-post t)
+ ;; If this is another case right under a previous case
+ ;; without intervening code, stay at the same
+ ;; indentation.
+ (goto-char (match-beginning 0))
+ (current-indentation))
+
+ (t
+ ;; Else, this is a new case. Outdent.
+ (- (current-indentation) csh-case-item-offset))
+ )
+ )))
+ (t;; Not a case-item. What to do relative to the nest-line?
+ (save-excursion
+ (goto-line nest-line)
+ (setq fence-post (save-excursion (end-of-line) (point)))
+ (save-excursion
+ (cond
+ ;;
+ ;; Check if we are in a continued statement
+ ((and (looking-at csh-multiline-re)
+ (save-excursion
+ (goto-line (1- start-line))
+ (looking-at csh-multiline-re)))
+ (if (looking-at ".*[\'\"]\\\\")
+ ;; If this is a continued string, indent under
+ ;; opening quote.
+ (progn
+ (re-search-forward "[\'\"]")
+ (forward-char -1))
+ (if (looking-at ".*([^\)\n]*\\\\")
+ ;; Else if this is a continued parenthesized
+ ;; list, indent after paren.
+ (re-search-forward "(" fence-post t)
+ ;; Else, indent after whitespace after first word.
+ (re-search-forward "[^ \t]+[ \t]+" fence-post t)))
+ (current-column))
+
+ ;; In order to locate the column of the keyword,
+ ;; which might be embedded within a case-item,
+ ;; it is necessary to use re-search-forward.
+ ;; Search by literal case, since shell is
+ ;; case-sensitive.
+ ((re-search-forward csh-keywords-re fence-post t)
+ (goto-char (match-beginning 1))
+ (if (looking-at csh-switch-re)
+ (+ (current-indentation) csh-case-item-offset)
+ (+ (current-indentation)
+ (if (null csh-indent)
+ 2 csh-indent)
+ )))
+
+ ((re-search-forward csh-case-default-re fence-post t)
+ (if (null csh-indent)
+ (progn
+ (goto-char (match-end 1))
+ (+ (current-indentation) 1))
+ (progn
+ (goto-char (match-beginning 1))
+ (+ (current-indentation) csh-indent))
+ ))
+
+ ;;
+ ;; Now detect first statement under a case item
+ ((looking-at csh-case-item-re)
+ (if (null csh-case-indent)
+ (progn
+ (re-search-forward csh-case-item-re fence-post t)
+ (goto-char (match-end 1))
+ (+ (current-column) 1))
+ (+ (current-indentation) csh-case-indent)))
+
+ ;;
+ ;; If this is the first statement under a control-flow
+ ;; label, indent one level.
+ ((csh-looking-at-label)
+ (+ (current-indentation) csh-indent))
+
+ ;; This is hosed when using current-column
+ ;; and there is a multi-command expression as the
+ ;; nester.
+ (t (current-indentation)))
+ )
+ ));; excursion over
+ );; Not a case-item
+ );;let
+ );; excursion
+ );; defun
+
+(defun csh-indent-command ()
+ "Indent current line relative to containing block and allow for
+csh-tab-always-indent customization"
+ (interactive)
+ (let (case-fold-search)
+ (cond ((save-excursion
+ (skip-chars-backward " \t")
+ (bolp))
+ (csh-indent-line))
+ (csh-tab-always-indent
+ (save-excursion
+ (csh-indent-line)))
+ (t (insert-tab))
+ ))
+ )
+
+(defun csh-indent-line ()
+ "Indent current line as far as it should go according
+to the syntax/context"
+ (interactive)
+ (let (case-fold-search)
+ (save-excursion
+ (beginning-of-line)
+ (if (bobp)
+ nil
+ ;;
+ ;; Align this line to current nesting level
+ (let*
+ (
+ (level-list (csh-get-nest-level)) ; Where to nest against
+ ;; (last-line-level (car level-list))
+ (this-line-level (current-indentation))
+ (nester-column (csh-get-nester-column (cdr level-list)))
+ (struct-match (csh-match-structure-and-reindent))
+ )
+ (if struct-match
+ (setq nester-column struct-match))
+ (if (eq nester-column this-line-level)
+ nil
+ (beginning-of-line)
+ (let ((beg (point)))
+ (back-to-indentation)
+ (delete-region beg (point)))
+ (indent-to nester-column))
+ );; let*
+ );; if
+ );; excursion
+ ;;
+ ;; Position point on this line
+ (let*
+ (
+ (this-line-level (current-indentation))
+ (this-bol (save-excursion
+ (beginning-of-line)
+ (point)))
+ (this-point (- (point) this-bol))
+ )
+ (cond ((> this-line-level this-point);; point in initial white space
+ (back-to-indentation))
+ (t nil)
+ );; cond
+ );; let*
+ );; let
+ );; defun
+
+(defun csh-indent-region (start end)
+ "From start to end, indent each line."
+ ;; The algorithm is just moving through the region line by line with
+ ;; the match noise turned off. Only modifies nonempty lines.
+ (save-excursion
+ (let (csh-match-and-tell
+ (endmark (copy-marker end)))
+
+ (goto-char start)
+ (beginning-of-line)
+ (setq start (point))
+ (while (> (marker-position endmark) start)
+ (if (not (and (bolp) (eolp)))
+ (csh-indent-line))
+ (forward-line 1)
+ (setq start (point)))
+
+ (set-marker endmark nil)
+ )
+ )
+ )
+
+(defun csh-line-to-string ()
+ "From point, construct a string from all characters on
+current line"
+ (skip-chars-forward " \t") ;; skip tabs as well as spaces
+ (buffer-substring (point)
+ (progn
+ (end-of-line 1)
+ (point))))
+
+(defun csh-looking-at-label ()
+ "Return true if current line is a label (not the default: case label)."
+ (and
+ (looking-at csh-label-re)
+ (not (looking-at "^\\s *default:"))))
+
+(defun csh-match-indent-level (begin-re end-re)
+ "Match the compound command and indent. Return nil on no match,
+indentation to use for this line otherwise."
+ (interactive)
+ (let* ((case-fold-search)
+ (nest-list
+ (save-excursion
+ (csh-get-compound-level begin-re end-re (point))
+ ))
+ ) ;; bindings
+ (if (null nest-list)
+ (progn
+ (if csh-match-and-tell
+ (message "No matching compound command"))
+ nil) ;; Propagate a miss.
+ (let* (
+ (nest-level (car nest-list))
+ (match-line (cdr nest-list))
+ ) ;; bindings
+ (if csh-match-and-tell
+ (save-excursion
+ (goto-line match-line)
+ (message "Matched ... %s" (csh-line-to-string))
+ ) ;; excursion
+ ) ;; if csh-match-and-tell
+ nest-level ;;Propagate a hit.
+ ) ;; let*
+ ) ;; if
+ ) ;; let*
+ ) ;; defun csh-match-indent-level
+
+(defun csh-match-structure-and-reindent ()
+ "If the current line matches one of the indenting keywords
+or one of the control structure ending keywords then reindent. Also
+if csh-match-and-tell is non-nil the matching structure will echo in
+the minibuffer"
+ (interactive)
+ (let (case-fold-search)
+ (save-excursion
+ (beginning-of-line)
+ (cond ((looking-at csh-else-re)
+ (csh-match-indent-level csh-if-re csh-endif-re))
+ ((looking-at csh-else-if-re)
+ (csh-match-indent-level csh-if-re csh-endif-re))
+ ((looking-at csh-endif-re)
+ (csh-match-indent-level csh-if-re csh-endif-re))
+ ((looking-at csh-end-re)
+ (csh-match-indent-level csh-iteration-keywords-re csh-end-re))
+ ((looking-at csh-endsw-re)
+ (csh-match-indent-level csh-switch-re csh-endsw-re))
+ ((csh-looking-at-label)
+ ;; Flush control-flow labels left since they don't nest.
+ 0)
+ ;;
+ (t nil)
+ );; cond
+ )
+ ))
+
+;;;###autoload
+(defun csh-mode ()
+ "csh-mode 2.0 - Major mode for editing csh and tcsh scripts.
+Special key bindings and commands:
+\\{csh-mode-map}
+Variables controlling indentation style:
+csh-indent
+ Indentation of csh statements with respect to containing block.
+ Default value is 4.
+csh-case-indent
+ Additional indentation for statements under case items.
+ Default value is nil which will align the statements one position
+ past the \")\" of the pattern.
+csh-case-item-offset
+ Additional indentation for case items within a case statement.
+ Default value is 2.
+csh-tab-always-indent
+ Controls the operation of the TAB key. If t (the default), always
+ reindent the current line. If nil, indent the current line only if
+ point is at the left margin or in the line's indentation; otherwise
+ insert a tab.
+csh-match-and-tell
+ If non-nil echo in the minibuffer the matching compound command
+ for the \"done\", \"}\", \"fi\", or \"endsw\". Default value is t.
+
+csh-comment-regexp
+ Regular expression used to recognize comments. Customize to support
+ csh-like languages. Default value is \"\^\\\\s *#\".
+
+Style Guide.
+ By setting
+ (setq csh-indent default-tab-width)
+
+ The following style is obtained:
+
+ if [ -z $foo ]
+ then
+ bar # <-- csh-group-offset is additive to csh-indent
+ foo
+ fi
+
+ By setting
+ (setq csh-indent default-tab-width)
+ (setq csh-group-offset (- 0 csh-indent))
+
+ The following style is obtained:
+
+ if [ -z $foo ]
+ then
+ bar
+ foo
+ fi
+
+ By setting
+ (setq csh-case-item-offset 1)
+ (setq csh-case-indent nil)
+
+ The following style is obtained:
+
+ case x in *
+ foo) bar # <-- csh-case-item-offset
+ baz;; # <-- csh-case-indent aligns with \")\"
+ foobar) foo
+ bar;;
+ endsw
+
+ By setting
+ (setq csh-case-item-offset 1)
+ (setq csh-case-indent 6)
+
+ The following style is obtained:
+
+ case x in *
+ foo) bar # <-- csh-case-item-offset
+ baz;; # <-- csh-case-indent
+ foobar) foo
+ bar;;
+ endsw
+
+
+Installation:
+ Put csh-mode.el in some directory in your load-path.
+ Put the following forms in your .emacs file.
+
+ (setq auto-mode-alist
+ (append auto-mode-alist
+ (list
+ '(\"\\\\.csh$\" . csh-mode)
+ '(\"\\\\.login\" . csh-mode))))
+
+ (setq csh-mode-hook
+ (function (lambda ()
+ (font-lock-mode 1) ;; font-lock the buffer
+ (setq csh-indent 8)
+ (setq csh-tab-always-indent t)
+ (setq csh-match-and-tell t)
+ (setq csh-align-to-keyword t) ;; Turn on keyword alignment
+ )))"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map csh-mode-map)
+ (setq major-mode 'csh-mode)
+ (setq mode-name "Csh")
+ (setq local-abbrev-table csh-mode-abbrev-table)
+ (set-syntax-table csh-mode-syntax-table)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'csh-indent-line)
+ (make-local-variable 'indent-region-function)
+ (setq indent-region-function 'csh-indent-region)
+ (make-local-variable 'comment-start)
+ (setq comment-start "# ")
+ (make-local-variable 'comment-end)
+ (setq comment-end "")
+ (make-local-variable 'comment-column)
+ (setq comment-column 32)
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "#+ *")
+ ;;
+ ;; config font-lock mode
+ (make-local-variable 'font-lock-keywords)
+ (setq font-lock-keywords csh-font-lock-keywords)
+ ;;
+ ;; Let the user customize
+ (run-hooks 'csh-mode-hook)
+ ) ;; defun
+
+;;
+;; Completion code supplied by Haavard Rue <hrue@imf.unit.no>.
+;;
+;;
+;; add a completion with a given type to the list
+;;
+(defun csh-addto-alist (completion type)
+ (setq csh-completion-list
+ (append csh-completion-list
+ (list (cons completion type)))))
+
+(defun csh-bol-point ()
+ (save-excursion
+ (beginning-of-line)
+ (point)))
+
+(defun csh-complete-symbol ()
+ "Perform completion."
+ (interactive)
+ (let* ((case-fold-search)
+ (end (point))
+ (beg (unwind-protect
+ (save-excursion
+ (backward-sexp 1)
+ (while (= (char-syntax (following-char)) ?\')
+ (forward-char 1))
+ (point))))
+ (pattern (buffer-substring beg end))
+ (predicate
+ ;;
+ ;; ` or $( mark a function
+ ;;
+ (save-excursion
+ (goto-char beg)
+ (if (or
+ (save-excursion
+ (backward-char 1)
+ (looking-at "`"))
+ (save-excursion
+ (backward-char 2)
+ (looking-at "\\$(")))
+ (function (lambda (sym)
+ (equal (cdr sym) csh-completion-type-function)))
+ ;;
+ ;; a $, ${ or ${# mark a variable
+ ;;
+ (if (or
+ (save-excursion
+ (backward-char 1)
+ (looking-at "\\$"))
+ (save-excursion
+ (backward-char 2)
+ (looking-at "\\${"))
+ (save-excursion
+ (backward-char 3)
+ (looking-at "\\${#")))
+ (function (lambda (sym)
+ (equal (cdr sym)
+ csh-completion-type-var)))
+ ;;
+ ;; don't know. use 'em all
+ ;;
+ (function (lambda (sym) t))))))
+ ;;
+ (completion (try-completion pattern csh-completion-list predicate)))
+ ;;
+ (cond ((eq completion t))
+ ;;
+ ;; oops, what is this ?
+ ;;
+ ((null completion)
+ (message "Can't find completion for \"%s\"" pattern))
+ ;;
+ ;; insert
+ ;;
+ ((not (string= pattern completion))
+ (delete-region beg end)
+ (insert completion))
+ ;;
+ ;; write possible completion in the minibuffer,
+ ;; use this instead of a seperate buffer (usual)
+ ;;
+ (t
+ (let ((list (all-completions pattern csh-completion-list predicate))
+ (string ""))
+ (while list
+ (progn
+ (setq string (concat string (format "%s " (car list))))
+ (setq list (cdr list))))
+ (message string))))))
+
+;;
+;; init the list and pickup all
+;;
+(defun csh-completion-init-and-pickup ()
+ (interactive)
+ (let (case-fold-search)
+ (csh-completion-list-init)
+ (csh-pickup-all)))
+
+;;
+;; init the list
+;;
+(defun csh-completion-list-init ()
+ (interactive)
+ (setq csh-completion-list
+ (list
+ (cons "break" csh-completion-type-misc)
+ (cons "breaksw" csh-completion-type-misc)
+ (cons "case" csh-completion-type-misc)
+ (cons "continue" csh-completion-type-misc)
+ (cons "endif" csh-completion-type-misc)
+ (cons "exit" csh-completion-type-misc)
+ (cons "foreach" csh-completion-type-misc)
+ (cons "if" csh-completion-type-misc)
+ (cons "while" csh-completion-type-misc))))
+
+(defun csh-eol-point ()
+ (save-excursion
+ (end-of-line)
+ (point)))
+
+(defun csh-pickup-all ()
+ "Pickup all completions in buffer."
+ (interactive)
+ (csh-pickup-completion-driver (point-min) (point-max) t))
+
+(defun csh-pickup-completion (regexp type match pmin pmax)
+ "Pickup completion in region and addit to the list, if not already
+there."
+ (let ((i 0) kw obj)
+ (save-excursion
+ (goto-char pmin)
+ (while (and
+ (re-search-forward regexp pmax t)
+ (match-beginning match)
+ (setq kw (buffer-substring
+ (match-beginning match)
+ (match-end match))))
+ (progn
+ (setq obj (assoc kw csh-completion-list))
+ (if (or (equal nil obj)
+ (and (not (equal nil obj))
+ (not (= type (cdr obj)))))
+ (progn
+ (setq i (1+ i))
+ (csh-addto-alist kw type))))))
+ i))
+
+(defun csh-pickup-completion-driver (pmin pmax message)
+ "Driver routine for csh-pickup-completion."
+ (if message
+ (message "pickup completion..."))
+ (let* (
+ (i1
+ (csh-pickup-completion csh-completion-regexp-var
+ csh-completion-type-var
+ csh-completion-match-var
+ pmin pmax))
+ (i2
+ (csh-pickup-completion csh-completion-regexp-var2
+ csh-completion-type-var
+ csh-completion-match-var2
+ pmin pmax))
+ (i3
+ (csh-pickup-completion csh-completion-regexp-function
+ csh-completion-type-function
+ csh-completion-match-function
+ pmin pmax)))
+ (if message
+ (message "pickup %d variables and %d functions." (+ i1 i2) i3))))
+
+(defun csh-pickup-this-line ()
+ "Pickup all completions in current line."
+ (interactive)
+ (csh-pickup-completion-driver (csh-bol-point) (csh-eol-point) nil))
+
+
+(provide 'csh-mode)
+;;; csh-mode.el ends here
diff --git a/contrib/tcsh/ed.chared.c b/contrib/tcsh/ed.chared.c
new file mode 100644
index 0000000..7703bbe
--- /dev/null
+++ b/contrib/tcsh/ed.chared.c
@@ -0,0 +1,4005 @@
+/* $Header: /src/pub/tcsh/ed.chared.c,v 3.59 1999/08/13 16:34:57 christos Exp $ */
+/*
+ * ed.chared.c: Character editing functions.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
+
+ e_dabbrev_expand() did not do proper completion if quoted spaces were present
+ in the string being completed. Exemple:
+
+ # echo hello\ world
+ hello world
+ # echo h<press key bound to dabbrev-expande>
+ # echo hello\<cursor>
+
+ Correct behavior is:
+ # echo h<press key bound to dabbrev-expande>
+ # echo hello\ world<cursor>
+
+ The same problem occured if spaces were present in a string withing quotation
+ marks. Example:
+
+ # echo "hello world"
+ hello world
+ # echo "h<press key bound to dabbrev-expande>
+ # echo "hello<cursor>
+
+ The former problem could be solved with minor modifications of c_preword()
+ and c_endword(). The latter, however, required a significant rewrite of
+ c_preword(), since quoted strings must be parsed from start to end to
+ determine if a given character is inside or outside the quotation marks.
+
+ Compare the following two strings:
+
+ # echo \"" 'foo \' bar\"
+ " 'foo \' bar\
+ # echo '\"" 'foo \' bar\"
+ \"" foo ' bar"
+
+ The only difference between the two echo lines is in the first character
+ after the echo command. The result is either one or three arguments.
+
+ */
+
+#include "sh.h"
+
+RCSID("$Id: ed.chared.c,v 3.59 1999/08/13 16:34:57 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+#include "ed.defns.h"
+
+/* #define SDEBUG */
+
+#define TCSHOP_NOP 0x00
+#define TCSHOP_DELETE 0x01
+#define TCSHOP_INSERT 0x02
+#define TCSHOP_CHANGE 0x04
+
+#define CHAR_FWD 0
+#define CHAR_BACK 1
+
+/*
+ * vi word treatment
+ * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
+ */
+#define C_CLASS_WHITE 1
+#define C_CLASS_ALNUM 2
+#define C_CLASS_OTHER 3
+
+static Char *InsertPos = InputBuf; /* Where insertion starts */
+static Char *ActionPos = 0; /* Where action begins */
+static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */
+/*
+ * Word search state
+ */
+static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
+static Char patbuf[INBUFSIZE]; /* Search target */
+static int patlen = 0;
+/*
+ * Char search state
+ */
+static int srch_dir = CHAR_FWD; /* Direction of last search */
+static Char srch_char = 0; /* Search target */
+
+/* all routines that start with c_ are private to this set of routines */
+static void c_alternativ_key_map __P((int));
+static void c_insert __P((int));
+static void c_delafter __P((int));
+static void c_delbefore __P((int));
+static int c_to_class __P((int));
+static Char *c_prev_word __P((Char *, Char *, int));
+static Char *c_next_word __P((Char *, Char *, int));
+static Char *c_number __P((Char *, int *, int));
+static Char *c_expand __P((Char *));
+static void c_excl __P((Char *));
+static void c_substitute __P((void));
+static void c_delfini __P((void));
+static int c_hmatch __P((Char *));
+static void c_hsetpat __P((void));
+#ifdef COMMENT
+static void c_get_word __P((Char **, Char **));
+#endif
+static Char *c_preword __P((Char *, Char *, int));
+static Char *c_nexword __P((Char *, Char *, int));
+static Char *c_endword __P((Char *, Char *, int));
+static Char *c_eword __P((Char *, Char *, int));
+static CCRETVAL c_get_histline __P((void));
+static CCRETVAL c_search_line __P((Char *, int));
+static CCRETVAL v_repeat_srch __P((int));
+static CCRETVAL e_inc_search __P((int));
+static CCRETVAL v_search __P((int));
+static CCRETVAL v_csearch_fwd __P((int, int, int));
+static CCRETVAL v_action __P((int));
+static CCRETVAL v_csearch_back __P((int, int, int));
+
+#if defined(DSPMBYTE)
+static void e_charfwd_mbyte __P((int));
+static void e_charback_mbyte __P((int));
+static int extdel;
+static int extins = 0;
+#endif
+
+static void
+c_alternativ_key_map(state)
+ int state;
+{
+ switch (state) {
+ case 0:
+ CurrentKeyMap = CcKeyMap;
+ break;
+ case 1:
+ CurrentKeyMap = CcAltMap;
+ break;
+ default:
+ return;
+ }
+
+ AltKeyMap = (Char) state;
+}
+
+static void
+c_insert(num)
+ register int num;
+{
+ register Char *cp;
+
+ if (LastChar + num >= InputLim)
+ return; /* can't go past end of buffer */
+
+ if (Cursor < LastChar) { /* if I must move chars */
+ for (cp = LastChar; cp >= Cursor; cp--)
+ cp[num] = *cp;
+ }
+ LastChar += num;
+}
+
+static void
+c_delafter(num)
+ register int num;
+{
+ register Char *cp, *kp = NULL;
+
+#if defined(DSPMBYTE)
+ Char *wkcp;
+
+ extdel = 0;
+#endif
+
+ if (num > LastChar - Cursor)
+ num = (int) (LastChar - Cursor); /* bounds check */
+
+ if (num > 0) { /* if I can delete anything */
+#if defined(DSPMBYTE)
+ /* check for code of deleted character */
+ if (_enable_mbdisp) {
+ for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) {
+ if (extdel == 0)
+ extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
+ else
+ extdel = 0; /* if 2nd. byte, force set to 0 */
+ }
+ }
+#endif
+ if (VImode) {
+ kp = UndoBuf; /* Set Up for VI undo command */
+ UndoAction = TCSHOP_INSERT;
+ UndoSize = num;
+ UndoPtr = Cursor;
+ for (cp = Cursor; cp <= LastChar; cp++) {
+ *kp++ = *cp; /* Save deleted chars into undobuf */
+ *cp = cp[num];
+ }
+ }
+ else
+ for (cp = Cursor; cp <= LastChar; cp++)
+ *cp = cp[num];
+ LastChar -= num;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) {
+ if( VImode ) {
+ UndoSize++;
+ *kp++ = *Cursor; /* Save deleted chars into undobuf */
+ }
+ for (cp = Cursor; cp <= LastChar; cp++)
+ *cp = cp[1];
+ LastChar--;
+ e_redisp( 1 );
+ }
+ else
+ extdel = 0;
+#endif
+ }
+#ifdef notdef
+ else {
+ /*
+ * XXX: We don't want to do that. In emacs mode overwrite should be
+ * sticky. I am not sure how that affects vi mode
+ */
+ inputmode = MODE_INSERT;
+ }
+#endif /* notdef */
+}
+
+static void
+c_delbefore(num) /* delete before dot, with bounds checking */
+ register int num;
+{
+ register Char *cp, *kp = NULL;
+
+#if defined(DSPMBYTE)
+ Char *nowcur, *wkcp;
+ Char delc;
+
+ extdel = 0;
+#endif
+
+ if (num > Cursor - InputBuf)
+ num = (int) (Cursor - InputBuf); /* bounds check */
+
+ if (num > 0) { /* if I can delete anything */
+#if defined(DSPMBYTE)
+ nowcur = Cursor - num;
+ delc = *nowcur;
+#endif
+ if (VImode) {
+ kp = UndoBuf; /* Set Up for VI undo command */
+ UndoAction = TCSHOP_INSERT;
+ UndoSize = num;
+ UndoPtr = Cursor - num;
+ for (cp = Cursor - num; cp <= LastChar; cp++) {
+ *kp++ = *cp;
+ *cp = cp[num];
+ }
+ }
+ else
+ for (cp = Cursor - num; cp <= LastChar; cp++)
+ *cp = cp[num];
+ LastChar -= num;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp) {
+ for (wkcp = InputBuf; wkcp < nowcur; wkcp++) {
+ if(extdel == 0)
+ extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
+ else
+ extdel = 0; /* if 2nd. byte, force set to 0 */
+ }
+ if (extdel && Ismbyte2(delc)) {
+ if( VImode ) {
+ UndoSize++;
+ UndoPtr--;
+ *kp++ = *(nowcur-1);
+ /* Save deleted chars into undobuf */
+ }
+ for (cp = nowcur - 1; cp <= LastChar; cp++)
+ *cp = cp[1];
+ LastChar--;
+ }
+ }
+ else
+ extdel = 0;
+#endif
+ }
+}
+
+static Char *
+c_preword(p, low, n)
+ register Char *p, *low;
+ register int n;
+{
+ while (n--) {
+ register Char *prev = low;
+ register Char *new;
+
+ while (prev < p) { /* Skip initial spaces */
+ if (!Isspace(*prev) || (Isspace(*prev) && *(prev-1) == (Char)'\\'))
+ break;
+ prev++;
+ }
+
+ new = prev;
+
+ while (new < p) {
+ prev = new;
+ new = c_endword(prev-1, p, 1); /* Skip to next space */
+ new++; /* Step away from end of word */
+ while (new <= p) { /* Skip trailing spaces */
+ if (!Isspace(*new) || (Isspace(*new) && *(new-1) == (Char)'\\'))
+ break;
+ new++;
+ }
+ }
+
+ p = prev; /* Set to previous word start */
+
+ }
+ if (p < low)
+ p = low;
+ return (p);
+}
+
+/*
+ * c_to_class() returns the class of the given character.
+ *
+ * This is used to make the c_prev_word() and c_next_word() functions
+ * work like vi's, which classify characters. A word is a sequence of
+ * characters belonging to the same class, classes being defined as
+ * follows:
+ *
+ * 1/ whitespace
+ * 2/ alphanumeric chars, + underscore
+ * 3/ others
+ */
+static int
+c_to_class(ch)
+register int ch;
+{
+ if (Isspace(ch))
+ return C_CLASS_WHITE;
+
+ if (Isdigit(ch) || Isalpha(ch) || ch == '_')
+ return C_CLASS_ALNUM;
+
+ return C_CLASS_OTHER;
+}
+
+static Char *
+c_prev_word(p, low, n)
+ register Char *p, *low;
+ register int n;
+{
+ p--;
+
+ if (!VImode) {
+ while (n--) {
+ while ((p >= low) && !isword(*p))
+ p--;
+ while ((p >= low) && isword(*p))
+ p--;
+ }
+
+ /* cp now points to one character before the word */
+ p++;
+ if (p < low)
+ p = low;
+ /* cp now points where we want it */
+ return(p);
+ }
+
+ while (n--) {
+ register int c_class;
+
+ if (p < low)
+ break;
+
+ /* scan until beginning of current word (may be all whitespace!) */
+ c_class = c_to_class(*p);
+ while ((p >= low) && c_class == c_to_class(*p))
+ p--;
+
+ /* if this was a non_whitespace word, we're ready */
+ if (c_class != C_CLASS_WHITE)
+ continue;
+
+ /* otherwise, move back to beginning of the word just found */
+ c_class = c_to_class(*p);
+ while ((p >= low) && c_class == c_to_class(*p))
+ p--;
+ }
+
+ p++; /* correct overshoot */
+
+ return (p);
+}
+
+static Char *
+c_next_word(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ if (!VImode) {
+ while (n--) {
+ while ((p < high) && !isword(*p))
+ p++;
+ while ((p < high) && isword(*p))
+ p++;
+ }
+ if (p > high)
+ p = high;
+ /* p now points where we want it */
+ return(p);
+ }
+
+ while (n--) {
+ register int c_class;
+
+ if (p >= high)
+ break;
+
+ /* scan until end of current word (may be all whitespace!) */
+ c_class = c_to_class(*p);
+ while ((p < high) && c_class == c_to_class(*p))
+ p++;
+
+ /* if this was all whitespace, we're ready */
+ if (c_class == C_CLASS_WHITE)
+ continue;
+
+ /* if we've found white-space at the end of the word, skip it */
+ while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
+ p++;
+ }
+
+ p--; /* correct overshoot */
+
+ return (p);
+}
+
+static Char *
+c_nexword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ while (n--) {
+ while ((p < high) && !Isspace(*p))
+ p++;
+ while ((p < high) && Isspace(*p))
+ p++;
+ }
+
+ if (p > high)
+ p = high;
+ /* p now points where we want it */
+ return(p);
+}
+
+/*
+ * Expand-History (originally "Magic-Space") code added by
+ * Ray Moody <ray@gibbs.physics.purdue.edu>
+ * this is a neat, but odd, addition.
+ */
+
+/*
+ * c_number: Ignore character p points to, return number appearing after that.
+ * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
+ * Return p pointing to last char used.
+ */
+
+/*
+ * dval is the number to subtract from for things like $-3
+ */
+
+static Char *
+c_number(p, num, dval)
+ register Char *p;
+ register int *num;
+ register int dval;
+{
+ register int i;
+ register int sign = 1;
+
+ if (*++p == '^') {
+ *num = 1;
+ return(p);
+ }
+ if (*p == '$') {
+ if (*++p != '-') {
+ *num = NCARGS; /* Handle $ */
+ return(--p);
+ }
+ sign = -1; /* Handle $- */
+ ++p;
+ }
+ for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
+ continue;
+ *num = (sign < 0 ? dval - i : i);
+ return(--p);
+}
+
+/*
+ * excl_expand: There is an excl to be expanded to p -- do the right thing
+ * with it and return a version of p advanced over the expanded stuff. Also,
+ * update tsh_cur and related things as appropriate...
+ */
+
+static Char *
+c_expand(p)
+ register Char *p;
+{
+ register Char *q;
+ register struct Hist *h = Histlist.Hnext;
+ register struct wordent *l;
+ int i, from, to, dval;
+ bool all_dig;
+ bool been_once = 0;
+ Char *op = p;
+ Char buf[INBUFSIZE];
+ Char *bend = buf;
+ Char *modbuf, *omodbuf;
+
+ if (!h)
+ goto excl_err;
+excl_sw:
+ switch (*(q = p + 1)) {
+
+ case '^':
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
+ break;
+
+ case '$':
+ if ((l = (h->Hlex).prev) != 0)
+ bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
+ break;
+
+ case '*':
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
+ break;
+
+ default:
+ if (been_once) { /* unknown argument */
+ /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ q -= 2;
+ break;
+ }
+ been_once = 1;
+
+ if (*q == ':') /* short form: !:arg */
+ --q;
+
+ if (*q != HIST) {
+ /*
+ * Search for a space, tab, or colon. See if we have a number (as
+ * in !1234:xyz). Remember the number.
+ */
+ for (i = 0, all_dig = 1;
+ *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
+ /*
+ * PWP: !-4 is a valid history argument too, therefore the test
+ * is if not a digit, or not a - as the first character.
+ */
+ if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
+ all_dig = 0;
+ else if (*q == '-')
+ all_dig = 2;/* we are sneeky about this */
+ else
+ i = 10 * i + *q - '0';
+ }
+ --q;
+
+ /*
+ * If we have a number, search for event i. Otherwise, search for
+ * a named event (as in !foo). (In this case, I is the length of
+ * the named event).
+ */
+ if (all_dig) {
+ if (all_dig == 2)
+ i = -i; /* make it negitive */
+ if (i < 0) /* if !-4 (for example) */
+ i = eventno + 1 + i; /* remember: i is < 0 */
+ for (; h; h = h->Hnext) {
+ if (h->Hnum == i)
+ break;
+ }
+ }
+ else {
+ for (i = (int) (q - p); h; h = h->Hnext) {
+ if ((l = &h->Hlex) != 0) {
+ if (!Strncmp(p + 1, l->next->word, (size_t) i))
+ break;
+ }
+ }
+ }
+ }
+ if (!h)
+ goto excl_err;
+ if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
+ q[1] == '$' || q[1] == '^') { /* get some args */
+ p = q[1] == ':' ? ++q : q;
+ /*
+ * Go handle !foo:*
+ */
+ if ((q[1] < '0' || q[1] > '9') &&
+ q[1] != '-' && q[1] != '$' && q[1] != '^')
+ goto excl_sw;
+ /*
+ * Go handle !foo:$
+ */
+ if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
+ goto excl_sw;
+ /*
+ * Count up the number of words in this event. Store it in dval.
+ * Dval will be fed to number.
+ */
+ dval = 0;
+ if ((l = h->Hlex.prev) != 0) {
+ for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
+ continue;
+ }
+ if (!dval)
+ goto excl_err;
+ if (q[1] == '-')
+ from = 0;
+ else
+ q = c_number(q, &from, dval);
+ if (q[1] == '-') {
+ ++q;
+ if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
+ to = dval - 1;
+ else
+ q = c_number(q, &to, dval);
+ }
+ else if (q[1] == '*') {
+ ++q;
+ to = NCARGS;
+ }
+ else {
+ to = from;
+ }
+ if (from < 0 || to < from)
+ goto excl_err;
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
+ }
+ else { /* get whole cmd */
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ }
+ break;
+ }
+
+ /*
+ * Apply modifiers, if any.
+ */
+ if (q[1] == ':') {
+ *bend = '\0';
+ modbuf = omodbuf = buf;
+ while (q[1] == ':' && modbuf != NULL) {
+ switch (q[2]) {
+ case 'r':
+ case 'e':
+ case 'h':
+ case 't':
+ case 'q':
+ case 'x':
+ case 'u':
+ case 'l':
+ if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
+ if (omodbuf != buf)
+ xfree((ptr_t) omodbuf);
+ omodbuf = modbuf;
+ }
+ ++q;
+ break;
+
+ case 'a':
+ case 'g':
+ /* Not implemented; this needs to be done before expanding
+ * lex. We don't have the words available to us anymore.
+ */
+ ++q;
+ break;
+
+ case 'p':
+ /* Ok */
+ ++q;
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ ++q;
+ break;
+ }
+ if (q[1])
+ ++q;
+ }
+ if (omodbuf != buf) {
+ (void) Strcpy(buf, omodbuf);
+ xfree((ptr_t) omodbuf);
+ bend = Strend(buf);
+ }
+ }
+
+ /*
+ * Now replace the text from op to q inclusive with the text from buf to
+ * bend.
+ */
+ q++;
+
+ /*
+ * Now replace text non-inclusively like a real CS major!
+ */
+ if (LastChar + (bend - buf) - (q - op) >= InputLim)
+ goto excl_err;
+ (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
+ (size_t) ((LastChar - q) * sizeof(Char)));
+ LastChar += (bend - buf) - (q - op);
+ Cursor += (bend - buf) - (q - op);
+ (void) memmove((ptr_t) op, (ptr_t) buf,
+ (size_t) ((bend - buf) * sizeof(Char)));
+ *LastChar = '\0';
+ return(op + (bend - buf));
+excl_err:
+ SoundBeep();
+ return(op + 1);
+}
+
+/*
+ * c_excl: An excl has been found at point p -- back up and find some white
+ * space (or the beginning of the buffer) and properly expand all the excl's
+ * from there up to the current cursor position. We also avoid (trying to)
+ * expanding '>!'
+ */
+
+static void
+c_excl(p)
+ register Char *p;
+{
+ register int i;
+ register Char *q;
+
+ /*
+ * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
+ * back p up to just before the current word.
+ */
+ if ((p[1] == ' ' || p[1] == '\t') &&
+ (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
+ for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
+ continue;
+ if (*q == '>')
+ ++p;
+ }
+ else {
+ while (*p != ' ' && *p != '\t' && p > InputBuf)
+ --p;
+ }
+
+ /*
+ * Forever: Look for history char. (Stop looking when we find the cursor.)
+ * Count backslashes. Of odd, skip history char. Return if all done.
+ * Expand if even number of backslashes.
+ */
+ for (;;) {
+ while (*p != HIST && p < Cursor)
+ ++p;
+ for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
+ continue;
+ if (i % 2 == 0)
+ ++p;
+ if (p >= Cursor)
+ return;
+ if (i % 2 == 1)
+ p = c_expand(p);
+ }
+}
+
+
+static void
+c_substitute()
+{
+ register Char *p;
+
+ /*
+ * Start p out one character before the cursor. Move it backwards looking
+ * for white space, the beginning of the line, or a history character.
+ */
+ for (p = Cursor - 1;
+ p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
+ continue;
+
+ /*
+ * If we found a history character, go expand it.
+ */
+ if (*p == HIST)
+ c_excl(p);
+ Refresh();
+}
+
+static void
+c_delfini() /* Finish up delete action */
+{
+ register int Size;
+
+ if (ActionFlag & TCSHOP_INSERT)
+ c_alternativ_key_map(0);
+
+ ActionFlag = TCSHOP_NOP;
+
+ if (ActionPos == 0)
+ return;
+
+ UndoAction = TCSHOP_INSERT;
+
+ if (Cursor > ActionPos) {
+ Size = (int) (Cursor-ActionPos);
+ c_delbefore(Size);
+ Cursor = ActionPos;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel) {
+ Cursor--;
+ e_redisp(1);
+ }
+#endif
+ RefCursor();
+ }
+ else if (Cursor < ActionPos) {
+ Size = (int)(ActionPos-Cursor);
+ c_delafter(Size);
+ }
+ else {
+ Size = 1;
+ c_delafter(Size);
+ }
+ UndoPtr = Cursor;
+ UndoSize = Size;
+}
+
+static Char *
+c_endword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ register int inquote = 0;
+ p++;
+
+ while (n--) {
+ while (p < high) { /* Skip spaces */
+ if (!Isspace(*p) || (Isspace(*p) && *(p-1) == (Char)'\\'))
+ break;
+ p++;
+ }
+ while (p < high) { /* Skip string */
+ if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
+ if ((!inquote && *(p-1) != (Char)'\\') || inquote) { /* Should it be honored? */
+ if (inquote == 0) inquote = *p;
+ else if (inquote == *p) inquote = 0;
+ }
+ }
+ if (!inquote && (Isspace(*p) && *(p-1) != (Char)'\\')) /* Break if unquoted space */
+ break;
+ p++;
+ }
+ }
+
+ p--;
+ return(p);
+}
+
+
+static Char *
+c_eword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ p++;
+
+ while (n--) {
+ while ((p < high) && Isspace(*p))
+ p++;
+
+ if (Isalnum(*p))
+ while ((p < high) && Isalnum(*p))
+ p++;
+ else
+ while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
+ p++;
+ }
+
+ p--;
+ return(p);
+}
+
+static CCRETVAL
+c_get_histline()
+{
+ struct Hist *hp;
+ int h;
+
+ if (Hist_num == 0) { /* if really the current line */
+ copyn(InputBuf, HistBuf, INBUFSIZE);
+ LastChar = InputBuf + (LastHist - HistBuf);
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+ }
+
+ hp = Histlist.Hnext;
+ if (hp == NULL)
+ return(CC_ERROR);
+
+ for (h = 1; h < Hist_num; h++) {
+ if ((hp->Hnext) == NULL) {
+ Hist_num = h;
+ return(CC_ERROR);
+ }
+ hp = hp->Hnext;
+ }
+
+ if (HistLit && hp->histline) {
+ copyn(InputBuf, hp->histline, INBUFSIZE);
+ CurrentHistLit = 1;
+ }
+ else {
+ (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex);
+ CurrentHistLit = 0;
+ }
+ LastChar = InputBuf + Strlen(InputBuf);
+
+ if (LastChar > InputBuf) {
+ if (LastChar[-1] == '\n')
+ LastChar--;
+#if 0
+ if (LastChar[-1] == ' ')
+ LastChar--;
+#endif
+ if (LastChar < InputBuf)
+ LastChar = InputBuf;
+ }
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+}
+
+static CCRETVAL
+c_search_line(pattern, dir)
+Char *pattern;
+int dir;
+{
+ Char *cp;
+ int len;
+
+ len = (int) Strlen(pattern);
+
+ if (dir == F_UP_SEARCH_HIST) {
+ for (cp = Cursor; cp >= InputBuf; cp--)
+ if (Strncmp(cp, pattern, (size_t) len) == 0 ||
+ Gmatch(cp, pattern)) {
+ Cursor = cp;
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+ } else {
+ for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
+ if (Strncmp(cp, pattern, (size_t) len) == 0 ||
+ Gmatch(cp, pattern)) {
+ Cursor = cp;
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+ }
+}
+
+static CCRETVAL
+e_inc_search(dir)
+ int dir;
+{
+ static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
+ STRbck[] = { 'b', 'c', 'k', '\0' };
+ static Char pchar = ':'; /* ':' = normal, '?' = failed */
+ static Char endcmd[2];
+ Char ch, *cp,
+ *oldCursor = Cursor,
+ oldpchar = pchar;
+ CCRETVAL ret = CC_NORM;
+ int oldHist_num = Hist_num,
+ oldpatlen = patlen,
+ newdir = dir,
+ done, redo;
+
+ if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
+ return(CC_ERROR);
+
+ for (;;) {
+
+ if (patlen == 0) { /* first round */
+ pchar = ':';
+ patbuf[patlen++] = '*';
+ }
+ done = redo = 0;
+ *LastChar++ = '\n';
+ for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
+ *cp; *LastChar++ = *cp++)
+ continue;
+ *LastChar++ = pchar;
+ for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
+ continue;
+ *LastChar = '\0';
+ Refresh();
+
+ if (GetNextChar(&ch) != 1)
+ return(e_send_eof(0));
+
+ switch (CurrentKeyMap[(unsigned char) ch]) {
+ case F_INSERT:
+ case F_DIGIT:
+ case F_MAGIC_SPACE:
+ if (patlen > INBUFSIZE - 3)
+ SoundBeep();
+ else {
+ patbuf[patlen++] = ch;
+ *LastChar++ = ch;
+ *LastChar = '\0';
+ Refresh();
+ }
+ break;
+
+ case F_INC_FWD:
+ newdir = F_DOWN_SEARCH_HIST;
+ redo++;
+ break;
+
+ case F_INC_BACK:
+ newdir = F_UP_SEARCH_HIST;
+ redo++;
+ break;
+
+ case F_DELPREV:
+ if (patlen > 1)
+ done++;
+ else
+ SoundBeep();
+ break;
+
+ default:
+ switch (ch) {
+ case 0007: /* ^G: Abort */
+ ret = CC_ERROR;
+ done++;
+ break;
+
+ case 0027: /* ^W: Append word */
+ /* No can do if globbing characters in pattern */
+ for (cp = &patbuf[1]; ; cp++)
+ if (cp >= &patbuf[patlen]) {
+ Cursor += patlen - 1;
+ cp = c_next_word(Cursor, LastChar, 1);
+ while (Cursor < cp && *Cursor != '\n') {
+ if (patlen > INBUFSIZE - 3) {
+ SoundBeep();
+ break;
+ }
+ patbuf[patlen++] = *Cursor;
+ *LastChar++ = *Cursor++;
+ }
+ Cursor = oldCursor;
+ *LastChar = '\0';
+ Refresh();
+ break;
+ } else if (isglob(*cp)) {
+ SoundBeep();
+ break;
+ }
+ break;
+
+ default: /* Terminate and execute cmd */
+ endcmd[0] = ch;
+ PushMacro(endcmd);
+ /*FALLTHROUGH*/
+
+ case 0033: /* ESC: Terminate */
+ ret = CC_REFRESH;
+ done++;
+ break;
+ }
+ break;
+ }
+
+ while (LastChar > InputBuf && *LastChar != '\n')
+ *LastChar-- = '\0';
+ *LastChar = '\0';
+
+ if (!done) {
+
+ /* Can't search if unmatched '[' */
+ for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
+ if (*cp == '[' || *cp == ']') {
+ ch = *cp;
+ break;
+ }
+
+ if (patlen > 1 && ch != '[') {
+ if (redo && newdir == dir) {
+ if (pchar == '?') { /* wrap around */
+ Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
+ if (c_get_histline() == CC_ERROR)
+ /* Hist_num was fixed by first call */
+ (void) c_get_histline();
+ Cursor = newdir == F_UP_SEARCH_HIST ?
+ LastChar : InputBuf;
+ } else
+ Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
+ }
+ patbuf[patlen++] = '*';
+ patbuf[patlen] = '\0';
+ if (Cursor < InputBuf || Cursor > LastChar ||
+ (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
+ LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
+ ret = newdir == F_UP_SEARCH_HIST ?
+ e_up_search_hist(0) : e_down_search_hist(0);
+ if (ret != CC_ERROR) {
+ Cursor = newdir == F_UP_SEARCH_HIST ?
+ LastChar : InputBuf;
+ (void) c_search_line(&patbuf[1], newdir);
+ }
+ }
+ patbuf[--patlen] = '\0';
+ if (ret == CC_ERROR) {
+ SoundBeep();
+ if (Hist_num != oldHist_num) {
+ Hist_num = oldHist_num;
+ if (c_get_histline() == CC_ERROR)
+ return(CC_ERROR);
+ }
+ Cursor = oldCursor;
+ pchar = '?';
+ } else {
+ pchar = ':';
+ }
+ }
+
+ ret = e_inc_search(newdir);
+
+ if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
+ /* break abort of failed search at last non-failed */
+ ret = CC_NORM;
+ }
+
+ }
+
+ if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
+ /* restore on normal return or error exit */
+ pchar = oldpchar;
+ patlen = oldpatlen;
+ if (Hist_num != oldHist_num) {
+ Hist_num = oldHist_num;
+ if (c_get_histline() == CC_ERROR)
+ return(CC_ERROR);
+ }
+ Cursor = oldCursor;
+ if (ret == CC_ERROR)
+ Refresh();
+ }
+ if (done || ret != CC_NORM)
+ return(ret);
+
+ }
+
+}
+
+static CCRETVAL
+v_search(dir)
+ int dir;
+{
+ Char ch;
+ Char tmpbuf[INBUFSIZE];
+ Char oldbuf[INBUFSIZE];
+ Char *oldlc, *oldc;
+ int tmplen;
+
+ copyn(oldbuf, InputBuf, INBUFSIZE);
+ oldlc = LastChar;
+ oldc = Cursor;
+ tmplen = 0;
+ tmpbuf[tmplen++] = '*';
+
+ InputBuf[0] = '\0';
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ searchdir = dir;
+
+ c_insert(2); /* prompt + '\n' */
+ *Cursor++ = '\n';
+ *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
+ Refresh();
+ for (ch = 0;ch == 0;) {
+ if (GetNextChar(&ch) != 1)
+ return(e_send_eof(0));
+ switch (ASC(ch)) {
+ case 0010: /* Delete and backspace */
+ case 0177:
+ if (tmplen > 1) {
+ *Cursor-- = '\0';
+ LastChar = Cursor;
+ tmpbuf[tmplen--] = '\0';
+ }
+ else {
+ copyn(InputBuf, oldbuf, INBUFSIZE);
+ LastChar = oldlc;
+ Cursor = oldc;
+ return(CC_REFRESH);
+ }
+ Refresh();
+ ch = 0;
+ break;
+
+ case 0033: /* ESC */
+#ifndef _OSD_POSIX
+ case '\r': /* Newline */
+ case '\n':
+#else
+ case '\012': /* Newline */
+ case '\015': /* Return */
+#endif
+ break;
+
+ default:
+ if (tmplen >= INBUFSIZE)
+ SoundBeep();
+ else {
+ tmpbuf[tmplen++] = ch;
+ *Cursor++ = ch;
+ LastChar = Cursor;
+ }
+ Refresh();
+ ch = 0;
+ break;
+ }
+ }
+
+ if (tmplen == 1) {
+ /*
+ * Use the old pattern, but wild-card it.
+ */
+ if (patlen == 0) {
+ InputBuf[0] = '\0';
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ Refresh();
+ return(CC_ERROR);
+ }
+ if (patbuf[0] != '*') {
+ (void) Strcpy(tmpbuf, patbuf);
+ patbuf[0] = '*';
+ (void) Strcpy(&patbuf[1], tmpbuf);
+ patlen++;
+ patbuf[patlen++] = '*';
+ patbuf[patlen] = '\0';
+ }
+ }
+ else {
+ tmpbuf[tmplen++] = '*';
+ tmpbuf[tmplen] = '\0';
+ (void) Strcpy(patbuf, tmpbuf);
+ patlen = tmplen;
+ }
+ LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
+ Cursor = LastChar = InputBuf;
+ if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
+ e_down_search_hist(0)) == CC_ERROR) {
+ Refresh();
+ return(CC_ERROR);
+ }
+ else {
+ if (ch == 0033) {
+ Refresh();
+ *LastChar++ = '\n';
+ *LastChar = '\0';
+ PastBottom();
+ return(CC_NEWLINE);
+ }
+ else
+ return(CC_REFRESH);
+ }
+}
+
+/*
+ * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
+ * entry point, called from the CcKeyMap indirected into the
+ * CcFuncTbl array.
+ */
+
+/*ARGSUSED*/
+CCRETVAL
+v_cmd_mode(c)
+ int c;
+{
+ USE(c);
+ InsertPos = 0;
+ ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
+ ActionPos = 0;
+ DoingArg = 0;
+ if (UndoPtr > Cursor)
+ UndoSize = (int)(UndoPtr - Cursor);
+ else
+ UndoSize = (int)(Cursor - UndoPtr);
+
+ inputmode = MODE_INSERT;
+ c_alternativ_key_map(1);
+#ifdef notdef
+ /*
+ * We don't want to move the cursor, because all the editing
+ * commands don't include the character under the cursor.
+ */
+ if (Cursor > InputBuf)
+ Cursor--;
+#endif
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_unassigned(c)
+ int c;
+{ /* bound to keys that arn't really assigned */
+ USE(c);
+ SoundBeep();
+ flush();
+ return(CC_NORM);
+}
+
+CCRETVAL
+e_insert(c)
+ register int c;
+{
+ register int i;
+#if defined(DSPMBYTE)
+ CCRETVAL ret;
+ static Char savec;
+ static int exterr = 0;
+#endif
+#ifndef SHORT_STRINGS
+ c &= ASCII; /* no meta chars ever */
+#endif
+#if defined(DSPMBYTE)
+ ret = (CCRETVAL) CC_NORM;
+#endif
+
+ if (!c)
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (LastChar + Argument >= InputLim)
+ return(CC_ERROR); /* end of buffer space */
+
+ if (Argument == 1) { /* How was this optimized ???? */
+
+#if defined(DSPMBYTE)
+ if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) {
+ extins = 0;
+ exterr = 0;
+ return(CC_ERROR);
+ }
+#endif
+ if (inputmode != MODE_INSERT) {
+ UndoBuf[UndoSize++] = *Cursor;
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(1); /* Do NOT use the saving ONE */
+ }
+
+ c_insert(1);
+
+#if defined(DSPMBYTE)
+ /* 1st. byte is store to special buffer, and replace space */
+ if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
+ extins++;
+ savec = (Char) c;
+ *Cursor++ = (Char) ' ';
+ }
+ else if (_enable_mbdisp && extins && Ismbyte2(c)) {
+ *(Cursor-1) = savec;
+ *Cursor++ = (Char) c;
+ extins = 0;
+ e_redisp(1);
+ Refresh();
+ ret = CC_REFRESH;
+ }
+ else
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ if (ret != CC_REFRESH)
+ RefPlusOne(); /* fast refresh for one char. */
+#else
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ RefPlusOne(); /* fast refresh for one char. */
+#endif
+ }
+ else {
+#if defined(DSPMBYTE)
+ /* Cannot use ESC-(number) for multi-byte */
+ if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
+ extins++;
+ exterr++;
+ return(CC_ERROR);
+ }
+ else if (_enable_mbdisp && extins && exterr && Ismbyte2(c))
+ {
+ extins = 0;
+ exterr = 0;
+ return(CC_ERROR);
+ }
+#endif
+ if (inputmode != MODE_INSERT) {
+
+ for(i=0;i<Argument;i++)
+ UndoBuf[UndoSize++] = *(Cursor+i);
+
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(Argument); /* Do NOT use the saving ONE */
+ }
+
+ c_insert(Argument);
+
+ while (Argument--)
+ *Cursor++ = (Char) c;
+ Refresh();
+ }
+
+ if (inputmode == MODE_REPLACE_1)
+ (void) v_cmd_mode(0);
+
+#if defined(DSPMBYTE)
+ return(ret);
+#else
+ return(CC_NORM);
+#endif
+}
+
+int
+InsertStr(s) /* insert ASCIZ s at cursor (for complete) */
+ Char *s;
+{
+ register int len;
+
+ if ((len = (int) Strlen(s)) <= 0)
+ return -1;
+ if (LastChar + len >= InputLim)
+ return -1; /* end of buffer space */
+
+ c_insert(len);
+ while (len--)
+ *Cursor++ = *s++;
+ return 0;
+}
+
+void
+DeleteBack(n) /* delete the n characters before . */
+ int n;
+{
+ if (n <= 0)
+ return;
+ if (Cursor >= &InputBuf[n]) {
+ c_delbefore(n); /* delete before dot */
+ if (n > Cursor - InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ else
+ Cursor -= n;
+#if defined(DSPMBYTE)
+ if(_enable_mbdisp && extdel && Cursor > InputBuf) {
+ Cursor--;
+ e_redisp(1);
+ }
+#endif
+ }
+}
+
+CCRETVAL
+e_digit(c) /* gray magic here */
+ register int c;
+{
+ if (!Isdigit(c))
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (LastCmd == F_ARGFOUR) /* if last command was ^U */
+ Argument = c - '0';
+ else {
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ }
+ return(CC_ARGHACK);
+ }
+ else {
+ if (LastChar + 1 >= InputLim)
+ return CC_ERROR; /* end of buffer space */
+
+ if (inputmode != MODE_INSERT) {
+ UndoBuf[UndoSize++] = *Cursor;
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(1); /* Do NOT use the saving ONE */
+ }
+ c_insert(1);
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ RefPlusOne(); /* fast refresh for one char. */
+ }
+ return(CC_NORM);
+}
+
+CCRETVAL
+e_argdigit(c) /* for ESC-n */
+ register int c;
+{
+ c &= ASCII;
+
+ if (!Isdigit(c))
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ }
+ else { /* else starting an argument */
+ Argument = c - '0';
+ DoingArg = 1;
+ }
+ return(CC_ARGHACK);
+}
+
+CCRETVAL
+v_zero(c) /* command mode 0 for vi */
+ register int c;
+{
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ return(CC_ARGHACK);
+ }
+ else { /* else starting an argument */
+ Cursor = InputBuf;
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_newline(c)
+ int c;
+{ /* always ignore argument */
+ USE(c);
+ /* PastBottom(); NOW done in ed.inputl.c */
+ *LastChar++ = '\n'; /* for the benefit of CSH */
+ *LastChar = '\0'; /* just in case */
+ if (VImode)
+ InsertPos = InputBuf; /* Reset editing position */
+ return(CC_NEWLINE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_send_eof(c)
+ int c;
+{ /* for when ^D is ONLY send-eof */
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_EOF);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_back(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_BACK);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_fwd(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_FWD);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_all(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_ALL);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_cm_complete(c)
+ int c;
+{
+ USE(c);
+ if (Cursor < LastChar)
+ Cursor++;
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_toggle_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num <= 0) {
+ return CC_ERROR;
+ }
+
+ hp = Histlist.Hnext;
+ if (hp == NULL) { /* this is only if no history */
+ return(CC_ERROR);
+ }
+
+ for (h = 1; h < Hist_num; h++)
+ hp = hp->Hnext;
+
+ if (!CurrentHistLit) {
+ if (hp->histline) {
+ copyn(InputBuf, hp->histline, INBUFSIZE);
+ CurrentHistLit = 1;
+ }
+ else {
+ return CC_ERROR;
+ }
+ }
+ else {
+ (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex);
+ CurrentHistLit = 0;
+ }
+
+ LastChar = InputBuf + Strlen(InputBuf);
+ if (LastChar > InputBuf) {
+ if (LastChar[-1] == '\n')
+ LastChar--;
+ if (LastChar[-1] == ' ')
+ LastChar--;
+ if (LastChar < InputBuf)
+ LastChar = InputBuf;
+ }
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_up_hist(c)
+ int c;
+{
+ Char beep = 0;
+
+ USE(c);
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num == 0) { /* save the current buffer away */
+ copyn(HistBuf, InputBuf, INBUFSIZE);
+ LastHist = HistBuf + (LastChar - InputBuf);
+ }
+
+ Hist_num += Argument;
+
+ if (c_get_histline() == CC_ERROR) {
+ beep = 1;
+ (void) c_get_histline(); /* Hist_num was fixed by first call */
+ }
+
+ Refresh();
+ if (beep)
+ return(CC_ERROR);
+ else
+ return(CC_NORM); /* was CC_UP_HIST */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_down_hist(c)
+ int c;
+{
+ USE(c);
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ Hist_num -= Argument;
+
+ if (Hist_num < 0) {
+ Hist_num = 0;
+ return(CC_ERROR); /* make it beep */
+ }
+
+ return(c_get_histline());
+}
+
+
+
+/*
+ * c_hmatch() return True if the pattern matches the prefix
+ */
+static int
+c_hmatch(str)
+Char *str;
+{
+ if (Strncmp(patbuf, str, (size_t) patlen) == 0)
+ return 1;
+ return Gmatch(str, patbuf);
+}
+
+/*
+ * c_hsetpat(): Set the history seatch pattern
+ */
+static void
+c_hsetpat()
+{
+ if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
+ patlen = (int) (Cursor - InputBuf);
+ if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
+ if (patlen >= 0) {
+ (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
+ patbuf[patlen] = '\0';
+ }
+ else
+ patlen = (int) Strlen(patbuf);
+ }
+#ifdef SDEBUG
+ xprintf("\nHist_num = %d\n", Hist_num);
+ xprintf("patlen = %d\n", patlen);
+ xprintf("patbuf = \"%S\"\n", patbuf);
+ xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
+#endif
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_up_search_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+ bool found = 0;
+
+ USE(c);
+ ActionFlag = TCSHOP_NOP;
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+ if (Hist_num < 0) {
+#ifdef DEBUG_EDIT
+ xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
+#endif
+ Hist_num = 0;
+ return(CC_ERROR);
+ }
+
+ if (Hist_num == 0)
+ {
+ copyn(HistBuf, InputBuf, INBUFSIZE);
+ LastHist = HistBuf + (LastChar - InputBuf);
+ }
+
+
+ hp = Histlist.Hnext;
+ if (hp == NULL)
+ return(CC_ERROR);
+
+ c_hsetpat(); /* Set search pattern !! */
+
+ for (h = 1; h <= Hist_num; h++)
+ hp = hp->Hnext;
+
+ while (hp != NULL) {
+ Char sbuf[INBUFSIZE], *hl;
+ if (hp->histline == NULL) {
+ hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex));
+ }
+ hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex);
+#ifdef SDEBUG
+ xprintf("Comparing with \"%S\"\n", hl);
+#endif
+ if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
+ hl[LastChar-InputBuf]) && c_hmatch(hl)) {
+ found++;
+ break;
+ }
+ h++;
+ hp = hp->Hnext;
+ }
+
+ if (!found) {
+#ifdef SDEBUG
+ xprintf("not found\n");
+#endif
+ return(CC_ERROR);
+ }
+
+ Hist_num = h;
+
+ return(c_get_histline());
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_down_search_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+ bool found = 0;
+
+ USE(c);
+ ActionFlag = TCSHOP_NOP;
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num == 0)
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ if (hp == 0)
+ return(CC_ERROR);
+
+ c_hsetpat(); /* Set search pattern !! */
+
+ for (h = 1; h < Hist_num && hp; h++) {
+ Char sbuf[INBUFSIZE], *hl;
+ if (hp->histline == NULL) {
+ hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex));
+ }
+ hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex);
+#ifdef SDEBUG
+ xprintf("Comparing with \"%S\"\n", hl);
+#endif
+ if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
+ hl[LastChar-InputBuf]) && c_hmatch(hl))
+ found = h;
+ hp = hp->Hnext;
+ }
+
+ if (!found) { /* is it the current history number? */
+ if (!c_hmatch(HistBuf)) {
+#ifdef SDEBUG
+ xprintf("not found\n");
+#endif
+ return(CC_ERROR);
+ }
+ }
+
+ Hist_num = found;
+
+ return(c_get_histline());
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_helpme(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_HELPME);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_correct(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_CORRECT);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_correctl(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_CORRECT_L);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_run_fg_editor(c)
+ int c;
+{
+ register struct process *pp;
+ extern bool tellwhat;
+
+ USE(c);
+ if ((pp = find_stop_ed()) != NULL) {
+ /* save our editor state so we can restore it */
+ tellwhat = 1;
+ copyn(WhichBuf, InputBuf, INBUFSIZE);
+ LastWhich = WhichBuf + (LastChar - InputBuf);
+ CursWhich = WhichBuf + (Cursor - InputBuf);
+ HistWhich = Hist_num;
+ Hist_num = 0; /* for the history commands */
+
+ /* put the tty in a sane mode */
+ PastBottom();
+ (void) Cookedmode(); /* make sure the tty is set up correctly */
+
+ /* do it! */
+ fg_proc_entry(pp);
+
+ (void) Rawmode(); /* go on */
+ Refresh();
+ tellwhat = 0;
+ }
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_choices(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_all(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_ALL);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_glob(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_GLOB);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_glob(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_EXPAND_GLOB);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_normalize_path(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_NORMALIZE_PATH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_normalize_command(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_NORMALIZE_COMMAND);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_vars(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_EXPAND_VARS);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_which(c)
+ int c;
+{ /* do a fast command line which(1) */
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_WHICH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_last_item(c)
+ int c;
+{ /* insert the last element of the prev. cmd */
+ register Char *cp;
+ register struct Hist *hp;
+ register struct wordent *wp, *firstp;
+ register int i;
+ Char buf[INBUFSIZE];
+
+ USE(c);
+ if (Argument <= 0)
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ if (hp == NULL) { /* this is only if no history */
+ return(CC_ERROR);
+ }
+
+ wp = (hp->Hlex).prev;
+
+ if (wp->prev == (struct wordent *) NULL)
+ return(CC_ERROR); /* an empty history entry */
+
+ firstp = (hp->Hlex).next;
+
+ /* back up arg words in lex */
+ for (i = 0; i < Argument && wp != firstp; i++) {
+ wp = wp->prev;
+ }
+
+ cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
+ *cp = '\0';
+ if (InsertStr(buf))
+ return(CC_ERROR);
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_dabbrev_expand(c)
+ int c;
+{ /* expand to preceding word matching prefix */
+ register Char *cp, *ncp, *bp;
+ register struct Hist *hp;
+ register int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
+ register bool found = 0;
+ Char hbuf[INBUFSIZE];
+ static int oldevent, hist, word;
+ static Char *start, *oldcursor;
+
+ USE(c);
+ if (Argument <= 0)
+ return(CC_ERROR);
+
+ cp = c_preword(Cursor, InputBuf, 1);
+ if (cp == Cursor || Isspace(*cp))
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ bp = InputBuf;
+ if (Argument == 1 && eventno == oldevent && cp == start &&
+ Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
+ /* continue previous search - go to last match (hist/word) */
+ if (hist != 0) { /* need to move up history */
+ for (i = 1; i < hist && hp != NULL; i++)
+ hp = hp->Hnext;
+ if (hp == NULL) /* "can't happen" */
+ return(CC_ERROR);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ *cp = '\0';
+ bp = hbuf;
+ hp = hp->Hnext;
+ }
+ cp = c_preword(cp, bp, word);
+ } else { /* starting new search */
+ oldevent = eventno;
+ start = cp;
+ patlen = (int) (Cursor - cp);
+ (void) Strncpy(patbuf, cp, patlen);
+ hist = 0;
+ word = 0;
+ }
+
+ while (!found) {
+ ncp = c_preword(cp, bp, 1);
+ if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
+ hist++;
+ word = 0;
+ if (hp == NULL)
+ return(CC_ERROR);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ *cp = '\0';
+ bp = hbuf;
+ hp = hp->Hnext;
+ continue;
+ } else {
+ word++;
+ len = (int) (c_endword(ncp-1, cp, 1) - ncp + 1);
+ cp = ncp;
+ }
+ if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
+ /* We don't fully check distinct matches as Gnuemacs does: */
+ if (Argument > 1) { /* just count matches */
+ if (++arg >= Argument)
+ found++;
+ } else { /* match if distinct from previous */
+ if (len != Cursor - start || Strncmp(cp, start, len) != 0)
+ found++;
+ }
+ }
+ }
+
+ if (LastChar + len - (Cursor - start) >= InputLim)
+ return(CC_ERROR); /* no room */
+ DeleteBack(Cursor - start);
+ c_insert(len);
+ while (len--)
+ *Cursor++ = *cp++;
+ oldcursor = Cursor;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_yank_kill(c)
+ int c;
+{ /* almost like GnuEmacs */
+ register Char *kp, *cp;
+
+ USE(c);
+ if (LastKill == KillBuf) /* if zero content */
+ return(CC_ERROR);
+
+ if (LastChar + (LastKill - KillBuf) >= InputLim)
+ return(CC_ERROR); /* end of buffer space */
+
+ /* else */
+ Mark = Cursor; /* set the mark */
+ cp = Cursor; /* for speed */
+
+ c_insert((int)(LastKill - KillBuf)); /* open the space, */
+ for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */
+ *cp++ = *kp;
+
+ if (Argument == 1) /* if an arg, cursor at beginning */
+ Cursor = cp; /* else cursor at end */
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_delprev(c) /* Backspace key in insert mode */
+ int c;
+{
+ int rc;
+
+ USE(c);
+ rc = CC_ERROR;
+
+ if (InsertPos != 0) {
+ if (Argument <= Cursor - InsertPos) {
+ c_delbefore(Argument); /* delete before */
+ Cursor -= Argument;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel) {
+ Cursor--;
+ e_redisp(c);
+ }
+#endif
+ rc = CC_REFRESH;
+ }
+ }
+ return(rc);
+} /* v_delprev */
+
+/*ARGSUSED*/
+CCRETVAL
+e_delprev(c)
+ int c;
+{
+ USE(c);
+ if (Cursor > InputBuf) {
+ c_delbefore(Argument); /* delete before dot */
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ else
+ Cursor -= Argument;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel && Cursor > InputBuf) {
+ Cursor--;
+ e_redisp(c);
+ }
+#endif
+ return(CC_REFRESH);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delwordprev(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ cp = c_prev_word(Cursor, InputBuf, Argument);
+
+ for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */
+ *kp++ = *p;
+ LastKill = kp;
+
+ c_delbefore((int)(Cursor - cp)); /* delete before dot */
+ Cursor = cp;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
+ *
+ * Changed the names of some of the ^D family of editor functions to
+ * correspond to what they actually do and created new e_delnext_list
+ * for completeness.
+ *
+ * Old names: New names:
+ *
+ * delete-char delete-char-or-eof
+ * F_DELNEXT F_DELNEXT_EOF
+ * e_delnext e_delnext_eof
+ * edelnxt edelnxteof
+ * delete-char-or-eof delete-char
+ * F_DELNEXT_EOF F_DELNEXT
+ * e_delnext_eof e_delnext
+ * edelnxteof edelnxt
+ * delete-char-or-list delete-char-or-list-or-eof
+ * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
+ * e_list_delnext e_delnext_list_eof
+ * edellsteof
+ * (no old equivalent) delete-char-or-list
+ * F_DELNEXT_LIST
+ * e_delnext_list
+ * e_delnxtlst
+ */
+
+/* added by mtk@ari.ncl.omron.co.jp (920818) */
+/* rename e_delnext() -> e_delnext_eof() */
+/*ARGSUSED*/
+CCRETVAL
+e_delnext(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) {/* if I'm at the end */
+ if (!VImode) {
+ return(CC_ERROR);
+ }
+ else {
+ if (Cursor != InputBuf)
+ Cursor--;
+ else
+ return(CC_ERROR);
+ }
+ }
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_eof(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) {/* if I'm at the end */
+ if (!VImode) {
+ if (Cursor == InputBuf) {
+ /* if I'm also at the beginning */
+ so_write(STReof, 4);/* then do a EOF */
+ flush();
+ return(CC_EOF);
+ }
+ else
+ return(CC_ERROR);
+ }
+ else {
+ if (Cursor != InputBuf)
+ Cursor--;
+ else
+ return(CC_ERROR);
+ }
+ }
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_list(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) { /* if I'm at the end */
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+ }
+ else {
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_list_eof(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) { /* if I'm at the end */
+ if (Cursor == InputBuf) { /* if I'm also at the beginning */
+ so_write(STReof, 4);/* then do a EOF */
+ flush();
+ return(CC_EOF);
+ }
+ else {
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+ }
+ }
+ else {
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_eof(c)
+ int c;
+{
+ CCRETVAL rv;
+
+ USE(c);
+ if (Cursor == LastChar && Cursor == InputBuf) {
+ so_write(STReof, 4); /* then do a EOF */
+ flush();
+ rv = CC_EOF;
+ }
+ else {
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ rv = CC_LIST_CHOICES;
+ }
+ return rv;
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delwordnext(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ cp = c_next_word(Cursor, LastChar, Argument);
+
+ for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */
+ *kp++ = *p;
+ LastKill = kp;
+
+ c_delafter((int)(cp - Cursor)); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_toend(c)
+ int c;
+{
+ USE(c);
+ Cursor = LastChar;
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tobeg(c)
+ int c;
+{
+ USE(c);
+ Cursor = InputBuf;
+
+ if (VImode) {
+ while (Isspace(*Cursor)) /* We want FIRST non space character */
+ Cursor++;
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ }
+
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killend(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < LastChar)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ LastChar = Cursor; /* zap! -- delete to end */
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_killbeg(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = InputBuf;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delbefore((int)(Cursor - InputBuf));
+ Cursor = InputBuf; /* zap! */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killall(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = InputBuf;
+ kp = KillBuf;
+ while (cp < LastChar)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ LastChar = InputBuf; /* zap! -- delete all of it */
+ Cursor = InputBuf;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killregion(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ if (!Mark)
+ return(CC_ERROR);
+
+ if (Mark > Cursor) {
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < Mark)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delafter((int)(cp - Cursor)); /* delete it - UNUSED BY VI mode */
+ }
+ else { /* mark is before cursor */
+ cp = Mark;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delbefore((int)(cp - Mark));
+ Cursor = Mark;
+ }
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_copyregion(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ if (!Mark)
+ return(CC_ERROR);
+
+ if (Mark > Cursor) {
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < Mark)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ }
+ else { /* mark is before cursor */
+ cp = Mark;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ }
+ return(CC_NORM); /* don't even need to Refresh() */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_charswitch(cc)
+ int cc;
+{
+ register Char c;
+
+ USE(cc);
+
+ /* do nothing if we are at beginning of line or have only one char */
+ if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
+ return(CC_ERROR);
+ }
+
+ if (Cursor < LastChar) {
+ Cursor++;
+ }
+ c = Cursor[-2];
+ Cursor[-2] = Cursor[-1];
+ Cursor[-1] = c;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_gcharswitch(cc)
+ int cc;
+{ /* gosmacs style ^T */
+ register Char c;
+
+ USE(cc);
+ if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
+ c = Cursor[-2];
+ Cursor[-2] = Cursor[-1];
+ Cursor[-1] = c;
+ return(CC_REFRESH);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+/*ARGSUSED*/
+static void
+e_charback_mbyte(argument)
+ int argument;
+{
+ if (!_enable_mbdisp) {
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf;
+ else
+ Cursor -= Argument;
+ }
+ else {
+ while (0 < argument && Cursor > InputBuf) {
+ if (Cursor - 1 != InputBuf &&
+ Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) {
+ Cursor--;
+ }
+ Cursor--;
+ argument--;
+ }
+ }
+}
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+e_charback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor > InputBuf) {
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+ e_charback_mbyte(Argument);
+#else
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf;
+ else
+ Cursor -= Argument;
+#endif
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_wordback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+/*ARGSUSED*/
+static void
+e_charfwd_mbyte(argument)
+ int argument;
+{
+ if (!_enable_mbdisp)
+ Cursor += argument;
+ else
+ while (0 < argument && Cursor < LastChar) {
+ if (Cursor + 1 != LastChar &&
+ Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) {
+ Cursor++;
+ }
+ Cursor++;
+ argument--;
+ }
+}
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+e_charfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor < LastChar) {
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+ e_charfwd_mbyte(Argument);
+#else
+ Cursor += Argument;
+#endif
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_wordfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_next_word(Cursor, LastChar, Argument);
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_nexword(Cursor, LastChar, Argument);
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordbegnext(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_next_word(Cursor, LastChar, Argument);
+ if (Cursor < LastChar)
+ Cursor++;
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+static CCRETVAL
+v_repeat_srch(c)
+ int c;
+{
+ CCRETVAL rv = CC_ERROR;
+#ifdef SDEBUG
+ xprintf("dir %d patlen %d patbuf %S\n",
+ c, patlen, patbuf);
+#endif
+
+ LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
+ LastChar = InputBuf;
+ switch (c) {
+ case F_DOWN_SEARCH_HIST:
+ rv = e_down_search_hist(0);
+ break;
+ case F_UP_SEARCH_HIST:
+ rv = e_up_search_hist(0);
+ break;
+ default:
+ break;
+ }
+ return rv;
+}
+
+static CCRETVAL
+v_csearch_back(ch, count, tflag)
+ int ch, count, tflag;
+{
+ Char *cp;
+
+ cp = Cursor;
+ while (count--) {
+ if (*cp == ch)
+ cp--;
+ while (cp > InputBuf && *cp != ch)
+ cp--;
+ }
+
+ if (cp < InputBuf || (cp == InputBuf && *cp != ch))
+ return(CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp++;
+
+ Cursor = cp;
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+static CCRETVAL
+v_csearch_fwd(ch, count, tflag)
+ int ch, count, tflag;
+{
+ Char *cp;
+
+ cp = Cursor;
+ while (count--) {
+ if(*cp == ch)
+ cp++;
+ while (cp < LastChar && *cp != ch)
+ cp++;
+ }
+
+ if (cp >= LastChar)
+ return(CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp--;
+
+ Cursor = cp;
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+static CCRETVAL
+v_action(c)
+ int c;
+{
+ register Char *cp, *kp;
+
+ if (ActionFlag == TCSHOP_DELETE) {
+ ActionFlag = TCSHOP_NOP;
+ ActionPos = 0;
+
+ UndoSize = 0;
+ kp = UndoBuf;
+ for (cp = InputBuf; cp < LastChar; cp++) {
+ *kp++ = *cp;
+ UndoSize++;
+ }
+
+ UndoAction = TCSHOP_INSERT;
+ UndoPtr = InputBuf;
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ if (c & TCSHOP_INSERT)
+ c_alternativ_key_map(0);
+
+ return(CC_REFRESH);
+ }
+#ifdef notdef
+ else if (ActionFlag == TCSHOP_NOP) {
+#endif
+ ActionPos = Cursor;
+ ActionFlag = c;
+ return(CC_ARGHACK); /* Do NOT clear out argument */
+#ifdef notdef
+ }
+ else {
+ ActionFlag = 0;
+ ActionPos = 0;
+ return(CC_ERROR);
+ }
+#endif
+}
+
+#ifdef COMMENT
+/* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
+static void
+c_get_word(begin, end)
+ Char **begin;
+ Char **end;
+{
+ Char *cp;
+
+ cp = &Cursor[0];
+ while (Argument--) {
+ while ((cp <= LastChar) && (isword(*cp)))
+ cp++;
+ *end = --cp;
+ while ((cp >= InputBuf) && (isword(*cp)))
+ cp--;
+ *begin = ++cp;
+ }
+}
+#endif /* COMMENT */
+
+/*ARGSUSED*/
+CCRETVAL
+e_uppercase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_capitolcase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ cp = Cursor;
+ for (; cp < end; cp++) {
+ if (Isalpha(*cp)) {
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
+ cp++;
+ break;
+ }
+ }
+ for (; cp < end; cp++)
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_lowercase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ for (cp = Cursor; cp < end; cp++)
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_set_mark(c)
+ int c;
+{
+ USE(c);
+ Mark = Cursor;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_exchange_mark(c)
+ int c;
+{
+ register Char *cp;
+
+ USE(c);
+ cp = Cursor;
+ Cursor = Mark;
+ Mark = cp;
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_argfour(c)
+ int c;
+{ /* multiply current argument by 4 */
+ USE(c);
+ if (Argument > 1000000)
+ return CC_ERROR;
+ DoingArg = 1;
+ Argument *= 4;
+ return(CC_ARGHACK);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_quote(c)
+ int c;
+{
+ Char ch;
+ int num;
+
+ USE(c);
+ QuoteModeOn();
+ num = GetNextChar(&ch);
+ QuoteModeOff();
+ if (num == 1)
+ return e_insert(ch);
+ else
+ return e_send_eof(0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_metanext(c)
+ int c;
+{
+ USE(c);
+ MetaNext = 1;
+ return(CC_ARGHACK); /* preserve argument */
+}
+
+#ifdef notdef
+/*ARGSUSED*/
+CCRETVAL
+e_extendnext(c)
+ int c;
+{
+ CurrentKeyMap = CcAltMap;
+ return(CC_ARGHACK); /* preserve argument */
+}
+
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+v_insbeg(c)
+ int c;
+{ /* move to beginning of line and start vi
+ * insert mode */
+ USE(c);
+ Cursor = InputBuf;
+ InsertPos = Cursor;
+
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ RefCursor(); /* move the cursor */
+ c_alternativ_key_map(0);
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_replone(c)
+ int c;
+{ /* vi mode overwrite one character */
+ USE(c);
+ c_alternativ_key_map(0);
+ inputmode = MODE_REPLACE_1;
+ UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
+ UndoPtr = Cursor;
+ UndoSize = 0;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_replmode(c)
+ int c;
+{ /* vi mode start overwriting */
+ USE(c);
+ c_alternativ_key_map(0);
+ inputmode = MODE_REPLACE;
+ UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
+ UndoPtr = Cursor;
+ UndoSize = 0;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_substchar(c)
+ int c;
+{ /* vi mode substitute for one char */
+ USE(c);
+ c_delafter(Argument);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_substline(c)
+ int c;
+{ /* vi mode replace whole line */
+ USE(c);
+ (void) e_killall(0);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_chgtoend(c)
+ int c;
+{ /* vi mode change to end of line */
+ USE(c);
+ (void) e_killend(0);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_insert(c)
+ int c;
+{ /* vi mode start inserting */
+ USE(c);
+ c_alternativ_key_map(0);
+
+ InsertPos = Cursor;
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_add(c)
+ int c;
+{ /* vi mode start adding */
+ USE(c);
+ c_alternativ_key_map(0);
+ if (Cursor < LastChar)
+ {
+ Cursor++;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ RefCursor();
+ }
+
+ InsertPos = Cursor;
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_addend(c)
+ int c;
+{ /* vi mode to add at end of line */
+ USE(c);
+ c_alternativ_key_map(0);
+ Cursor = LastChar;
+
+ InsertPos = LastChar; /* Mark where insertion begins */
+ UndoPtr = LastChar;
+ UndoAction = TCSHOP_DELETE;
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_change_case(cc)
+ int cc;
+{
+ char c;
+
+ USE(cc);
+ if (Cursor < LastChar) {
+#ifndef WINNT
+ c = *Cursor;
+#else
+ c = CHAR & *Cursor;
+#endif /* WINNT */
+ if (Isupper(c))
+ *Cursor++ = Tolower(c);
+ else if (Islower(c))
+ *Cursor++ = Toupper(c);
+ else
+ Cursor++;
+ RefPlusOne(); /* fast refresh for one char */
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand(c)
+ int c;
+{
+ register Char *p;
+ extern bool justpr;
+
+ USE(c);
+ for (p = InputBuf; Isspace(*p); p++)
+ continue;
+ if (p == LastChar)
+ return(CC_ERROR);
+
+ justpr++;
+ Expand++;
+ return(e_newline(0));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_startover(c)
+ int c;
+{ /* erase all of current line, start again */
+ USE(c);
+ ResetInLine(0); /* reset the input pointers */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_redisp(c)
+ int c;
+{
+ USE(c);
+ ClearLines();
+ ClearDisp();
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_cleardisp(c)
+ int c;
+{
+ USE(c);
+ ClearScreen(); /* clear the whole real screen */
+ ClearDisp(); /* reset everything */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_int(c)
+ int c;
+{
+ USE(c);
+#if defined(_MINIX) || defined(WINNT)
+ /* SAK PATCH: erase all of current line, start again */
+ ResetInLine(0); /* reset the input pointers */
+ xputchar('\n');
+ ClearDisp();
+ return (CC_REFRESH);
+#else /* !_MINIX && !WINNT */
+ /* do no editing */
+ return (CC_NORM);
+#endif /* _MINIX || WINNT */
+}
+
+/*
+ * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
+ * Function to send a character back to the input stream in cooked
+ * mode. Only works if we have TIOCSTI
+ */
+/*ARGSUSED*/
+CCRETVAL
+e_stuff_char(c)
+ int c;
+{
+#ifdef TIOCSTI
+ extern int Tty_raw_mode;
+ int was_raw = Tty_raw_mode;
+ char ch = (char) c;
+
+ if (was_raw)
+ (void) Cookedmode();
+
+ (void) write(SHIN, "\n", 1);
+ (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
+
+ if (was_raw)
+ (void) Rawmode();
+ return(e_redisp(c));
+#else /* !TIOCSTI */
+ return(CC_ERROR);
+#endif /* !TIOCSTI */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_insovr(c)
+ int c;
+{
+ USE(c);
+ inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_dsusp(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_flusho(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_quit(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_tsusp(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_stopo(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_history(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ c_substitute();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_magic_space(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ c_substitute();
+ return(e_insert(' '));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_inc_fwd(c)
+ int c;
+{
+ USE(c);
+ patlen = 0;
+ return e_inc_search(F_DOWN_SEARCH_HIST);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_inc_back(c)
+ int c;
+{
+ USE(c);
+ patlen = 0;
+ return e_inc_search(F_UP_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_copyprev(c)
+ int c;
+{
+ register Char *cp, *oldc, *dp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ oldc = Cursor;
+ /* does a bounds check */
+ cp = c_prev_word(Cursor, InputBuf, Argument);
+
+ c_insert((int)(oldc - cp));
+ for (dp = oldc; cp < oldc && dp < LastChar; cp++)
+ *dp++ = *cp;
+
+ Cursor = dp; /* put cursor at end */
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_starto(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_load_average(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+#ifdef TIOCSTAT
+ /*
+ * Here we pass &c to the ioctl because some os's (NetBSD) expect it
+ * there even if they don't use it. (lukem@netbsd.org)
+ */
+ if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
+#endif
+ xprintf(CGETS(5, 1, "Load average unavailable\n"));
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_chgmeta(c)
+ int c;
+{
+ USE(c);
+ /*
+ * Delete with insert == change: first we delete and then we leave in
+ * insert mode.
+ */
+ return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_delmeta(c)
+ int c;
+{
+ USE(c);
+ return(v_action(TCSHOP_DELETE));
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+v_endword(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_endword(Cursor, LastChar, Argument);
+
+ if (ActionFlag & TCSHOP_DELETE)
+ {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_eword(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_eword(Cursor, LastChar, Argument);
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_char_fwd(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ srch_dir = CHAR_FWD;
+ srch_char = ch;
+
+ return v_csearch_fwd(ch, Argument, 0);
+
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_char_back(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ srch_dir = CHAR_BACK;
+ srch_char = ch;
+
+ return v_csearch_back(ch, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_charto_fwd(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ return v_csearch_fwd(ch, Argument, 1);
+
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_charto_back(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ return v_csearch_back(ch, Argument, 1);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rchar_fwd(c)
+ int c;
+{
+ USE(c);
+ if (srch_char == 0)
+ return CC_ERROR;
+
+ return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
+ v_csearch_back(srch_char, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rchar_back(c)
+ int c;
+{
+ USE(c);
+ if (srch_char == 0)
+ return CC_ERROR;
+
+ return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
+ v_csearch_back(srch_char, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_undo(c)
+ int c;
+{
+ register int loop;
+ register Char *kp, *cp;
+ Char temp;
+ int size;
+
+ USE(c);
+ switch (UndoAction) {
+ case TCSHOP_DELETE|TCSHOP_INSERT:
+ case TCSHOP_DELETE:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ kp = UndoBuf;
+ for (loop=0; loop < UndoSize; loop++) /* copy the chars */
+ *kp++ = *cp++; /* into UndoBuf */
+
+ for (cp = UndoPtr; cp <= LastChar; cp++)
+ *cp = cp[UndoSize];
+
+ LastChar -= UndoSize;
+ Cursor = UndoPtr;
+
+ UndoAction = TCSHOP_INSERT;
+ break;
+
+ case TCSHOP_INSERT:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ Cursor = UndoPtr;
+ kp = UndoBuf;
+ c_insert(UndoSize); /* open the space, */
+ for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
+ *cp++ = *kp++;
+
+ UndoAction = TCSHOP_DELETE;
+ break;
+
+ case TCSHOP_CHANGE:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ Cursor = UndoPtr;
+ kp = UndoBuf;
+ size = (int)(Cursor-LastChar); /* NOT NSL independant */
+ if (size < UndoSize)
+ size = UndoSize;
+ for(loop = 0; loop < size; loop++) {
+ temp = *kp;
+ *kp++ = *cp;
+ *cp++ = temp;
+ }
+ break;
+
+ default:
+ return(CC_ERROR);
+ }
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_ush_meta(c)
+ int c;
+{
+ USE(c);
+ return v_search(F_UP_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_dsh_meta(c)
+ int c;
+{
+ USE(c);
+ return v_search(F_DOWN_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rsrch_fwd(c)
+ int c;
+{
+ USE(c);
+ if (patlen == 0) return(CC_ERROR);
+ return(v_repeat_srch(searchdir));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rsrch_back(c)
+ int c;
+{
+ USE(c);
+ if (patlen == 0) return(CC_ERROR);
+ return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
+ F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
+}
+
+#ifndef WINNT
+/* Since ed.defns.h is generated from ed.defns.c, these empty
+ functions will keep the F_NUM_FNS consistent
+ */
+CCRETVAL
+e_copy_to_clipboard(c)
+ int c;
+{
+ USE(c);
+ return CC_ERROR;
+}
+
+CCRETVAL
+e_paste_from_clipboard(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+
+CCRETVAL
+e_dosify_next(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+CCRETVAL
+e_dosify_prev(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+#else /* WINNT */
+/*ARGSUSED*/
+CCRETVAL
+e_dosify_next(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ cp = Cursor;
+ while( cp < LastChar) {
+ if ( (*cp & CHAR == ' ') && (cp[-1] & CHAR != '\\') )
+ break;
+ cp++;
+ }
+
+ for (p = Cursor, kp = KillBuf; p < cp; p++) {/* save the text */
+ if ( ( *p & CHAR ) == '/') {
+ *kp++ = '\\';
+ *kp++ = '\\';
+ }
+ else
+ *kp++ = *p;
+ }
+ LastKill = kp;
+
+ c_delafter((int)(cp - Cursor)); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return (e_yank_kill(c));
+}
+/*ARGSUSED*/
+CCRETVAL
+e_dosify_prev(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ cp = Cursor-1;
+ /* Skip trailing spaces */
+ while ((cp > InputBuf) && ( (*cp & CHAR) == ' '))
+ cp--;
+
+ while (cp > InputBuf) {
+ if ( ((*cp & CHAR) == ' ') && ((cp[-1] & CHAR) != '\\') )
+ break;
+ cp--;
+ }
+
+ for (p = cp, kp = KillBuf; p < Cursor; p++) {/* save the text */
+ if ( ( *p & CHAR ) == '/') {
+ *kp++ = '\\';
+ *kp++ = '\\';
+ }
+ else
+ *kp++ = *p;
+ }
+ LastKill = kp;
+
+ c_delbefore((int)(Cursor - cp)); /* delete before dot */
+ Cursor = cp;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ return(e_yank_kill(c));
+}
+#endif /* !WINNT */
+
+#ifdef notdef
+void
+MoveCursor(n) /* move cursor + right - left char */
+ int n;
+{
+ Cursor = Cursor + n;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return;
+}
+
+Char *
+GetCursor()
+{
+ return(Cursor);
+}
+
+int
+PutCursor(p)
+ Char *p;
+{
+ if (p < InputBuf || p > LastChar)
+ return 1; /* Error */
+ Cursor = p;
+ return 0;
+}
+#endif
diff --git a/contrib/tcsh/ed.decls.h b/contrib/tcsh/ed.decls.h
new file mode 100644
index 0000000..4b96d6d
--- /dev/null
+++ b/contrib/tcsh/ed.decls.h
@@ -0,0 +1,274 @@
+/* $Header: /src/pub/tcsh/ed.decls.h,v 3.28 1998/09/04 21:16:38 christos Exp $ */
+/*
+ * ed.decls.h: Editor external definitions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_ed_decls
+#define _h_ed_decls
+
+/*
+ * ed.chared.c
+ */
+extern int InsertStr __P((Char *));
+extern void DeleteBack __P((int));
+
+/*
+ * ed.init.c
+ */
+#ifdef SIG_WINDOW
+extern void check_window_size __P((int));
+extern sigret_t window_change __P((int));
+#endif /* SIG_WINDOW */
+extern int ed_Setup __P((int));
+extern void ed_Init __P((void));
+extern int Cookedmode __P((void));
+extern int Rawmode __P((void));
+extern void ed_set_tty_eight_bit __P((void));
+
+extern void QuoteModeOn __P((void));
+extern void QuoteModeOff __P((void));
+extern void ResetInLine __P((int));
+extern int Load_input_line __P((void));
+
+/*
+ * ed.term.c:
+ */
+extern void dosetty __P((Char **, struct command *));
+extern int tty_getty __P((int, ttydata_t *));
+extern int tty_setty __P((int, ttydata_t *));
+extern void tty_getchar __P((ttydata_t *, unsigned char *));
+extern void tty_setchar __P((ttydata_t *, unsigned char *));
+extern speed_t tty_getspeed __P((ttydata_t *));
+extern int tty_gettabs __P((ttydata_t *));
+extern int tty_geteightbit __P((ttydata_t *));
+extern int tty_cooked_mode __P((ttydata_t *));
+#ifdef _IBMR2
+extern void tty_setdisc __P((int, int));
+#endif /* _IBMR2 */
+
+/*
+ * ed.screen.c
+ */
+extern void terminit __P((void));
+extern void SetAttributes __P((int));
+extern void so_write __P((Char *, int));
+extern void ClearScreen __P((void));
+extern void MoveToLine __P((int));
+extern void MoveToChar __P((int));
+extern void ClearEOL __P((int));
+extern void Insert_write __P((Char *, int));
+extern void DeleteChars __P((int));
+extern void TellTC __P((char *));
+extern void SetTC __P((char *, char *));
+extern void EchoTC __P((Char **));
+extern int SetArrowKeys __P((CStr *, XmapVal *, int));
+extern int IsArrowKey __P((Char *));
+extern void ResetArrowKeys __P((void));
+extern void DefaultArrowKeys __P((void));
+extern int ClearArrowKeys __P((CStr *));
+extern void PrintArrowKeys __P((CStr *));
+extern void BindArrowKeys __P((void));
+extern void SoundBeep __P((void));
+extern int CanWeTab __P((void));
+extern void ChangeSize __P((int, int));
+#ifdef SIG_WINDOW
+extern int GetSize __P((int *, int *));
+#endif /* SIG_WINDOW */
+extern void ClearToBottom __P((void));
+extern void GetTermCaps __P((void));
+
+/*
+ * ed.defns.c
+ */
+extern void editinit __P((void));
+extern void ed_InitNLSMaps __P((void));
+#ifdef DEBUG_EDIT
+extern void CheckMaps __P((void));
+#endif
+extern void ed_InitMaps __P((void));
+extern void ed_InitEmacsMaps __P((void));
+extern void ed_InitVIMaps __P((void));
+
+extern CCRETVAL e_unassigned __P((int));
+extern CCRETVAL e_insert __P((int));
+extern CCRETVAL e_newline __P((int));
+extern CCRETVAL e_delprev __P((int));
+extern CCRETVAL e_delnext __P((int));
+/* added by mtk@ari.ncl.omron.co.jp (920818) */
+extern CCRETVAL e_delnext_eof __P((int));
+extern CCRETVAL e_delnext_list __P((int));
+extern CCRETVAL e_delnext_list_eof __P((int)); /* for ^D */
+extern CCRETVAL e_toend __P((int));
+extern CCRETVAL e_tobeg __P((int));
+extern CCRETVAL e_charback __P((int));
+extern CCRETVAL e_charfwd __P((int));
+extern CCRETVAL e_quote __P((int));
+extern CCRETVAL e_startover __P((int));
+extern CCRETVAL e_redisp __P((int));
+extern CCRETVAL e_wordback __P((int));
+extern CCRETVAL e_wordfwd __P((int));
+extern CCRETVAL v_wordbegnext __P((int));
+extern CCRETVAL e_uppercase __P((int));
+extern CCRETVAL e_lowercase __P((int));
+extern CCRETVAL e_capitolcase __P((int));
+extern CCRETVAL e_cleardisp __P((int));
+extern CCRETVAL e_complete __P((int));
+extern CCRETVAL e_correct __P((int));
+extern CCRETVAL e_correctl __P((int));
+extern CCRETVAL e_up_hist __P((int));
+extern CCRETVAL e_down_hist __P((int));
+extern CCRETVAL e_up_search_hist __P((int));
+extern CCRETVAL e_down_search_hist __P((int));
+extern CCRETVAL e_helpme __P((int));
+extern CCRETVAL e_list_choices __P((int));
+extern CCRETVAL e_delwordprev __P((int));
+extern CCRETVAL e_delwordnext __P((int));
+extern CCRETVAL e_digit __P((int));
+extern CCRETVAL e_argdigit __P((int));
+extern CCRETVAL v_zero __P((int));
+extern CCRETVAL e_killend __P((int));
+extern CCRETVAL e_killbeg __P((int));
+extern CCRETVAL e_metanext __P((int));
+#ifdef notdef
+extern CCRETVAL e_extendnext __P((int));
+#endif
+extern CCRETVAL e_send_eof __P((int));
+extern CCRETVAL e_charswitch __P((int));
+extern CCRETVAL e_gcharswitch __P((int));
+extern CCRETVAL e_which __P((int));
+extern CCRETVAL e_yank_kill __P((int));
+extern CCRETVAL e_tty_dsusp __P((int));
+extern CCRETVAL e_tty_flusho __P((int));
+extern CCRETVAL e_tty_quit __P((int));
+extern CCRETVAL e_tty_tsusp __P((int));
+extern CCRETVAL e_tty_stopo __P((int));
+extern CCRETVAL e_tty_starto __P((int));
+extern CCRETVAL e_argfour __P((int));
+extern CCRETVAL e_set_mark __P((int));
+extern CCRETVAL e_exchange_mark __P((int));
+extern CCRETVAL e_last_item __P((int));
+extern CCRETVAL v_cmd_mode __P((int));
+extern CCRETVAL v_insert __P((int));
+extern CCRETVAL v_replmode __P((int));
+extern CCRETVAL v_replone __P((int));
+extern CCRETVAL v_substline __P((int));
+extern CCRETVAL v_substchar __P((int));
+extern CCRETVAL v_add __P((int));
+extern CCRETVAL v_addend __P((int));
+extern CCRETVAL v_insbeg __P((int));
+extern CCRETVAL v_chgtoend __P((int));
+extern CCRETVAL e_killregion __P((int));
+extern CCRETVAL e_killall __P((int));
+extern CCRETVAL e_copyregion __P((int));
+extern CCRETVAL e_tty_int __P((int));
+extern CCRETVAL e_run_fg_editor __P((int));
+extern CCRETVAL e_list_eof __P((int));
+extern CCRETVAL e_expand_history __P((int));
+extern CCRETVAL e_magic_space __P((int));
+extern CCRETVAL e_list_glob __P((int));
+extern CCRETVAL e_expand_glob __P((int));
+extern CCRETVAL e_insovr __P((int));
+extern CCRETVAL v_cm_complete __P((int));
+extern CCRETVAL e_copyprev __P((int));
+extern CCRETVAL v_change_case __P((int));
+extern CCRETVAL e_expand __P((int));
+extern CCRETVAL e_expand_vars __P((int));
+extern CCRETVAL e_toggle_hist __P((int));
+extern CCRETVAL e_load_average __P((int));
+extern CCRETVAL v_delprev __P((int));
+extern CCRETVAL v_delmeta __P((int));
+extern CCRETVAL v_wordfwd __P((int));
+extern CCRETVAL v_wordback __P((int));
+extern CCRETVAL v_endword __P((int));
+extern CCRETVAL v_eword __P((int));
+extern CCRETVAL v_undo __P((int));
+extern CCRETVAL v_ush_meta __P((int));
+extern CCRETVAL v_dsh_meta __P((int));
+extern CCRETVAL v_rsrch_fwd __P((int));
+extern CCRETVAL v_rsrch_back __P((int));
+extern CCRETVAL v_char_fwd __P((int));
+extern CCRETVAL v_char_back __P((int));
+extern CCRETVAL v_chgmeta __P((int));
+extern CCRETVAL e_inc_fwd __P((int));
+extern CCRETVAL e_inc_back __P((int));
+extern CCRETVAL v_rchar_fwd __P((int));
+extern CCRETVAL v_rchar_back __P((int));
+extern CCRETVAL v_charto_fwd __P((int));
+extern CCRETVAL v_charto_back __P((int));
+extern CCRETVAL e_normalize_path __P((int));
+extern CCRETVAL e_normalize_command __P((int));
+extern CCRETVAL e_stuff_char __P((int));
+extern CCRETVAL e_list_all __P((int));
+extern CCRETVAL e_complete_all __P((int));
+extern CCRETVAL e_complete_fwd __P((int));
+extern CCRETVAL e_complete_back __P((int));
+extern CCRETVAL e_dabbrev_expand __P((int));
+extern CCRETVAL e_copy_to_clipboard __P((int));
+extern CCRETVAL e_paste_from_clipboard __P((int));
+extern CCRETVAL e_dosify_next __P((int));
+extern CCRETVAL e_dosify_prev __P((int));
+
+/*
+ * ed.inputl.c
+ */
+extern int Inputl __P((void));
+extern int GetNextChar __P((Char *));
+extern void PushMacro __P((Char *));
+
+/*
+ * ed.refresh.c
+ */
+extern void ClearLines __P((void));
+extern void ClearDisp __P((void));
+extern void Refresh __P((void));
+extern void RefCursor __P((void));
+extern void RefPlusOne __P((void));
+extern void PastBottom __P((void));
+
+/*
+ * ed.xmap.c
+ */
+extern XmapVal *XmapStr __P((CStr *));
+extern XmapVal *XmapCmd __P((int));
+extern void AddXkey __P((CStr *, XmapVal *, int));
+extern void ClearXkey __P((KEYCMD *, CStr *));
+extern int GetXkey __P((CStr *, XmapVal *));
+extern void ResetXmap __P((void));
+extern int DeleteXkey __P((CStr *));
+extern void PrintXkey __P((CStr *));
+extern int printOne __P((CStr *, XmapVal *, int));
+extern int parseescape __P((const Char **));
+extern unsigned char *unparsestring __P((CStr *, unsigned char *, Char *));
+
+#endif /* _h_ed_decls */
diff --git a/contrib/tcsh/ed.defns.c b/contrib/tcsh/ed.defns.c
new file mode 100644
index 0000000..41d7992
--- /dev/null
+++ b/contrib/tcsh/ed.defns.c
@@ -0,0 +1,1949 @@
+/* $Header: /src/pub/tcsh/ed.defns.c,v 3.33 1998/11/24 18:17:18 christos Exp $ */
+/*
+ * ed.defns.c: Editor function definitions and initialization
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.defns.c,v 3.33 1998/11/24 18:17:18 christos Exp $")
+
+#include "ed.h"
+
+static void ed_InitMetaBindings __P((void));
+
+PFCmd CcFuncTbl[] = { /* table of available commands */
+ e_unassigned,
+/* no #define here -- this is a dummy to detect initing of the key map */
+ e_unassigned,
+#define F_UNASSIGNED 1
+ e_insert,
+#define F_INSERT 2
+ e_newline,
+#define F_NEWLINE 3
+ e_delprev,
+#define F_DELPREV 4
+ e_delnext,
+#define F_DELNEXT 5
+ e_toend,
+#define F_TOEND 6
+ e_tobeg,
+#define F_TOBEG 7
+ e_charback,
+#define F_CHARBACK 8
+ e_charfwd,
+#define F_CHARFWD 9
+ e_quote,
+#define F_QUOTE 10
+ e_startover,
+#define F_STARTOVER 11
+ e_redisp,
+#define F_REDISP 12
+ e_tty_int,
+#define F_TTY_INT 13
+ e_wordback,
+#define F_WORDBACK 14
+ e_wordfwd,
+#define F_WORDFWD 15
+ e_cleardisp,
+#define F_CLEARDISP 16
+ e_complete,
+#define F_COMPLETE 17
+ e_correct,
+#define F_CORRECT 18
+ e_up_hist,
+#define F_UP_HIST 19
+ e_down_hist,
+#define F_DOWN_HIST 20
+ e_up_search_hist,
+#define F_UP_SEARCH_HIST 21
+ e_down_search_hist,
+#define F_DOWN_SEARCH_HIST 22
+ e_helpme,
+#define F_HELPME 23
+ e_list_choices,
+#define F_LIST_CHOICES 24
+ e_delwordprev,
+#define F_DELWORDPREV 25
+ e_delwordnext,
+#define F_DELWORDNEXT 26
+ e_digit,
+#define F_DIGIT 27
+ e_killend,
+#define F_KILLEND 28
+ e_killbeg,
+#define F_KILLBEG 29
+ e_metanext,
+#define F_METANEXT 30
+ e_send_eof,
+#define F_SEND_EOF 31
+ e_charswitch,
+#define F_CHARSWITCH 32
+ e_which,
+#define F_WHICH 33
+ e_yank_kill,
+#define F_YANK_KILL 34
+ e_tty_dsusp,
+#define F_TTY_DSUSP 35
+ e_tty_flusho,
+#define F_TTY_FLUSHO 36
+ e_tty_quit,
+#define F_TTY_QUIT 37
+ e_tty_tsusp,
+#define F_TTY_TSUSP 38
+ e_tty_stopo,
+#define F_TTY_STOPO 39
+ e_tty_starto,
+#define F_TTY_STARTO 40
+ e_argfour,
+#define F_ARGFOUR 41
+ e_set_mark,
+#define F_SET_MARK 42
+ e_exchange_mark,
+#define F_EXCHANGE_MARK 43
+ e_last_item,
+#define F_LAST_ITEM 44
+ e_delnext_list_eof,
+#define F_DELNEXT_LIST_EOF 45
+ v_cmd_mode,
+#define V_CMD_MODE 46
+ v_insert,
+#define V_INSERT 47
+ e_argdigit,
+#define F_ARGDIGIT 48
+ e_killregion,
+#define F_KILLREGION 49
+ e_copyregion,
+#define F_COPYREGION 50
+ e_gcharswitch,
+#define F_GCHARSWITCH 51
+ e_run_fg_editor,
+#define F_RUN_FG_EDITOR 52
+ e_unassigned, /* place holder for sequence lead in character */
+#define F_XKEY 53
+ e_uppercase,
+#define F_CASEUPPER 54
+ e_lowercase,
+#define F_CASELOWER 55
+ e_capitolcase,
+#define F_CASECAPITAL 56
+ v_zero,
+#define V_ZERO 57
+ v_add,
+#define V_ADD 58
+ v_addend,
+#define V_ADDEND 59
+ v_wordbegnext,
+#define V_WORDBEGNEXT 60
+ e_killall,
+#define F_KILLALL 61
+ e_unassigned,
+/* F_EXTENDNEXT removed */
+ v_insbeg,
+#define V_INSBEG 63
+ v_replmode,
+#define V_REPLMODE 64
+ v_replone,
+#define V_REPLONE 65
+ v_substline,
+#define V_SUBSTLINE 66
+ v_substchar,
+#define V_SUBSTCHAR 67
+ v_chgtoend,
+#define V_CHGTOEND 68
+ e_list_eof,
+#define F_LIST_EOF 69
+ e_list_glob,
+#define F_LIST_GLOB 70
+ e_expand_history,
+#define F_EXPAND_HISTORY 71
+ e_magic_space,
+#define F_MAGIC_SPACE 72
+ e_insovr,
+#define F_INSOVR 73
+ v_cm_complete,
+#define V_CM_COMPLETE 74
+ e_copyprev,
+#define F_COPYPREV 75
+ e_correctl,
+#define F_CORRECT_L 76
+ e_expand_glob,
+#define F_EXPAND_GLOB 77
+ e_expand_vars,
+#define F_EXPAND_VARS 78
+ e_toggle_hist,
+#define F_TOGGLE_HIST 79
+ v_change_case,
+#define V_CHGCASE 80
+ e_expand,
+#define F_EXPAND 81
+ e_load_average,
+#define F_LOAD_AVERAGE 82
+ v_delprev,
+#define V_DELPREV 83
+ v_delmeta,
+#define V_DELMETA 84
+ v_wordfwd,
+#define V_WORDFWD 85
+ v_wordback,
+#define V_WORDBACK 86
+ v_endword,
+#define V_ENDWORD 87
+ v_eword,
+#define V_EWORD 88
+ v_undo,
+#define V_UNDO 89
+ v_ush_meta,
+#define V_USH_META 90
+ v_dsh_meta,
+#define V_DSH_META 91
+ v_rsrch_fwd,
+#define V_RSRCH_FWD 92
+ v_rsrch_back,
+#define V_RSRCH_BACK 93
+ v_char_fwd,
+#define V_CHAR_FWD 94
+ v_char_back,
+#define V_CHAR_BACK 95
+ v_chgmeta,
+#define V_CHGMETA 96
+ e_inc_fwd,
+#define F_INC_FWD 97
+ e_inc_back,
+#define F_INC_BACK 98
+ v_rchar_fwd,
+#define V_RCHAR_FWD 99
+ v_rchar_back,
+#define V_RCHAR_BACK 100
+ v_charto_fwd,
+#define V_CHARTO_FWD 101
+ v_charto_back,
+#define V_CHARTO_BACK 102
+ e_normalize_path,
+#define F_PATH_NORM 103
+ e_delnext_eof, /* added by mtk@ari.ncl.omron.co.jp (920818) */
+#define F_DELNEXT_EOF 104
+ e_stuff_char,
+#define F_STUFF_CHAR 105
+ e_complete_all,
+#define F_COMPLETE_ALL 106
+ e_list_all,
+#define F_LIST_ALL 107
+ e_complete_fwd,
+#define F_COMPLETE_FWD 108
+ e_complete_back,
+#define F_COMPLETE_BACK 109
+ e_delnext_list,
+#define F_DELNEXT_LIST 110
+ e_normalize_command,
+#define F_COMMAND_NORM 111
+ e_dabbrev_expand,
+#define F_DABBREV_EXPAND 112
+ e_copy_to_clipboard,
+#define F_COPY_CLIP 113
+ e_paste_from_clipboard,
+#define F_PASTE_CLIP 114
+ e_dosify_next,
+#define F_DOSIFY_NEXT 115
+ e_dosify_prev,
+#define F_DOSIFY_PREV 116
+ 0 /* DUMMY VALUE */
+#define F_NUM_FNS 117
+
+};
+
+KEYCMD NumFuns = F_NUM_FNS;
+
+KEYCMD CcKeyMap[NT_NUM_KEYS]; /* the real key map */
+KEYCMD CcAltMap[NT_NUM_KEYS]; /* the alternative key map */
+#define F_NUM_FUNCNAMES (F_NUM_FNS + 2)
+struct KeyFuncs FuncNames[F_NUM_FUNCNAMES];
+
+#ifdef WINNT
+extern KEYCMD CcEmacsMap[];
+extern KEYCMD CcViMap[];
+extern KEYCMD CcViCmdMap[];
+#else /* !WINNT*/
+KEYCMD CcEmacsMap[] = {
+/* keymap table, each index into above tbl; should be 256*sizeof(KEYCMD)
+ bytes long */
+
+ F_SET_MARK, /* ^@ */
+ F_TOBEG, /* ^A */
+ F_CHARBACK, /* ^B */
+ F_TTY_INT, /* ^C */
+ F_DELNEXT_LIST_EOF, /* ^D */
+ F_TOEND, /* ^E */
+ F_CHARFWD, /* ^F */
+ F_UNASSIGNED, /* ^G */
+ F_DELPREV, /* ^H */
+ F_COMPLETE, /* ^I */
+ F_NEWLINE, /* ^J */
+ F_KILLEND, /* ^K */
+ F_CLEARDISP, /* ^L */
+ F_NEWLINE, /* ^M */
+ F_DOWN_HIST, /* ^N */
+ F_TTY_FLUSHO, /* ^O */
+ F_UP_HIST, /* ^P */
+ F_TTY_STARTO, /* ^Q */
+ F_REDISP, /* ^R */
+ F_TTY_STOPO, /* ^S */
+ F_CHARSWITCH, /* ^T */
+ F_KILLALL, /* ^U */
+ F_QUOTE, /* ^V */
+ F_KILLREGION, /* ^W */
+ F_XKEY, /* ^X */
+ F_YANK_KILL, /* ^Y */
+ F_TTY_TSUSP, /* ^Z */
+ F_METANEXT, /* ^[ */
+ F_TTY_QUIT, /* ^\ */
+ F_TTY_DSUSP, /* ^] */
+ F_UNASSIGNED, /* ^^ */
+ F_UNASSIGNED, /* ^_ */
+ F_INSERT, /* SPACE */
+ F_INSERT, /* ! */
+ F_INSERT, /* " */
+ F_INSERT, /* # */
+ F_INSERT, /* $ */
+ F_INSERT, /* % */
+ F_INSERT, /* & */
+ F_INSERT, /* ' */
+ F_INSERT, /* ( */
+ F_INSERT, /* ) */
+ F_INSERT, /* * */
+ F_INSERT, /* + */
+ F_INSERT, /* , */
+ F_INSERT, /* - */
+ F_INSERT, /* . */
+ F_INSERT, /* / */
+ F_DIGIT, /* 0 */
+ F_DIGIT, /* 1 */
+ F_DIGIT, /* 2 */
+ F_DIGIT, /* 3 */
+ F_DIGIT, /* 4 */
+ F_DIGIT, /* 5 */
+ F_DIGIT, /* 6 */
+ F_DIGIT, /* 7 */
+ F_DIGIT, /* 8 */
+ F_DIGIT, /* 9 */
+ F_INSERT, /* : */
+ F_INSERT, /* ; */
+ F_INSERT, /* < */
+ F_INSERT, /* = */
+ F_INSERT, /* > */
+ F_INSERT, /* ? */
+ F_INSERT, /* @ */
+ F_INSERT, /* A */
+ F_INSERT, /* B */
+ F_INSERT, /* C */
+ F_INSERT, /* D */
+ F_INSERT, /* E */
+ F_INSERT, /* F */
+ F_INSERT, /* G */
+ F_INSERT, /* H */
+ F_INSERT, /* I */
+ F_INSERT, /* J */
+ F_INSERT, /* K */
+ F_INSERT, /* L */
+ F_INSERT, /* M */
+ F_INSERT, /* N */
+ F_INSERT, /* O */
+ F_INSERT, /* P */
+ F_INSERT, /* Q */
+ F_INSERT, /* R */
+ F_INSERT, /* S */
+ F_INSERT, /* T */
+ F_INSERT, /* U */
+ F_INSERT, /* V */
+ F_INSERT, /* W */
+ F_INSERT, /* X */
+ F_INSERT, /* Y */
+ F_INSERT, /* Z */
+ F_INSERT, /* [ */
+ F_INSERT, /* \ */
+ F_INSERT, /* ] */
+ F_INSERT, /* ^ */
+ F_INSERT, /* _ */
+ F_INSERT, /* ` */
+ F_INSERT, /* a */
+ F_INSERT, /* b */
+ F_INSERT, /* c */
+ F_INSERT, /* d */
+ F_INSERT, /* e */
+ F_INSERT, /* f */
+ F_INSERT, /* g */
+ F_INSERT, /* h */
+ F_INSERT, /* i */
+ F_INSERT, /* j */
+ F_INSERT, /* k */
+ F_INSERT, /* l */
+ F_INSERT, /* m */
+ F_INSERT, /* n */
+ F_INSERT, /* o */
+ F_INSERT, /* p */
+ F_INSERT, /* q */
+ F_INSERT, /* r */
+ F_INSERT, /* s */
+ F_INSERT, /* t */
+ F_INSERT, /* u */
+ F_INSERT, /* v */
+ F_INSERT, /* w */
+ F_INSERT, /* x */
+ F_INSERT, /* y */
+ F_INSERT, /* z */
+ F_INSERT, /* { */
+ F_INSERT, /* | */
+ F_INSERT, /* } */
+ F_INSERT, /* ~ */
+ F_DELPREV, /* ^? */
+ F_UNASSIGNED, /* M-^@ */
+ F_UNASSIGNED, /* M-^A */
+ F_UNASSIGNED, /* M-^B */
+ F_UNASSIGNED, /* M-^C */
+ F_LIST_CHOICES, /* M-^D */
+ F_UNASSIGNED, /* M-^E */
+ F_UNASSIGNED, /* M-^F */
+ F_UNASSIGNED, /* M-^G */
+ F_DELWORDPREV, /* M-^H */
+ F_COMPLETE, /* M-^I */
+ F_UNASSIGNED, /* M-^J */
+ F_UNASSIGNED, /* M-^K */
+ F_CLEARDISP, /* M-^L */
+ F_UNASSIGNED, /* M-^M */
+ F_UNASSIGNED, /* M-^N */
+ F_UNASSIGNED, /* M-^O */
+ F_UNASSIGNED, /* M-^P */
+ F_UNASSIGNED, /* M-^Q */
+ F_UNASSIGNED, /* M-^R */
+ F_UNASSIGNED, /* M-^S */
+ F_UNASSIGNED, /* M-^T */
+ F_UNASSIGNED, /* M-^U */
+ F_UNASSIGNED, /* M-^V */
+ F_UNASSIGNED, /* M-^W */
+ F_UNASSIGNED, /* M-^X */
+ F_UNASSIGNED, /* M-^Y */
+ F_RUN_FG_EDITOR, /* M-^Z */
+ F_COMPLETE, /* M-^[ */
+ F_UNASSIGNED, /* M-^\ */
+ F_UNASSIGNED, /* M-^] */
+ F_UNASSIGNED, /* M-^^ */
+ F_COPYPREV, /* M-^_ */
+ F_EXPAND_HISTORY, /* M-SPACE */
+ F_EXPAND_HISTORY, /* M-! */
+ F_UNASSIGNED, /* M-" */
+ F_UNASSIGNED, /* M-# */
+ F_CORRECT_L, /* M-$ */
+ F_UNASSIGNED, /* M-% */
+ F_UNASSIGNED, /* M-& */
+ F_UNASSIGNED, /* M-' */
+ F_UNASSIGNED, /* M-( */
+ F_UNASSIGNED, /* M-) */
+ F_UNASSIGNED, /* M-* */
+ F_UNASSIGNED, /* M-+ */
+ F_UNASSIGNED, /* M-, */
+ F_UNASSIGNED, /* M-- */
+ F_UNASSIGNED, /* M-. */
+ F_DABBREV_EXPAND, /* M-/ */
+ F_ARGDIGIT, /* M-0 */
+ F_ARGDIGIT, /* M-1 */
+ F_ARGDIGIT, /* M-2 */
+ F_ARGDIGIT, /* M-3 */
+ F_ARGDIGIT, /* M-4 */
+ F_ARGDIGIT, /* M-5 */
+ F_ARGDIGIT, /* M-6 */
+ F_ARGDIGIT, /* M-7 */
+ F_ARGDIGIT, /* M-8 */
+ F_ARGDIGIT, /* M-9 */
+ F_UNASSIGNED, /* M-: */
+ F_UNASSIGNED, /* M-; */
+ F_UNASSIGNED, /* M-< */
+ F_UNASSIGNED, /* M-= */
+ F_UNASSIGNED, /* M-> */
+ F_WHICH, /* M-? */
+ F_UNASSIGNED, /* M-@ */
+ F_UNASSIGNED, /* M-A */
+ F_WORDBACK, /* M-B */
+ F_CASECAPITAL, /* M-C */
+ F_DELWORDNEXT, /* M-D */
+ F_UNASSIGNED, /* M-E */
+ F_WORDFWD, /* M-F */
+ F_UNASSIGNED, /* M-G */
+ F_HELPME, /* M-H */
+ F_UNASSIGNED, /* M-I */
+ F_UNASSIGNED, /* M-J */
+ F_UNASSIGNED, /* M-K */
+ F_CASELOWER, /* M-L */
+ F_UNASSIGNED, /* M-M */
+ F_DOWN_SEARCH_HIST, /* M-N */
+ F_XKEY, /* M-O *//* extended key esc PWP Mar 88 */
+ F_UP_SEARCH_HIST, /* M-P */
+ F_UNASSIGNED, /* M-Q */
+ F_TOGGLE_HIST, /* M-R */
+ F_CORRECT, /* M-S */
+ F_UNASSIGNED, /* M-T */
+ F_CASEUPPER, /* M-U */
+ F_UNASSIGNED, /* M-V */
+ F_COPYREGION, /* M-W */
+ F_UNASSIGNED, /* M-X */
+ F_UNASSIGNED, /* M-Y */
+ F_UNASSIGNED, /* M-Z */
+ F_XKEY, /* M-[ *//* extended key esc -mf Oct 87 */
+ F_UNASSIGNED, /* M-\ */
+ F_UNASSIGNED, /* M-] */
+ F_UNASSIGNED, /* M-^ */
+ F_LAST_ITEM, /* M-_ */
+ F_UNASSIGNED, /* M-` */
+ F_UNASSIGNED, /* M-a */
+ F_WORDBACK, /* M-b */
+ F_CASECAPITAL, /* M-c */
+ F_DELWORDNEXT, /* M-d */
+ F_UNASSIGNED, /* M-e */
+ F_WORDFWD, /* M-f */
+ F_UNASSIGNED, /* M-g */
+ F_HELPME, /* M-h */
+ F_UNASSIGNED, /* M-i */
+ F_UNASSIGNED, /* M-j */
+ F_UNASSIGNED, /* M-k */
+ F_CASELOWER, /* M-l */
+ F_UNASSIGNED, /* M-m */
+ F_DOWN_SEARCH_HIST, /* M-n */
+ F_UNASSIGNED, /* M-o */
+ F_UP_SEARCH_HIST, /* M-p */
+ F_UNASSIGNED, /* M-q */
+ F_TOGGLE_HIST, /* M-r */
+ F_CORRECT, /* M-s */
+ F_UNASSIGNED, /* M-t */
+ F_CASEUPPER, /* M-u */
+ F_UNASSIGNED, /* M-v */
+ F_COPYREGION, /* M-w */
+ F_UNASSIGNED, /* M-x */
+ F_UNASSIGNED, /* M-y */
+ F_UNASSIGNED, /* M-z */
+ F_UNASSIGNED, /* M-{ */
+ F_UNASSIGNED, /* M-| */
+ F_UNASSIGNED, /* M-} */
+ F_UNASSIGNED, /* M-~ */
+ F_DELWORDPREV /* M-^? */
+};
+
+/*
+ * keymap table for vi. Each index into above tbl; should be
+ * 256 entries long. Vi mode uses a sticky-extend to do command mode:
+ * insert mode characters are in the normal keymap, and command mode
+ * in the extended keymap.
+ */
+static KEYCMD CcViMap[] = {
+#ifdef KSHVI
+ F_UNASSIGNED, /* ^@ */
+ F_INSERT, /* ^A */
+ F_INSERT, /* ^B */
+ F_INSERT, /* ^C */
+ F_INSERT, /* ^D */
+ F_INSERT, /* ^E */
+ F_INSERT, /* ^F */
+ F_INSERT, /* ^G */
+ V_DELPREV, /* ^H */ /* BackSpace key */
+ F_COMPLETE, /* ^I */ /* Tab Key */
+ F_NEWLINE, /* ^J */
+ F_INSERT, /* ^K */
+ F_INSERT, /* ^L */
+ F_NEWLINE, /* ^M */
+ F_INSERT, /* ^N */
+ F_INSERT, /* ^O */
+ F_INSERT, /* ^P */
+ F_TTY_STARTO, /* ^Q */
+ F_INSERT, /* ^R */
+ F_INSERT, /* ^S */
+ F_INSERT, /* ^T */
+ F_INSERT, /* ^U */
+ F_QUOTE, /* ^V */
+ F_DELWORDPREV, /* ^W */ /* Only until start edit pos */
+ F_INSERT, /* ^X */
+ F_INSERT, /* ^Y */
+ F_INSERT, /* ^Z */
+ V_CMD_MODE, /* ^[ */ /* [ Esc ] key */
+ F_TTY_QUIT, /* ^\ */
+ F_INSERT, /* ^] */
+ F_INSERT, /* ^^ */
+ F_INSERT, /* ^_ */
+#else /* !KSHVI */
+ F_UNASSIGNED, /* ^@ */ /* NOTE: These mapping do NOT */
+ F_TOBEG, /* ^A */ /* Correspond well to the KSH */
+ F_CHARBACK, /* ^B */ /* VI editting assignments */
+ F_TTY_INT, /* ^C */ /* On the other hand they are */
+ F_LIST_EOF, /* ^D */ /* convenient any many people */
+ F_TOEND, /* ^E */ /* have gotten used to them */
+ F_CHARFWD, /* ^F */
+ F_LIST_GLOB, /* ^G */
+ F_DELPREV, /* ^H */ /* BackSpace key */
+ F_COMPLETE, /* ^I */ /* Tab Key */
+ F_NEWLINE, /* ^J */
+ F_KILLEND, /* ^K */
+ F_CLEARDISP, /* ^L */
+ F_NEWLINE, /* ^M */
+ F_DOWN_HIST, /* ^N */
+ F_TTY_FLUSHO, /* ^O */
+ F_UP_HIST, /* ^P */
+ F_TTY_STARTO, /* ^Q */
+ F_REDISP, /* ^R */
+ F_TTY_STOPO, /* ^S */
+ F_CHARSWITCH, /* ^T */
+ F_KILLBEG, /* ^U */
+ F_QUOTE, /* ^V */
+ F_DELWORDPREV, /* ^W */
+ F_EXPAND, /* ^X */
+ F_TTY_DSUSP, /* ^Y */
+ F_TTY_TSUSP, /* ^Z */
+ V_CMD_MODE, /* ^[ */
+ F_TTY_QUIT, /* ^\ */
+ F_UNASSIGNED, /* ^] */
+ F_UNASSIGNED, /* ^^ */
+ F_UNASSIGNED, /* ^_ */
+#endif /* KSHVI */
+ F_INSERT, /* SPACE */
+ F_INSERT, /* ! */
+ F_INSERT, /* " */
+ F_INSERT, /* # */
+ F_INSERT, /* $ */
+ F_INSERT, /* % */
+ F_INSERT, /* & */
+ F_INSERT, /* ' */
+ F_INSERT, /* ( */
+ F_INSERT, /* ) */
+ F_INSERT, /* * */
+ F_INSERT, /* + */
+ F_INSERT, /* , */
+ F_INSERT, /* - */
+ F_INSERT, /* . */
+ F_INSERT, /* / */
+ F_INSERT, /* 0 */
+ F_INSERT, /* 1 */
+ F_INSERT, /* 2 */
+ F_INSERT, /* 3 */
+ F_INSERT, /* 4 */
+ F_INSERT, /* 5 */
+ F_INSERT, /* 6 */
+ F_INSERT, /* 7 */
+ F_INSERT, /* 8 */
+ F_INSERT, /* 9 */
+ F_INSERT, /* : */
+ F_INSERT, /* ; */
+ F_INSERT, /* < */
+ F_INSERT, /* = */
+ F_INSERT, /* > */
+ F_INSERT, /* ? */
+ F_INSERT, /* @ */
+ F_INSERT, /* A */
+ F_INSERT, /* B */
+ F_INSERT, /* C */
+ F_INSERT, /* D */
+ F_INSERT, /* E */
+ F_INSERT, /* F */
+ F_INSERT, /* G */
+ F_INSERT, /* H */
+ F_INSERT, /* I */
+ F_INSERT, /* J */
+ F_INSERT, /* K */
+ F_INSERT, /* L */
+ F_INSERT, /* M */
+ F_INSERT, /* N */
+ F_INSERT, /* O */
+ F_INSERT, /* P */
+ F_INSERT, /* Q */
+ F_INSERT, /* R */
+ F_INSERT, /* S */
+ F_INSERT, /* T */
+ F_INSERT, /* U */
+ F_INSERT, /* V */
+ F_INSERT, /* W */
+ F_INSERT, /* X */
+ F_INSERT, /* Y */
+ F_INSERT, /* Z */
+ F_INSERT, /* [ */
+ F_INSERT, /* \ */
+ F_INSERT, /* ] */
+ F_INSERT, /* ^ */
+ F_INSERT, /* _ */
+ F_INSERT, /* ` */
+ F_INSERT, /* a */
+ F_INSERT, /* b */
+ F_INSERT, /* c */
+ F_INSERT, /* d */
+ F_INSERT, /* e */
+ F_INSERT, /* f */
+ F_INSERT, /* g */
+ F_INSERT, /* h */
+ F_INSERT, /* i */
+ F_INSERT, /* j */
+ F_INSERT, /* k */
+ F_INSERT, /* l */
+ F_INSERT, /* m */
+ F_INSERT, /* n */
+ F_INSERT, /* o */
+ F_INSERT, /* p */
+ F_INSERT, /* q */
+ F_INSERT, /* r */
+ F_INSERT, /* s */
+ F_INSERT, /* t */
+ F_INSERT, /* u */
+ F_INSERT, /* v */
+ F_INSERT, /* w */
+ F_INSERT, /* x */
+ F_INSERT, /* y */
+ F_INSERT, /* z */
+ F_INSERT, /* { */
+ F_INSERT, /* | */
+ F_INSERT, /* } */
+ F_INSERT, /* ~ */
+ F_DELPREV, /* ^? */
+ F_UNASSIGNED, /* M-^@ */
+ F_UNASSIGNED, /* M-^A */
+ F_UNASSIGNED, /* M-^B */
+ F_UNASSIGNED, /* M-^C */
+ F_UNASSIGNED, /* M-^D */
+ F_UNASSIGNED, /* M-^E */
+ F_UNASSIGNED, /* M-^F */
+ F_UNASSIGNED, /* M-^G */
+ F_UNASSIGNED, /* M-^H */
+ F_UNASSIGNED, /* M-^I */
+ F_UNASSIGNED, /* M-^J */
+ F_UNASSIGNED, /* M-^K */
+ F_UNASSIGNED, /* M-^L */
+ F_UNASSIGNED, /* M-^M */
+ F_UNASSIGNED, /* M-^N */
+ F_UNASSIGNED, /* M-^O */
+ F_UNASSIGNED, /* M-^P */
+ F_UNASSIGNED, /* M-^Q */
+ F_UNASSIGNED, /* M-^R */
+ F_UNASSIGNED, /* M-^S */
+ F_UNASSIGNED, /* M-^T */
+ F_UNASSIGNED, /* M-^U */
+ F_UNASSIGNED, /* M-^V */
+ F_UNASSIGNED, /* M-^W */
+ F_UNASSIGNED, /* M-^X */
+ F_UNASSIGNED, /* M-^Y */
+ F_UNASSIGNED, /* M-^Z */
+ F_UNASSIGNED, /* M-^[ */
+ F_UNASSIGNED, /* M-^\ */
+ F_UNASSIGNED, /* M-^] */
+ F_UNASSIGNED, /* M-^^ */
+ F_UNASSIGNED, /* M-^_ */
+ F_UNASSIGNED, /* M-SPACE */
+ F_UNASSIGNED, /* M-! */
+ F_UNASSIGNED, /* M-" */
+ F_UNASSIGNED, /* M-# */
+ F_UNASSIGNED, /* M-$ */
+ F_UNASSIGNED, /* M-% */
+ F_UNASSIGNED, /* M-& */
+ F_UNASSIGNED, /* M-' */
+ F_UNASSIGNED, /* M-( */
+ F_UNASSIGNED, /* M-) */
+ F_UNASSIGNED, /* M-* */
+ F_UNASSIGNED, /* M-+ */
+ F_UNASSIGNED, /* M-, */
+ F_UNASSIGNED, /* M-- */
+ F_UNASSIGNED, /* M-. */
+ F_UNASSIGNED, /* M-/ */
+ F_UNASSIGNED, /* M-0 */
+ F_UNASSIGNED, /* M-1 */
+ F_UNASSIGNED, /* M-2 */
+ F_UNASSIGNED, /* M-3 */
+ F_UNASSIGNED, /* M-4 */
+ F_UNASSIGNED, /* M-5 */
+ F_UNASSIGNED, /* M-6 */
+ F_UNASSIGNED, /* M-7 */
+ F_UNASSIGNED, /* M-8 */
+ F_UNASSIGNED, /* M-9 */
+ F_UNASSIGNED, /* M-: */
+ F_UNASSIGNED, /* M-; */
+ F_UNASSIGNED, /* M-< */
+ F_UNASSIGNED, /* M-= */
+ F_UNASSIGNED, /* M-> */
+ F_UNASSIGNED, /* M-? */
+ F_UNASSIGNED, /* M-@ */
+ F_UNASSIGNED, /* M-A */
+ F_UNASSIGNED, /* M-B */
+ F_UNASSIGNED, /* M-C */
+ F_UNASSIGNED, /* M-D */
+ F_UNASSIGNED, /* M-E */
+ F_UNASSIGNED, /* M-F */
+ F_UNASSIGNED, /* M-G */
+ F_UNASSIGNED, /* M-H */
+ F_UNASSIGNED, /* M-I */
+ F_UNASSIGNED, /* M-J */
+ F_UNASSIGNED, /* M-K */
+ F_UNASSIGNED, /* M-L */
+ F_UNASSIGNED, /* M-M */
+ F_UNASSIGNED, /* M-N */
+ F_UNASSIGNED, /* M-O */
+ F_UNASSIGNED, /* M-P */
+ F_UNASSIGNED, /* M-Q */
+ F_UNASSIGNED, /* M-R */
+ F_UNASSIGNED, /* M-S */
+ F_UNASSIGNED, /* M-T */
+ F_UNASSIGNED, /* M-U */
+ F_UNASSIGNED, /* M-V */
+ F_UNASSIGNED, /* M-W */
+ F_UNASSIGNED, /* M-X */
+ F_UNASSIGNED, /* M-Y */
+ F_UNASSIGNED, /* M-Z */
+ F_UNASSIGNED, /* M-[ */
+ F_UNASSIGNED, /* M-\ */
+ F_UNASSIGNED, /* M-] */
+ F_UNASSIGNED, /* M-^ */
+ F_UNASSIGNED, /* M-_ */
+ F_UNASSIGNED, /* M-` */
+ F_UNASSIGNED, /* M-a */
+ F_UNASSIGNED, /* M-b */
+ F_UNASSIGNED, /* M-c */
+ F_UNASSIGNED, /* M-d */
+ F_UNASSIGNED, /* M-e */
+ F_UNASSIGNED, /* M-f */
+ F_UNASSIGNED, /* M-g */
+ F_UNASSIGNED, /* M-h */
+ F_UNASSIGNED, /* M-i */
+ F_UNASSIGNED, /* M-j */
+ F_UNASSIGNED, /* M-k */
+ F_UNASSIGNED, /* M-l */
+ F_UNASSIGNED, /* M-m */
+ F_UNASSIGNED, /* M-n */
+ F_UNASSIGNED, /* M-o */
+ F_UNASSIGNED, /* M-p */
+ F_UNASSIGNED, /* M-q */
+ F_UNASSIGNED, /* M-r */
+ F_UNASSIGNED, /* M-s */
+ F_UNASSIGNED, /* M-t */
+ F_UNASSIGNED, /* M-u */
+ F_UNASSIGNED, /* M-v */
+ F_UNASSIGNED, /* M-w */
+ F_UNASSIGNED, /* M-x */
+ F_UNASSIGNED, /* M-y */
+ F_UNASSIGNED, /* M-z */
+ F_UNASSIGNED, /* M-{ */
+ F_UNASSIGNED, /* M-| */
+ F_UNASSIGNED, /* M-} */
+ F_UNASSIGNED, /* M-~ */
+ F_UNASSIGNED /* M-^? */
+};
+
+KEYCMD CcViCmdMap[] = {
+ F_UNASSIGNED, /* ^@ */
+ F_TOBEG, /* ^A */
+ F_UNASSIGNED, /* ^B */
+ F_TTY_INT, /* ^C */
+ F_LIST_CHOICES, /* ^D */
+ F_TOEND, /* ^E */
+ F_UNASSIGNED, /* ^F */
+ F_LIST_GLOB, /* ^G */
+ F_CHARBACK, /* ^H */
+ V_CM_COMPLETE, /* ^I */
+ F_NEWLINE, /* ^J */
+ F_KILLEND, /* ^K */
+ F_CLEARDISP, /* ^L */
+ F_NEWLINE, /* ^M */
+ F_DOWN_HIST, /* ^N */
+ F_TTY_FLUSHO, /* ^O */
+ F_UP_HIST, /* ^P */
+ F_TTY_STARTO, /* ^Q */
+ F_REDISP, /* ^R */
+ F_TTY_STOPO, /* ^S */
+ F_UNASSIGNED, /* ^T */
+ F_KILLBEG, /* ^U */
+ F_UNASSIGNED, /* ^V */
+ F_DELWORDPREV, /* ^W */
+ F_EXPAND, /* ^X */
+ F_UNASSIGNED, /* ^Y */
+ F_UNASSIGNED, /* ^Z */
+ F_METANEXT, /* ^[ */
+ F_TTY_QUIT, /* ^\ */
+ F_UNASSIGNED, /* ^] */
+ F_UNASSIGNED, /* ^^ */
+ F_UNASSIGNED, /* ^_ */
+ F_CHARFWD, /* SPACE */
+ F_EXPAND_HISTORY, /* ! */
+ F_UNASSIGNED, /* " */
+ F_UNASSIGNED, /* # */
+ F_TOEND, /* $ */
+ F_UNASSIGNED, /* % */
+ F_UNASSIGNED, /* & */
+ F_UNASSIGNED, /* ' */
+ F_UNASSIGNED, /* ( */
+ F_UNASSIGNED, /* ) */
+ F_EXPAND_GLOB, /* * */
+ F_DOWN_HIST, /* + */
+ V_RCHAR_BACK, /* , */
+ F_UP_HIST, /* - */
+ F_UNASSIGNED, /* . */
+ V_DSH_META, /* / */
+ V_ZERO, /* 0 */
+ F_ARGDIGIT, /* 1 */
+ F_ARGDIGIT, /* 2 */
+ F_ARGDIGIT, /* 3 */
+ F_ARGDIGIT, /* 4 */
+ F_ARGDIGIT, /* 5 */
+ F_ARGDIGIT, /* 6 */
+ F_ARGDIGIT, /* 7 */
+ F_ARGDIGIT, /* 8 */
+ F_ARGDIGIT, /* 9 */
+ F_UNASSIGNED, /* : */
+ V_RCHAR_FWD, /* ; */
+ F_UNASSIGNED, /* < */
+ F_UNASSIGNED, /* = */
+ F_UNASSIGNED, /* > */
+ V_USH_META, /* ? */
+ F_UNASSIGNED, /* @ */
+ V_ADDEND, /* A */
+ V_WORDBACK, /* B */
+ V_CHGTOEND, /* C */
+ F_KILLEND, /* D */
+ V_ENDWORD, /* E */
+ V_CHAR_BACK, /* F */
+ F_UNASSIGNED, /* G */
+ F_UNASSIGNED, /* H */
+ V_INSBEG, /* I */
+ F_DOWN_SEARCH_HIST, /* J */
+ F_UP_SEARCH_HIST, /* K */
+ F_UNASSIGNED, /* L */
+ F_UNASSIGNED, /* M */
+ V_RSRCH_BACK, /* N */
+ F_XKEY, /* O */
+ F_UNASSIGNED, /* P */
+ F_UNASSIGNED, /* Q */
+ V_REPLMODE, /* R */
+ V_SUBSTLINE, /* S */
+ V_CHARTO_BACK, /* T */
+ F_UNASSIGNED, /* U */
+ F_EXPAND_VARS, /* V */
+ V_WORDFWD, /* W */
+ F_DELPREV, /* X */
+ F_UNASSIGNED, /* Y */
+ F_UNASSIGNED, /* Z */
+ F_XKEY, /* [ */
+ F_UNASSIGNED, /* \ */
+ F_UNASSIGNED, /* ] */
+ F_TOBEG, /* ^ */
+ F_UNASSIGNED, /* _ */
+ F_UNASSIGNED, /* ` */
+ V_ADD, /* a */
+ F_WORDBACK, /* b */
+ V_CHGMETA, /* c */
+ V_DELMETA, /* d */
+ V_EWORD, /* e */
+ V_CHAR_FWD, /* f */
+ F_UNASSIGNED, /* g */
+ F_CHARBACK, /* h */
+ V_INSERT, /* i */
+ F_DOWN_HIST, /* j */
+ F_UP_HIST, /* k */
+ F_CHARFWD, /* l */
+ F_UNASSIGNED, /* m */
+ V_RSRCH_FWD, /* n */
+ F_UNASSIGNED, /* o */
+ F_UNASSIGNED, /* p */
+ F_UNASSIGNED, /* q */
+ V_REPLONE, /* r */
+ V_SUBSTCHAR, /* s */
+ V_CHARTO_FWD, /* t */
+ V_UNDO, /* u */
+ F_EXPAND_VARS, /* v */
+ V_WORDBEGNEXT, /* w */
+ F_DELNEXT_EOF, /* x */
+ F_UNASSIGNED, /* y */
+ F_UNASSIGNED, /* z */
+ F_UNASSIGNED, /* { */
+ F_UNASSIGNED, /* | */
+ F_UNASSIGNED, /* } */
+ V_CHGCASE, /* ~ */
+ F_DELPREV, /* ^? */
+ F_UNASSIGNED, /* M-^@ */
+ F_UNASSIGNED, /* M-^A */
+ F_UNASSIGNED, /* M-^B */
+ F_UNASSIGNED, /* M-^C */
+ F_UNASSIGNED, /* M-^D */
+ F_UNASSIGNED, /* M-^E */
+ F_UNASSIGNED, /* M-^F */
+ F_UNASSIGNED, /* M-^G */
+ F_UNASSIGNED, /* M-^H */
+ F_UNASSIGNED, /* M-^I */
+ F_UNASSIGNED, /* M-^J */
+ F_UNASSIGNED, /* M-^K */
+ F_UNASSIGNED, /* M-^L */
+ F_UNASSIGNED, /* M-^M */
+ F_UNASSIGNED, /* M-^N */
+ F_UNASSIGNED, /* M-^O */
+ F_UNASSIGNED, /* M-^P */
+ F_UNASSIGNED, /* M-^Q */
+ F_UNASSIGNED, /* M-^R */
+ F_UNASSIGNED, /* M-^S */
+ F_UNASSIGNED, /* M-^T */
+ F_UNASSIGNED, /* M-^U */
+ F_UNASSIGNED, /* M-^V */
+ F_UNASSIGNED, /* M-^W */
+ F_UNASSIGNED, /* M-^X */
+ F_UNASSIGNED, /* M-^Y */
+ F_UNASSIGNED, /* M-^Z */
+ F_UNASSIGNED, /* M-^[ */
+ F_UNASSIGNED, /* M-^\ */
+ F_UNASSIGNED, /* M-^] */
+ F_UNASSIGNED, /* M-^^ */
+ F_UNASSIGNED, /* M-^_ */
+ F_UNASSIGNED, /* M-SPACE */
+ F_UNASSIGNED, /* M-! */
+ F_UNASSIGNED, /* M-" */
+ F_UNASSIGNED, /* M-# */
+ F_UNASSIGNED, /* M-$ */
+ F_UNASSIGNED, /* M-% */
+ F_UNASSIGNED, /* M-& */
+ F_UNASSIGNED, /* M-' */
+ F_UNASSIGNED, /* M-( */
+ F_UNASSIGNED, /* M-) */
+ F_UNASSIGNED, /* M-* */
+ F_UNASSIGNED, /* M-+ */
+ F_UNASSIGNED, /* M-, */
+ F_UNASSIGNED, /* M-- */
+ F_UNASSIGNED, /* M-. */
+ F_UNASSIGNED, /* M-/ */
+ F_UNASSIGNED, /* M-0 */
+ F_UNASSIGNED, /* M-1 */
+ F_UNASSIGNED, /* M-2 */
+ F_UNASSIGNED, /* M-3 */
+ F_UNASSIGNED, /* M-4 */
+ F_UNASSIGNED, /* M-5 */
+ F_UNASSIGNED, /* M-6 */
+ F_UNASSIGNED, /* M-7 */
+ F_UNASSIGNED, /* M-8 */
+ F_UNASSIGNED, /* M-9 */
+ F_UNASSIGNED, /* M-: */
+ F_UNASSIGNED, /* M-; */
+ F_UNASSIGNED, /* M-< */
+ F_UNASSIGNED, /* M-= */
+ F_UNASSIGNED, /* M-> */
+ F_HELPME, /* M-? */
+ F_UNASSIGNED, /* M-@ */
+ F_UNASSIGNED, /* M-A */
+ F_UNASSIGNED, /* M-B */
+ F_UNASSIGNED, /* M-C */
+ F_UNASSIGNED, /* M-D */
+ F_UNASSIGNED, /* M-E */
+ F_UNASSIGNED, /* M-F */
+ F_UNASSIGNED, /* M-G */
+ F_UNASSIGNED, /* M-H */
+ F_UNASSIGNED, /* M-I */
+ F_UNASSIGNED, /* M-J */
+ F_UNASSIGNED, /* M-K */
+ F_UNASSIGNED, /* M-L */
+ F_UNASSIGNED, /* M-M */
+ F_UNASSIGNED, /* M-N */
+ F_XKEY, /* M-O *//* extended key esc PWP Mar 88 */
+ F_UNASSIGNED, /* M-P */
+ F_UNASSIGNED, /* M-Q */
+ F_UNASSIGNED, /* M-R */
+ F_UNASSIGNED, /* M-S */
+ F_UNASSIGNED, /* M-T */
+ F_UNASSIGNED, /* M-U */
+ F_UNASSIGNED, /* M-V */
+ F_UNASSIGNED, /* M-W */
+ F_UNASSIGNED, /* M-X */
+ F_UNASSIGNED, /* M-Y */
+ F_UNASSIGNED, /* M-Z */
+ F_XKEY, /* M-[ *//* extended key esc -mf Oct 87 */
+ F_UNASSIGNED, /* M-\ */
+ F_UNASSIGNED, /* M-] */
+ F_UNASSIGNED, /* M-^ */
+ F_UNASSIGNED, /* M-_ */
+ F_UNASSIGNED, /* M-` */
+ F_UNASSIGNED, /* M-a */
+ F_UNASSIGNED, /* M-b */
+ F_UNASSIGNED, /* M-c */
+ F_UNASSIGNED, /* M-d */
+ F_UNASSIGNED, /* M-e */
+ F_UNASSIGNED, /* M-f */
+ F_UNASSIGNED, /* M-g */
+ F_UNASSIGNED, /* M-h */
+ F_UNASSIGNED, /* M-i */
+ F_UNASSIGNED, /* M-j */
+ F_UNASSIGNED, /* M-k */
+ F_UNASSIGNED, /* M-l */
+ F_UNASSIGNED, /* M-m */
+ F_UNASSIGNED, /* M-n */
+ F_UNASSIGNED, /* M-o */
+ F_UNASSIGNED, /* M-p */
+ F_UNASSIGNED, /* M-q */
+ F_UNASSIGNED, /* M-r */
+ F_UNASSIGNED, /* M-s */
+ F_UNASSIGNED, /* M-t */
+ F_UNASSIGNED, /* M-u */
+ F_UNASSIGNED, /* M-v */
+ F_UNASSIGNED, /* M-w */
+ F_UNASSIGNED, /* M-x */
+ F_UNASSIGNED, /* M-y */
+ F_UNASSIGNED, /* M-z */
+ F_UNASSIGNED, /* M-{ */
+ F_UNASSIGNED, /* M-| */
+ F_UNASSIGNED, /* M-} */
+ F_UNASSIGNED, /* M-~ */
+ F_UNASSIGNED /* M-^? */
+};
+#endif /* WINNT */
+
+
+void
+editinit()
+{
+ struct KeyFuncs *f;
+
+#if defined(NLS_CATALOGS) || defined(WINNT)
+ int i;
+
+ for (i = 0; i < F_NUM_FUNCNAMES; i++)
+ xfree((ptr_t) FuncNames[i].desc);
+#endif
+
+ f = FuncNames;
+ f->name = "backward-char";
+ f->func = F_CHARBACK;
+ f->desc = CSAVS(3, 1, "Move back a character");
+
+ f++;
+ f->name = "backward-delete-char";
+ f->func = F_DELPREV;
+ f->desc = CSAVS(3, 2, "Delete the character behind cursor");
+
+ f++;
+ f->name = "backward-delete-word";
+ f->func = F_DELWORDPREV;
+ f->desc = CSAVS(3, 3,
+ "Cut from beginning of current word to cursor - saved in cut buffer");
+
+ f++;
+ f->name = "backward-kill-line";
+ f->func = F_KILLBEG;
+ f->desc = CSAVS(3, 4,
+ "Cut from beginning of line to cursor - save in cut buffer");
+
+ f++;
+ f->name = "backward-word";
+ f->func = F_WORDBACK;
+ f->desc = CSAVS(3, 5, "Move to beginning of current word");
+
+ f++;
+ f->name = "beginning-of-line";
+ f->func = F_TOBEG;
+ f->desc = CSAVS(3, 6, "Move to beginning of line");
+
+ f++;
+ f->name = "capitalize-word";
+ f->func = F_CASECAPITAL;
+ f->desc = CSAVS(3, 7,
+ "Capitalize the characters from cursor to end of current word");
+
+ f++;
+ f->name = "change-case";
+ f->func = V_CHGCASE;
+ f->desc = CSAVS(3, 8,
+ "Vi change case of character under cursor and advance one character");
+
+ f++;
+ f->name = "change-till-end-of-line";
+ f->func = V_CHGTOEND; /* backward compat. */
+ f->desc = CSAVS(3, 9, "Vi change to end of line");
+
+ f++;
+ f->name = "clear-screen";
+ f->func = F_CLEARDISP;
+ f->desc = CSAVS(3, 10, "Clear screen leaving current line on top");
+
+ f++;
+ f->name = "complete-word";
+ f->func = F_COMPLETE;
+ f->desc = CSAVS(3, 11, "Complete current word");
+
+ f++;
+ f->name = "complete-word-fwd";
+ f->func = F_COMPLETE_FWD;
+ f->desc = CSAVS(3, 12, "Tab forward through files");
+
+ f++;
+ f->name = "complete-word-back";
+ f->func = F_COMPLETE_BACK;
+ f->desc = CSAVS(3, 13, "Tab backward through files");
+
+ f++;
+ f->name = "complete-word-raw";
+ f->func = F_COMPLETE_ALL;
+ f->desc = CSAVS(3, 14,
+ "Complete current word ignoring programmable completions");
+
+ f++;
+ f->name = "copy-prev-word";
+ f->func = F_COPYPREV;
+ f->desc = CSAVS(3, 15, "Copy current word to cursor");
+
+ f++;
+ f->name = "copy-region-as-kill";
+ f->func = F_COPYREGION;
+ f->desc = CSAVS(3, 16, "Copy area between mark and cursor to cut buffer");
+
+ f++;
+ f->name = "dabbrev-expand";
+ f->func = F_DABBREV_EXPAND;
+ f->desc = CSAVS(3, 17,
+ "Expand to preceding word for which this is a prefix");
+
+ f++;
+ f->name = "delete-char";
+ f->func = F_DELNEXT;
+ f->desc = CSAVS(3, 18, "Delete character under cursor");
+
+ f++;
+ f->name = "delete-char-or-eof";
+ f->func = F_DELNEXT_EOF;
+ f->desc = CSAVS(3, 19,
+ "Delete character under cursor or signal end of file on an empty line");
+
+ f++;
+ f->name = "delete-char-or-list";
+ f->func = F_DELNEXT_LIST;
+ f->desc = CSAVS(3, 20,
+ "Delete character under cursor or list completions if at end of line");
+
+ f++;
+ f->name = "delete-char-or-list-or-eof";
+ f->func = F_DELNEXT_LIST_EOF;
+ f->desc = CSAVS(3, 21,
+ "Delete character under cursor, list completions or signal end of file");
+
+ f++;
+ f->name = "delete-word";
+ f->func = F_DELWORDNEXT;
+ f->desc = CSAVS(3, 22,
+ "Cut from cursor to end of current word - save in cut buffer");
+
+ f++;
+ f->name = "digit";
+ f->func = F_DIGIT;
+ f->desc = CSAVS(3, 23, "Adds to argument if started or enters digit");
+
+ f++;
+ f->name = "digit-argument";
+ f->func = F_ARGDIGIT;
+ f->desc = CSAVS(3, 24, "Digit that starts argument");
+
+ f++;
+ f->name = "down-history";
+ f->func = F_DOWN_HIST;
+ f->desc = CSAVS(3, 25, "Move to next history line");
+
+ f++;
+ f->name = "downcase-word";
+ f->func = F_CASELOWER;
+ f->desc = CSAVS(3, 26,
+ "Lowercase the characters from cursor to end of current word");
+
+ f++;
+ f->name = "end-of-file";
+ f->func = F_SEND_EOF;
+ f->desc = CSAVS(3, 27, "Indicate end of file");
+
+ f++;
+ f->name = "end-of-line";
+ f->func = F_TOEND;
+ f->desc = CSAVS(3, 28, "Move cursor to end of line");
+
+ f++;
+ f->name = "exchange-point-and-mark";
+ f->func = F_EXCHANGE_MARK;
+ f->desc = CSAVS(3, 29, "Exchange the cursor and mark");
+
+ f++;
+ f->name = "expand-glob";
+ f->func = F_EXPAND_GLOB;
+ f->desc = CSAVS(3, 30, "Expand file name wildcards");
+
+ f++;
+ f->name = "expand-history";
+ f->func = F_EXPAND_HISTORY;
+ f->desc = CSAVS(3, 31, "Expand history escapes");
+
+ f++;
+ f->name = "expand-line";
+ f->func = F_EXPAND;
+ f->desc = CSAVS(3, 32, "Expand the history escapes in a line");
+
+ f++;
+ f->name = "expand-variables";
+ f->func = F_EXPAND_VARS;
+ f->desc = CSAVS(3, 33, "Expand variables");
+
+ f++;
+ f->name = "forward-char";
+ f->func = F_CHARFWD;
+ f->desc = CSAVS(3, 34, "Move forward one character");
+
+ f++;
+ f->name = "forward-word";
+ f->func = F_WORDFWD;
+ f->desc = CSAVS(3, 35, "Move forward to end of current word");
+
+ f++;
+ f->name = "gosmacs-transpose-chars";
+ f->func = F_GCHARSWITCH;
+ f->desc = CSAVS(3, 36, "Exchange the two characters before the cursor");
+
+ f++;
+ f->name = "history-search-backward";
+ f->func = F_UP_SEARCH_HIST;
+ f->desc = CSAVS(3, 37,
+ "Search in history backward for line beginning as current");
+
+ f++;
+ f->name = "history-search-forward";
+ f->func = F_DOWN_SEARCH_HIST;
+ f->desc = CSAVS(3, 38,
+ "Search in history forward for line beginning as current");
+
+ f++;
+ f->name = "insert-last-word";
+ f->func = F_LAST_ITEM;
+ f->desc = CSAVS(3, 39, "Insert last item of previous command");
+
+ f++;
+ f->name = "i-search-fwd";
+ f->func = F_INC_FWD;
+ f->desc = CSAVS(3, 40, "Incremental search forward");
+
+ f++;
+ f->name = "i-search-back";
+ f->func = F_INC_BACK;
+ f->desc = CSAVS(3, 41, "Incremental search backward");
+
+ f++;
+ f->name = "keyboard-quit";
+ f->func = F_STARTOVER;
+ f->desc = CSAVS(3, 42, "Clear line");
+
+ f++;
+ f->name = "kill-line";
+ f->func = F_KILLEND;
+ f->desc = CSAVS(3, 43, "Cut to end of line and save in cut buffer");
+
+ f++;
+ f->name = "kill-region";
+ f->func = F_KILLREGION;
+ f->desc = CSAVS(3, 44,
+ "Cut area between mark and cursor and save in cut buffer");
+
+ f++;
+ f->name = "kill-whole-line";
+ f->func = F_KILLALL;
+ f->desc = CSAVS(3, 45, "Cut the entire line and save in cut buffer");
+
+ f++;
+ f->name = "list-choices";
+ f->func = F_LIST_CHOICES;
+ f->desc = CSAVS(3, 46, "List choices for completion");
+
+ f++;
+ f->name = "list-choices-raw";
+ f->func = F_LIST_ALL;
+ f->desc = CSAVS(3, 47,
+ "List choices for completion overriding programmable completion");
+
+ f++;
+ f->name = "list-glob";
+ f->func = F_LIST_GLOB;
+ f->desc = CSAVS(3, 48, "List file name wildcard matches");
+
+ f++;
+ f->name = "list-or-eof";
+ f->func = F_LIST_EOF;
+ f->desc = CSAVS(3, 49,
+ "List choices for completion or indicate end of file if empty line");
+
+ f++;
+ f->name = "load-average";
+ f->func = F_LOAD_AVERAGE;
+ f->desc = CSAVS(3, 50, "Display load average and current process status");
+
+ f++;
+ f->name = "magic-space";
+ f->func = F_MAGIC_SPACE;
+ f->desc = CSAVS(3, 51, "Expand history escapes and insert a space");
+
+ f++;
+ f->name = "newline";
+ f->func = F_NEWLINE;
+ f->desc = CSAVS(3, 52, "Execute command");
+
+ f++;
+ f->name = "normalize-path";
+ f->func = F_PATH_NORM;
+ f->desc = CSAVS(3, 53,
+ "Expand pathnames, eliminating leading .'s and ..'s");
+
+ f++;
+ f->name = "normalize-command";
+ f->func = F_COMMAND_NORM;
+ f->desc = CSAVS(3, 54,
+ "Expand commands to the resulting pathname or alias");
+
+ f++;
+ f->name = "overwrite-mode";
+ f->func = F_INSOVR;
+ f->desc = CSAVS(3, 55,
+ "Switch from insert to overwrite mode or vice versa");
+
+ f++;
+ f->name = "prefix-meta";
+ f->func = F_METANEXT;
+ f->desc = CSAVS(3, 56, "Add 8th bit to next character typed");
+
+ f++;
+ f->name = "quoted-insert";
+ f->func = F_QUOTE;
+ f->desc = CSAVS(3, 57, "Add the next character typed to the line verbatim");
+
+ f++;
+ f->name = "redisplay";
+ f->func = F_REDISP;
+ f->desc = CSAVS(3, 58, "Redisplay everything");
+
+ f++;
+ f->name = "run-fg-editor";
+ f->func = F_RUN_FG_EDITOR;
+ f->desc = CSAVS(3, 59, "Restart stopped editor");
+
+ f++;
+ f->name = "run-help";
+ f->func = F_HELPME;
+ f->desc = CSAVS(3, 60, "Look for help on current command");
+
+ f++;
+ f->name = "self-insert-command";
+ f->func = F_INSERT;
+ f->desc = CSAVS(3, 61, "This character is added to the line");
+
+ f++;
+ f->name = "sequence-lead-in";
+ f->func = F_XKEY;
+ f->desc = CSAVS(3, 62,
+ "This character is the first in a character sequence");
+
+ f++;
+ f->name = "set-mark-command";
+ f->func = F_SET_MARK;
+ f->desc = CSAVS(3, 63, "Set the mark at cursor");
+
+ f++;
+ f->name = "spell-word";
+ f->func = F_CORRECT;
+ f->desc = CSAVS(3, 64, "Correct the spelling of current word");
+
+ f++;
+ f->name = "spell-line";
+ f->func = F_CORRECT_L;
+ f->desc = CSAVS(3, 65, "Correct the spelling of entire line");
+
+ f++;
+ f->name = "stuff-char";
+ f->func = F_STUFF_CHAR;
+ f->desc = CSAVS(3, 66, "Send character to tty in cooked mode");
+
+ f++;
+ f->name = "toggle-literal-history";
+ f->func = F_TOGGLE_HIST;
+ f->desc = CSAVS(3, 67,
+ "Toggle between literal and lexical current history line");
+
+ f++;
+ f->name = "transpose-chars";
+ f->func = F_CHARSWITCH;
+ f->desc = CSAVS(3, 68,
+ "Exchange the character to the left of the cursor with the one under");
+
+ f++;
+ f->name = "transpose-gosling";
+ f->func = F_GCHARSWITCH;
+ f->desc = CSAVS(3, 69, "Exchange the two characters before the cursor");
+
+ f++;
+ f->name = "tty-dsusp";
+ f->func = F_TTY_DSUSP;
+ f->desc = CSAVS(3, 70, "Tty delayed suspend character");
+
+ f++;
+ f->name = "tty-flush-output";
+ f->func = F_TTY_FLUSHO;
+ f->desc = CSAVS(3, 71, "Tty flush output character");
+
+ f++;
+ f->name = "tty-sigintr";
+ f->func = F_TTY_INT;
+ f->desc = CSAVS(3, 72, "Tty interrupt character");
+
+ f++;
+ f->name = "tty-sigquit";
+ f->func = F_TTY_QUIT;
+ f->desc = CSAVS(3, 73, "Tty quit character");
+
+ f++;
+ f->name = "tty-sigtsusp";
+ f->func = F_TTY_TSUSP;
+ f->desc = CSAVS(3, 74, "Tty suspend character");
+
+ f++;
+ f->name = "tty-start-output";
+ f->func = F_TTY_STARTO;
+ f->desc = CSAVS(3, 75, "Tty allow output character");
+
+ f++;
+ f->name = "tty-stop-output";
+ f->func = F_TTY_STOPO;
+ f->desc = CSAVS(3, 76, "Tty disallow output character");
+
+ f++;
+ f->name = "undefined-key";
+ f->func = F_UNASSIGNED;
+ f->desc = CSAVS(3, 77, "Indicates unbound character");
+
+ f++;
+ f->name = "universal-argument";
+ f->func = F_ARGFOUR;
+ f->desc = CSAVS(3, 78, "Emacs universal argument (argument times 4)");
+
+ f++;
+ f->name = "up-history";
+ f->func = F_UP_HIST;
+ f->desc = CSAVS(3, 79, "Move to previous history line");
+
+ f++;
+ f->name = "upcase-word";
+ f->func = F_CASEUPPER;
+ f->desc = CSAVS(3, 80,
+ "Uppercase the characters from cursor to end of current word");
+
+ f++;
+ f->name = "vi-beginning-of-next-word";
+ f->func = V_WORDBEGNEXT;
+ f->desc = CSAVS(3, 81, "Vi goto the beginning of next word");
+
+ f++;
+ f->name = "vi-add";
+ f->func = V_ADD;
+ f->desc = CSAVS(3, 82, "Vi enter insert mode after the cursor");
+
+ f++;
+ f->name = "vi-add-at-eol";
+ f->func = V_ADDEND;
+ f->desc = CSAVS(3, 83, "Vi enter insert mode at end of line");
+
+ f++;
+ f->name = "vi-chg-case";
+ f->func = V_CHGCASE;
+ f->desc = CSAVS(3, 84,
+ "Vi change case of character under cursor and advance one character");
+
+ f++;
+ f->name = "vi-chg-meta";
+ f->func = V_CHGMETA;
+ f->desc = CSAVS(3, 85, "Vi change prefix command");
+
+ f++;
+ f->name = "vi-chg-to-eol";
+ f->func = V_CHGTOEND;
+ f->desc = CSAVS(3, 86, "Vi change to end of line");
+
+ f++;
+ f->name = "vi-cmd-mode";
+ f->func = V_CMD_MODE;
+ f->desc = CSAVS(3, 87,
+ "Enter vi command mode (use alternative key bindings)");
+
+ f++;
+ f->name = "vi-cmd-mode-complete";
+ f->func = V_CM_COMPLETE;
+ f->desc = CSAVS(3, 88, "Vi command mode complete current word");
+
+ f++;
+ f->name = "vi-delprev";
+ f->func = V_DELPREV;
+ f->desc = CSAVS(3, 89, "Vi move to previous character (backspace)");
+
+ f++;
+ f->name = "vi-delmeta";
+ f->func = V_DELMETA;
+ f->desc = CSAVS(3, 90, "Vi delete prefix command");
+
+ f++;
+ f->name = "vi-endword";
+ f->func = V_ENDWORD;
+ f->desc = CSAVS(3, 91,
+ "Vi move to the end of the current space delimited word");
+
+ f++;
+ f->name = "vi-eword";
+ f->func = V_EWORD;
+ f->desc = CSAVS(3, 92, "Vi move to the end of the current word");
+
+ f++;
+ f->name = "vi-char-back";
+ f->func = V_CHAR_BACK;
+ f->desc = CSAVS(3, 93, "Vi move to the character specified backward");
+
+ f++;
+ f->name = "vi-char-fwd";
+ f->func = V_CHAR_FWD;
+ f->desc = CSAVS(3, 94, "Vi move to the character specified forward");
+
+ f++;
+ f->name = "vi-charto-back";
+ f->func = V_CHARTO_BACK;
+ f->desc = CSAVS(3, 95, "Vi move up to the character specified backward");
+
+ f++;
+ f->name = "vi-charto-fwd";
+ f->func = V_CHARTO_FWD;
+ f->desc = CSAVS(3, 96, "Vi move up to the character specified forward");
+
+ f++;
+ f->name = "vi-insert";
+ f->func = V_INSERT;
+ f->desc = CSAVS(3, 97, "Enter vi insert mode");
+
+ f++;
+ f->name = "vi-insert-at-bol";
+ f->func = V_INSBEG;
+ f->desc = CSAVS(3, 98, "Enter vi insert mode at beginning of line");
+
+ f++;
+ f->name = "vi-repeat-char-fwd";
+ f->func = V_RCHAR_FWD;
+ f->desc = CSAVS(3, 99,
+ "Vi repeat current character search in the same search direction");
+
+ f++;
+ f->name = "vi-repeat-char-back";
+ f->func = V_RCHAR_BACK;
+ f->desc = CSAVS(3, 100,
+ "Vi repeat current character search in the opposite search direction");
+
+ f++;
+ f->name = "vi-repeat-search-fwd";
+ f->func = V_RSRCH_FWD;
+ f->desc = CSAVS(3, 101,
+ "Vi repeat current search in the same search direction");
+
+ f++;
+ f->name = "vi-repeat-search-back";
+ f->func = V_RSRCH_BACK;
+ f->desc = CSAVS(3, 102,
+ "Vi repeat current search in the opposite search direction");
+
+ f++;
+ f->name = "vi-replace-char";
+ f->func = V_REPLONE;
+ f->desc = CSAVS(3, 103,
+ "Vi replace character under the cursor with the next character typed");
+
+ f++;
+ f->name = "vi-replace-mode";
+ f->func = V_REPLMODE;
+ f->desc = CSAVS(3, 104, "Vi replace mode");
+
+ f++;
+ f->name = "vi-search-back";
+ f->func = V_USH_META;
+ f->desc = CSAVS(3, 105, "Vi search history backward");
+
+ f++;
+ f->name = "vi-search-fwd";
+ f->func = V_DSH_META;
+ f->desc = CSAVS(3, 106, "Vi search history forward");
+
+ f++;
+ f->name = "vi-substitute-char";
+ f->func = V_SUBSTCHAR;
+ f->desc = CSAVS(3, 107,
+ "Vi replace character under the cursor and enter insert mode");
+
+ f++;
+ f->name = "vi-substitute-line";
+ f->func = V_SUBSTLINE;
+ f->desc = CSAVS(3, 108, "Vi replace entire line");
+
+ f++;
+ f->name = "vi-word-back";
+ f->func = V_WORDBACK;
+ f->desc = CSAVS(3, 109, "Vi move to the previous word");
+
+ f++;
+ f->name = "vi-word-fwd";
+ f->func = V_WORDFWD;
+ f->desc = CSAVS(3, 110, "Vi move to the next word");
+
+ f++;
+ f->name = "vi-undo";
+ f->func = V_UNDO;
+ f->desc = CSAVS(3, 111, "Vi undo last change");
+
+ f++;
+ f->name = "vi-zero";
+ f->func = V_ZERO;
+ f->desc = CSAVS(3, 112, "Vi goto the beginning of line");
+
+ f++;
+ f->name = "which-command";
+ f->func = F_WHICH;
+ f->desc = CSAVS(3, 113, "Perform which of current command");
+
+ f++;
+ f->name = "yank";
+ f->func = F_YANK_KILL;
+ f->desc = CSAVS(3, 114, "Paste cut buffer at cursor position");
+
+ f++;
+ f->name = "e_copy_to_clipboard";
+ f->func = F_COPY_CLIP;
+ f->desc = CSAVS(3, 115, "(win32 only)Copy cut buffer to system clipboard");
+ f++;
+ f->name = "e_paste_from_clipboard";
+ f->func = F_PASTE_CLIP;
+ f->desc = CSAVS(3, 116, "(win32 only)Paste clipboard buffer at cursor position");
+ f++;
+ f->name = "e_dosify_next";
+ f->func = F_DOSIFY_NEXT;
+ f->desc = CSAVS(3, 117, "(win32 only)Convert each '/' in next word to '\\\\'");
+ f++;
+ f->name = "e_dosify_prev";
+ f->func = F_DOSIFY_PREV;
+ f->desc = CSAVS(3, 118, "(win32 only)Convert each '/' in previous word to '\\\\'");
+
+ f++;
+ f->name = NULL;
+ f->func = 0;
+ f->desc = NULL;
+
+ f++;
+ if (f - FuncNames != F_NUM_FUNCNAMES)
+ abort();
+}
+
+#ifdef DEBUG_EDIT
+void
+CheckMaps()
+{ /* check the size of the key maps */
+ int c1 = (NT_NUM_KEYS * sizeof(KEYCMD));
+
+ if ((sizeof(CcKeyMap)) != c1)
+ xprintf("CcKeyMap should be %d entries, but is %d.\r\n",
+ NT_NUM_KEYS, sizeof(CcKeyMap) / sizeof(KEYCMD)));
+
+ if ((sizeof(CcAltMap)) != c1)
+ xprintf("CcAltMap should be %d entries, but is %d.\r\n",
+ NT_NUM_KEYS, (sizeof(CcAltMap) / sizeof(KEYCMD)));
+
+ if ((sizeof(CcEmacsMap)) != c1)
+ xprintf("CcEmacsMap should be %d entries, but is %d.\r\n",
+ NT_NUM_KEYS, (sizeof(CcEmacsMap) / sizeof(KEYCMD)));
+
+ if ((sizeof(CcViMap)) != c1)
+ xprintf("CcViMap should be %d entries, but is %d.\r\n",
+ NT_NUM_KEYS, (sizeof(CcViMap) / sizeof(KEYCMD)));
+
+ if ((sizeof(CcViCmdMap)) != c1)
+ xprintf("CcViCmdMap should be %d entries, but is %d.\r\n",
+ NT_NUM_KEYS, (sizeof(CcViCmdMap) / sizeof(KEYCMD)));
+}
+
+#endif
+
+bool MapsAreInited = 0;
+bool NLSMapsAreInited = 0;
+bool NoNLSRebind;
+
+void
+ed_InitNLSMaps()
+{
+ register int i;
+
+ if (AsciiOnly)
+ return;
+ if (NoNLSRebind)
+ return;
+ for (i = 0200; i <= 0377; i++) {
+ if (Isprint(i)) {
+ CcKeyMap[i] = F_INSERT;
+ }
+ }
+ NLSMapsAreInited = 1;
+}
+
+static void
+ed_InitMetaBindings()
+{
+ Char buf[3];
+ int i;
+ CStr cstr;
+ KEYCMD *map;
+
+ map = CcKeyMap;
+ for (i = 0; i <= 0377 && CcKeyMap[i] != F_METANEXT; i++)
+ continue;
+ if (i > 0377) {
+ for (i = 0; i <= 0377 && CcAltMap[i] != F_METANEXT; i++)
+ continue;
+ if (i > 0377) {
+ i = CTL_ESC('\033');
+ if (VImode)
+ map = CcAltMap;
+ }
+ else {
+ map = CcAltMap;
+ }
+ }
+ buf[0] = (Char) i;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = 2;
+ for (i = 0200; i <= 0377; i++) {
+ if (map[i] != F_INSERT && map[i] != F_UNASSIGNED && map[i] != F_XKEY) {
+#ifndef _OSD_POSIX
+ buf[1] = i & ASCII;
+#else
+ buf[1] = _toebcdic[_toascii[i] & ASCII];
+#endif
+ AddXkey(&cstr, XmapCmd((int) map[i]), XK_CMD);
+ }
+ }
+ map[buf[0]] = F_XKEY;
+}
+
+void
+ed_InitVIMaps()
+{
+ register int i;
+
+ VImode = 1;
+ ResetXmap();
+ for (i = 0; i < NT_NUM_KEYS; i++) {
+ CcKeyMap[i] = CcViMap[i];
+ CcAltMap[i] = CcViCmdMap[i];
+ }
+ ed_InitMetaBindings();
+ ed_InitNLSMaps();
+ ResetArrowKeys();
+ BindArrowKeys();
+}
+
+void
+ed_InitEmacsMaps()
+{
+ int i;
+ Char buf[3];
+ CStr cstr;
+ cstr.buf = buf;
+ cstr.len = 2;
+
+ VImode = 0;
+ ResetXmap();
+ for (i = 0; i < NT_NUM_KEYS; i++) {
+ CcKeyMap[i] = CcEmacsMap[i];
+ CcAltMap[i] = F_UNASSIGNED;
+ }
+ ed_InitMetaBindings();
+ ed_InitNLSMaps();
+ buf[0] = CTL_ESC('\030');
+ buf[2] = 0;
+ buf[1] = CTL_ESC('\030');
+ AddXkey(&cstr, XmapCmd(F_EXCHANGE_MARK), XK_CMD);
+ buf[1] = '*';
+ AddXkey(&cstr, XmapCmd(F_EXPAND_GLOB), XK_CMD);
+ buf[1] = '$';
+ AddXkey(&cstr, XmapCmd(F_EXPAND_VARS), XK_CMD);
+ buf[1] = 'G';
+ AddXkey(&cstr, XmapCmd(F_LIST_GLOB), XK_CMD);
+ buf[1] = 'g';
+ AddXkey(&cstr, XmapCmd(F_LIST_GLOB), XK_CMD);
+ buf[1] = 'n';
+ AddXkey(&cstr, XmapCmd(F_PATH_NORM), XK_CMD);
+ buf[1] = 'N';
+ AddXkey(&cstr, XmapCmd(F_PATH_NORM), XK_CMD);
+ buf[1] = '?';
+ AddXkey(&cstr, XmapCmd(F_COMMAND_NORM), XK_CMD);
+ buf[1] = '\t';
+ AddXkey(&cstr, XmapCmd(F_COMPLETE_ALL), XK_CMD);
+ buf[1] = CTL_ESC('\004'); /* ^D */
+ AddXkey(&cstr, XmapCmd(F_LIST_ALL), XK_CMD);
+ ResetArrowKeys();
+ BindArrowKeys();
+}
+
+void
+ed_InitMaps()
+{
+ if (MapsAreInited)
+ return;
+#ifdef _OSD_POSIX
+ /* This machine has an EBCDIC charset. The assumptions made for the
+ * initialized keymaps therefore don't hold, since they are based on
+ * ASCII (or ISO8859-1).
+ * Here, we do a one-time transformation to EBCDIC environment
+ * for the key initializations.
+ */
+ {
+ KEYCMD temp[NT_NUM_KEYS];
+ static KEYCMD *const list[3] = { CcEmacsMap, CcViMap, CcViCmdMap };
+ register int i, table;
+
+ for (table=0; table<3; ++table)
+ {
+ /* copy ASCII ordered map to temp table */
+ for (i = 0; i < NT_NUM_KEYS; i++) {
+ temp[i] = list[table][i];
+ }
+ /* write back as EBCDIC ordered map */
+ for (i = 0; i < NT_NUM_KEYS; i++) {
+ list[table][_toebcdic[i]] = temp[i];
+ }
+ }
+ }
+#endif /* _OSD_POSIX */
+
+#ifdef VIDEFAULT
+ ed_InitVIMaps();
+#else
+ ed_InitEmacsMaps();
+#endif
+
+ MapsAreInited = 1;
+}
diff --git a/contrib/tcsh/ed.h b/contrib/tcsh/ed.h
new file mode 100644
index 0000000..659a0a6
--- /dev/null
+++ b/contrib/tcsh/ed.h
@@ -0,0 +1,254 @@
+/* $Header: /src/pub/tcsh/ed.h,v 3.28 1998/11/24 18:17:21 christos Exp $ */
+/*
+ * ed.h: Editor declarations and globals
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_ed
+#define _h_ed
+
+#ifndef EXTERN
+# define EXTERN extern
+#endif
+
+#define TABSIZE 8 /* usually 8 spaces/tab */
+#define MAXMACROLEVELS 10 /* max number of nested kbd macros */
+
+#ifndef WINNT
+# define NT_NUM_KEYS 256
+#endif /* WINNT */
+
+extern int errno;
+
+/****************************************************************************/
+/* stuff for the different states returned by the character editor routines */
+/****************************************************************************/
+
+#define CCRETVAL char /* size needed for the different char editor */
+ /* return values */
+
+#define KEYCMD unsigned char /* size needed to index into CcFuncTbl */
+ /* Must be unsigned */
+
+typedef CCRETVAL(*PFCmd) __P((int)); /* pointer to function returning CCRETVAL */
+
+struct KeyFuncs { /* for the "bind" shell command */
+ char *name; /* function name for bind command */
+ int func; /* function numeric value */
+ char *desc; /* description of function */
+};
+
+extern PFCmd CcFuncTbl[]; /* table of available commands */
+extern KEYCMD CcKeyMap[]; /* keymap table, each index into above tbl */
+extern KEYCMD CcAltMap[]; /* Alt keymap table */
+extern KEYCMD CcEmacsMap[]; /* keymap table for Emacs default bindings */
+extern KEYCMD CcViCmdMap[]; /* for Vi command mode defaults */
+extern struct KeyFuncs FuncNames[]; /* string names vs. CcFuncTbl indices */
+
+extern KEYCMD NumFuns; /* number of KEYCMDs in above table */
+
+#define CC_ERROR 100 /* there should NOT be 100 different... */
+#define CC_FATAL 101 /* fatal error: inconsistant, must
+ * reset */
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_COMPLETE 3
+#define CC_LIST_CHOICES 4
+#define CC_LIST_GLOB 5
+#define CC_EXPAND_GLOB 6
+#define CC_HELPME 9
+#define CC_CORRECT 10
+#define CC_WHICH 11
+#define CC_ARGHACK 12
+#define CC_CORRECT_L 13
+#define CC_REFRESH 14
+#define CC_EXPAND_VARS 15
+#define CC_NORMALIZE_PATH 16
+#define CC_LIST_ALL 17
+#define CC_COMPLETE_ALL 18
+#define CC_COMPLETE_FWD 19
+#define CC_COMPLETE_BACK 20
+#define CC_NORMALIZE_COMMAND 21
+
+typedef struct {
+ Char *buf;
+ int len;
+} CStr;
+
+typedef union Xmapval { /* value passed to the Xkey routines */
+ KEYCMD cmd;
+ CStr str;
+} XmapVal;
+
+#define XK_NOD -1 /* Internal tree node */
+#define XK_CMD 0 /* X-key was an editor command */
+#define XK_STR 1 /* X-key was a string macro */
+#define XK_EXE 2 /* X-key was a unix command */
+
+/****************************/
+/* Editor state and buffers */
+/****************************/
+
+EXTERN KEYCMD *CurrentKeyMap; /* current command key map */
+EXTERN int inputmode; /* insert, replace, replace1 mode */
+EXTERN Char GettingInput; /* true if getting an input line (mostly) */
+EXTERN Char NeedsRedraw; /* for editor and twenex error messages */
+EXTERN Char InputBuf[INBUFSIZE]; /* the real input data */
+EXTERN Char *LastChar, *Cursor; /* point to the next open space */
+EXTERN Char *InputLim; /* limit of size of InputBuf */
+EXTERN Char MetaNext; /* flags for ^V and ^[ functions */
+EXTERN Char AltKeyMap; /* Using alternative command map (for vi mode) */
+EXTERN Char VImode; /* true if running in vi mode (PWP 6-27-88) */
+EXTERN Char *Mark; /* the emacs "mark" (dot is Cursor) */
+EXTERN Char DoingArg; /* true if we have an argument */
+EXTERN int Argument; /* "universal" argument value */
+EXTERN KEYCMD LastCmd; /* previous command executed */
+EXTERN Char KillBuf[INBUFSIZE]; /* kill buffer */
+EXTERN Char *LastKill; /* points to end of kill buffer */
+
+EXTERN Char UndoBuf[INBUFSIZE];
+EXTERN Char *UndoPtr;
+EXTERN int UndoSize;
+EXTERN int UndoAction;
+
+EXTERN Char HistBuf[INBUFSIZE]; /* history buffer */
+EXTERN Char *LastHist; /* points to end of history buffer */
+EXTERN int Hist_num; /* what point up the history we are at now. */
+EXTERN Char WhichBuf[INBUFSIZE]; /* buffer for which command */
+EXTERN Char *LastWhich; /* points to end of which buffer */
+EXTERN Char *CursWhich; /* points to the cursor point in which buf */
+EXTERN int HistWhich; /* Hist_num is saved in this */
+EXTERN char Expand; /* true if we are expanding a line */
+extern Char HistLit; /* true if history lines are shown literal */
+EXTERN Char CurrentHistLit; /* Literal status of current show history line */
+
+/*
+ * These are truly extern
+ */
+extern int MacroLvl;
+
+EXTERN Char *KeyMacro[MAXMACROLEVELS];
+
+EXTERN Char **Display; /* display buffer seed vector */
+EXTERN int CursorV, /* real cursor vertical (line) */
+ CursorH, /* real cursor horisontal (column) */
+ TermV, /* number of real screen lines
+ * (sizeof(DisplayBuf) / width */
+ TermH; /* screen width */
+EXTERN Char **Vdisplay; /* new buffer */
+
+/* Variables that describe terminal ability */
+EXTERN int T_Lines, T_Cols; /* Rows and Cols of the terminal */
+EXTERN Char T_CanIns; /* true if I can insert characters */
+EXTERN Char T_CanDel; /* dito for delete characters */
+EXTERN Char T_Tabs; /* true if tty interface is passing tabs */
+EXTERN Char T_Margin;
+#define MARGIN_AUTO 1 /* term has auto margins */
+#define MARGIN_MAGIC 2 /* concept glitch */
+EXTERN speed_t T_Speed; /* Tty input Baud rate */
+EXTERN Char T_CanCEOL; /* true if we can clear to end of line */
+EXTERN Char T_CanUP; /* true if this term can do reverse linefeen */
+EXTERN Char T_HasMeta; /* true if we have a meta key */
+
+/* note the extra characters in the Strchr() call in this macro */
+#define isword(c) (Isalpha(c)||Isdigit(c)||Strchr(word_chars,c))
+#define min(x,y) (((x)<(y))?(x):(y))
+#define max(x,y) (((x)>(y))?(x):(y))
+
+/*
+ * Terminal dependend data structures
+ */
+typedef struct {
+#ifdef WINNT
+ int dummy;
+#else /* !WINNT */
+# if defined(POSIX) || defined(TERMIO)
+# ifdef POSIX
+ struct termios d_t;
+# else
+ struct termio d_t;
+# endif /* POSIX */
+# else /* SGTTY */
+# ifdef TIOCGETP
+ struct sgttyb d_t;
+# endif /* TIOCGETP */
+# ifdef TIOCGETC
+ struct tchars d_tc;
+# endif /* TIOCGETC */
+# ifdef TIOCGPAGE
+ struct ttypagestat d_pc;
+# endif /* TIOCGPAGE */
+# ifdef TIOCLGET
+ int d_lb;
+# endif /* TIOCLGET */
+# endif /* POSIX || TERMIO */
+# ifdef TIOCGLTC
+ struct ltchars d_ltc;
+# endif /* TIOCGLTC */
+#endif /* WINNT */
+} ttydata_t;
+
+#define MODE_INSERT 0
+#define MODE_REPLACE 1
+#define MODE_REPLACE_1 2
+
+#define EX_IO 0 /* while we are executing */
+#define ED_IO 1 /* while we are editing */
+#define TS_IO 2 /* new mode from terminal */
+#define QU_IO 2 /* used only for quoted chars */
+#define NN_IO 3 /* The number of entries */
+
+#if defined(POSIX) || defined(TERMIO)
+# define M_INPUT 0
+# define M_OUTPUT 1
+# define M_CONTROL 2
+# define M_LINED 3
+# define M_CHAR 4
+# define M_NN 5
+#else /* GSTTY */
+# define M_CONTROL 0
+# define M_LOCAL 1
+# define M_CHAR 2
+# define M_NN 3
+#endif /* TERMIO */
+typedef struct {
+ char *t_name;
+ int t_setmask;
+ int t_clrmask;
+} ttyperm_t[NN_IO][M_NN];
+
+extern ttyperm_t ttylist;
+#include "ed.decls.h"
+
+#endif /* _h_ed */
diff --git a/contrib/tcsh/ed.init.c b/contrib/tcsh/ed.init.c
new file mode 100644
index 0000000..aa31987
--- /dev/null
+++ b/contrib/tcsh/ed.init.c
@@ -0,0 +1,736 @@
+/* $Header: /src/pub/tcsh/ed.init.c,v 3.41 1999/02/06 15:01:16 christos Exp $ */
+/*
+ * ed.init.c: Editor initializations
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTS_ION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.init.c,v 3.41 1999/02/06 15:01:16 christos Exp $")
+
+#include "ed.h"
+#include "ed.term.h"
+#include "tc.h"
+#include "ed.defns.h"
+
+/* ed.init.c -- init routines for the line editor */
+/* #define DEBUG_TTY */
+
+int Tty_raw_mode = 0; /* Last tty change was to raw mode */
+int MacroLvl = -1; /* pointer to current macro nesting level; */
+ /* (-1 == none) */
+static int Tty_quote_mode = 0; /* Last tty change was to quote mode */
+static unsigned char vdisable; /* The value of _POSIX_VDISABLE from
+ * pathconf(2) */
+
+int Tty_eight_bit = -1; /* does the tty handle eight bits */
+
+extern bool GotTermCaps;
+
+static ttydata_t extty, edtty, tstty;
+#define qutty tstty
+
+extern int insource;
+#define SHTTY (insource ? OLDSTD : SHIN)
+
+#define uc unsigned char
+static unsigned char ttychars[NN_IO][C_NCC] = {
+ {
+ (uc)CINTR, (uc)CQUIT, (uc)CERASE, (uc)CKILL,
+ (uc)CEOF, (uc)CEOL, (uc)CEOL2, (uc)CSWTCH,
+ (uc)CDSWTCH, (uc)CERASE2, (uc)CSTART, (uc)CSTOP,
+ (uc)CWERASE, (uc)CSUSP, (uc)CDSUSP, (uc)CREPRINT,
+ (uc)CDISCARD, (uc)CLNEXT, (uc)CSTATUS, (uc)CPAGE,
+ (uc)CPGOFF, (uc)CKILL2, (uc)CBRK, (uc)CMIN,
+ (uc)CTIME
+ },
+ {
+ CINTR, CQUIT, CERASE, CKILL,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
+ 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0
+ }
+};
+
+#ifdef SIG_WINDOW
+void
+check_window_size(force)
+ int force;
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+ int lins, cols;
+
+ /* don't want to confuse things here */
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIG_WINDOW)) & ~sigmask(SIG_WINDOW);
+#else /* BSDSIGS */
+ (void) sighold(SIG_WINDOW);
+#endif /* BSDSIGS */
+ /*
+ * From: bret@shark.agps.lanl.gov (Bret Thaeler) Avoid sunview bug, where a
+ * partially hidden window gets a SIG_WINDOW every time the text is
+ * scrolled
+ */
+ if (GetSize(&lins, &cols) || force) {
+ if (GettingInput) {
+ ClearLines();
+ ClearDisp();
+ MoveToLine(0);
+ MoveToChar(0);
+ ChangeSize(lins, cols);
+ Refresh();
+ }
+ else
+ ChangeSize(lins, cols);
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask); /* can change it again */
+#else /* BSDSIGS */
+ (void) sigrelse(SIG_WINDOW);
+#endif /* BSDSIGS */
+}
+
+sigret_t
+/*ARGSUSED*/
+window_change(snum)
+int snum;
+{
+#ifdef UNRELSIGS
+ /* If we were called as a signal handler, restore it. */
+ if (snum > 0)
+ sigset(snum, window_change);
+#endif /* UNRELSIGS */
+ check_window_size(0);
+#ifndef SIGVOID
+ return (snum);
+#endif
+}
+
+#endif /* SIG_WINDOW */
+
+void
+ed_set_tty_eight_bit()
+{
+ if (tty_getty(SHTTY, &extty) == -1) {
+#ifdef DEBUG_TTY
+ xprintf("ed_set_tty_eight_bit: tty_getty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return;
+ }
+ Tty_eight_bit = tty_geteightbit(&extty);
+}
+
+
+int
+ed_Setup(rst)
+ int rst;
+{
+ static int havesetup = 0;
+ struct varent *imode;
+
+ if (havesetup) /* if we have never been called */
+ return(0);
+
+#if defined(POSIX) && defined(_PC_VDISABLE) && !defined(BSD4_4) && \
+ !defined(WINNT)
+ {
+ long pcret;
+
+ if ((pcret = fpathconf(SHTTY, _PC_VDISABLE)) == -1L)
+ vdisable = (unsigned char) _POSIX_VDISABLE;
+ else
+ vdisable = (unsigned char) pcret;
+ if (vdisable != (unsigned char) _POSIX_VDISABLE && rst != 0)
+ for (rst = 0; rst < C_NCC; rst++) {
+ if (ttychars[ED_IO][rst] == (unsigned char) _POSIX_VDISABLE)
+ ttychars[ED_IO][rst] = vdisable;
+ if (ttychars[EX_IO][rst] == (unsigned char) _POSIX_VDISABLE)
+ ttychars[EX_IO][rst] = vdisable;
+ }
+ }
+#else /* ! POSIX || !_PC_VDISABLE || BSD4_4 || WINNT */
+ vdisable = (unsigned char) _POSIX_VDISABLE;
+#endif /* POSIX && _PC_VDISABLE && !BSD4_4 && !WINNT */
+
+ if ((imode = adrof(STRinputmode)) != NULL) {
+ if (!Strcmp(*(imode->vec), STRinsert))
+ inputmode = MODE_INSERT;
+ else if (!Strcmp(*(imode->vec), STRoverwrite))
+ inputmode = MODE_REPLACE;
+ }
+ else
+ inputmode = MODE_INSERT;
+ ed_InitMaps();
+ Hist_num = 0;
+ Expand = 0;
+
+#ifndef WINNT
+ if (tty_getty(SHTTY, &extty) == -1) {
+# ifdef DEBUG_TTY
+ xprintf("ed_Setup: tty_getty: %s\n", strerror(errno));
+# endif /* DEBUG_TTY */
+ return(-1);
+ }
+
+ tstty = edtty = extty;
+
+ T_Speed = tty_getspeed(&extty);
+ T_Tabs = tty_gettabs(&extty);
+ Tty_eight_bit = tty_geteightbit(&extty);
+
+# if defined(POSIX) || defined(TERMIO)
+ extty.d_t.c_iflag &= ~ttylist[EX_IO][M_INPUT].t_clrmask;
+ extty.d_t.c_iflag |= ttylist[EX_IO][M_INPUT].t_setmask;
+
+ extty.d_t.c_oflag &= ~ttylist[EX_IO][M_OUTPUT].t_clrmask;
+ extty.d_t.c_oflag |= ttylist[EX_IO][M_OUTPUT].t_setmask;
+
+ extty.d_t.c_cflag &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
+ extty.d_t.c_cflag |= ttylist[EX_IO][M_CONTROL].t_setmask;
+
+ extty.d_t.c_lflag &= ~ttylist[EX_IO][M_LINED].t_clrmask;
+ extty.d_t.c_lflag |= ttylist[EX_IO][M_LINED].t_setmask;
+
+# if defined(IRIX3_3) && SYSVREL < 4
+ extty.d_t.c_line = NTTYDISC;
+# endif /* IRIX3_3 && SYSVREL < 4 */
+
+# else /* GSTTY */ /* V7, Berkeley style tty */
+
+ if (T_Tabs) { /* order of &= and |= is important to XTABS */
+ extty.d_t.sg_flags &= ~(ttylist[EX_IO][M_CONTROL].t_clrmask|XTABS);
+ extty.d_t.sg_flags |= ttylist[EX_IO][M_CONTROL].t_setmask;
+ }
+ else {
+ extty.d_t.sg_flags &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
+ extty.d_t.sg_flags |= (ttylist[EX_IO][M_CONTROL].t_setmask|XTABS);
+ }
+
+ extty.d_lb &= ~ttylist[EX_IO][M_LOCAL].t_clrmask;
+ extty.d_lb |= ttylist[EX_IO][M_LOCAL].t_setmask;
+
+# endif /* GSTTY */
+ /*
+ * Reset the tty chars to reasonable defaults
+ * If they are disabled, then enable them.
+ */
+ if (rst) {
+ if (tty_cooked_mode(&tstty)) {
+ tty_getchar(&tstty, ttychars[TS_IO]);
+ /*
+ * Don't affect CMIN and CTIME for the editor mode
+ */
+ for (rst = 0; rst < C_NCC - 2; rst++)
+ if (ttychars[TS_IO][rst] != vdisable &&
+ ttychars[ED_IO][rst] != vdisable)
+ ttychars[ED_IO][rst] = ttychars[TS_IO][rst];
+ for (rst = 0; rst < C_NCC; rst++)
+ if (ttychars[TS_IO][rst] != vdisable &&
+ ttychars[EX_IO][rst] != vdisable)
+ ttychars[EX_IO][rst] = ttychars[TS_IO][rst];
+ }
+ tty_setchar(&extty, ttychars[EX_IO]);
+ if (tty_setty(SHTTY, &extty) == -1) {
+# ifdef DEBUG_TTY
+ xprintf("ed_Setup: tty_setty: %s\n", strerror(errno));
+# endif /* DEBUG_TTY */
+ return(-1);
+ }
+ }
+ else
+ tty_setchar(&extty, ttychars[EX_IO]);
+
+# ifdef SIG_WINDOW
+ (void) sigset(SIG_WINDOW, window_change); /* for window systems */
+# endif
+#else /* WINNT */
+# ifdef DEBUG
+ if (rst)
+ xprintf("rst received in ed_Setup() %d\n", rst);
+# endif
+#endif /* WINNT */
+ havesetup = 1;
+ return(0);
+}
+
+void
+ed_Init()
+{
+ ResetInLine(1); /* reset the input pointers */
+ GettingInput = 0; /* just in case */
+ LastKill = KillBuf; /* no kill buffer */
+
+#ifdef DEBUG_EDIT
+ CheckMaps(); /* do a little error checking on key maps */
+#endif
+
+ if (ed_Setup(0) == -1)
+ return;
+
+ /*
+ * if we have been called before but GotTermCaps isn't set, our TERM has
+ * changed, so get new termcaps and try again
+ */
+
+ if (!GotTermCaps)
+ GetTermCaps(); /* does the obvious, but gets term type each
+ * time */
+
+#ifndef WINNT
+# if defined(TERMIO) || defined(POSIX)
+ edtty.d_t.c_iflag &= ~ttylist[ED_IO][M_INPUT].t_clrmask;
+ edtty.d_t.c_iflag |= ttylist[ED_IO][M_INPUT].t_setmask;
+
+ edtty.d_t.c_oflag &= ~ttylist[ED_IO][M_OUTPUT].t_clrmask;
+ edtty.d_t.c_oflag |= ttylist[ED_IO][M_OUTPUT].t_setmask;
+
+ edtty.d_t.c_cflag &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
+ edtty.d_t.c_cflag |= ttylist[ED_IO][M_CONTROL].t_setmask;
+
+ edtty.d_t.c_lflag &= ~ttylist[ED_IO][M_LINED].t_clrmask;
+ edtty.d_t.c_lflag |= ttylist[ED_IO][M_LINED].t_setmask;
+
+
+# if defined(IRIX3_3) && SYSVREL < 4
+ edtty.d_t.c_line = NTTYDISC;
+# endif /* IRIX3_3 && SYSVREL < 4 */
+
+# else /* GSTTY */
+
+ if (T_Tabs) { /* order of &= and |= is important to XTABS */
+ edtty.d_t.sg_flags &= ~(ttylist[ED_IO][M_CONTROL].t_clrmask | XTABS);
+ edtty.d_t.sg_flags |= ttylist[ED_IO][M_CONTROL].t_setmask;
+ }
+ else {
+ edtty.d_t.sg_flags &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
+ edtty.d_t.sg_flags |= (ttylist[ED_IO][M_CONTROL].t_setmask | XTABS);
+ }
+
+ edtty.d_lb &= ~ttylist[ED_IO][M_LOCAL].t_clrmask;
+ edtty.d_lb |= ttylist[ED_IO][M_LOCAL].t_setmask;
+# endif /* POSIX || TERMIO */
+
+ tty_setchar(&edtty, ttychars[ED_IO]);
+#endif /* WINNT */
+}
+
+/*
+ * Check and re-init the line. set the terminal into 1 char at a time mode.
+ */
+int
+Rawmode()
+{
+ if (Tty_raw_mode)
+ return (0);
+
+#ifdef WINNT
+ do_nt_raw_mode();
+#else /* !WINNT */
+# ifdef _IBMR2
+ tty_setdisc(SHTTY, ED_IO);
+# endif /* _IBMR2 */
+
+ if (tty_getty(SHTTY, &tstty) == -1) {
+# ifdef DEBUG_TTY
+ xprintf("Rawmode: tty_getty: %s\n", strerror(errno));
+# endif /* DEBUG_TTY */
+ return(-1);
+ }
+
+ /*
+ * We always keep up with the eight bit setting and the speed of the
+ * tty. But only we only believe changes that are made to cooked mode!
+ */
+# if defined(POSIX) || defined(TERMIO)
+ Tty_eight_bit = tty_geteightbit(&tstty);
+ T_Speed = tty_getspeed(&tstty);
+
+# ifdef POSIX
+ /*
+ * Fix from: Steven (Steve) B. Green <xrsbg@charney.gsfc.nasa.gov>
+ * Speed was not being set up correctly under POSIX.
+ */
+ if (tty_getspeed(&extty) != T_Speed || tty_getspeed(&edtty) != T_Speed) {
+ (void) cfsetispeed(&extty.d_t, T_Speed);
+ (void) cfsetospeed(&extty.d_t, T_Speed);
+ (void) cfsetispeed(&edtty.d_t, T_Speed);
+ (void) cfsetospeed(&edtty.d_t, T_Speed);
+ }
+# endif /* POSIX */
+# else /* GSTTY */
+
+ T_Speed = tty_getspeed(&tstty);
+ Tty_eight_bit = tty_geteightbit(&tstty);
+
+ if (extty.d_t.sg_ispeed != tstty.d_t.sg_ispeed) {
+ extty.d_t.sg_ispeed = tstty.d_t.sg_ispeed;
+ edtty.d_t.sg_ispeed = tstty.d_t.sg_ispeed;
+ }
+
+ if (extty.d_t.sg_ospeed != tstty.d_t.sg_ospeed) {
+ extty.d_t.sg_ospeed = tstty.d_t.sg_ospeed;
+ edtty.d_t.sg_ospeed = tstty.d_t.sg_ospeed;
+ }
+# endif /* POSIX || TERMIO */
+
+ if (tty_cooked_mode(&tstty)) {
+ /*
+ * re-test for some things here (like maybe the user typed
+ * "stty -tabs"
+ */
+ if (tty_gettabs(&tstty) == 0)
+ T_Tabs = 0;
+ else
+ T_Tabs = CanWeTab();
+
+# if defined(POSIX) || defined(TERMIO)
+ extty.d_t.c_cflag = tstty.d_t.c_cflag;
+ extty.d_t.c_cflag &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
+ extty.d_t.c_cflag |= ttylist[EX_IO][M_CONTROL].t_setmask;
+
+ edtty.d_t.c_cflag = tstty.d_t.c_cflag;
+ edtty.d_t.c_cflag &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
+ edtty.d_t.c_cflag |= ttylist[ED_IO][M_CONTROL].t_setmask;
+
+ extty.d_t.c_lflag = tstty.d_t.c_lflag;
+ extty.d_t.c_lflag &= ~ttylist[EX_IO][M_LINED].t_clrmask;
+ extty.d_t.c_lflag |= ttylist[EX_IO][M_LINED].t_setmask;
+
+ edtty.d_t.c_lflag = tstty.d_t.c_lflag;
+ edtty.d_t.c_lflag &= ~ttylist[ED_IO][M_LINED].t_clrmask;
+ edtty.d_t.c_lflag |= ttylist[ED_IO][M_LINED].t_setmask;
+
+ extty.d_t.c_iflag = tstty.d_t.c_iflag;
+ extty.d_t.c_iflag &= ~ttylist[EX_IO][M_INPUT].t_clrmask;
+ extty.d_t.c_iflag |= ttylist[EX_IO][M_INPUT].t_setmask;
+
+ edtty.d_t.c_iflag = tstty.d_t.c_iflag;
+ edtty.d_t.c_iflag &= ~ttylist[ED_IO][M_INPUT].t_clrmask;
+ edtty.d_t.c_iflag |= ttylist[ED_IO][M_INPUT].t_setmask;
+
+ extty.d_t.c_oflag = tstty.d_t.c_oflag;
+ extty.d_t.c_oflag &= ~ttylist[EX_IO][M_OUTPUT].t_clrmask;
+ extty.d_t.c_oflag |= ttylist[EX_IO][M_OUTPUT].t_setmask;
+
+ edtty.d_t.c_oflag = tstty.d_t.c_oflag;
+ edtty.d_t.c_oflag &= ~ttylist[ED_IO][M_OUTPUT].t_clrmask;
+ edtty.d_t.c_oflag |= ttylist[ED_IO][M_OUTPUT].t_setmask;
+
+# else /* GSTTY */
+
+ extty.d_t.sg_flags = tstty.d_t.sg_flags;
+
+ extty.d_t.sg_flags &= ~ttylist[EX_IO][M_CONTROL].t_clrmask;
+ extty.d_t.sg_flags |= ttylist[EX_IO][M_CONTROL].t_setmask;
+
+ if (T_Tabs) /* order of &= and |= is important to XTABS */
+ extty.d_t.sg_flags &= ~XTABS;
+ else
+ extty.d_t.sg_flags |= XTABS;
+
+ extty.d_lb = tstty.d_lb;
+ extty.d_lb &= ~ttylist[EX_IO][M_LOCAL].t_clrmask;
+ extty.d_lb |= ttylist[EX_IO][M_LOCAL].t_setmask;
+
+ edtty.d_t.sg_flags = extty.d_t.sg_flags;
+ if (T_Tabs) { /* order of &= and |= is important to XTABS */
+ edtty.d_t.sg_flags &=
+ ~(ttylist[ED_IO][M_CONTROL].t_clrmask|XTABS);
+ edtty.d_t.sg_flags |= ttylist[ED_IO][M_CONTROL].t_setmask;
+ }
+ else {
+ edtty.d_t.sg_flags &= ~ttylist[ED_IO][M_CONTROL].t_clrmask;
+ edtty.d_t.sg_flags |=
+ (ttylist[ED_IO][M_CONTROL].t_setmask|XTABS);
+ }
+
+ edtty.d_lb = tstty.d_lb;
+ edtty.d_lb &= ~ttylist[ED_IO][M_LOCAL].t_clrmask;
+ edtty.d_lb |= ttylist[ED_IO][M_LOCAL].t_setmask;
+
+# endif /* TERMIO || POSIX */
+
+ {
+ extern int didsetty;
+ int i;
+
+ tty_getchar(&tstty, ttychars[TS_IO]);
+ /*
+ * Check if the user made any changes.
+ * If he did, then propagate the changes to the
+ * edit and execute data structures.
+ */
+ for (i = 0; i < C_NCC; i++)
+ if (ttychars[TS_IO][i] != ttychars[EX_IO][i])
+ break;
+
+ if (i != C_NCC || didsetty) {
+ didsetty = 0;
+ /*
+ * Propagate changes only to the unprotected chars
+ * that have been modified just now.
+ */
+ for (i = 0; i < C_NCC; i++) {
+ if (!((ttylist[ED_IO][M_CHAR].t_setmask & C_SH(i))) &&
+ (ttychars[TS_IO][i] != ttychars[EX_IO][i]))
+ ttychars[ED_IO][i] = ttychars[TS_IO][i];
+ if (ttylist[ED_IO][M_CHAR].t_clrmask & C_SH(i))
+ ttychars[ED_IO][i] = vdisable;
+ }
+ tty_setchar(&edtty, ttychars[ED_IO]);
+
+ for (i = 0; i < C_NCC; i++) {
+ if (!((ttylist[EX_IO][M_CHAR].t_setmask & C_SH(i))) &&
+ (ttychars[TS_IO][i] != ttychars[EX_IO][i]))
+ ttychars[EX_IO][i] = ttychars[TS_IO][i];
+ if (ttylist[EX_IO][M_CHAR].t_clrmask & C_SH(i))
+ ttychars[EX_IO][i] = vdisable;
+ }
+ tty_setchar(&extty, ttychars[EX_IO]);
+ }
+
+ }
+ }
+ if (tty_setty(SHTTY, &edtty) == -1) {
+# ifdef DEBUG_TTY
+ xprintf("Rawmode: tty_setty: %s\n", strerror(errno));
+# endif /* DEBUG_TTY */
+ return(-1);
+ }
+#endif /* WINNT */
+ Tty_raw_mode = 1;
+ flush(); /* flush any buffered output */
+ return (0);
+}
+
+int
+Cookedmode()
+{ /* set tty in normal setup */
+#ifdef WINNT
+ do_nt_cooked_mode();
+#else
+ signalfun_t orig_intr;
+
+# ifdef _IBMR2
+ tty_setdisc(SHTTY, EX_IO);
+# endif /* _IBMR2 */
+
+ if (!Tty_raw_mode)
+ return (0);
+
+ /* hold this for reseting tty */
+# ifdef BSDSIGS
+ orig_intr = (signalfun_t) signal(SIGINT, SIG_IGN);
+# else
+# ifdef SIG_HOLD
+ /*
+ * sigset doesn't return the previous handler if the signal is held,
+ * it will return SIG_HOLD instead. So instead of restoring the
+ * the signal we would end up installing a blocked SIGINT with a
+ * SIG_IGN signal handler. This is what happened when Cookedmode
+ * was called from sched_run, disabling interrupt for the rest
+ * of your session.
+ *
+ * This is what we do:
+ * - if the signal is blocked, keep it that way
+ * - else set it to SIG_IGN
+ *
+ * Casper Dik (casper@fwi.uva.nl)
+ */
+ orig_intr = (signalfun_t) sigset(SIGINT, SIG_HOLD);
+ if (orig_intr != SIG_HOLD)
+ (void) sigset(SIGINT, SIG_IGN); /* returns SIG_HOLD */
+# else /* !SIG_HOLD */
+ /*
+ * No SIG_HOLD; probably no reliable signals as well.
+ */
+ orig_intr = (signalfun_t) sigset(SIGINT, SIG_IGN);
+# endif /* SIG_HOLD */
+# endif /* BSDSIGS */
+ if (tty_setty(SHTTY, &extty) == -1) {
+# ifdef DEBUG_TTY
+ xprintf("Cookedmode: tty_setty: %s\n", strerror(errno));
+# endif /* DEBUG_TTY */
+ return -1;
+ }
+# ifdef BSDSIGS
+ (void) signal(SIGINT, orig_intr); /* take these again */
+# else
+ (void) sigset(SIGINT, orig_intr); /* take these again */
+# endif /* BSDSIGS */
+#endif /* WINNT */
+
+ Tty_raw_mode = 0;
+ return (0);
+}
+
+void
+ResetInLine(macro)
+ int macro;
+{
+ Cursor = InputBuf; /* reset cursor */
+ LastChar = InputBuf;
+ InputLim = &InputBuf[INBUFSIZE - 2];
+ Mark = InputBuf;
+ MetaNext = 0;
+ CurrentKeyMap = CcKeyMap;
+ AltKeyMap = 0;
+ Hist_num = 0;
+ DoingArg = 0;
+ Argument = 1;
+#ifdef notdef
+ LastKill = KillBuf; /* no kill buffer */
+#endif
+ LastCmd = F_UNASSIGNED; /* previous command executed */
+ if (macro)
+ MacroLvl = -1; /* no currently active macros */
+}
+
+static Char *Input_Line = NULL;
+int
+Load_input_line()
+{
+#ifdef SUNOS4
+ long chrs = 0;
+#else /* !SUNOS4 */
+ /*
+ * *Everyone* else has an int, but SunOS wants long!
+ * This breaks where int != long (alpha)
+ */
+ int chrs = 0;
+#endif /* SUNOS4 */
+
+ if (Input_Line)
+ xfree((ptr_t) Input_Line);
+ Input_Line = NULL;
+
+ if (Tty_raw_mode)
+ return 0;
+
+#if defined(FIONREAD) && !defined(OREO)
+ (void) ioctl(SHIN, FIONREAD, (ioctl_t) &chrs);
+ if (chrs > 0) {
+ char buf[BUFSIZE];
+
+ chrs = read(SHIN, buf, (size_t) min(chrs, BUFSIZE - 1));
+ if (chrs > 0) {
+ buf[chrs] = '\0';
+ Input_Line = Strsave(str2short(buf));
+ PushMacro(Input_Line);
+ }
+#ifdef convex
+ /* need to print errno message in case file is migrated */
+ if (chrs < 0)
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#endif
+ }
+#endif /* FIONREAD && !OREO */
+ return chrs > 0;
+}
+
+/*
+ * Bugfix (in Swedish) by:
+ * Johan Widen
+ * SICS, PO Box 1263, S-163 13 SPANGA, SWEDEN
+ * {mcvax,munnari,cernvax,diku,inria,prlb2,penet,ukc,unido}!enea!sics.se!jw
+ * Internet: jw@sics.se
+ *
+ * (via Hans J Albertsson (thanks))
+ */
+void
+QuoteModeOn()
+{
+ if (MacroLvl >= 0)
+ return;
+
+#ifndef WINNT
+ qutty = edtty;
+
+#if defined(TERMIO) || defined(POSIX)
+ qutty.d_t.c_iflag &= ~ttylist[QU_IO][M_INPUT].t_clrmask;
+ qutty.d_t.c_iflag |= ttylist[QU_IO][M_INPUT].t_setmask;
+
+ qutty.d_t.c_oflag &= ~ttylist[QU_IO][M_OUTPUT].t_clrmask;
+ qutty.d_t.c_oflag |= ttylist[QU_IO][M_OUTPUT].t_setmask;
+
+ qutty.d_t.c_cflag &= ~ttylist[QU_IO][M_CONTROL].t_clrmask;
+ qutty.d_t.c_cflag |= ttylist[QU_IO][M_CONTROL].t_setmask;
+
+ qutty.d_t.c_lflag &= ~ttylist[QU_IO][M_LINED].t_clrmask;
+ qutty.d_t.c_lflag |= ttylist[QU_IO][M_LINED].t_setmask;
+#else /* GSTTY */
+ qutty.d_t.sg_flags &= ~ttylist[QU_IO][M_CONTROL].t_clrmask;
+ qutty.d_t.sg_flags |= ttylist[QU_IO][M_CONTROL].t_setmask;
+ qutty.d_lb &= ~ttylist[QU_IO][M_LOCAL].t_clrmask;
+ qutty.d_lb |= ttylist[QU_IO][M_LOCAL].t_setmask;
+
+#endif /* TERMIO || POSIX */
+ if (tty_setty(SHTTY, &qutty) == -1) {
+#ifdef DEBUG_TTY
+ xprintf("QuoteModeOn: tty_setty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return;
+ }
+#endif /* !WINNT */
+ Tty_quote_mode = 1;
+ return;
+}
+
+void
+QuoteModeOff()
+{
+ if (!Tty_quote_mode)
+ return;
+ Tty_quote_mode = 0;
+ if (tty_setty(SHTTY, &edtty) == -1) {
+#ifdef DEBUG_TTY
+ xprintf("QuoteModeOff: tty_setty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return;
+ }
+ return;
+}
diff --git a/contrib/tcsh/ed.inputl.c b/contrib/tcsh/ed.inputl.c
new file mode 100644
index 0000000..2842d7d
--- /dev/null
+++ b/contrib/tcsh/ed.inputl.c
@@ -0,0 +1,903 @@
+/* $Header: /src/pub/tcsh/ed.inputl.c,v 3.47 1999/04/20 07:48:39 christos Exp $ */
+/*
+ * ed.inputl.c: Input line handling.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.inputl.c,v 3.47 1999/04/20 07:48:39 christos Exp $")
+
+#include "ed.h"
+#include "ed.defns.h" /* for the function names */
+#include "tw.h" /* for twenex stuff */
+
+#define OKCMD (INBUFSIZE+INBUFSIZE)
+
+/* ed.inputl -- routines to get a single line from the input. */
+
+extern bool tellwhat;
+extern bool MapsAreInited;
+extern bool Tty_raw_mode;
+
+/* mismatched first character */
+static Char mismatch[] =
+ {'!', '^' , '\\', '-', '%', '\0', '"', '\'', '`', '\0' };
+
+static int Repair __P((void));
+static int GetNextCommand __P((KEYCMD *, Char *));
+static int SpellLine __P((int));
+static int CompleteLine __P((void));
+static void RunCommand __P((Char *));
+static void doeval1 __P((Char **));
+
+static bool rotate = 0;
+
+
+static int
+Repair()
+{
+ if (NeedsRedraw) {
+ ClearLines();
+ ClearDisp();
+ NeedsRedraw = 0;
+ }
+ Refresh();
+ Argument = 1;
+ DoingArg = 0;
+ curchoice = -1;
+ return (int) (LastChar - InputBuf);
+}
+
+/* CCRETVAL */
+int
+Inputl()
+{
+ CCRETVAL retval;
+ KEYCMD cmdnum = 0;
+ extern KEYCMD NumFuns;
+ unsigned char tch; /* the place where read() goes */
+ Char ch;
+ int num; /* how many chars we have read at NL */
+ int expnum;
+ struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
+ struct varent *autol = adrof(STRautolist);
+ struct varent *matchbeep = adrof(STRmatchbeep);
+ struct varent *imode = adrof(STRinputmode);
+ Char *SaveChar, *CorrChar;
+ Char Origin[INBUFSIZE], Change[INBUFSIZE];
+ int matchval; /* from tenematch() */
+ COMMAND fn;
+ int curlen = 0;
+ int newlen;
+ int idx;
+
+ if (!MapsAreInited) /* double extra just in case */
+ ed_InitMaps();
+
+ ClearDisp(); /* reset the display stuff */
+ ResetInLine(0); /* reset the input pointers */
+ if (GettingInput)
+ MacroLvl = -1; /* editor was interrupted during input */
+
+ if (imode) {
+ if (!Strcmp(*(imode->vec), STRinsert))
+ inputmode = MODE_INSERT;
+ else if (!Strcmp(*(imode->vec), STRoverwrite))
+ inputmode = MODE_REPLACE;
+ }
+
+#if defined(FIONREAD) && !defined(OREO)
+ if (!Tty_raw_mode && MacroLvl < 0) {
+# ifdef SUNOS4
+ long chrs = 0;
+# else /* !SUNOS4 */
+ /*
+ * *Everyone* else has an int, but SunOS wants long!
+ * This breaks where int != long (alpha)
+ */
+ int chrs = 0;
+# endif /* SUNOS4 */
+
+ (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
+ if (chrs == 0) {
+ if (Rawmode() < 0)
+ return 0;
+ }
+ }
+#endif /* FIONREAD && !OREO */
+
+ GettingInput = 1;
+ NeedsRedraw = 0;
+
+ if (tellwhat) {
+ copyn(InputBuf, WhichBuf, INBUFSIZE);
+ LastChar = InputBuf + (LastWhich - WhichBuf);
+ Cursor = InputBuf + (CursWhich - WhichBuf);
+ tellwhat = 0;
+ Hist_num = HistWhich;
+ }
+ if (Expand) {
+ (void) e_up_hist(0);
+ Expand = 0;
+ }
+ Refresh(); /* print the prompt */
+
+ for (num = OKCMD; num == OKCMD;) { /* while still editing this line */
+#ifdef DEBUG_EDIT
+ if (Cursor > LastChar)
+ xprintf("Cursor > LastChar\r\n");
+ if (Cursor < InputBuf)
+ xprintf("Cursor < InputBuf\r\n");
+ if (Cursor > InputLim)
+ xprintf("Cursor > InputLim\r\n");
+ if (LastChar > InputLim)
+ xprintf("LastChar > InputLim\r\n");
+ if (InputLim != &InputBuf[INBUFSIZE - 2])
+ xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
+ if ((!DoingArg) && (Argument != 1))
+ xprintf("(!DoingArg) && (Argument != 1)\r\n");
+ if (CcKeyMap[0] == 0)
+ xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
+#endif
+
+ /* if EOF or error */
+ if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
+ break;
+ }
+
+ if (cmdnum >= NumFuns) {/* BUG CHECK command */
+#ifdef DEBUG_EDIT
+ xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
+#endif
+ continue; /* try again */
+ }
+
+ /* now do the real command */
+ retval = (*CcFuncTbl[cmdnum]) (ch);
+
+ /* save the last command here */
+ LastCmd = cmdnum;
+
+ /* make sure fn is initialized */
+ fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
+
+ /* use any return value */
+ switch (retval) {
+
+ case CC_REFRESH:
+ Refresh();
+ /*FALLTHROUGH*/
+ case CC_NORM: /* normal char */
+ Argument = 1;
+ DoingArg = 0;
+ /*FALLTHROUGH*/
+ case CC_ARGHACK: /* Suggested by Rich Salz */
+ /* <rsalz@pineapple.bbn.com> */
+ curchoice = -1;
+ curlen = (int) (LastChar - InputBuf);
+ break; /* keep going... */
+
+ case CC_EOF: /* end of file typed */
+ curchoice = -1;
+ curlen = (int) (LastChar - InputBuf);
+ num = 0;
+ break;
+
+ case CC_WHICH: /* tell what this command does */
+ tellwhat = 1;
+ copyn(WhichBuf, InputBuf, INBUFSIZE);
+ LastWhich = WhichBuf + (LastChar - InputBuf);
+ CursWhich = WhichBuf + (Cursor - InputBuf);
+ *LastChar++ = '\n'; /* for the benifit of CSH */
+ HistWhich = Hist_num;
+ Hist_num = 0; /* for the history commands */
+ num = (int) (LastChar - InputBuf); /* number characters read */
+ break;
+
+ case CC_NEWLINE: /* normal end of line */
+ curlen = 0;
+ curchoice = -1;
+ matchval = 1;
+ if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
+ !Strcmp(*(crct->vec), STRall))) {
+ PastBottom();
+ copyn(Origin, InputBuf, INBUFSIZE);
+ SaveChar = LastChar;
+ if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
+ PastBottom();
+ copyn(Change, InputBuf, INBUFSIZE);
+ *Strchr(Change, '\n') = '\0';
+ CorrChar = LastChar; /* Save the corrected end */
+ LastChar = InputBuf; /* Null the current line */
+ SoundBeep();
+ printprompt(2, short2str(Change));
+ Refresh();
+ if (read(SHIN, (char *) &tch, 1) < 0)
+#ifdef convex
+ /*
+ * need to print error message in case file
+ * is migrated
+ */
+ if (errno && errno != EINTR)
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#else
+ break;
+#endif
+ ch = tch;
+ if (ch == 'y' || ch == ' ') {
+ LastChar = CorrChar; /* Restore the corrected end */
+ xprintf(CGETS(6, 2, "yes\n"));
+ }
+ else {
+ copyn(InputBuf, Origin, INBUFSIZE);
+ LastChar = SaveChar;
+ if (ch == 'e') {
+ xprintf(CGETS(6, 3, "edit\n"));
+ *LastChar-- = '\0';
+ Cursor = LastChar;
+ printprompt(3, NULL);
+ ClearLines();
+ ClearDisp();
+ Refresh();
+ break;
+ }
+ else if (ch == 'a') {
+ xprintf(CGETS(6, 4, "abort\n"));
+ LastChar = InputBuf; /* Null the current line */
+ Cursor = LastChar;
+ printprompt(0, NULL);
+ Refresh();
+ break;
+ }
+ xprintf(CGETS(6, 5, "no\n"));
+ }
+ flush();
+ }
+ } else if (crct && !Strcmp(*(crct->vec), STRcomplete)) {
+ if (LastChar > InputBuf && LastChar[-1] == '\n') {
+ LastChar[-1] = '\0';
+ LastChar--;
+ Cursor = LastChar;
+ }
+ match_unique_match = 1; /* match unique matches */
+ matchval = CompleteLine();
+ match_unique_match = 0;
+ curlen = (int) (LastChar - InputBuf);
+ if (matchval != 1) {
+ PastBottom();
+ }
+ if (matchval == 0) {
+ xprintf(CGETS(6, 6, "No matching command\n"));
+ } else if (matchval == 2) {
+ xprintf(CGETS(6, 7, "Ambiguous command\n"));
+ }
+ if (NeedsRedraw) {
+ ClearLines();
+ ClearDisp();
+ NeedsRedraw = 0;
+ }
+ Refresh();
+ Argument = 1;
+ DoingArg = 0;
+ if (matchval == 1) {
+ PastBottom();
+ *LastChar++ = '\n';
+ *LastChar = '\0';
+ }
+ curlen = (int) (LastChar - InputBuf);
+ }
+ else
+ PastBottom();
+
+ if (matchval == 1) {
+ tellwhat = 0; /* just in case */
+ Hist_num = 0; /* for the history commands */
+ /* return the number of chars read */
+ num = (int) (LastChar - InputBuf);
+ /*
+ * For continuation lines, we set the prompt to prompt 2
+ */
+ printprompt(1, NULL);
+ }
+ break;
+
+ case CC_CORRECT:
+ if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
+ SoundBeep(); /* Beep = No match/ambiguous */
+ curlen = Repair();
+ break;
+
+ case CC_CORRECT_L:
+ if (SpellLine(FALSE) < 0)
+ SoundBeep(); /* Beep = No match/ambiguous */
+ curlen = Repair();
+ break;
+
+
+ case CC_COMPLETE:
+ case CC_COMPLETE_ALL:
+ case CC_COMPLETE_FWD:
+ case CC_COMPLETE_BACK:
+ switch (retval) {
+ case CC_COMPLETE:
+ fn = RECOGNIZE;
+ curlen = (int) (LastChar - InputBuf);
+ curchoice = -1;
+ rotate = 0;
+ break;
+ case CC_COMPLETE_ALL:
+ fn = RECOGNIZE_ALL;
+ curlen = (int) (LastChar - InputBuf);
+ curchoice = -1;
+ rotate = 0;
+ break;
+ case CC_COMPLETE_FWD:
+ fn = RECOGNIZE_SCROLL;
+ curchoice++;
+ rotate = 1;
+ break;
+ case CC_COMPLETE_BACK:
+ fn = RECOGNIZE_SCROLL;
+ curchoice--;
+ rotate = 1;
+ break;
+ default:
+ abort();
+ }
+ if (InputBuf[curlen] && rotate) {
+ newlen = (int) (LastChar - InputBuf);
+ for (idx = (int) (Cursor - InputBuf);
+ idx <= newlen; idx++)
+ InputBuf[idx - newlen + curlen] =
+ InputBuf[idx];
+ LastChar = InputBuf + curlen;
+ Cursor = Cursor - newlen + curlen;
+ }
+ curlen = (int) (LastChar - InputBuf);
+
+
+ if (adrof(STRautoexpand))
+ (void) e_expand_history(0);
+ /*
+ * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
+ * A separate variable now controls beeping after
+ * completion, independently of autolisting.
+ */
+ expnum = (int) (Cursor - InputBuf);
+ switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
+ case 1:
+ if (non_unique_match && matchbeep &&
+ (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
+ SoundBeep();
+ break;
+ case 0:
+ if (matchbeep) {
+ if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
+ Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
+ Strcmp(*(matchbeep->vec), STRnotunique) == 0)
+ SoundBeep();
+ }
+ else
+ SoundBeep();
+ break;
+ default:
+ if (matchval < 0) { /* Error from tenematch */
+ curchoice = -1;
+ SoundBeep();
+ break;
+ }
+ if (matchbeep) {
+ if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
+ Strcmp(*(matchbeep->vec), STRnotunique) == 0))
+ SoundBeep();
+ }
+ else
+ SoundBeep();
+ /*
+ * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
+ * attempted completion is ambiguous, list the choices.
+ * (PWP: this is the best feature addition to tcsh I have
+ * seen in many months.)
+ */
+ if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 ||
+ expnum == Cursor - InputBuf)) {
+ PastBottom();
+ fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
+ (void) tenematch(InputBuf, Cursor-InputBuf, fn);
+ }
+ break;
+ }
+ if (NeedsRedraw) {
+ PastBottom();
+ ClearLines();
+ ClearDisp();
+ NeedsRedraw = 0;
+ }
+ Refresh();
+ Argument = 1;
+ DoingArg = 0;
+ break;
+
+ case CC_LIST_CHOICES:
+ case CC_LIST_ALL:
+ if (InputBuf[curlen] && rotate) {
+ newlen = (int) (LastChar - InputBuf);
+ for (idx = (int) (Cursor - InputBuf);
+ idx <= newlen; idx++)
+ InputBuf[idx - newlen + curlen] =
+ InputBuf[idx];
+ LastChar = InputBuf + curlen;
+ Cursor = Cursor - newlen + curlen;
+ }
+ curlen = (int) (LastChar - InputBuf);
+ if (curchoice >= 0)
+ curchoice--;
+
+ fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
+ /* should catch ^C here... */
+ if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
+ SoundBeep();
+ Refresh();
+ Argument = 1;
+ DoingArg = 0;
+ break;
+
+
+ case CC_LIST_GLOB:
+ if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
+ SoundBeep();
+ curlen = Repair();
+ break;
+
+ case CC_EXPAND_GLOB:
+ if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
+ SoundBeep(); /* Beep = No match */
+ curlen = Repair();
+ break;
+
+ case CC_NORMALIZE_PATH:
+ if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
+ SoundBeep(); /* Beep = No match */
+ curlen = Repair();
+ break;
+
+ case CC_EXPAND_VARS:
+ if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
+ SoundBeep(); /* Beep = No match */
+ curlen = Repair();
+ break;
+
+ case CC_NORMALIZE_COMMAND:
+ if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
+ SoundBeep(); /* Beep = No match */
+ curlen = Repair();
+ break;
+
+ case CC_HELPME:
+ xputchar('\n');
+ /* should catch ^C here... */
+ (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
+ Refresh();
+ Argument = 1;
+ DoingArg = 0;
+ curchoice = -1;
+ curlen = (int) (LastChar - InputBuf);
+ break;
+
+ case CC_FATAL: /* fatal error, reset to known state */
+#ifdef DEBUG_EDIT
+ xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
+#endif /* DEBUG_EDIT */
+ /* put (real) cursor in a known place */
+ ClearDisp(); /* reset the display stuff */
+ ResetInLine(1); /* reset the input pointers */
+ Refresh(); /* print the prompt again */
+ Argument = 1;
+ DoingArg = 0;
+ curchoice = -1;
+ curlen = (int) (LastChar - InputBuf);
+ break;
+
+ case CC_ERROR:
+ default: /* functions we don't know about */
+ DoingArg = 0;
+ Argument = 1;
+ SoundBeep();
+ flush();
+ curchoice = -1;
+ curlen = (int) (LastChar - InputBuf);
+ break;
+ }
+ }
+ (void) Cookedmode(); /* make sure the tty is set up correctly */
+ GettingInput = 0;
+ flush(); /* flush any buffered output */
+ return num;
+}
+
+void
+PushMacro(str)
+ Char *str;
+{
+ if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
+ MacroLvl++;
+ KeyMacro[MacroLvl] = str;
+ }
+ else {
+ SoundBeep();
+ flush();
+ }
+}
+
+/*
+ * Like eval, only using the current file descriptors
+ */
+static Char **gv = NULL, **gav = NULL;
+
+static void
+doeval1(v)
+ Char **v;
+{
+ Char **oevalvec;
+ Char *oevalp;
+ int my_reenter;
+ Char **savegv;
+ jmp_buf_t osetexit;
+
+ oevalvec = evalvec;
+ oevalp = evalp;
+ savegv = gv;
+ gav = v;
+
+
+ gflag = 0, tglob(gav);
+ if (gflag) {
+ gv = gav = globall(gav);
+ gargv = 0;
+ if (gav == 0)
+ stderror(ERR_NOMATCH);
+ gav = copyblk(gav);
+ }
+ else {
+ gv = NULL;
+ gav = copyblk(gav);
+ trim(gav);
+ }
+
+ getexit(osetexit);
+
+ /* PWP: setjmp/longjmp bugfix for optimizing compilers */
+#ifdef cray
+ my_reenter = 1; /* assume non-zero return val */
+ if (setexit() == 0) {
+ my_reenter = 0; /* Oh well, we were wrong */
+#else /* !cray */
+ if ((my_reenter = setexit()) == 0) {
+#endif /* cray */
+ evalvec = gav;
+ evalp = 0;
+ process(0);
+ }
+
+ evalvec = oevalvec;
+ evalp = oevalp;
+ doneinp = 0;
+
+ if (gv)
+ blkfree(gv);
+
+ gv = savegv;
+ resexit(osetexit);
+ if (my_reenter)
+ stderror(ERR_SILENT);
+}
+
+static void
+RunCommand(str)
+ Char *str;
+{
+ Char *cmd[2];
+
+ xputchar('\n'); /* Start on a clean line */
+
+ cmd[0] = str;
+ cmd[1] = NULL;
+
+ (void) Cookedmode();
+ GettingInput = 0;
+
+ doeval1(cmd);
+
+ (void) Rawmode();
+ GettingInput = 1;
+
+ ClearLines();
+ ClearDisp();
+ NeedsRedraw = 0;
+ Refresh();
+}
+
+static int
+GetNextCommand(cmdnum, ch)
+ KEYCMD *cmdnum;
+ register Char *ch;
+{
+ KEYCMD cmd = 0;
+ int num;
+
+ while (cmd == 0 || cmd == F_XKEY) {
+ if ((num = GetNextChar(ch)) != 1) { /* if EOF or error */
+ return num;
+ }
+#ifdef KANJI
+ if (!adrof(STRnokanji) && (*ch & META)) {
+ MetaNext = 0;
+ cmd = F_INSERT;
+ break;
+ }
+ else
+#endif /* KANJI */
+ if (MetaNext) {
+ MetaNext = 0;
+ *ch |= META;
+ }
+ /* XXX: This needs to be fixed so that we don't just truncate
+ * the character, we unquote it.
+ */
+ if (*ch < NT_NUM_KEYS)
+ cmd = CurrentKeyMap[*ch];
+ else
+ cmd = CurrentKeyMap[(unsigned char) *ch];
+ if (cmd == F_XKEY) {
+ XmapVal val;
+ CStr cstr;
+ cstr.buf = ch;
+ cstr.len = Strlen(ch);
+ switch (GetXkey(&cstr, &val)) {
+ case XK_CMD:
+ cmd = val.cmd;
+ break;
+ case XK_STR:
+ PushMacro(val.str.buf);
+ break;
+ case XK_EXE:
+ RunCommand(val.str.buf);
+ break;
+ default:
+ abort();
+ break;
+ }
+ }
+ if (!AltKeyMap)
+ CurrentKeyMap = CcKeyMap;
+ }
+ *cmdnum = cmd;
+ return OKCMD;
+}
+
+int
+GetNextChar(cp)
+ register Char *cp;
+{
+ register int num_read;
+ int tried = 0;
+ unsigned char tcp;
+
+ for (;;) {
+ if (MacroLvl < 0) {
+ if (!Load_input_line())
+ break;
+ }
+ if (*KeyMacro[MacroLvl] == 0) {
+ MacroLvl--;
+ continue;
+ }
+ *cp = *KeyMacro[MacroLvl]++ & CHAR;
+ if (*KeyMacro[MacroLvl] == 0) { /* Needed for QuoteMode On */
+ MacroLvl--;
+ }
+ return (1);
+ }
+
+ if (Rawmode() < 0) /* make sure the tty is set up correctly */
+ return 0; /* oops: SHIN was closed */
+
+#ifdef WINNT
+ __nt_want_vcode = 1;
+#endif /* WINNT */
+ while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) {
+ if (errno == EINTR)
+ continue;
+ if (!tried && fixio(SHIN, errno) != -1)
+ tried = 1;
+ else {
+#ifdef convex
+ /* need to print error message in case the file is migrated */
+ if (errno != EINTR)
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#endif /* convex */
+#ifdef WINNT
+ __nt_want_vcode = 0;
+#endif /* WINNT */
+ *cp = '\0';
+ return -1;
+ }
+ }
+#ifdef WINNT
+ if (__nt_want_vcode == 2)
+ *cp = __nt_vcode;
+ else
+ *cp = tcp;
+ __nt_want_vcode = 0;
+#else
+ *cp = tcp;
+#endif /* WINNT */
+ return num_read;
+}
+
+/*
+ * SpellLine - do spelling correction on the entire command line
+ * (which may have trailing newline).
+ * If cmdonly is set, only check spelling of command words.
+ * Return value:
+ * -1: Something was incorrectible, and nothing was corrected
+ * 0: Everything was correct
+ * 1: Something was corrected
+ */
+static int
+SpellLine(cmdonly)
+ int cmdonly;
+{
+ int endflag, matchval;
+ Char *argptr, *OldCursor, *OldLastChar;
+
+ OldLastChar = LastChar;
+ OldCursor = Cursor;
+ argptr = InputBuf;
+ endflag = 1;
+ matchval = 0;
+ do {
+ while (ismetahash(*argptr) || iscmdmeta(*argptr))
+ argptr++;
+ for (Cursor = argptr;
+ *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
+ (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
+ Cursor++)
+ continue;
+ if (*Cursor == '\0') {
+ Cursor = LastChar;
+ if (LastChar[-1] == '\n')
+ Cursor--;
+ endflag = 0;
+ }
+ /* Obey current history character settings */
+ mismatch[0] = HIST;
+ mismatch[1] = HISTSUB;
+ if (!Strchr(mismatch, *argptr) &&
+ (!cmdonly || starting_a_command(argptr, InputBuf))) {
+#ifdef WINNT
+ /*
+ * This hack avoids correcting drive letter changes
+ */
+ if((Cursor - InputBuf) != 2 || (char)InputBuf[1] != ':')
+#endif /* WINNT */
+ {
+#ifdef HASH_SPELL_CHECK
+ Char save;
+ size_t len = Cursor - InputBuf;
+
+ save = InputBuf[len];
+ InputBuf[len] = '\0';
+ if (find_cmd(InputBuf, 0) != 0) {
+ InputBuf[len] = save;
+ argptr = Cursor;
+ continue;
+ }
+ InputBuf[len] = save;
+#endif /* HASH_SPELL_CHECK */
+ switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
+ case 1: /* corrected */
+ matchval = 1;
+ break;
+ case -1: /* couldn't be corrected */
+ if (!matchval)
+ matchval = -1;
+ break;
+ default: /* was correct */
+ break;
+ }
+ }
+ if (LastChar != OldLastChar) {
+ if (argptr < OldCursor)
+ OldCursor += (LastChar - OldLastChar);
+ OldLastChar = LastChar;
+ }
+ }
+ argptr = Cursor;
+ } while (endflag);
+ Cursor = OldCursor;
+ return matchval;
+}
+
+/*
+ * CompleteLine - do command completion on the entire command line
+ * (which may have trailing newline).
+ * Return value:
+ * 0: No command matched or failure
+ * 1: One command matched
+ * 2: Several commands matched
+ */
+static int
+CompleteLine()
+{
+ int endflag, tmatch;
+ Char *argptr, *OldCursor, *OldLastChar;
+
+ OldLastChar = LastChar;
+ OldCursor = Cursor;
+ argptr = InputBuf;
+ endflag = 1;
+ do {
+ while (ismetahash(*argptr) || iscmdmeta(*argptr))
+ argptr++;
+ for (Cursor = argptr;
+ *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
+ (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
+ Cursor++)
+ continue;
+ if (*Cursor == '\0') {
+ Cursor = LastChar;
+ if (LastChar[-1] == '\n')
+ Cursor--;
+ endflag = 0;
+ }
+ if (!Strchr(mismatch, *argptr) && starting_a_command(argptr, InputBuf)) {
+ tmatch = tenematch(InputBuf, Cursor - InputBuf, RECOGNIZE);
+ if (tmatch <= 0) {
+ return 0;
+ } else if (tmatch > 1) {
+ return 2;
+ }
+ if (LastChar != OldLastChar) {
+ if (argptr < OldCursor)
+ OldCursor += (LastChar - OldLastChar);
+ OldLastChar = LastChar;
+ }
+ }
+ argptr = Cursor;
+ } while (endflag);
+ Cursor = OldCursor;
+ return 1;
+}
+
diff --git a/contrib/tcsh/ed.refresh.c b/contrib/tcsh/ed.refresh.c
new file mode 100644
index 0000000..46333c9
--- /dev/null
+++ b/contrib/tcsh/ed.refresh.c
@@ -0,0 +1,1317 @@
+/* $Header: /src/pub/tcsh/ed.refresh.c,v 3.25 1998/11/24 18:17:22 christos Exp $ */
+/*
+ * ed.refresh.c: Lower level screen refreshing functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.refresh.c,v 3.25 1998/11/24 18:17:22 christos Exp $")
+
+#include "ed.h"
+/* #define DEBUG_UPDATE */
+/* #define DEBUG_REFRESH */
+/* #define DEBUG_LITERAL */
+
+/* refresh.c -- refresh the current set of lines on the screen */
+
+Char *litptr[256];
+static int vcursor_h, vcursor_v;
+static int rprompt_h, rprompt_v;
+
+static void Draw __P((int));
+static void Vdraw __P((int));
+static void RefreshPromptpart __P((Char *));
+static void update_line __P((Char *, Char *, int));
+static void str_insert __P((Char *, int, int, Char *, int));
+static void str_delete __P((Char *, int, int, int));
+static void str_cp __P((Char *, Char *, int));
+static void PutPlusOne __P((int));
+static void cpy_pad_spaces __P((Char *, Char *, int));
+#if defined(DSPMBYTE)
+static Char *update_line_fix_mbyte_point __P((Char *, Char *, int));
+#endif
+#if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
+static void dprintf __P((char *, ...));
+#ifdef DEBUG_UPDATE
+static void dprintstr __P((char *, Char *, Char *));
+
+static void
+dprintstr(str, f, t)
+char *str;
+Char *f, *t;
+{
+ dprintf("%s:\"", str);
+ while (f < t)
+ dprintf("%c", *f++ & ASCII);
+ dprintf("\"\r\n");
+}
+#endif /* DEBUG_UPDATE */
+
+/* dprintf():
+ * Print to $DEBUGTTY, so that we can test editing on one pty, and
+ * print debugging stuff on another. Don't interrupt the shell while
+ * debugging cause you'll mangle up the file descriptors!
+ */
+static void
+#ifdef FUNCPROTO
+dprintf(char *fmt, ...)
+#else
+dprintf(va_list)
+ va_dcl
+#endif /* __STDC__ */
+{
+ static int fd = -1;
+ char *dtty;
+
+ if ((dtty = getenv("DEBUGTTY"))) {
+ int o;
+ va_list va;
+#ifdef FUNCPROTO
+ va_start(va, fmt);
+#else
+ char *fmt;
+ va_start(va);
+ fmt = va_arg(va, char *);
+#endif /* __STDC__ */
+
+ if (fd == -1)
+ fd = open(dtty, O_RDWR);
+ o = SHOUT;
+ flush();
+ SHOUT = fd;
+ xvprintf(fmt, va);
+ va_end(va);
+ flush();
+ SHOUT = o;
+ }
+}
+#endif /* DEBUG_UPDATE || DEBUG_REFRESH || DEBUG_LITERAL */
+
+static void
+Draw(c) /* draw c, expand tabs, ctl chars */
+ register int c;
+{
+ register Char ch = c & CHAR;
+
+ if (Isprint(ch)) {
+ Vdraw(c);
+ return;
+ }
+ /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
+ if (ch == '\n') { /* expand the newline */
+ /*
+ * Don't force a newline if Vdraw does it (i.e. we're at end of line)
+ * - or we will get two newlines and possibly garbage in between
+ */
+ int oldv = vcursor_v;
+
+ Vdraw('\0'); /* assure end of line */
+ if (oldv == vcursor_v) {
+ vcursor_h = 0; /* reset cursor pos */
+ vcursor_v++;
+ }
+ return;
+ }
+ if (ch == '\t') { /* expand the tab */
+ for (;;) {
+ Vdraw(' ');
+ if ((vcursor_h & 07) == 0)
+ break; /* go until tab stop */
+ }
+ }
+ else if (Iscntrl(ch)) {
+#ifndef _OSD_POSIX
+ Vdraw('^');
+ if (ch == CTL_ESC('\177')) {
+ Vdraw('?');
+ }
+ else {
+ /* uncontrolify it; works only for iso8859-1 like sets */
+ Vdraw((c | 0100));
+#else /*_OSD_POSIX*/
+ if (ch == CTL_ESC('\177')) {
+ Vdraw('^');
+ Vdraw('?');
+ }
+ else {
+ if (Isupper(_toebcdic[_toascii[c]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
+ {
+ Vdraw('^');
+ Vdraw(_toebcdic[_toascii[c]|0100]);
+ }
+ else
+ {
+ Vdraw('\\');
+ Vdraw(((c >> 6) & 7) + '0');
+ Vdraw(((c >> 3) & 7) + '0');
+ Vdraw((c & 7) + '0');
+ }
+#endif /*_OSD_POSIX*/
+ }
+ }
+#ifdef KANJI
+ else if (!adrof(STRnokanji)) {
+ Vdraw(c);
+ return;
+ }
+#endif
+ else {
+ Vdraw('\\');
+ Vdraw(((c >> 6) & 7) + '0');
+ Vdraw(((c >> 3) & 7) + '0');
+ Vdraw((c & 7) + '0');
+ }
+}
+
+static void
+Vdraw(c) /* draw char c onto V lines */
+ register int c;
+{
+#ifdef DEBUG_REFRESH
+# ifdef SHORT_STRINGS
+ dprintf("Vdrawing %6.6o '%c'\r\n", c, c & ASCII);
+# else
+ dprintf("Vdrawing %3.3o '%c'\r\n", c, c);
+# endif /* SHORT_STRNGS */
+#endif /* DEBUG_REFRESH */
+
+ Vdisplay[vcursor_v][vcursor_h] = (Char) c;
+ vcursor_h++; /* advance to next place */
+ if (vcursor_h >= TermH) {
+ Vdisplay[vcursor_v][TermH] = '\0'; /* assure end of line */
+ vcursor_h = 0; /* reset it. */
+ vcursor_v++;
+#ifdef DEBUG_REFRESH
+ if (vcursor_v >= TermV) { /* should NEVER happen. */
+ dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
+ vcursor_v, TermV);
+ abort();
+ }
+#endif /* DEBUG_REFRESH */
+ }
+}
+
+/*
+ * RefreshPromptpart()
+ * draws a prompt element, expanding literals (we know it's ASCIZ)
+ */
+static void
+RefreshPromptpart(buf)
+ Char *buf;
+{
+ register Char *cp;
+ static unsigned int litnum = 0;
+ if (buf == NULL)
+ {
+ litnum = 0;
+ return;
+ }
+
+ for (cp = buf; *cp; cp++) {
+ if (*cp & LITERAL) {
+ if (litnum < (sizeof(litptr) / sizeof(litptr[0]))) {
+ litptr[litnum] = cp;
+#ifdef DEBUG_LITERAL
+ dprintf("litnum = %d, litptr = %x:\r\n",
+ litnum, litptr[litnum]);
+#endif /* DEBUG_LITERAL */
+ }
+ while (*cp & LITERAL)
+ cp++;
+ if (*cp)
+ Vdraw((int) (litnum++ | LITERAL));
+ else {
+ /*
+ * XXX: This is a bug, we lose the last literal, if it is not
+ * followed by a normal character, but it is too hard to fix
+ */
+ break;
+ }
+ }
+ else
+ Draw(*cp);
+ }
+}
+
+/*
+ * Refresh()
+ * draws the new virtual screen image from the current input
+ * line, then goes line-by-line changing the real image to the new
+ * virtual image. The routine to re-draw a line can be replaced
+ * easily in hopes of a smarter one being placed there.
+ */
+static int OldvcV = 0;
+void
+Refresh()
+{
+ register int cur_line;
+ register Char *cp;
+ int cur_h, cur_v = 0, new_vcv;
+ int rhdiff;
+ Char oldgetting;
+
+#ifdef DEBUG_REFRESH
+ dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
+ dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
+#endif /* DEBUG_REFRESH */
+ oldgetting = GettingInput;
+ GettingInput = 0; /* avoid re-entrance via SIGWINCH */
+
+ /* reset the Vdraw cursor, temporarily draw rprompt to calculate its size */
+ vcursor_h = 0;
+ vcursor_v = 0;
+ RefreshPromptpart(NULL);
+ RefreshPromptpart(RPromptBuf);
+ rprompt_h = vcursor_h;
+ rprompt_v = vcursor_v;
+
+ /* reset the Vdraw cursor, draw prompt */
+ vcursor_h = 0;
+ vcursor_v = 0;
+ RefreshPromptpart(NULL);
+ RefreshPromptpart(PromptBuf);
+ cur_h = -1; /* set flag in case I'm not set */
+
+ /* draw the current input buffer */
+ for (cp = InputBuf; (cp < LastChar); cp++) {
+ if (cp == Cursor) {
+ cur_h = vcursor_h; /* save for later */
+ cur_v = vcursor_v;
+ }
+ Draw(*cp);
+ }
+
+ if (cur_h == -1) { /* if I haven't been set yet, I'm at the end */
+ cur_h = vcursor_h;
+ cur_v = vcursor_v;
+ }
+
+ rhdiff = TermH - vcursor_h - rprompt_h;
+ if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
+ /*
+ * have a right-hand side prompt that will fit on
+ * the end of the first line with at least one
+ * character gap to the input buffer.
+ */
+ while (--rhdiff > 0) /* pad out with spaces */
+ Draw(' ');
+ RefreshPromptpart(RPromptBuf);
+ }
+ else {
+ rprompt_h = 0; /* flag "not using rprompt" */
+ rprompt_v = 0;
+ }
+
+ new_vcv = vcursor_v; /* must be done BEFORE the NUL is written */
+ Vdraw('\0'); /* put NUL on end */
+
+#ifdef DEBUG_REFRESH
+ dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
+ TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
+#endif /* DEBUG_REFRESH */
+
+#ifdef DEBUG_UPDATE
+ dprintf("updating %d lines.\r\n", new_vcv);
+#endif /* DEBUG_UPDATE */
+ for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
+ /* NOTE THAT update_line MAY CHANGE Display[cur_line] */
+ update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
+#ifdef WINNT
+ flush();
+#endif /* WINNT */
+
+ /*
+ * Copy the new line to be the current one, and pad out with spaces
+ * to the full width of the terminal so that if we try moving the
+ * cursor by writing the character that is at the end of the
+ * screen line, it won't be a NUL or some old leftover stuff.
+ */
+ cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
+#ifdef notdef
+ (void) Strncpy(Display[cur_line], Vdisplay[cur_line], (size_t) TermH);
+ Display[cur_line][TermH] = '\0'; /* just in case */
+#endif
+ }
+#ifdef DEBUG_REFRESH
+ dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
+ vcursor_v, OldvcV, cur_line);
+#endif /* DEBUG_REFRESH */
+ if (OldvcV > new_vcv) {
+ for (; cur_line <= OldvcV; cur_line++) {
+ update_line(Display[cur_line], STRNULL, cur_line);
+ *Display[cur_line] = '\0';
+ }
+ }
+ OldvcV = new_vcv; /* set for next time */
+#ifdef DEBUG_REFRESH
+ dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
+ CursorH, CursorV, cur_h, cur_v);
+#endif /* DEBUG_REFRESH */
+#ifdef WINNT
+ flush();
+#endif /* WINNT */
+ MoveToLine(cur_v); /* go to where the cursor is */
+ MoveToChar(cur_h);
+ SetAttributes(0); /* Clear all attributes */
+ flush(); /* send the output... */
+ GettingInput = oldgetting; /* reset to old value */
+}
+
+#ifdef notdef
+GotoBottom()
+{ /* used to go to last used screen line */
+ MoveToLine(OldvcV);
+}
+
+#endif
+
+void
+PastBottom()
+{ /* used to go to last used screen line */
+ MoveToLine(OldvcV);
+ (void) putraw('\r');
+ (void) putraw('\n');
+ ClearDisp();
+ flush();
+}
+
+
+/* insert num characters of s into d (in front of the character) at dat,
+ maximum length of d is dlen */
+static void
+str_insert(d, dat, dlen, s, num)
+ register Char *d;
+ register int dat, dlen;
+ register Char *s;
+ register int num;
+{
+ register Char *a, *b;
+
+ if (num <= 0)
+ return;
+ if (num > dlen - dat)
+ num = dlen - dat;
+
+#ifdef DEBUG_REFRESH
+ dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, short2str(d));
+ dprintf("s == \"%s\"n", short2str(s));
+#endif /* DEBUG_REFRESH */
+
+ /* open up the space for num chars */
+ if (num > 0) {
+ b = d + dlen - 1;
+ a = b - num;
+ while (a >= &d[dat])
+ *b-- = *a--;
+ d[dlen] = '\0'; /* just in case */
+ }
+#ifdef DEBUG_REFRESH
+ dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, short2str(d));
+ dprintf("s == \"%s\"n", short2str(s));
+#endif /* DEBUG_REFRESH */
+
+ /* copy the characters */
+ for (a = d + dat; (a < d + dlen) && (num > 0); num--)
+ *a++ = *s++;
+
+#ifdef DEBUG_REFRESH
+ dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, d, short2str(s));
+ dprintf("s == \"%s\"n", short2str(s));
+#endif /* DEBUG_REFRESH */
+}
+
+/* delete num characters d at dat, maximum length of d is dlen */
+static void
+str_delete(d, dat, dlen, num)
+ register Char *d;
+ register int dat, dlen, num;
+{
+ register Char *a, *b;
+
+ if (num <= 0)
+ return;
+ if (dat + num >= dlen) {
+ d[dat] = '\0';
+ return;
+ }
+
+#ifdef DEBUG_REFRESH
+ dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, short2str(d));
+#endif /* DEBUG_REFRESH */
+
+ /* open up the space for num chars */
+ if (num > 0) {
+ b = d + dat;
+ a = b + num;
+ while (a < &d[dlen])
+ *b++ = *a++;
+ d[dlen] = '\0'; /* just in case */
+ }
+#ifdef DEBUG_REFRESH
+ dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
+ num, dat, dlen, short2str(d));
+#endif /* DEBUG_REFRESH */
+}
+
+static void
+str_cp(a, b, n)
+ register Char *a, *b;
+ register int n;
+{
+ while (n-- && *b)
+ *a++ = *b++;
+}
+
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+static Char *
+update_line_fix_mbyte_point(start, target, d)
+ Char *start, *target;
+ int d;
+{
+ if (_enable_mbdisp) {
+ while (*start) {
+ if (target == start)
+ break;
+ if (target < start)
+ return target + d;
+ if (Ismbyte1(*start) && Ismbyte2(*(start + 1)))
+ start++;
+ start++;
+ }
+ }
+ return target;
+}
+#endif
+
+/* ****************************************************************
+ update_line() is based on finding the middle difference of each line
+ on the screen; vis:
+
+ /old first difference
+ /beginning of line | /old last same /old EOL
+ v v v v
+old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
+new: eddie> Oh, my little buggy says to me, as lurgid as
+ ^ ^ ^ ^
+ \beginning of line | \new last same \new end of line
+ \new first difference
+
+ all are character pointers for the sake of speed. Special cases for
+ no differences, as well as for end of line additions must be handled.
+**************************************************************** */
+
+/* Minimum at which doing an insert it "worth it". This should be about
+ * half the "cost" of going into insert mode, inserting a character, and
+ * going back out. This should really be calculated from the termcap
+ * data... For the moment, a good number for ANSI terminals.
+ */
+#define MIN_END_KEEP 4
+
+static void /* could be changed to make it smarter */
+update_line(old, new, cur_line)
+ register Char *old, *new;
+ int cur_line;
+{
+ register Char *o, *n, *p, c;
+ Char *ofd, *ols, *oe, *nfd, *nls, *ne;
+ Char *osb, *ose, *nsb, *nse;
+ int fx, sx;
+
+ /*
+ * find first diff
+ */
+ for (o = old, n = new; *o && (*o == *n); o++, n++)
+ continue;
+ ofd = o;
+ nfd = n;
+
+ /*
+ * Find the end of both old and new
+ */
+ while (*o)
+ o++;
+ /*
+ * Remove any trailing blanks off of the end, being careful not to
+ * back up past the beginning.
+ */
+ while (ofd < o) {
+ if (o[-1] != ' ')
+ break;
+ o--;
+ }
+ oe = o;
+ *oe = (Char) 0;
+
+ while (*n)
+ n++;
+
+ /* remove blanks from end of new */
+ while (nfd < n) {
+ if (n[-1] != ' ')
+ break;
+ n--;
+ }
+ ne = n;
+ *ne = (Char) 0;
+
+ /*
+ * if no diff, continue to next line of redraw
+ */
+ if (*ofd == '\0' && *nfd == '\0') {
+#ifdef DEBUG_UPDATE
+ dprintf("no difference.\r\n");
+#endif /* DEBUG_UPDATE */
+ return;
+ }
+
+ /*
+ * find last same pointer
+ */
+ while ((o > ofd) && (n > nfd) && (*--o == *--n))
+ continue;
+ ols = ++o;
+ nls = ++n;
+
+ /*
+ * find same begining and same end
+ */
+ osb = ols;
+ nsb = nls;
+ ose = ols;
+ nse = nls;
+
+ /*
+ * case 1: insert: scan from nfd to nls looking for *ofd
+ */
+ if (*ofd) {
+ for (c = *ofd, n = nfd; n < nls; n++) {
+ if (c == *n) {
+ for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
+ continue;
+ /*
+ * if the new match is longer and it's worth keeping, then we
+ * take it
+ */
+ if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
+ nsb = n;
+ nse = p;
+ osb = ofd;
+ ose = o;
+ }
+ }
+ }
+ }
+
+ /*
+ * case 2: delete: scan from ofd to ols looking for *nfd
+ */
+ if (*nfd) {
+ for (c = *nfd, o = ofd; o < ols; o++) {
+ if (c == *o) {
+ for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
+ continue;
+ /*
+ * if the new match is longer and it's worth keeping, then we
+ * take it
+ */
+ if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
+ nsb = nfd;
+ nse = n;
+ osb = o;
+ ose = p;
+ }
+ }
+ }
+ }
+#ifdef notdef
+ /*
+ * If `last same' is before `same end' re-adjust
+ */
+ if (ols < ose)
+ ols = ose;
+ if (nls < nse)
+ nls = nse;
+#endif
+
+ /*
+ * Pragmatics I: If old trailing whitespace or not enough characters to
+ * save to be worth it, then don't save the last same info.
+ */
+ if ((oe - ols) < MIN_END_KEEP) {
+ ols = oe;
+ nls = ne;
+ }
+
+ /*
+ * Pragmatics II: if the terminal isn't smart enough, make the data dumber
+ * so the smart update doesn't try anything fancy
+ */
+
+ /*
+ * fx is the number of characters we need to insert/delete: in the
+ * beginning to bring the two same begins together
+ */
+ fx = (int) ((nsb - nfd) - (osb - ofd));
+ /*
+ * sx is the number of characters we need to insert/delete: in the end to
+ * bring the two same last parts together
+ */
+ sx = (int) ((nls - nse) - (ols - ose));
+
+ if (!T_CanIns) {
+ if (fx > 0) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+ if (sx > 0) {
+ ols = oe;
+ nls = ne;
+ }
+ if ((ols - ofd) < (nls - nfd)) {
+ ols = oe;
+ nls = ne;
+ }
+ }
+ if (!T_CanDel) {
+ if (fx < 0) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+ if (sx < 0) {
+ ols = oe;
+ nls = ne;
+ }
+ if ((ols - ofd) > (nls - nfd)) {
+ ols = oe;
+ nls = ne;
+ }
+ }
+
+ /*
+ * Pragmatics III: make sure the middle shifted pointers are correct if
+ * they don't point to anything (we may have moved ols or nls).
+ */
+ /* if the change isn't worth it, don't bother */
+ /* was: if (osb == ose) */
+ if ((ose - osb) < MIN_END_KEEP) {
+ osb = ols;
+ ose = ols;
+ nsb = nls;
+ nse = nls;
+ }
+
+ /*
+ * Now that we are done with pragmatics we recompute fx, sx
+ */
+ fx = (int) ((nsb - nfd) - (osb - ofd));
+ sx = (int) ((nls - nse) - (ols - ose));
+
+#ifdef DEBUG_UPDATE
+ dprintf("\n");
+ dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
+ ofd - old, osb - old, ose - old, ols - old, oe - old);
+ dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
+ nfd - new, nsb - new, nse - new, nls - new, ne - new);
+ dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
+ dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
+ dprintstr("old- oe", old, oe);
+ dprintstr("new- ne", new, ne);
+ dprintstr("old-ofd", old, ofd);
+ dprintstr("new-nfd", new, nfd);
+ dprintstr("ofd-osb", ofd, osb);
+ dprintstr("nfd-nsb", nfd, nsb);
+ dprintstr("osb-ose", osb, ose);
+ dprintstr("nsb-nse", nsb, nse);
+ dprintstr("ose-ols", ose, ols);
+ dprintstr("nse-nls", nse, nls);
+ dprintstr("ols- oe", ols, oe);
+ dprintstr("nls- ne", nls, ne);
+#endif /* DEBUG_UPDATE */
+
+ /*
+ * CursorV to this line cur_line MUST be in this routine so that if we
+ * don't have to change the line, we don't move to it. CursorH to first
+ * diff char
+ */
+ MoveToLine(cur_line);
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+ ofd = update_line_fix_mbyte_point(old, ofd, -1);
+ osb = update_line_fix_mbyte_point(old, osb, 1);
+ ose = update_line_fix_mbyte_point(old, ose, -1);
+ ols = update_line_fix_mbyte_point(old, ols, 1);
+ nfd = update_line_fix_mbyte_point(new, nfd, -1);
+ nsb = update_line_fix_mbyte_point(new, nsb, 1);
+ nse = update_line_fix_mbyte_point(new, nse, -1);
+ nls = update_line_fix_mbyte_point(new, nls, 1);
+#endif
+
+ /*
+ * at this point we have something like this:
+ *
+ * /old /ofd /osb /ose /ols /oe
+ * v.....................v v..................v v........v
+ * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
+ * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
+ * ^.....................^ ^..................^ ^........^
+ * \new \nfd \nsb \nse \nls \ne
+ *
+ * fx is the difference in length between the the chars between nfd and
+ * nsb, and the chars between ofd and osb, and is thus the number of
+ * characters to delete if < 0 (new is shorter than old, as above),
+ * or insert (new is longer than short).
+ *
+ * sx is the same for the second differences.
+ */
+
+ /*
+ * if we have a net insert on the first difference, AND inserting the net
+ * amount ((nsb-nfd) - (osb-ofd)) won't push the last useful character
+ * (which is ne if nls != ne, otherwise is nse) off the edge of the screen
+ * (TermH - 1) else we do the deletes first so that we keep everything we
+ * need to.
+ */
+
+ /*
+ * if the last same is the same like the end, there is no last same part,
+ * otherwise we want to keep the last same part set p to the last useful
+ * old character
+ */
+ p = (ols != oe) ? oe : ose;
+
+ /*
+ * if (There is a diffence in the beginning) && (we need to insert
+ * characters) && (the number of characters to insert is less than the term
+ * width) We need to do an insert! else if (we need to delete characters)
+ * We need to delete characters! else No insert or delete
+ */
+ if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
+#ifdef DEBUG_UPDATE
+ dprintf("first diff insert at %d...\r\n", nfd - new);
+#endif /* DEBUG_UPDATE */
+ /*
+ * Move to the first char to insert, where the first diff is.
+ */
+ MoveToChar(nfd - new);
+ /*
+ * Check if we have stuff to keep at end
+ */
+ if (nsb != ne) {
+#ifdef DEBUG_UPDATE
+ dprintf("with stuff to keep at end\r\n");
+#endif /* DEBUG_UPDATE */
+ /*
+ * insert fx chars of new starting at nfd
+ */
+ if (fx > 0) {
+#ifdef DEBUG_UPDATE
+ if (!T_CanIns)
+ dprintf(" ERROR: cannot insert in early first diff\n");
+#endif /* DEBUG_UPDATE */
+ Insert_write(nfd, fx);
+ str_insert(old, (int) (ofd - old), TermH, nfd, fx);
+ }
+ /*
+ * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
+ */
+ so_write(nfd + fx, (nsb - nfd) - fx);
+ str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
+ }
+ else {
+#ifdef DEBUG_UPDATE
+ dprintf("without anything to save\r\n");
+#endif /* DEBUG_UPDATE */
+ so_write(nfd, (nsb - nfd));
+ str_cp(ofd, nfd, (int) (nsb - nfd));
+ /*
+ * Done
+ */
+ return;
+ }
+ }
+ else if (fx < 0) {
+#ifdef DEBUG_UPDATE
+ dprintf("first diff delete at %d...\r\n", ofd - old);
+#endif /* DEBUG_UPDATE */
+ /*
+ * move to the first char to delete where the first diff is
+ */
+ MoveToChar(ofd - old);
+ /*
+ * Check if we have stuff to save
+ */
+ if (osb != oe) {
+#ifdef DEBUG_UPDATE
+ dprintf("with stuff to save at end\r\n");
+#endif /* DEBUG_UPDATE */
+ /*
+ * fx is less than zero *always* here but we check for code
+ * symmetry
+ */
+ if (fx < 0) {
+#ifdef DEBUG_UPDATE
+ if (!T_CanDel)
+ dprintf(" ERROR: cannot delete in first diff\n");
+#endif /* DEBUG_UPDATE */
+ DeleteChars(-fx);
+ str_delete(old, (int) (ofd - old), TermH, -fx);
+ }
+ /*
+ * write (nsb-nfd) chars of new starting at nfd
+ */
+ so_write(nfd, (nsb - nfd));
+ str_cp(ofd, nfd, (int) (nsb - nfd));
+
+ }
+ else {
+#ifdef DEBUG_UPDATE
+ dprintf("but with nothing left to save\r\n");
+#endif /* DEBUG_UPDATE */
+ /*
+ * write (nsb-nfd) chars of new starting at nfd
+ */
+ so_write(nfd, (nsb - nfd));
+#ifdef DEBUG_REFRESH
+ dprintf("cleareol %d\n", (oe - old) - (ne - new));
+#endif /* DEBUG_UPDATE */
+#ifndef WINNT
+ ClearEOL((oe - old) - (ne - new));
+#else
+ /*
+ * The calculation above does not work too well on NT
+ */
+ ClearEOL(TermH - CursorH);
+#endif /*WINNT*/
+ /*
+ * Done
+ */
+ return;
+ }
+ }
+ else
+ fx = 0;
+
+ if (sx < 0) {
+#ifdef DEBUG_UPDATE
+ dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
+#endif /* DEBUG_UPDATE */
+ /*
+ * Check if we have stuff to delete
+ */
+ /*
+ * fx is the number of characters inserted (+) or deleted (-)
+ */
+
+ MoveToChar((ose - old) + fx);
+ /*
+ * Check if we have stuff to save
+ */
+ if (ols != oe) {
+#ifdef DEBUG_UPDATE
+ dprintf("with stuff to save at end\r\n");
+#endif /* DEBUG_UPDATE */
+ /*
+ * Again a duplicate test.
+ */
+ if (sx < 0) {
+#ifdef DEBUG_UPDATE
+ if (!T_CanDel)
+ dprintf(" ERROR: cannot delete in second diff\n");
+#endif /* DEBUG_UPDATE */
+ DeleteChars(-sx);
+ }
+
+ /*
+ * write (nls-nse) chars of new starting at nse
+ */
+ so_write(nse, (nls - nse));
+ }
+ else {
+ int olen = (int) (oe - old + fx);
+ if (olen > TermH)
+ olen = TermH;
+#ifdef DEBUG_UPDATE
+ dprintf("but with nothing left to save\r\n");
+#endif /* DEBUG_UPDATE */
+ so_write(nse, (nls - nse));
+#ifdef DEBUG_REFRESH
+ dprintf("cleareol %d\n", olen - (ne - new));
+#endif /* DEBUG_UPDATE */
+#ifndef WINNT
+ ClearEOL(olen - (ne - new));
+#else
+ /*
+ * The calculation above does not work too well on NT
+ */
+ ClearEOL(TermH - CursorH);
+#endif /*WINNT*/
+ }
+ }
+
+ /*
+ * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
+ */
+ if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
+#ifdef DEBUG_UPDATE
+ dprintf("late first diff insert at %d...\r\n", nfd - new);
+#endif /* DEBUG_UPDATE */
+
+ MoveToChar(nfd - new);
+ /*
+ * Check if we have stuff to keep at the end
+ */
+ if (nsb != ne) {
+#ifdef DEBUG_UPDATE
+ dprintf("with stuff to keep at end\r\n");
+#endif /* DEBUG_UPDATE */
+ /*
+ * We have to recalculate fx here because we set it
+ * to zero above as a flag saying that we hadn't done
+ * an early first insert.
+ */
+ fx = (int) ((nsb - nfd) - (osb - ofd));
+ if (fx > 0) {
+ /*
+ * insert fx chars of new starting at nfd
+ */
+#ifdef DEBUG_UPDATE
+ if (!T_CanIns)
+ dprintf(" ERROR: cannot insert in late first diff\n");
+#endif /* DEBUG_UPDATE */
+ Insert_write(nfd, fx);
+ str_insert(old, (int) (ofd - old), TermH, nfd, fx);
+ }
+
+ /*
+ * write (nsb-nfd) - fx chars of new starting at (nfd + fx)
+ */
+ so_write(nfd + fx, (nsb - nfd) - fx);
+ str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
+ }
+ else {
+#ifdef DEBUG_UPDATE
+ dprintf("without anything to save\r\n");
+#endif /* DEBUG_UPDATE */
+ so_write(nfd, (nsb - nfd));
+ str_cp(ofd, nfd, (int) (nsb - nfd));
+ }
+ }
+
+ /*
+ * line is now NEW up to nse
+ */
+ if (sx >= 0) {
+#ifdef DEBUG_UPDATE
+ dprintf("second diff insert at %d...\r\n", nse - new);
+#endif /* DEBUG_UPDATE */
+ MoveToChar(nse - new);
+ if (ols != oe) {
+#ifdef DEBUG_UPDATE
+ dprintf("with stuff to keep at end\r\n");
+#endif /* DEBUG_UPDATE */
+ if (sx > 0) {
+ /* insert sx chars of new starting at nse */
+#ifdef DEBUG_UPDATE
+ if (!T_CanIns)
+ dprintf(" ERROR: cannot insert in second diff\n");
+#endif /* DEBUG_UPDATE */
+ Insert_write(nse, sx);
+ }
+
+ /*
+ * write (nls-nse) - sx chars of new starting at (nse + sx)
+ */
+ so_write(nse + sx, (nls - nse) - sx);
+ }
+ else {
+#ifdef DEBUG_UPDATE
+ dprintf("without anything to save\r\n");
+#endif /* DEBUG_UPDATE */
+ so_write(nse, (nls - nse));
+
+ /*
+ * No need to do a clear-to-end here because we were doing
+ * a second insert, so we will have over written all of the
+ * old string.
+ */
+ }
+ }
+#ifdef DEBUG_UPDATE
+ dprintf("done.\r\n");
+#endif /* DEBUG_UPDATE */
+}
+
+
+static void
+cpy_pad_spaces(dst, src, width)
+ register Char *dst, *src;
+ register int width;
+{
+ register int i;
+
+ for (i = 0; i < width; i++) {
+ if (*src == (Char) 0)
+ break;
+ *dst++ = *src++;
+ }
+
+ while (i < width) {
+ *dst++ = ' ';
+ i++;
+ }
+ *dst = (Char) 0;
+}
+
+void
+RefCursor()
+{ /* only move to new cursor pos */
+ register Char *cp, c;
+ register int h, th, v;
+
+ /* first we must find where the cursor is... */
+ h = 0;
+ v = 0;
+ th = TermH; /* optimize for speed */
+
+ for (cp = PromptBuf; *cp; cp++) { /* do prompt */
+ if (*cp & LITERAL)
+ continue;
+ c = *cp & CHAR; /* extra speed plus strip the inverse */
+ h++; /* all chars at least this long */
+
+ /* from wolman%crltrx.DEC@decwrl.dec.com (Alec Wolman) */
+ /* lets handle newline as part of the prompt */
+
+ if (c == '\n') {
+ h = 0;
+ v++;
+ }
+ else {
+ if (c == '\t') { /* if a tab, to next tab stop */
+ while (h & 07) {
+ h++;
+ }
+ }
+ else if (Iscntrl(c)) { /* if control char */
+ h++;
+ if (h > th) { /* if overflow, compensate */
+ h = 1;
+ v++;
+ }
+ }
+ else if (!Isprint(c)) {
+ h += 3;
+ if (h > th) { /* if overflow, compensate */
+ h = h - th;
+ v++;
+ }
+ }
+ }
+
+ if (h >= th) { /* check, extra long tabs picked up here also */
+ h = 0;
+ v++;
+ }
+ }
+
+ for (cp = InputBuf; cp < Cursor; cp++) { /* do input buffer to Cursor */
+ c = *cp & CHAR; /* extra speed plus strip the inverse */
+ h++; /* all chars at least this long */
+
+ if (c == '\n') { /* handle newline in data part too */
+ h = 0;
+ v++;
+ }
+ else {
+ if (c == '\t') { /* if a tab, to next tab stop */
+ while (h & 07) {
+ h++;
+ }
+ }
+ else if (Iscntrl(c)) { /* if control char */
+ h++;
+ if (h > th) { /* if overflow, compensate */
+ h = 1;
+ v++;
+ }
+ }
+ else if (!Isprint(c)) {
+ h += 3;
+ if (h > th) { /* if overflow, compensate */
+ h = h - th;
+ v++;
+ }
+ }
+ }
+
+ if (h >= th) { /* check, extra long tabs picked up here also */
+ h = 0;
+ v++;
+ }
+ }
+
+ /* now go there */
+ MoveToLine(v);
+ MoveToChar(h);
+ flush();
+}
+
+static void
+PutPlusOne(c)
+ int c;
+{
+ (void) putraw(c);
+ Display[CursorV][CursorH++] = (Char) c;
+ if (CursorH >= TermH) { /* if we must overflow */
+ CursorH = 0;
+ CursorV++;
+ OldvcV++;
+ if (T_Margin & MARGIN_AUTO) {
+ if (T_Margin & MARGIN_MAGIC) {
+ (void) putraw(' ');
+ (void) putraw('\b');
+ }
+ }
+ else {
+ (void) putraw('\r');
+ (void) putraw('\n');
+ }
+ }
+}
+
+void
+RefPlusOne()
+{ /* we added just one char, handle it fast.
+ * assumes that screen cursor == real cursor */
+ register Char c, mc;
+
+ c = Cursor[-1] & CHAR; /* the char we just added */
+
+ if (c == '\t' || Cursor != LastChar) {
+ Refresh(); /* too hard to handle */
+ return;
+ }
+
+ if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
+ Refresh(); /* clear out rprompt if less than one char gap*/
+ return;
+ } /* else (only do at end of line, no TAB) */
+
+ if (Iscntrl(c)) { /* if control char, do caret */
+#ifndef _OSD_POSIX
+ mc = (c == '\177') ? '?' : (c | 0100);
+ PutPlusOne('^');
+ PutPlusOne(mc);
+#else /*_OSD_POSIX*/
+ if (_toascii[c] == '\177' || Isupper(_toebcdic[_toascii[c]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL)
+ {
+ mc = (_toascii[c] == '\177') ? '?' : _toebcdic[_toascii[c]|0100];
+ PutPlusOne('^');
+ PutPlusOne(mc);
+ }
+ else
+ {
+ PutPlusOne('\\');
+ PutPlusOne(((c >> 6) & 7) + '0');
+ PutPlusOne(((c >> 3) & 7) + '0');
+ PutPlusOne((c & 7) + '0');
+ }
+#endif /*_OSD_POSIX*/
+ }
+ else if (Isprint(c)) { /* normal char */
+ PutPlusOne(c);
+ }
+#ifdef KANJI
+ else if (!adrof(STRnokanji)) {
+ PutPlusOne(c);
+ }
+#endif
+ else {
+ PutPlusOne('\\');
+ PutPlusOne(((c >> 6) & 7) + '0');
+ PutPlusOne(((c >> 3) & 7) + '0');
+ PutPlusOne((c & 7) + '0');
+ }
+ flush();
+}
+
+/* clear the screen buffers so that new new prompt starts fresh. */
+
+void
+ClearDisp()
+{
+ register int i;
+
+ CursorV = 0; /* clear the display buffer */
+ CursorH = 0;
+ for (i = 0; i < TermV; i++)
+ (void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
+ OldvcV = 0;
+}
+
+void
+ClearLines()
+{ /* Make sure all lines are *really* blank */
+ register int i;
+
+ if (T_CanCEOL) {
+ /*
+ * Clear the lines from the bottom up so that if we try moving
+ * the cursor down by writing the character that is at the end
+ * of the screen line, we won't rewrite a character that shouldn't
+ * be there.
+ */
+ for (i = OldvcV; i >= 0; i--) { /* for each line on the screen */
+ MoveToLine(i);
+ MoveToChar(0);
+ ClearEOL(TermH);
+ }
+ }
+ else {
+ MoveToLine(OldvcV); /* go to last line */
+ (void) putraw('\r'); /* go to BOL */
+ (void) putraw('\n'); /* go to new line */
+ }
+}
diff --git a/contrib/tcsh/ed.screen.c b/contrib/tcsh/ed.screen.c
new file mode 100644
index 0000000..2d4be8a
--- /dev/null
+++ b/contrib/tcsh/ed.screen.c
@@ -0,0 +1,1706 @@
+/* $Header: /src/pub/tcsh/ed.screen.c,v 3.46 1999/02/06 15:18:56 christos Exp $ */
+/*
+ * ed.screen.c: Editor/termcap-curses interface
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.screen.c,v 3.46 1999/02/06 15:18:56 christos Exp $")
+
+#include "ed.h"
+#include "tc.h"
+#include "ed.defns.h"
+
+#ifndef POSIX
+/*
+ * We don't prototype these, cause some systems have them wrong!
+ */
+extern int tgetent __P(());
+extern char *tgetstr __P(());
+extern int tgetflag __P(());
+extern int tgetnum __P(());
+extern char *tgoto __P(());
+# define PUTPURE putpure
+# define PUTRAW putraw
+#else
+extern int tgetent __P((char *, char *));
+extern char *tgetstr __P((char *, char **));
+extern int tgetflag __P((char *));
+extern int tgetnum __P((char *));
+extern char *tgoto __P((char *, int, int));
+extern void tputs __P((char *, int, void (*)(int)));
+# define PUTPURE ((void (*)__P((int))) putpure)
+# define PUTRAW ((void (*)__P((int))) putraw)
+#endif
+
+
+/* #define DEBUG_LITERAL */
+
+/*
+ * IMPORTANT NOTE: these routines are allowed to look at the current screen
+ * and the current possition assuming that it is correct. If this is not
+ * true, then the update will be WRONG! This is (should be) a valid
+ * assumption...
+ */
+
+#define TC_BUFSIZE 2048
+
+#define GoodStr(a) (tstr[a].str != NULL && tstr[a].str[0] != '\0')
+#define Str(a) tstr[a].str
+#define Val(a) tval[a].val
+
+static struct {
+ char *b_name;
+ int b_rate;
+} baud_rate[] = {
+
+#ifdef B0
+ { "0", B0 },
+#endif
+#ifdef B50
+ { "50", B50 },
+#endif
+#ifdef B75
+ { "75", B75 },
+#endif
+#ifdef B110
+ { "110", B110 },
+#endif
+#ifdef B134
+ { "134", B134 },
+#endif
+#ifdef B150
+ { "150", B150 },
+#endif
+#ifdef B200
+ { "200", B200 },
+#endif
+#ifdef B300
+ { "300", B300 },
+#endif
+#ifdef B600
+ { "600", B600 },
+#endif
+#ifdef B900
+ { "900", B900 },
+#endif
+#ifdef B1200
+ { "1200", B1200 },
+#endif
+#ifdef B1800
+ { "1800", B1800 },
+#endif
+#ifdef B2400
+ { "2400", B2400 },
+#endif
+#ifdef B3600
+ { "3600", B3600 },
+#endif
+#ifdef B4800
+ { "4800", B4800 },
+#endif
+#ifdef B7200
+ { "7200", B7200 },
+#endif
+#ifdef B9600
+ { "9600", B9600 },
+#endif
+#ifdef EXTA
+ { "19200", EXTA },
+#endif
+#ifdef B19200
+ { "19200", B19200 },
+#endif
+#ifdef EXTB
+ { "38400", EXTB },
+#endif
+#ifdef B38400
+ { "38400", B38400 },
+#endif
+ { NULL, 0 }
+};
+
+#define T_al 0
+#define T_bl 1
+#define T_cd 2
+#define T_ce 3
+#define T_ch 4
+#define T_cl 5
+#define T_dc 6
+#define T_dl 7
+#define T_dm 8
+#define T_ed 9
+#define T_ei 10
+#define T_fs 11
+#define T_ho 12
+#define T_ic 13
+#define T_im 14
+#define T_ip 15
+#define T_kd 16
+#define T_kl 17
+#define T_kr 18
+#define T_ku 19
+#define T_md 20
+#define T_me 21
+#define T_nd 22
+#define T_se 23
+#define T_so 24
+#define T_ts 25
+#define T_up 26
+#define T_us 27
+#define T_ue 28
+#define T_vb 29
+#define T_DC 30
+#define T_DO 31
+#define T_IC 32
+#define T_LE 33
+#define T_RI 34
+#define T_UP 35
+#define T_str 36
+static struct termcapstr {
+ char *name;
+ char *long_name;
+ char *str;
+} tstr[T_str + 1];
+
+
+#define T_am 0
+#define T_pt 1
+#define T_li 2
+#define T_co 3
+#define T_km 4
+#define T_xn 5
+#define T_val 6
+static struct termcapval {
+ char *name;
+ char *long_name;
+ int val;
+} tval[T_val + 1];
+
+void
+terminit()
+{
+#ifdef NLS_CATALOGS
+ int i;
+
+ for (i = 0; i < T_str + 1; i++)
+ xfree((ptr_t) tstr[i].long_name);
+
+ for (i = 0; i < T_val + 1; i++)
+ xfree((ptr_t) tval[i].long_name);
+#endif
+
+ tstr[T_al].name = "al";
+ tstr[T_al].long_name = CSAVS(4, 1, "add new blank line");
+
+ tstr[T_bl].name = "bl";
+ tstr[T_bl].long_name = CSAVS(4, 2, "audible bell");
+
+ tstr[T_cd].name = "cd";
+ tstr[T_cd].long_name = CSAVS(4, 3, "clear to bottom");
+
+ tstr[T_ce].name = "ce";
+ tstr[T_ce].long_name = CSAVS(4, 4, "clear to end of line");
+
+ tstr[T_ch].name = "ch";
+ tstr[T_ch].long_name = CSAVS(4, 5, "cursor to horiz pos");
+
+ tstr[T_cl].name = "cl";
+ tstr[T_cl].long_name = CSAVS(4, 6, "clear screen");
+
+ tstr[T_dc].name = "dc";
+ tstr[T_dc].long_name = CSAVS(4, 7, "delete a character");
+
+ tstr[T_dl].name = "dl";
+ tstr[T_dl].long_name = CSAVS(4, 8, "delete a line");
+
+ tstr[T_dm].name = "dm";
+ tstr[T_dm].long_name = CSAVS(4, 9, "start delete mode");
+
+ tstr[T_ed].name = "ed";
+ tstr[T_ed].long_name = CSAVS(4, 10, "end delete mode");
+
+ tstr[T_ei].name = "ei";
+ tstr[T_ei].long_name = CSAVS(4, 11, "end insert mode");
+
+ tstr[T_fs].name = "fs";
+ tstr[T_fs].long_name = CSAVS(4, 12, "cursor from status line");
+
+ tstr[T_ho].name = "ho";
+ tstr[T_ho].long_name = CSAVS(4, 13, "home cursor");
+
+ tstr[T_ic].name = "ic";
+ tstr[T_ic].long_name = CSAVS(4, 14, "insert character");
+
+ tstr[T_im].name = "im";
+ tstr[T_im].long_name = CSAVS(4, 15, "start insert mode");
+
+ tstr[T_ip].name = "ip";
+ tstr[T_ip].long_name = CSAVS(4, 16, "insert padding");
+
+ tstr[T_kd].name = "kd";
+ tstr[T_kd].long_name = CSAVS(4, 17, "sends cursor down");
+
+ tstr[T_kl].name = "kl";
+ tstr[T_kl].long_name = CSAVS(4, 18, "sends cursor left");
+
+ tstr[T_kr].name = "kr";
+ tstr[T_kr].long_name = CSAVS(4, 19, "sends cursor right");
+
+ tstr[T_ku].name = "ku";
+ tstr[T_ku].long_name = CSAVS(4, 20, "sends cursor up");
+
+ tstr[T_md].name = "md";
+ tstr[T_md].long_name = CSAVS(4, 21, "begin bold");
+
+ tstr[T_me].name = "me";
+ tstr[T_me].long_name = CSAVS(4, 22, "end attributes");
+
+ tstr[T_nd].name = "nd";
+ tstr[T_nd].long_name = CSAVS(4, 23, "non destructive space");
+
+ tstr[T_se].name = "se";
+ tstr[T_se].long_name = CSAVS(4, 24, "end standout");
+
+ tstr[T_so].name = "so";
+ tstr[T_so].long_name = CSAVS(4, 25, "begin standout");
+
+ tstr[T_ts].name = "ts";
+ tstr[T_ts].long_name = CSAVS(4, 26, "cursor to status line");
+
+ tstr[T_up].name = "up";
+ tstr[T_up].long_name = CSAVS(4, 27, "cursor up one");
+
+ tstr[T_us].name = "us";
+ tstr[T_us].long_name = CSAVS(4, 28, "begin underline");
+
+ tstr[T_ue].name = "ue";
+ tstr[T_ue].long_name = CSAVS(4, 29, "end underline");
+
+ tstr[T_vb].name = "vb";
+ tstr[T_vb].long_name = CSAVS(4, 30, "visible bell");
+
+ tstr[T_DC].name = "DC";
+ tstr[T_DC].long_name = CSAVS(4, 31, "delete multiple chars");
+
+ tstr[T_DO].name = "DO";
+ tstr[T_DO].long_name = CSAVS(4, 32, "cursor down multiple");
+
+ tstr[T_IC].name = "IC";
+ tstr[T_IC].long_name = CSAVS(4, 33, "insert multiple chars");
+
+ tstr[T_LE].name = "LE";
+ tstr[T_LE].long_name = CSAVS(4, 34, "cursor left multiple");
+
+ tstr[T_RI].name = "RI";
+ tstr[T_RI].long_name = CSAVS(4, 35, "cursor right multiple");
+
+ tstr[T_UP].name = "UP";
+ tstr[T_UP].long_name = CSAVS(4, 36, "cursor up multiple");
+
+ tstr[T_str].name = NULL;
+ tstr[T_str].long_name = NULL;
+
+
+ tval[T_am].name = "am";
+ tval[T_am].long_name = CSAVS(4, 37, "Has automatic margins");
+
+ tval[T_pt].name = "pt";
+ tval[T_pt].long_name = CSAVS(4, 38, "Can use physical tabs");
+
+ tval[T_li].name = "li";
+ tval[T_li].long_name = CSAVS(4, 39, "Number of lines");
+
+ tval[T_co].name = "co";
+ tval[T_co].long_name = CSAVS(4, 40, "Number of columns");
+
+ tval[T_km].name = "km";
+ tval[T_km].long_name = CSAVS(4, 41, "Has meta key");
+
+ tval[T_xn].name = "xn";
+ tval[T_xn].long_name = CSAVS(4, 42, "Newline ignored at right margin");
+
+ tval[T_val].name = NULL;
+ tval[T_val].long_name = NULL;
+}
+
+/*
+ * A very useful table from justin@crim.ca (Justin Bur) :-)
+ * (Modified by per@erix.ericsson.se (Per Hedeland)
+ * - first (and second:-) case fixed)
+ *
+ * Description Termcap variables tcsh behavior
+ * am xn UseRightmost SendCRLF
+ * -------------- ------- ------- ------------ ------------
+ * Automargins yes no yes no
+ * Magic Margins yes yes yes no
+ * No Wrap no -- yes yes
+ */
+
+static bool me_all = 0; /* does two or more of the attributes use me */
+
+static void ReBufferDisplay __P((void));
+static void TCalloc __P((struct termcapstr *, char *));
+
+
+static void
+TCalloc(t, cap)
+ struct termcapstr *t;
+ char *cap;
+{
+ static char termcap_alloc[TC_BUFSIZE];
+ char termbuf[TC_BUFSIZE];
+ struct termcapstr *ts;
+ static int tloc = 0;
+ int tlen, clen;
+
+ if (cap == NULL || *cap == '\0') {
+ t->str = NULL;
+ return;
+ }
+ else
+ clen = strlen(cap);
+
+ if (t->str == NULL)
+ tlen = 0;
+ else
+ tlen = strlen(t->str);
+
+ /*
+ * New string is shorter; no need to allocate space
+ */
+ if (clen <= tlen) {
+ (void) strcpy(t->str, cap);
+ return;
+ }
+
+ /*
+ * New string is longer; see if we have enough space to append
+ */
+ if (tloc + 3 < TC_BUFSIZE) {
+ (void) strcpy(t->str = &termcap_alloc[tloc], cap);
+ tloc += clen + 1; /* one for \0 */
+ return;
+ }
+
+ /*
+ * Compact our buffer; no need to check compaction, cause we know it
+ * fits...
+ */
+ tlen = 0;
+ for (ts = tstr; ts->name != NULL; ts++)
+ if (t != ts && ts->str != NULL && ts->str[0] != '\0') {
+ char *ptr;
+
+ for (ptr = ts->str; *ptr != '\0'; termbuf[tlen++] = *ptr++)
+ continue;
+ termbuf[tlen++] = '\0';
+ }
+ (void) memmove((ptr_t) termcap_alloc, (ptr_t) termbuf, (size_t) TC_BUFSIZE);
+ tloc = tlen;
+ if (tloc + 3 >= TC_BUFSIZE) {
+ stderror(ERR_NAME | ERR_TCNOSTR);
+ return;
+ }
+ (void) strcpy(t->str = &termcap_alloc[tloc], cap);
+ tloc += clen + 1; /* one for \0 */
+ return;
+}
+
+
+/*ARGSUSED*/
+void
+TellTC(what)
+ char *what;
+{
+ struct termcapstr *t;
+
+ USE(what);
+ xprintf(CGETS(7, 1, "\n\tTcsh thinks your terminal has the\n"));
+ xprintf(CGETS(7, 2, "\tfollowing characteristics:\n\n"));
+ xprintf(CGETS(7, 3, "\tIt has %d columns and %d lines\n"),
+ Val(T_co), Val(T_li));
+ xprintf(CGETS(7, 4, "\tIt has %s meta key\n"), T_HasMeta ?
+ CGETS(7, 5, "a") : CGETS(7, 6, "no"));
+ xprintf(CGETS(7, 7, "\tIt can%s use tabs\n"), T_Tabs ?
+ "" : CGETS(7, 8, " not"));
+ xprintf(CGETS(7, 9, "\tIt %s automatic margins\n"),
+ (T_Margin&MARGIN_AUTO)?
+ CGETS(7, 10, "has"):
+ CGETS(7, 11, "does not have"));
+ if (T_Margin & MARGIN_AUTO)
+ xprintf(CGETS(7, 12, "\tIt %s magic margins\n"),
+ (T_Margin & MARGIN_MAGIC) ?
+ CGETS(7, 10, "has"):
+ CGETS(7, 11, "does not have"));
+
+ for (t = tstr; t->name != NULL; t++)
+ xprintf("\t%36s (%s) == %s\n", t->long_name, t->name,
+ t->str && *t->str ? t->str : CGETS(7, 13, "(empty)"));
+ xputchar('\n');
+}
+
+
+static void
+ReBufferDisplay()
+{
+ register int i;
+ Char **b;
+ Char **bufp;
+
+ b = Display;
+ Display = NULL;
+ if (b != NULL) {
+ for (bufp = b; *bufp != NULL; bufp++)
+ xfree((ptr_t) * bufp);
+ xfree((ptr_t) b);
+ }
+ b = Vdisplay;
+ Vdisplay = NULL;
+ if (b != NULL) {
+ for (bufp = b; *bufp != NULL; bufp++)
+ xfree((ptr_t) * bufp);
+ xfree((ptr_t) b);
+ }
+ TermH = Val(T_co);
+ TermV = (INBUFSIZE * 4) / TermH + 1;
+ b = (Char **) xmalloc((size_t) (sizeof(Char *) * (TermV + 1)));
+ for (i = 0; i < TermV; i++)
+ b[i] = (Char *) xmalloc((size_t) (sizeof(Char) * (TermH + 1)));
+ b[TermV] = NULL;
+ Display = b;
+ b = (Char **) xmalloc((size_t) (sizeof(Char *) * (TermV + 1)));
+ for (i = 0; i < TermV; i++)
+ b[i] = (Char *) xmalloc((size_t) (sizeof(Char) * (TermH + 1)));
+ b[TermV] = NULL;
+ Vdisplay = b;
+}
+
+void
+SetTC(what, how)
+ char *what, *how;
+{
+ struct termcapstr *ts;
+ struct termcapval *tv;
+
+ /*
+ * Do the strings first
+ */
+ setname("settc");
+ for (ts = tstr; ts->name != NULL; ts++)
+ if (strcmp(ts->name, what) == 0)
+ break;
+ if (ts->name != NULL) {
+ TCalloc(ts, how);
+ /*
+ * Reset variables
+ */
+ if (GoodStr(T_me) && GoodStr(T_ue))
+ me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
+ else
+ me_all = 0;
+ if (GoodStr(T_me) && GoodStr(T_se))
+ me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
+
+ T_CanCEOL = GoodStr(T_ce);
+ T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
+ T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
+ T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
+ return;
+ }
+
+ /*
+ * Do the numeric ones second
+ */
+ for (tv = tval; tv->name != NULL; tv++)
+ if (strcmp(tv->name, what) == 0)
+ break;
+
+ if (tv->name != NULL) {
+ if (tv == &tval[T_pt] || tv == &tval[T_km] ||
+ tv == &tval[T_am] || tv == &tval[T_xn]) {
+ if (strcmp(how, "yes") == 0)
+ tv->val = 1;
+ else if (strcmp(how, "no") == 0)
+ tv->val = 0;
+ else {
+ stderror(ERR_SETTCUS, tv->name);
+ return;
+ }
+ T_Tabs = (Char) Val(T_pt);
+ T_HasMeta = (Char) Val(T_km);
+ T_Margin = (Char) Val(T_am) ? MARGIN_AUTO : 0;
+ T_Margin |= (Char) Val(T_xn) ? MARGIN_MAGIC : 0;
+ if (tv == &tval[T_am] || tv == &tval[T_xn])
+ ChangeSize(Val(T_li), Val(T_co));
+ return;
+ }
+ else {
+ tv->val = atoi(how);
+ T_Cols = (Char) Val(T_co);
+ T_Lines = (Char) Val(T_li);
+ if (tv == &tval[T_co] || tv == &tval[T_li])
+ ChangeSize(Val(T_li), Val(T_co));
+ return;
+ }
+ }
+ stderror(ERR_NAME | ERR_TCCAP, what);
+ return;
+}
+
+
+/*
+ * Print the termcap string out with variable substitution
+ */
+void
+EchoTC(v)
+ Char **v;
+{
+ char *cap, *scap, cv[BUFSIZE];
+ int arg_need, arg_cols, arg_rows;
+ int verbose = 0, silent = 0;
+ char *area;
+ static char *fmts = "%s\n", *fmtd = "%d\n";
+ struct termcapstr *t;
+ char buf[TC_BUFSIZE];
+
+ area = buf;
+
+ setname("echotc");
+
+ tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else
+ v = gargv = saveblk(v);
+ trim(v);
+
+ if (!*v || *v[0] == '\0')
+ return;
+ if (v[0][0] == '-') {
+ switch (v[0][1]) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ silent = 1;
+ break;
+ default:
+ stderror(ERR_NAME | ERR_TCUSAGE);
+ break;
+ }
+ v++;
+ }
+ if (!*v || *v[0] == '\0')
+ return;
+ (void) strcpy(cv, short2str(*v));
+ if (strcmp(cv, "tabs") == 0) {
+ xprintf(fmts, T_Tabs ? CGETS(7, 14, "yes") :
+ CGETS(7, 15, "no"));
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "meta") == 0) {
+ xprintf(fmts, Val(T_km) ? CGETS(7, 14, "yes") :
+ CGETS(7, 15, "no"));
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "xn") == 0) {
+ xprintf(fmts, T_Margin & MARGIN_MAGIC ? CGETS(7, 14, "yes") :
+ CGETS(7, 15, "no"));
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "am") == 0) {
+ xprintf(fmts, T_Margin & MARGIN_AUTO ? CGETS(7, 14, "yes") :
+ CGETS(7, 15, "no"));
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "baud") == 0) {
+ int i;
+
+ for (i = 0; baud_rate[i].b_name != NULL; i++)
+ if (T_Speed == baud_rate[i].b_rate) {
+ xprintf(fmts, baud_rate[i].b_name);
+ flush();
+ return;
+ }
+ xprintf(fmtd, 0);
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "rows") == 0 || strcmp(cv, "lines") == 0) {
+ xprintf(fmtd, Val(T_li));
+ flush();
+ return;
+ }
+ else if (strcmp(cv, "cols") == 0) {
+ xprintf(fmtd, Val(T_co));
+ flush();
+ return;
+ }
+
+ /*
+ * Try to use our local definition first
+ */
+ scap = NULL;
+ for (t = tstr; t->name != NULL; t++)
+ if (strcmp(t->name, cv) == 0) {
+ scap = t->str;
+ break;
+ }
+ if (t->name == NULL)
+ scap = tgetstr(cv, &area);
+ if (!scap || scap[0] == '\0') {
+ if (tgetflag(cv)) {
+ xprintf(CGETS(7, 14, "yes\n"));
+ return;
+ }
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCCAP, cv);
+ }
+
+ /*
+ * Count home many values we need for this capability.
+ */
+ for (cap = scap, arg_need = 0; *cap; cap++)
+ if (*cap == '%')
+ switch (*++cap) {
+ case 'd':
+ case '2':
+ case '3':
+ case '.':
+ case '+':
+ arg_need++;
+ break;
+ case '%':
+ case '>':
+ case 'i':
+ case 'r':
+ case 'n':
+ case 'B':
+ case 'D':
+ break;
+ default:
+ /*
+ * hpux has lot's of them...
+ */
+ if (verbose)
+ stderror(ERR_NAME | ERR_TCPARM, *cap);
+ /* This is bad, but I won't complain */
+ break;
+ }
+
+ switch (arg_need) {
+ case 0:
+ v++;
+ if (*v && *v[0]) {
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
+ }
+ (void) tputs(scap, 1, PUTRAW);
+ break;
+ case 1:
+ v++;
+ if (!*v || *v[0] == '\0')
+ stderror(ERR_NAME | ERR_TCNARGS, cv, 1);
+ arg_cols = 0;
+ arg_rows = atoi(short2str(*v));
+ v++;
+ if (*v && *v[0]) {
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
+ }
+ (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, PUTRAW);
+ break;
+ default:
+ /* This is wrong, but I will ignore it... */
+ if (verbose)
+ stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
+ /*FALLTHROUGH*/
+ case 2:
+ v++;
+ if (!*v || *v[0] == '\0') {
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
+ }
+ arg_cols = atoi(short2str(*v));
+ v++;
+ if (!*v || *v[0] == '\0') {
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
+ }
+ arg_rows = atoi(short2str(*v));
+ v++;
+ if (*v && *v[0]) {
+ if (silent)
+ return;
+ else
+ stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
+ }
+ (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, PUTRAW);
+ break;
+ }
+ flush();
+ if (gargv) {
+ blkfree(gargv);
+ gargv = 0;
+ }
+}
+
+bool GotTermCaps = 0;
+
+static struct {
+ Char *name;
+ int key;
+ XmapVal fun;
+ int type;
+} arrow[] = {
+#define A_K_DN 0
+ { STRdown, T_kd },
+#define A_K_UP 1
+ { STRup, T_ku },
+#define A_K_LT 2
+ { STRleft, T_kl },
+#define A_K_RT 3
+ { STRright, T_kr }
+};
+
+
+void
+ResetArrowKeys()
+{
+ arrow[A_K_DN].fun.cmd = F_DOWN_HIST;
+ arrow[A_K_DN].type = XK_CMD;
+
+ arrow[A_K_UP].fun.cmd = F_UP_HIST;
+ arrow[A_K_UP].type = XK_CMD;
+
+ arrow[A_K_LT].fun.cmd = F_CHARBACK;
+ arrow[A_K_LT].type = XK_CMD;
+
+ arrow[A_K_RT].fun.cmd = F_CHARFWD;
+ arrow[A_K_RT].type = XK_CMD;
+
+}
+
+void
+DefaultArrowKeys()
+{
+ static Char strA[] = {033, '[', 'A', '\0'};
+ static Char strB[] = {033, '[', 'B', '\0'};
+ static Char strC[] = {033, '[', 'C', '\0'};
+ static Char strD[] = {033, '[', 'D', '\0'};
+ static Char stOA[] = {033, 'O', 'A', '\0'};
+ static Char stOB[] = {033, 'O', 'B', '\0'};
+ static Char stOC[] = {033, 'O', 'C', '\0'};
+ static Char stOD[] = {033, 'O', 'D', '\0'};
+
+ CStr cs;
+#ifdef _OSD_POSIX
+ if (strA[0] == 033)
+ {
+ strA[0] = CTL_ESC('\033');
+ strB[0] = CTL_ESC('\033');
+ strC[0] = CTL_ESC('\033');
+ strD[0] = CTL_ESC('\033');
+ stOA[0] = CTL_ESC('\033');
+ stOB[0] = CTL_ESC('\033');
+ stOC[0] = CTL_ESC('\033');
+ stOD[0] = CTL_ESC('\033');
+ }
+#endif
+
+ cs.len = 3;
+
+ cs.buf = strA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ cs.buf = strB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ cs.buf = strC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ cs.buf = strD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ cs.buf = stOA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ cs.buf = stOB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ cs.buf = stOC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ cs.buf = stOD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+
+ if (VImode) {
+ cs.len = 2;
+ cs.buf = &strA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ cs.buf = &strB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ cs.buf = &strC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ cs.buf = &strD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ cs.buf = &stOA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
+ cs.buf = &stOB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
+ cs.buf = &stOC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
+ cs.buf = &stOD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
+ }
+}
+
+
+int
+SetArrowKeys(name, fun, type)
+ CStr *name;
+ XmapVal *fun;
+ int type;
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ if (Strcmp(name->buf, arrow[i].name) == 0) {
+ arrow[i].fun = *fun;
+ arrow[i].type = type;
+ return 0;
+ }
+ return -1;
+}
+
+int
+IsArrowKey(name)
+ Char *name;
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ if (Strcmp(name, arrow[i].name) == 0)
+ return 1;
+ return 0;
+}
+
+int
+ClearArrowKeys(name)
+ CStr *name;
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ if (Strcmp(name->buf, arrow[i].name) == 0) {
+ arrow[i].type = XK_NOD;
+ return 0;
+ }
+ return -1;
+}
+
+void
+PrintArrowKeys(name)
+ CStr *name;
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (name->len == 0 || Strcmp(name->buf, arrow[i].name) == 0)
+ if (arrow[i].type != XK_NOD) {
+ CStr cs;
+ cs.buf = arrow[i].name;
+ cs.len = Strlen(cs.buf);
+ (void) printOne(&cs, &arrow[i].fun, arrow[i].type);
+ }
+}
+
+
+void
+BindArrowKeys()
+{
+ KEYCMD *map, *dmap;
+ int i, j;
+ char *p;
+ CStr cs;
+
+ if (!GotTermCaps)
+ return;
+ map = VImode ? CcAltMap : CcKeyMap;
+ dmap = VImode ? CcViCmdMap : CcEmacsMap;
+
+ DefaultArrowKeys();
+
+ for (i = 0; i < 4; i++) {
+ p = tstr[arrow[i].key].str;
+ if (p && *p) {
+ j = (unsigned char) *p;
+ cs.buf = str2short(p);
+ cs.len = Strlen(cs.buf);
+ /*
+ * Assign the arrow keys only if:
+ *
+ * 1. They are multi-character arrow keys and the user
+ * has not re-assigned the leading character, or
+ * has re-assigned the leading character to be F_XKEY
+ * 2. They are single arrow keys pointing to an unassigned key.
+ */
+ if (arrow[i].type == XK_NOD) {
+ ClearXkey(map, &cs);
+ }
+ else {
+ if (p[1] && (dmap[j] == map[j] || map[j] == F_XKEY)) {
+ AddXkey(&cs, &arrow[i].fun, arrow[i].type);
+ map[j] = F_XKEY;
+ }
+ else if (map[j] == F_UNASSIGNED) {
+ ClearXkey(map, &cs);
+ if (arrow[i].type == XK_CMD)
+ map[j] = arrow[i].fun.cmd;
+ else
+ AddXkey(&cs, &arrow[i].fun, arrow[i].type);
+ }
+ }
+ }
+ }
+}
+
+static Char cur_atr = 0; /* current attributes */
+
+void
+SetAttributes(atr)
+ int atr;
+{
+ atr &= ATTRIBUTES;
+ if (atr != cur_atr) {
+ if (me_all && GoodStr(T_me)) {
+ if (((cur_atr & BOLD) && !(atr & BOLD)) ||
+ ((cur_atr & UNDER) && !(atr & UNDER)) ||
+ ((cur_atr & STANDOUT) && !(atr & STANDOUT))) {
+ (void) tputs(Str(T_me), 1, PUTPURE);
+ cur_atr = 0;
+ }
+ }
+ if ((atr & BOLD) != (cur_atr & BOLD)) {
+ if (atr & BOLD) {
+ if (GoodStr(T_md) && GoodStr(T_me)) {
+ (void) tputs(Str(T_md), 1, PUTPURE);
+ cur_atr |= BOLD;
+ }
+ }
+ else {
+ if (GoodStr(T_md) && GoodStr(T_me)) {
+ (void) tputs(Str(T_me), 1, PUTPURE);
+ if ((cur_atr & STANDOUT) && GoodStr(T_se)) {
+ (void) tputs(Str(T_se), 1, PUTPURE);
+ cur_atr &= ~STANDOUT;
+ }
+ if ((cur_atr & UNDER) && GoodStr(T_ue)) {
+ (void) tputs(Str(T_ue), 1, PUTPURE);
+ cur_atr &= ~UNDER;
+ }
+ cur_atr &= ~BOLD;
+ }
+ }
+ }
+ if ((atr & STANDOUT) != (cur_atr & STANDOUT)) {
+ if (atr & STANDOUT) {
+ if (GoodStr(T_so) && GoodStr(T_se)) {
+ (void) tputs(Str(T_so), 1, PUTPURE);
+ cur_atr |= STANDOUT;
+ }
+ }
+ else {
+ if (GoodStr(T_se)) {
+ (void) tputs(Str(T_se), 1, PUTPURE);
+ cur_atr &= ~STANDOUT;
+ }
+ }
+ }
+ if ((atr & UNDER) != (cur_atr & UNDER)) {
+ if (atr & UNDER) {
+ if (GoodStr(T_us) && GoodStr(T_ue)) {
+ (void) tputs(Str(T_us), 1, PUTPURE);
+ cur_atr |= UNDER;
+ }
+ }
+ else {
+ if (GoodStr(T_ue)) {
+ (void) tputs(Str(T_ue), 1, PUTPURE);
+ cur_atr &= ~UNDER;
+ }
+ }
+ }
+ }
+}
+
+/* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */
+int
+CanWeTab()
+{
+ return (Val(T_pt));
+}
+
+void
+MoveToLine(where) /* move to line <where> (first line == 0) */
+ int where; /* as efficiently as possible; */
+{
+ int del;
+
+ if (where == CursorV)
+ return;
+
+ if (where > TermV) {
+#ifdef DEBUG_SCREEN
+ xprintf("MoveToLine: where is ridiculous: %d\r\n", where);
+ flush();
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+
+ del = where - CursorV;
+
+#ifndef WINNT
+ if (del > 0) {
+ while (del > 0) {
+ if ((T_Margin & MARGIN_AUTO) && Display[CursorV][0] != '\0') {
+ /* move without newline */
+ MoveToChar(TermH - 1);
+ so_write(&Display[CursorV][CursorH], 1); /* updates CursorH/V*/
+ del--;
+ }
+ else {
+ if ((del > 1) && GoodStr(T_DO)) {
+ (void) tputs(tgoto(Str(T_DO), del, del), del, PUTPURE);
+ del = 0;
+ }
+ else {
+ for ( ; del > 0; del--)
+ (void) putraw('\n');
+ CursorH = 0; /* because the \n will become \r\n */
+ }
+ }
+ }
+ }
+ else { /* del < 0 */
+ if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
+ (void) tputs(tgoto(Str(T_UP), -del, -del), -del, PUTPURE);
+ else {
+ int i;
+ if (GoodStr(T_up))
+ for (i = 0; i < -del; i++)
+ (void) tputs(Str(T_up), 1, PUTPURE);
+ }
+ }
+#else /* WINNT */
+ NT_MoveToLineOrChar(del, 1);
+#endif /* !WINNT */
+ CursorV = where; /* now where is here */
+}
+
+void
+MoveToChar(where) /* move to character position (where) */
+ int where;
+{ /* as efficiently as possible */
+#ifndef WINNT
+ int del;
+
+mc_again:
+#endif /* WINNT */
+ if (where == CursorH)
+ return;
+
+ if (where >= TermH) {
+#ifdef DEBUG_SCREEN
+ xprintf("MoveToChar: where is riduculous: %d\r\n", where);
+ flush();
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+
+ if (!where) { /* if where is first column */
+ (void) putraw('\r'); /* do a CR */
+ CursorH = 0;
+ return;
+ }
+
+#ifndef WINNT
+ del = where - CursorH;
+
+ if ((del < -4 || del > 4) && GoodStr(T_ch))
+ /* go there directly */
+ (void) tputs(tgoto(Str(T_ch), where, where), where, PUTPURE);
+ else {
+ int i;
+ if (del > 0) { /* moving forward */
+ if ((del > 4) && GoodStr(T_RI))
+ (void) tputs(tgoto(Str(T_RI), del, del), del, PUTPURE);
+ else {
+ if (T_Tabs) { /* if I can do tabs, use them */
+ if ((CursorH & 0370) != (where & 0370)) {
+ /* if not within tab stop */
+ for (i = (CursorH & 0370); i < (where & 0370); i += 8)
+ (void) putraw('\t'); /* then tab over */
+ CursorH = where & 0370;
+ /* Note: considering that we often want to go to
+ TermH - 1 for the wrapping, it would be nice to
+ optimize this case by tabbing to the last column
+ - but this doesn't work for all terminals! */
+ }
+ }
+ /* it's usually cheaper to just write the chars, so we do. */
+
+ /* NOTE THAT so_write() WILL CHANGE CursorH!!! */
+ so_write(&Display[CursorV][CursorH], where - CursorH);
+
+ }
+ }
+ else { /* del < 0 := moving backward */
+ if ((-del > 4) && GoodStr(T_LE))
+ (void) tputs(tgoto(Str(T_LE), -del, -del), -del, PUTPURE);
+ else { /* can't go directly there */
+ /* if the "cost" is greater than the "cost" from col 0 */
+ if (T_Tabs ? (-del > ((where >> 3) + (where & 07)))
+ : (-del > where)) {
+ (void) putraw('\r'); /* do a CR */
+ CursorH = 0;
+ goto mc_again; /* and try again */
+ }
+ for (i = 0; i < -del; i++)
+ (void) putraw('\b');
+ }
+ }
+ }
+#else /* WINNT */
+ NT_MoveToLineOrChar(where, 0);
+#endif /* !WINNT */
+ CursorH = where; /* now where is here */
+}
+
+void
+so_write(cp, n)
+ register Char *cp;
+ register int n;
+{
+ if (n <= 0)
+ return; /* catch bugs */
+
+ if (n > TermH) {
+#ifdef DEBUG_SCREEN
+ xprintf("so_write: n is riduculous: %d\r\n", n);
+ flush();
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+
+ do {
+ if (*cp & LITERAL) {
+ extern Char *litptr[];
+ Char *d;
+
+#ifdef DEBUG_LITERAL
+ xprintf("so: litnum %d, litptr %x\r\n",
+ *cp & CHAR, litptr[*cp & CHAR]);
+#endif /* DEBUG_LITERAL */
+#if defined(WINNT) && !defined(COLOR_LS_F)
+ {
+ char buf[256], *ptr = &buf[0];
+ for (d = litptr[*cp++ & CHAR]; *d & LITERAL; d++)
+ *ptr++ = (*d & CHAR);
+ flush();
+ set_cons_attr(buf);
+ }
+#else /* !WINNT || COLOR_LS_F */
+ for (d = litptr[*cp++ & CHAR]; *d & LITERAL; d++)
+ (void) putraw(*d & CHAR);
+#endif /* WINNT && !COLOR_LS_F */
+ (void) putraw(*d);
+
+ }
+ else
+ (void) putraw(*cp++);
+ CursorH++;
+ } while (--n);
+
+ if (CursorH >= TermH) { /* wrap? */
+ if (T_Margin & MARGIN_AUTO) { /* yes */
+ CursorH = 0;
+ CursorV++;
+ if (T_Margin & MARGIN_MAGIC) {
+ /* force the wrap to avoid the "magic" situation */
+ Char c;
+ if ((c = Display[CursorV][CursorH]) != '\0')
+ so_write(&c, 1);
+ else
+ (void) putraw(' ');
+ CursorH = 1;
+ }
+ }
+ else /* no wrap, but cursor stays on screen */
+ CursorH = TermH - 1;
+ }
+}
+
+
+void
+DeleteChars(num) /* deletes <num> characters */
+ int num;
+{
+ if (num <= 0)
+ return;
+
+ if (!T_CanDel) {
+#ifdef DEBUG_EDIT
+ xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n"));
+#endif /* DEBUG_EDIT */
+ flush();
+ return;
+ }
+
+ if (num > TermH) {
+#ifdef DEBUG_SCREEN
+ xprintf(CGETS(7, 17, "DeleteChars: num is riduculous: %d\r\n"), num);
+ flush();
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+
+ if (GoodStr(T_DC)) /* if I have multiple delete */
+ if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more expen. */
+ (void) tputs(tgoto(Str(T_DC), num, num), num, PUTPURE);
+ return;
+ }
+
+ if (GoodStr(T_dm)) /* if I have delete mode */
+ (void) tputs(Str(T_dm), 1, PUTPURE);
+
+ if (GoodStr(T_dc)) /* else do one at a time */
+ while (num--)
+ (void) tputs(Str(T_dc), 1, PUTPURE);
+
+ if (GoodStr(T_ed)) /* if I have delete mode */
+ (void) tputs(Str(T_ed), 1, PUTPURE);
+}
+
+void
+Insert_write(cp, num) /* Puts terminal in insert character mode, */
+ register Char *cp;
+ register int num; /* or inserts num characters in the line */
+{
+ if (num <= 0)
+ return;
+ if (!T_CanIns) {
+#ifdef DEBUG_EDIT
+ xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n"));
+#endif /* DEBUG_EDIT */
+ flush();
+ return;
+ }
+
+ if (num > TermH) {
+#ifdef DEBUG_SCREEN
+ xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num);
+ flush();
+#endif /* DEBUG_SCREEN */
+ return;
+ }
+
+ if (GoodStr(T_IC)) /* if I have multiple insert */
+ if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expen. */
+ (void) tputs(tgoto(Str(T_IC), num, num), num, PUTPURE);
+ so_write(cp, num); /* this updates CursorH/V */
+ return;
+ }
+
+ if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
+ (void) tputs(Str(T_im), 1, PUTPURE);
+
+ CursorH += num;
+ do
+ (void) putraw(*cp++);
+ while (--num);
+
+ if (GoodStr(T_ip)) /* have to make num chars insert */
+ (void) tputs(Str(T_ip), 1, PUTPURE);
+
+ (void) tputs(Str(T_ei), 1, PUTPURE);
+ return;
+ }
+
+ do {
+ if (GoodStr(T_ic)) /* have to make num chars insert */
+ (void) tputs(Str(T_ic), 1, PUTPURE); /* insert a char */
+
+ (void) putraw(*cp++);
+
+ CursorH++;
+
+ if (GoodStr(T_ip)) /* have to make num chars insert */
+ (void) tputs(Str(T_ip), 1, PUTPURE);/* pad the inserted char */
+
+ } while (--num);
+
+}
+
+void
+ClearEOL(num) /* clear to end of line. There are num */
+ int num; /* characters to clear */
+{
+ register int i;
+
+ if (num <= 0)
+ return;
+
+ if (T_CanCEOL && GoodStr(T_ce))
+ (void) tputs(Str(T_ce), 1, PUTPURE);
+ else {
+ for (i = 0; i < num; i++)
+ (void) putraw(' ');
+ CursorH += num; /* have written num spaces */
+ }
+}
+
+void
+ClearScreen()
+{ /* clear the whole screen and home */
+ if (GoodStr(T_cl))
+ /* send the clear screen code */
+ (void) tputs(Str(T_cl), Val(T_li), PUTPURE);
+ else if (GoodStr(T_ho) && GoodStr(T_cd)) {
+ (void) tputs(Str(T_ho), Val(T_li), PUTPURE); /* home */
+ /* clear to bottom of screen */
+ (void) tputs(Str(T_cd), Val(T_li), PUTPURE);
+ }
+ else {
+ (void) putraw('\r');
+ (void) putraw('\n');
+ }
+}
+
+void
+SoundBeep()
+{ /* produce a sound */
+ beep_cmd ();
+ if (adrof(STRnobeep))
+ return;
+
+ if (GoodStr(T_vb) && adrof(STRvisiblebell))
+ (void) tputs(Str(T_vb), 1, PUTPURE); /* visible bell */
+ else if (GoodStr(T_bl))
+ /* what termcap says we should use */
+ (void) tputs(Str(T_bl), 1, PUTPURE);
+ else
+#ifndef WINNT
+ (void) putraw(CTL_ESC('\007')); /* an ASCII bell; ^G */
+#else /* WINNT */
+ MessageBeep(MB_ICONQUESTION);
+#endif /* !WINNT */
+}
+
+void
+ClearToBottom()
+{ /* clear to the bottom of the screen */
+ if (GoodStr(T_cd))
+ (void) tputs(Str(T_cd), Val(T_li), PUTPURE);
+ else if (GoodStr(T_ce))
+ (void) tputs(Str(T_ce), Val(T_li), PUTPURE);
+}
+
+void
+GetTermCaps()
+{ /* read in the needed terminal capabilites */
+ register int i;
+ char *ptr;
+ char buf[TC_BUFSIZE];
+ static char bp[TC_BUFSIZE];
+ char *area;
+ struct termcapstr *t;
+
+
+#ifdef SIG_WINDOW
+# ifdef BSDSIGS
+ sigmask_t omask;
+# endif /* BSDSIGS */
+ int lins, cols;
+
+ /* don't want to confuse things here */
+# ifdef BSDSIGS
+ omask = sigblock(sigmask(SIG_WINDOW)) & ~sigmask(SIG_WINDOW);
+# else /* BSDSIGS */
+ (void) sighold(SIG_WINDOW);
+# endif /* BSDSIGS */
+#endif /* SIG_WINDOW */
+ area = buf;
+
+ GotTermCaps = 1;
+
+ setname("gettermcaps");
+ ptr = getenv("TERM");
+
+#ifdef apollo
+ /*
+ * If we are on a pad, we pretend that we are dumb. Otherwise the termcap
+ * library will put us in a weird screen mode, thinking that we are going
+ * to use curses
+ */
+ if (isapad())
+ ptr = "dumb";
+#endif /* apollo */
+
+ if (!ptr || !ptr[0] || !strcmp(ptr, "wm") || !strcmp(ptr,"dmx"))
+ ptr = "dumb";
+
+ setzero(bp, TC_BUFSIZE);
+
+ i = tgetent(bp, ptr);
+ if (i <= 0) {
+ if (i == -1) {
+#if (SYSVREL == 0) || defined(IRIS3D)
+ xprintf(CGETS(7, 20, "%s: Cannot open /etc/termcap.\n"), progname);
+ }
+ else if (i == 0) {
+#endif /* SYSVREL */
+ xprintf(CGETS(7, 21,
+ "%s: No entry for terminal type \"%s\"\n"), progname,
+ getenv("TERM"));
+ }
+ xprintf(CGETS(7, 22, "%s: using dumb terminal settings.\n"), progname);
+ Val(T_co) = 80; /* do a dumb terminal */
+ Val(T_pt) = Val(T_km) = Val(T_li) = 0;
+ for (t = tstr; t->name != NULL; t++)
+ TCalloc(t, NULL);
+ }
+ else {
+ /* Can we tab */
+ Val(T_pt) = tgetflag("pt") && !tgetflag("xt");
+ /* do we have a meta? */
+ Val(T_km) = (tgetflag("km") || tgetflag("MT"));
+ Val(T_am) = tgetflag("am");
+ Val(T_xn) = tgetflag("xn");
+ Val(T_co) = tgetnum("co");
+ Val(T_li) = tgetnum("li");
+ for (t = tstr; t->name != NULL; t++)
+ TCalloc(t, tgetstr(t->name, &area));
+ }
+ if (Val(T_co) < 2)
+ Val(T_co) = 80; /* just in case */
+ if (Val(T_li) < 1)
+ Val(T_li) = 24;
+
+ T_Cols = (Char) Val(T_co);
+ T_Lines = (Char) Val(T_li);
+ if (T_Tabs)
+ T_Tabs = (Char) Val(T_pt);
+ T_HasMeta = (Char) Val(T_km);
+ T_Margin = (Char) Val(T_am) ? MARGIN_AUTO : 0;
+ T_Margin |= (Char) Val(T_xn) ? MARGIN_MAGIC : 0;
+ T_CanCEOL = GoodStr(T_ce);
+ T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
+ T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
+ T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
+ if (GoodStr(T_me) && GoodStr(T_ue))
+ me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
+ else
+ me_all = 0;
+ if (GoodStr(T_me) && GoodStr(T_se))
+ me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
+
+
+#ifdef DEBUG_SCREEN
+ if (!T_CanUP) {
+ xprintf(CGETS(7, 23, "%s: WARNING: Your terminal cannot move up.\n",
+ progname));
+ xprintf(CGETS(7, 24, "Editing may be odd for long lines.\n"));
+ }
+ if (!T_CanCEOL)
+ xprintf(CGETS(7, 25, "no clear EOL capability.\n"));
+ if (!T_CanDel)
+ xprintf(CGETS(7, 26, "no delete char capability.\n"));
+ if (!T_CanIns)
+ xprintf(CGETS(7, 27, "no insert char capability.\n"));
+#endif /* DEBUG_SCREEN */
+
+
+
+#ifdef SIG_WINDOW
+ (void) GetSize(&lins, &cols); /* get the correct window size */
+ ChangeSize(lins, cols);
+
+# ifdef BSDSIGS
+ (void) sigsetmask(omask); /* can change it again */
+# else /* BSDSIGS */
+ (void) sigrelse(SIG_WINDOW);
+# endif /* BSDSIGS */
+#else /* SIG_WINDOW */
+ ChangeSize(Val(T_li), Val(T_co));
+#endif /* SIG_WINDOW */
+
+ BindArrowKeys();
+}
+
+#ifdef SIG_WINDOW
+/* GetSize():
+ * Return the new window size in lines and cols, and
+ * true if the size was changed. This can fail if SHIN
+ * is not a tty, but it will work in most cases.
+ */
+int
+GetSize(lins, cols)
+ int *lins, *cols;
+{
+ *cols = Val(T_co);
+ *lins = Val(T_li);
+
+#ifdef TIOCGWINSZ
+# define KNOWsize
+# ifndef lint
+ {
+ struct winsize ws; /* from 4.3 */
+
+ if (ioctl(SHIN, TIOCGWINSZ, (ioctl_t) &ws) != -1) {
+ if (ws.ws_col)
+ *cols = ws.ws_col;
+ if (ws.ws_row)
+ *lins = ws.ws_row;
+ }
+ }
+# endif /* !lint */
+#else /* TIOCGWINSZ */
+# ifdef TIOCGSIZE
+# define KNOWsize
+ {
+ struct ttysize ts; /* from Sun */
+
+ if (ioctl(SHIN, TIOCGSIZE, (ioctl_t) &ts) != -1) {
+ if (ts.ts_cols)
+ *cols = ts.ts_cols;
+ if (ts.ts_lines)
+ *lins = ts.ts_lines;
+ }
+ }
+# endif /* TIOCGSIZE */
+#endif /* TIOCGWINSZ */
+
+ return (Val(T_co) != *cols || Val(T_li) != *lins);
+}
+
+#endif /* SIGWINDOW */
+
+void
+ChangeSize(lins, cols)
+ int lins, cols;
+{
+ /*
+ * Just in case
+ */
+ Val(T_co) = (cols < 2) ? 80 : cols;
+ Val(T_li) = (lins < 1) ? 24 : lins;
+
+#ifdef WINNT
+ nt_set_size(lins,cols);
+#endif /* WINNT */
+#ifdef KNOWsize
+ /*
+ * We want to affect the environment only when we have a valid
+ * setup, not when we get bad settings. Consider the following scenario:
+ * We just logged in, and we have not initialized the editor yet.
+ * We reset termcap with tset, and not $TERMCAP has the right
+ * terminal size. But since the editor is not initialized yet, and
+ * the kernel's notion of the terminal size might be wrong we arrive
+ * here with lines = columns = 0. If we reset the environment we lose
+ * our only chance to get the window size right.
+ */
+ if (Val(T_co) == cols && Val(T_li) == lins) {
+ Char buf[10];
+ char *tptr;
+
+ if (getenv("COLUMNS")) {
+ (void) Itoa(Val(T_co), buf, 0, 0);
+ tsetenv(STRCOLUMNS, buf);
+ }
+
+ if (getenv("LINES")) {
+ (void) Itoa(Val(T_li), buf, 0, 0);
+ tsetenv(STRLINES, buf);
+ }
+
+ if ((tptr = getenv("TERMCAP")) != NULL) {
+ /* Leave 64 characters slop in case we enlarge the termcap string */
+ Char termcap[1024+64], backup[1024+64], *ptr;
+ int i;
+
+ ptr = str2short(tptr);
+ (void) Strncpy(termcap, ptr, 1024);
+ termcap[1023] = '\0';
+
+ /* update termcap string; first do columns */
+ buf[0] = 'c';
+ buf[1] = 'o';
+ buf[2] = '#';
+ buf[3] = '\0';
+ if ((ptr = Strstr(termcap, buf)) == NULL) {
+ (void) Strcpy(backup, termcap);
+ }
+ else {
+ i = (int) (ptr - termcap + Strlen(buf));
+ (void) Strncpy(backup, termcap, (size_t) i);
+ backup[i] = '\0';
+ (void) Itoa(Val(T_co), buf, 0, 0);
+ (void) Strcat(backup + i, buf);
+ ptr = Strchr(ptr, ':');
+ (void) Strcat(backup, ptr);
+ }
+
+ /* now do lines */
+ buf[0] = 'l';
+ buf[1] = 'i';
+ buf[2] = '#';
+ buf[3] = '\0';
+ if ((ptr = Strstr(backup, buf)) == NULL) {
+ (void) Strcpy(termcap, backup);
+ }
+ else {
+ i = (int) (ptr - backup + Strlen(buf));
+ (void) Strncpy(termcap, backup, (size_t) i);
+ termcap[i] = '\0';
+ (void) Itoa(Val(T_li), buf, 0, 0);
+ (void) Strcat(termcap, buf);
+ ptr = Strchr(ptr, ':');
+ (void) Strcat(termcap, ptr);
+ }
+ /*
+ * Chop the termcap string at 1024 characters to avoid core-dumps
+ * in the termcap routines
+ */
+ termcap[1023] = '\0';
+ tsetenv(STRTERMCAP, termcap);
+ }
+ }
+#endif /* KNOWsize */
+
+ ReBufferDisplay(); /* re-make display buffers */
+ ClearDisp();
+}
diff --git a/contrib/tcsh/ed.term.c b/contrib/tcsh/ed.term.c
new file mode 100644
index 0000000..9e73064
--- /dev/null
+++ b/contrib/tcsh/ed.term.c
@@ -0,0 +1,1150 @@
+/* $Header: /src/pub/tcsh/ed.term.c,v 1.24 1999/08/12 14:19:23 christos Exp $ */
+/*
+ * ed.term.c: Low level terminal interface
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+#ifndef WINNT
+
+RCSID("$Id: ed.term.c,v 1.24 1999/08/12 14:19:23 christos Exp $")
+
+#include "ed.h"
+#include "ed.term.h"
+
+int didsetty = 0;
+ttyperm_t ttylist = {
+ {
+#if defined(POSIX) || defined(TERMIO)
+ { "iflag:", ICRNL, (INLCR|IGNCR) },
+ { "oflag:", (OPOST|ONLCR), ONLRET },
+ { "cflag:", 0, 0 },
+ { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
+ (NOFLSH|ECHONL|EXTPROC|FLUSHO|IDEFAULT) },
+#else /* GSTTY */
+ { "nrmal:", (ECHO|CRMOD|ANYP), (CBREAK|RAW|LCASE|VTDELAY|ALLDELAY) },
+ { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) },
+#endif /* POSIX || TERMIO */
+ { "chars:", 0, 0 },
+ },
+ {
+#if defined(POSIX) || defined(TERMIO)
+ { "iflag:", (INLCR|ICRNL), IGNCR },
+ { "oflag:", (OPOST|ONLCR), ONLRET },
+ { "cflag:", 0, 0 },
+ { "lflag:", ISIG,
+ (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO|
+ IDEFAULT) },
+#else /* GSTTY */
+ { "nrmal:", (CBREAK|CRMOD|ANYP), (RAW|ECHO|LCASE|VTDELAY|ALLDELAY) },
+ { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) },
+#endif /* POSIX || TERMIO */
+ { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
+ C_SH(C_WERASE)|C_SH(C_REPRINT)|C_SH(C_SUSP)|C_SH(C_DSUSP)|
+ C_SH(C_EOF)|C_SH(C_EOL)|C_SH(C_DISCARD)|C_SH(C_PGOFF)|
+ C_SH(C_KILL2)|C_SH(C_PAGE)|C_SH(C_STATUS)|C_SH(C_LNEXT)),
+ 0 }
+ },
+ {
+#if defined(POSIX) || defined(TERMIO)
+ { "iflag:", 0, IXON | IXOFF },
+ { "oflag:", 0, 0 },
+ { "cflag:", 0, 0 },
+ { "lflag:", 0, ISIG | IEXTEN },
+#else /* GSTTY */
+ { "nrmal:", RAW, CBREAK },
+ { "local:", 0, 0 },
+#endif /* POSIX || TERMIO */
+ { "chars:", 0, 0 },
+ }
+};
+
+static struct tcshmodes {
+ char *m_name;
+#ifdef SOLARIS2
+ unsigned long m_value;
+#else /* !SOLARIS2 */
+ int m_value;
+#endif /* SOLARIS2 */
+ int m_type;
+} modelist[] = {
+#if defined(POSIX) || defined(TERMIO)
+
+# ifdef IGNBRK
+ { "ignbrk", IGNBRK, M_INPUT },
+# endif /* IGNBRK */
+# ifdef BRKINT
+ { "brkint", BRKINT, M_INPUT },
+# endif /* BRKINT */
+# ifdef IGNPAR
+ { "ignpar", IGNPAR, M_INPUT },
+# endif /* IGNPAR */
+# ifdef PARMRK
+ { "parmrk", PARMRK, M_INPUT },
+# endif /* PARMRK */
+# ifdef INPCK
+ { "inpck", INPCK, M_INPUT },
+# endif /* INPCK */
+# ifdef ISTRIP
+ { "istrip", ISTRIP, M_INPUT },
+# endif /* ISTRIP */
+# ifdef INLCR
+ { "inlcr", INLCR, M_INPUT },
+# endif /* INLCR */
+# ifdef IGNCR
+ { "igncr", IGNCR, M_INPUT },
+# endif /* IGNCR */
+# ifdef ICRNL
+ { "icrnl", ICRNL, M_INPUT },
+# endif /* ICRNL */
+# ifdef IUCLC
+ { "iuclc", IUCLC, M_INPUT },
+# endif /* IUCLC */
+# ifdef IXON
+ { "ixon", IXON, M_INPUT },
+# endif /* IXON */
+# ifdef IXANY
+ { "ixany", IXANY, M_INPUT },
+# endif /* IXANY */
+# ifdef IXOFF
+ { "ixoff", IXOFF, M_INPUT },
+# endif /* IXOFF */
+# ifdef IMAXBEL
+ { "imaxbel",IMAXBEL,M_INPUT },
+# endif /* IMAXBEL */
+# ifdef IDELETE
+ { "idelete",IDELETE,M_INPUT },
+# endif /* IDELETE */
+
+# ifdef OPOST
+ { "opost", OPOST, M_OUTPUT },
+# endif /* OPOST */
+# ifdef OLCUC
+ { "olcuc", OLCUC, M_OUTPUT },
+# endif /* OLCUC */
+# ifdef ONLCR
+ { "onlcr", ONLCR, M_OUTPUT },
+# endif /* ONLCR */
+# ifdef OCRNL
+ { "ocrnl", OCRNL, M_OUTPUT },
+# endif /* OCRNL */
+# ifdef ONOCR
+ { "onocr", ONOCR, M_OUTPUT },
+# endif /* ONOCR */
+# ifdef ONOEOT
+ { "onoeot", ONOEOT, M_OUTPUT },
+# endif /* ONOEOT */
+# ifdef ONLRET
+ { "onlret", ONLRET, M_OUTPUT },
+# endif /* ONLRET */
+# ifdef OFILL
+ { "ofill", OFILL, M_OUTPUT },
+# endif /* OFILL */
+# ifdef OFDEL
+ { "ofdel", OFDEL, M_OUTPUT },
+# endif /* OFDEL */
+# ifdef NLDLY
+ { "nldly", NLDLY, M_OUTPUT },
+# endif /* NLDLY */
+# ifdef CRDLY
+ { "crdly", CRDLY, M_OUTPUT },
+# endif /* CRDLY */
+# ifdef TABDLY
+ { "tabdly", TABDLY, M_OUTPUT },
+# endif /* TABDLY */
+# ifdef XTABS
+ { "xtabs", XTABS, M_OUTPUT },
+# endif /* XTABS */
+# ifdef BSDLY
+ { "bsdly", BSDLY, M_OUTPUT },
+# endif /* BSDLY */
+# ifdef VTDLY
+ { "vtdly", VTDLY, M_OUTPUT },
+# endif /* VTDLY */
+# ifdef FFDLY
+ { "ffdly", FFDLY, M_OUTPUT },
+# endif /* FFDLY */
+# ifdef PAGEOUT
+ { "pageout",PAGEOUT,M_OUTPUT },
+# endif /* PAGEOUT */
+# ifdef WRAP
+ { "wrap", WRAP, M_OUTPUT },
+# endif /* WRAP */
+
+# ifdef CIGNORE
+ { "cignore",CIGNORE,M_CONTROL },
+# endif /* CBAUD */
+# ifdef CBAUD
+ { "cbaud", CBAUD, M_CONTROL },
+# endif /* CBAUD */
+# ifdef CSTOPB
+ { "cstopb", CSTOPB, M_CONTROL },
+# endif /* CSTOPB */
+# ifdef CREAD
+ { "cread", CREAD, M_CONTROL },
+# endif /* CREAD */
+# ifdef PARENB
+ { "parenb", PARENB, M_CONTROL },
+# endif /* PARENB */
+# ifdef PARODD
+ { "parodd", PARODD, M_CONTROL },
+# endif /* PARODD */
+# ifdef HUPCL
+ { "hupcl", HUPCL, M_CONTROL },
+# endif /* HUPCL */
+# ifdef CLOCAL
+ { "clocal", CLOCAL, M_CONTROL },
+# endif /* CLOCAL */
+# ifdef LOBLK
+ { "loblk", LOBLK, M_CONTROL },
+# endif /* LOBLK */
+# ifdef CIBAUD
+ { "cibaud", CIBAUD, M_CONTROL },
+# endif /* CIBAUD */
+# ifdef CRTSCTS
+# ifdef CCTS_OFLOW
+ { "ccts_oflow",CCTS_OFLOW,M_CONTROL },
+# else
+ { "crtscts",CRTSCTS,M_CONTROL },
+# endif /* CCTS_OFLOW */
+# endif /* CRTSCTS */
+# ifdef CRTS_IFLOW
+ { "crts_iflow",CRTS_IFLOW,M_CONTROL },
+# endif /* CRTS_IFLOW */
+# ifdef MDMBUF
+ { "mdmbuf", MDMBUF, M_CONTROL },
+# endif /* MDMBUF */
+# ifdef RCV1EN
+ { "rcv1en", RCV1EN, M_CONTROL },
+# endif /* RCV1EN */
+# ifdef XMT1EN
+ { "xmt1en", XMT1EN, M_CONTROL },
+# endif /* XMT1EN */
+
+# ifdef ISIG
+ { "isig", ISIG, M_LINED },
+# endif /* ISIG */
+# ifdef ICANON
+ { "icanon", ICANON, M_LINED },
+# endif /* ICANON */
+# ifdef XCASE
+ { "xcase", XCASE, M_LINED },
+# endif /* XCASE */
+# ifdef ECHO
+ { "echo", ECHO, M_LINED },
+# endif /* ECHO */
+# ifdef ECHOE
+ { "echoe", ECHOE, M_LINED },
+# endif /* ECHOE */
+# ifdef ECHOK
+ { "echok", ECHOK, M_LINED },
+# endif /* ECHOK */
+# ifdef ECHONL
+ { "echonl", ECHONL, M_LINED },
+# endif /* ECHONL */
+# ifdef NOFLSH
+ { "noflsh", NOFLSH, M_LINED },
+# endif /* NOFLSH */
+# ifdef TOSTOP
+ { "tostop", TOSTOP, M_LINED },
+# endif /* TOSTOP */
+# ifdef ECHOCTL
+ { "echoctl",ECHOCTL,M_LINED },
+# endif /* ECHOCTL */
+# ifdef ECHOPRT
+ { "echoprt",ECHOPRT,M_LINED },
+# endif /* ECHOPRT */
+# ifdef ECHOKE
+ { "echoke", ECHOKE, M_LINED },
+# endif /* ECHOKE */
+# ifdef DEFECHO
+ { "defecho",DEFECHO,M_LINED },
+# endif /* DEFECHO */
+# ifdef FLUSHO
+ { "flusho", FLUSHO, M_LINED },
+# endif /* FLUSHO */
+# ifdef PENDIN
+ { "pendin", PENDIN, M_LINED },
+# endif /* PENDIN */
+# ifdef IEXTEN
+ { "iexten", IEXTEN, M_LINED },
+# endif /* IEXTEN */
+# ifdef NOKERNINFO
+ { "nokerninfo",NOKERNINFO,M_LINED },
+# endif /* NOKERNINFO */
+# ifdef ALTWERASE
+ { "altwerase",ALTWERASE,M_LINED },
+# endif /* ALTWERASE */
+# ifdef EXTPROC
+ { "extproc",EXTPROC,M_LINED },
+# endif /* EXTPROC */
+# ifdef IDEFAULT
+ { "idefault",IDEFAULT,M_LINED },
+# endif /* IDEFAULT */
+
+#else /* GSTTY */
+
+# ifdef TANDEM
+ { "tandem", TANDEM, M_CONTROL },
+# endif /* TANDEM */
+# ifdef CBREAK
+ { "cbreak", CBREAK, M_CONTROL },
+# endif /* CBREAK */
+# ifdef LCASE
+ { "lcase", LCASE, M_CONTROL },
+# endif /* LCASE */
+# ifdef ECHO
+ { "echo", ECHO, M_CONTROL },
+# endif /* ECHO */
+# ifdef CRMOD
+ { "crmod", CRMOD, M_CONTROL },
+# endif /* CRMOD */
+# ifdef RAW
+ { "raw", RAW, M_CONTROL },
+# endif /* RAW */
+# ifdef ODDP
+ { "oddp", ODDP, M_CONTROL },
+# endif /* ODDP */
+# ifdef EVENP
+ { "evenp", EVENP, M_CONTROL },
+# endif /* EVENP */
+# ifdef ANYP
+ { "anyp", ANYP, M_CONTROL },
+# endif /* ANYP */
+# ifdef NLDELAY
+ { "nldelay",NLDELAY,M_CONTROL },
+# endif /* NLDELAY */
+# ifdef TBDELAY
+ { "tbdelay",TBDELAY,M_CONTROL },
+# endif /* TBDELAY */
+# ifdef XTABS
+ { "xtabs", XTABS, M_CONTROL },
+# endif /* XTABS */
+# ifdef CRDELAY
+ { "crdelay",CRDELAY,M_CONTROL },
+# endif /* CRDELAY */
+# ifdef VTDELAY
+ { "vtdelay",VTDELAY,M_CONTROL },
+# endif /* VTDELAY */
+# ifdef BSDELAY
+ { "bsdelay",BSDELAY,M_CONTROL },
+# endif /* BSDELAY */
+# ifdef CRTBS
+ { "crtbs", CRTBS, M_CONTROL },
+# endif /* CRTBS */
+# ifdef PRTERA
+ { "prtera", PRTERA, M_CONTROL },
+# endif /* PRTERA */
+# ifdef CRTERA
+ { "crtera", CRTERA, M_CONTROL },
+# endif /* CRTERA */
+# ifdef TILDE
+ { "tilde", TILDE, M_CONTROL },
+# endif /* TILDE */
+# ifdef MDMBUF
+ { "mdmbuf", MDMBUF, M_CONTROL },
+# endif /* MDMBUF */
+# ifdef LITOUT
+ { "litout", LITOUT, M_CONTROL },
+# endif /* LITOUT */
+# ifdef TOSTOP
+ { "tostop", TOSTOP, M_CONTROL },
+# endif /* TOSTOP */
+# ifdef FLUSHO
+ { "flusho", FLUSHO, M_CONTROL },
+# endif /* FLUSHO */
+# ifdef NOHANG
+ { "nohang", NOHANG, M_CONTROL },
+# endif /* NOHANG */
+# ifdef L001000
+ { "l001000",L001000,M_CONTROL },
+# endif /* L001000 */
+# ifdef CRTKIL
+ { "crtkil", CRTKIL, M_CONTROL },
+# endif /* CRTKIL */
+# ifdef PASS8
+ { "pass8", PASS8, M_CONTROL },
+# endif /* PASS8 */
+# ifdef CTLECH
+ { "ctlech", CTLECH, M_CONTROL },
+# endif /* CTLECH */
+# ifdef PENDIN
+ { "pendin", PENDIN, M_CONTROL },
+# endif /* PENDIN */
+# ifdef DECCTQ
+ { "decctq", DECCTQ, M_CONTROL },
+# endif /* DECCTQ */
+# ifdef NOFLSH
+ { "noflsh", NOFLSH, M_CONTROL },
+# endif /* NOFLSH */
+
+# ifdef LCRTBS
+ { "lcrtbs", LCRTBS, M_LOCAL },
+# endif /* LCRTBS */
+# ifdef LPRTERA
+ { "lprtera",LPRTERA,M_LOCAL },
+# endif /* LPRTERA */
+# ifdef LCRTERA
+ { "lcrtera",LCRTERA,M_LOCAL },
+# endif /* LCRTERA */
+# ifdef LTILDE
+ { "ltilde", LTILDE, M_LOCAL },
+# endif /* LTILDE */
+# ifdef LMDMBUF
+ { "lmdmbuf",LMDMBUF,M_LOCAL },
+# endif /* LMDMBUF */
+# ifdef LLITOUT
+ { "llitout",LLITOUT,M_LOCAL },
+# endif /* LLITOUT */
+# ifdef LTOSTOP
+ { "ltostop",LTOSTOP,M_LOCAL },
+# endif /* LTOSTOP */
+# ifdef LFLUSHO
+ { "lflusho",LFLUSHO,M_LOCAL },
+# endif /* LFLUSHO */
+# ifdef LNOHANG
+ { "lnohang",LNOHANG,M_LOCAL },
+# endif /* LNOHANG */
+# ifdef LCRTKIL
+ { "lcrtkil",LCRTKIL,M_LOCAL },
+# endif /* LCRTKIL */
+# ifdef LPASS8
+ { "lpass8", LPASS8, M_LOCAL },
+# endif /* LPASS8 */
+# ifdef LCTLECH
+ { "lctlech",LCTLECH,M_LOCAL },
+# endif /* LCTLECH */
+# ifdef LPENDIN
+ { "lpendin",LPENDIN,M_LOCAL },
+# endif /* LPENDIN */
+# ifdef LDECCTQ
+ { "ldecctq",LDECCTQ,M_LOCAL },
+# endif /* LDECCTQ */
+# ifdef LNOFLSH
+ { "lnoflsh",LNOFLSH,M_LOCAL },
+# endif /* LNOFLSH */
+
+#endif /* POSIX || TERMIO */
+# if defined(VINTR) || defined(TIOCGETC)
+ { "intr", C_SH(C_INTR), M_CHAR },
+# endif /* VINTR */
+# if defined(VQUIT) || defined(TIOCGETC)
+ { "quit", C_SH(C_QUIT), M_CHAR },
+# endif /* VQUIT */
+# if defined(VERASE) || defined(TIOCGETP)
+ { "erase", C_SH(C_ERASE), M_CHAR },
+# endif /* VERASE */
+# if defined(VKILL) || defined(TIOCGETP)
+ { "kill", C_SH(C_KILL), M_CHAR },
+# endif /* VKILL */
+# if defined(VEOF) || defined(TIOCGETC)
+ { "eof", C_SH(C_EOF), M_CHAR },
+# endif /* VEOF */
+# if defined(VEOL)
+ { "eol", C_SH(C_EOL), M_CHAR },
+# endif /* VEOL */
+# if defined(VEOL2)
+ { "eol2", C_SH(C_EOL2), M_CHAR },
+# endif /* VEOL2 */
+# if defined(VSWTCH)
+ { "swtch", C_SH(C_SWTCH), M_CHAR },
+# endif /* VSWTCH */
+# if defined(VDSWTCH)
+ { "dswtch", C_SH(C_DSWTCH), M_CHAR },
+# endif /* VDSWTCH */
+# if defined(VERASE2)
+ { "erase2", C_SH(C_ERASE2), M_CHAR },
+# endif /* VERASE2 */
+# if defined(VSTART) || defined(TIOCGETC)
+ { "start", C_SH(C_START), M_CHAR },
+# endif /* VSTART */
+# if defined(VSTOP) || defined(TIOCGETC)
+ { "stop", C_SH(C_STOP), M_CHAR },
+# endif /* VSTOP */
+# if defined(VWERASE) || defined(TIOCGLTC)
+ { "werase", C_SH(C_WERASE), M_CHAR },
+# endif /* VWERASE */
+# if defined(VSUSP) || defined(TIOCGLTC)
+ { "susp", C_SH(C_SUSP), M_CHAR },
+# endif /* VSUSP */
+# if defined(VDSUSP) || defined(TIOCGLTC)
+ { "dsusp", C_SH(C_DSUSP), M_CHAR },
+# endif /* VDSUSP */
+# if defined(VREPRINT) || defined(TIOCGLTC)
+ { "reprint", C_SH(C_REPRINT),M_CHAR },
+# endif /* WREPRINT */
+# if defined(VDISCARD) || defined(TIOCGLTC)
+ { "discard", C_SH(C_DISCARD),M_CHAR },
+# endif /* VDISCARD */
+# if defined(VLNEXT) || defined(TIOCGLTC)
+ { "lnext", C_SH(C_LNEXT), M_CHAR },
+# endif /* VLNEXT */
+# if defined(VSTATUS) || defined(TIOCGPAGE)
+ { "status", C_SH(C_STATUS), M_CHAR },
+# endif /* VSTATUS */
+# if defined(VPAGE) || defined(TIOCGPAGE)
+ { "page", C_SH(C_PAGE), M_CHAR },
+# endif /* VPAGE */
+# if defined(VPGOFF) || defined(TIOCGPAGE)
+ { "pgoff", C_SH(C_PGOFF), M_CHAR },
+# endif /* VPGOFF */
+# if defined(VKILL2)
+ { "kill2", C_SH(C_KILL2), M_CHAR },
+# endif /* VKILL2 */
+# if defined(VBRK) || defined(TIOCGETC)
+ { "brk", C_SH(C_BRK), M_CHAR },
+# endif /* VBRK */
+# if defined(VMIN)
+ { "min", C_SH(C_MIN), M_CHAR },
+# endif /* VMIN */
+# if defined(VTIME)
+ { "time", C_SH(C_TIME), M_CHAR },
+# endif /* VTIME */
+ { NULL, 0, -1 },
+};
+
+/*
+ * If EAGAIN and/or EWOULDBLOCK are defined, we can't just return -1 in all
+ * situations where ioctl() does.
+ *
+ * On AIX 4.1.5 (and presumably some other versions and OSes), as you
+ * perform the manual test suite in the README, if you 'bg' vi immediately
+ * after suspending it, all is well, but if you wait a few seconds,
+ * usually ioctl() will return -1, which previously caused tty_setty() to
+ * return -1, causing Rawmode() to return -1, causing Inputl() to return
+ * 0, causing bgetc() to return -1, causing readc() to set doneinp to 1,
+ * causing process() to break out of the main loop, causing tcsh to exit
+ * prematurely.
+ *
+ * If ioctl()'s errno is EAGAIN/EWOULDBLOCK ("Resource temporarily
+ * unavailable"), apparently the tty is being messed with by the OS and we
+ * need to try again. In my testing, ioctl() was never called more than
+ * twice in a row.
+ *
+ * -- Dan Harkless <dan@wave.eng.uci.edu>
+ *
+ * So, I retry all ioctl's in case others happen to fail too (christos)
+ */
+
+#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+# define OKERROR(e) (((e) == EAGAIN) || ((e) == EWOULDBLOCK) || ((e) == EINTR))
+#elif defined(EGAIN)
+# define OKERROR(e) (((e) == EAGAIN) || ((e) == EINTR))
+#elif defined(EWOULDBLOCK)
+# define OKERROR(e) (((e) == EWOULDBLOCK) || ((e) == EINTR))
+#else
+# define OKERROR(e) ((e) == EINTR)
+#endif
+
+/* Retry a system call */
+#define RETRY(x) \
+ for (;;) \
+ if ((x) == -1) { \
+ if (OKERROR(errno)) \
+ continue; \
+ else \
+ return -1; \
+ } \
+ else \
+ break \
+
+/*ARGSUSED*/
+void
+dosetty(v, t)
+ Char **v;
+ struct command *t;
+{
+ struct tcshmodes *m;
+ char x, *d;
+ int aflag = 0;
+ Char *s;
+ int z = EX_IO;
+ char cmdname[BUFSIZE];
+
+ USE(t);
+ setname(strcpy(cmdname, short2str(*v++)));
+
+ while (v && *v && v[0][0] == '-' && v[0][2] == '\0')
+ switch (v[0][1]) {
+ case 'a':
+ aflag++;
+ v++;
+ break;
+ case 'd':
+ v++;
+ z = ED_IO;
+ break;
+ case 'x':
+ v++;
+ z = EX_IO;
+ break;
+ case 'q':
+ v++;
+ z = QU_IO;
+ break;
+ default:
+ stderror(ERR_NAME | ERR_SYSTEM, short2str(v[0]),
+ CGETS(8, 1, "Unknown switch"));
+ break;
+ }
+
+ didsetty = 1;
+ if (!v || !*v) {
+ int i = -1;
+ int len = 0, st = 0, cu;
+ for (m = modelist; m->m_name; m++) {
+ if (m->m_type != i) {
+ xprintf("%s%s", i != -1 ? "\n" : "",
+ ttylist[z][m->m_type].t_name);
+ i = m->m_type;
+ st = len = strlen(ttylist[z][m->m_type].t_name);
+ }
+
+ x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0';
+ x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x;
+
+ if (x != '\0' || aflag) {
+ cu = strlen(m->m_name) + (x != '\0') + 1;
+ if (len + cu >= T_Cols) {
+ xprintf("\n%*s", st, "");
+ len = st + cu;
+ }
+ else
+ len += cu;
+ if (x != '\0')
+ xprintf("%c%s ", x, m->m_name);
+ else
+ xprintf("%s ", m->m_name);
+ }
+ }
+ xputchar('\n');
+ return;
+ }
+ while (v && (s = *v++)) {
+ switch (*s) {
+ case '+':
+ case '-':
+ x = *s++;
+ break;
+ default:
+ x = '\0';
+ break;
+ }
+ d = short2str(s);
+ for (m = modelist; m->m_name; m++)
+ if (strcmp(m->m_name, d) == 0)
+ break;
+ if (!m->m_name)
+ stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument"));
+
+ switch (x) {
+ case '+':
+ ttylist[z][m->m_type].t_setmask |= m->m_value;
+ ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ case '-':
+ ttylist[z][m->m_type].t_setmask &= ~m->m_value;
+ ttylist[z][m->m_type].t_clrmask |= m->m_value;
+ break;
+ default:
+ ttylist[z][m->m_type].t_setmask &= ~m->m_value;
+ ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ }
+ }
+} /* end dosetty */
+
+int
+tty_getty(fd, td)
+ int fd;
+ ttydata_t *td;
+{
+#ifdef POSIX
+ RETRY(tcgetattr(fd, &td->d_t));
+#else /* TERMIO || GSTTY */
+# ifdef TERMIO
+ RETRY(ioctl(fd, TCGETA, (ioctl_t) &td->d_t));
+# else /* GSTTY */
+# ifdef TIOCGETP
+ RETRY(ioctl(fd, TIOCGETP, (ioctl_t) &td->d_t));
+# endif /* TIOCGETP */
+# ifdef TIOCGETC
+ RETRY(ioctl(fd, TIOCGETC, (ioctl_t) &td->d_tc));
+# endif /* TIOCGETC */
+# ifdef TIOCGPAGE
+ RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc));
+# endif /* TIOCGPAGE */
+# ifdef TIOCLGET
+ RETRY(ioctl(fd, TIOCLGET, (ioctl_t) &td->d_lb));
+# endif /* TIOCLGET */
+# endif /* TERMIO */
+#endif /* POSIX */
+
+#ifdef TIOCGLTC
+ RETRY(ioctl(fd, TIOCGLTC, (ioctl_t) &td->d_ltc));
+#endif /* TIOCGLTC */
+
+ return 0;
+}
+
+int
+tty_setty(fd, td)
+ int fd;
+ ttydata_t *td;
+{
+#ifdef POSIX
+ RETRY(tcsetattr(fd, TCSADRAIN, &td->d_t));
+#else
+# ifdef TERMIO
+ RETRY(ioctl(fd, TCSETAW, (ioctl_t) &td->d_t));
+# else
+# ifdef TIOCSETN
+ RETRY(ioctl(fd, TIOCSETN, (ioctl_t) &td->d_t));
+# endif /* TIOCSETN */
+# ifdef TIOCGETC
+ RETRY(ioctl(fd, TIOCSETC, (ioctl_t) &td->d_tc));
+# endif /* TIOCGETC */
+# ifdef TIOCGPAGE
+ RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc));
+# endif /* TIOCGPAGE */
+# ifdef TIOCLGET
+ RETRY(ioctl(fd, TIOCLSET, (ioctl_t) &td->d_lb));
+# endif /* TIOCLGET */
+# endif /* TERMIO */
+#endif /* POSIX */
+
+#ifdef TIOCGLTC
+ RETRY(ioctl(fd, TIOCSLTC, (ioctl_t) &td->d_ltc));
+#endif /* TIOCGLTC */
+
+ return 0;
+}
+
+void
+tty_getchar(td, s)
+ ttydata_t *td;
+ unsigned char *s;
+{
+#ifdef TIOCGLTC
+ {
+ struct ltchars *n = &td->d_ltc;
+
+ s[C_SUSP] = n->t_suspc;
+ s[C_DSUSP] = n->t_dsuspc;
+ s[C_REPRINT] = n->t_rprntc;
+ s[C_DISCARD] = n->t_flushc;
+ s[C_WERASE] = n->t_werasc;
+ s[C_LNEXT] = n->t_lnextc;
+ }
+#endif /* TIOCGLTC */
+
+#if defined(POSIX) || defined(TERMIO)
+ {
+# ifdef POSIX
+ struct termios *n = &td->d_t;
+# else
+ struct termio *n = &td->d_t;
+# endif /* POSIX */
+
+# ifdef VINTR
+ s[C_INTR] = n->c_cc[VINTR];
+# endif /* VINTR */
+# ifdef VQUIT
+ s[C_QUIT] = n->c_cc[VQUIT];
+# endif /* VQUIT */
+# ifdef VERASE
+ s[C_ERASE] = n->c_cc[VERASE];
+# endif /* VERASE */
+# ifdef VKILL
+ s[C_KILL] = n->c_cc[VKILL];
+# endif /* VKILL */
+# ifdef VEOF
+ s[C_EOF] = n->c_cc[VEOF];
+# endif /* VEOF */
+# ifdef VEOL
+ s[C_EOL] = n->c_cc[VEOL];
+# endif /* VEOL */
+# ifdef VEOL2
+ s[C_EOL2] = n->c_cc[VEOL2];
+# endif /* VEOL2 */
+# ifdef VSWTCH
+ s[C_SWTCH] = n->c_cc[VSWTCH];
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+ s[C_DSWTCH] = n->c_cc[VDSWTCH];
+# endif /* VDSWTCH */
+# ifdef VERASE2
+ s[C_ERASE2] = n->c_cc[VERASE2];
+# endif /* VERASE2 */
+# ifdef VSTART
+ s[C_START] = n->c_cc[VSTART];
+# endif /* VSTART */
+# ifdef VSTOP
+ s[C_STOP] = n->c_cc[VSTOP];
+# endif /* VSTOP */
+# ifdef VWERASE
+ s[C_WERASE] = n->c_cc[VWERASE];
+# endif /* VWERASE */
+# ifdef VSUSP
+ s[C_SUSP] = n->c_cc[VSUSP];
+# endif /* VSUSP */
+# ifdef VDSUSP
+ s[C_DSUSP] = n->c_cc[VDSUSP];
+# endif /* VDSUSP */
+# ifdef VREPRINT
+ s[C_REPRINT] = n->c_cc[VREPRINT];
+# endif /* WREPRINT */
+# ifdef VDISCARD
+ s[C_DISCARD] = n->c_cc[VDISCARD];
+# endif /* VDISCARD */
+# ifdef VLNEXT
+ s[C_LNEXT] = n->c_cc[VLNEXT];
+# endif /* VLNEXT */
+# ifdef VSTATUS
+ s[C_STATUS] = n->c_cc[VSTATUS];
+# endif /* VSTATUS */
+# ifdef VPAGE
+ s[C_PAGE] = n->c_cc[VPAGE];
+# endif /* VPAGE */
+# ifdef VPGOFF
+ s[C_PGOFF] = n->c_cc[VPGOFF];
+# endif /* VPGOFF */
+# ifdef VKILL2
+ s[C_KILL2] = n->c_cc[VKILL2];
+# endif /* KILL2 */
+# ifdef VMIN
+ s[C_MIN] = n->c_cc[VMIN];
+# endif /* VMIN */
+# ifdef VTIME
+ s[C_TIME] = n->c_cc[VTIME];
+# endif /* VTIME */
+ }
+
+#else /* SGTTY */
+
+# ifdef TIOCGPAGE
+ {
+ struct ttypagestat *n = &td->d_pc;
+
+ s[C_STATUS] = n->tps_statc;
+ s[C_PAGE] = n->tps_pagec;
+ s[C_PGOFF] = n->tps_pgoffc;
+ }
+# endif /* TIOCGPAGE */
+
+# ifdef TIOCGETC
+ {
+ struct tchars *n = &td->d_tc;
+
+ s[C_INTR] = n->t_intrc;
+ s[C_QUIT] = n->t_quitc;
+ s[C_START] = n->t_startc;
+ s[C_STOP] = n->t_stopc;
+ s[C_EOF] = n->t_eofc;
+ s[C_BRK] = n->t_brkc;
+ }
+# endif /* TIOCGETC */
+
+# ifdef TIOCGETP
+ {
+ struct sgttyb *n = &td->d_t;
+
+ s[C_ERASE] = n->sg_erase;
+ s[C_KILL] = n->sg_kill;
+ }
+# endif /* TIOCGETP */
+#endif /* !POSIX || TERMIO */
+
+} /* tty_getchar */
+
+
+void
+tty_setchar(td, s)
+ ttydata_t *td;
+ unsigned char *s;
+{
+#ifdef TIOCGLTC
+ {
+ struct ltchars *n = &td->d_ltc;
+
+ n->t_suspc = s[C_SUSP];
+ n->t_dsuspc = s[C_DSUSP];
+ n->t_rprntc = s[C_REPRINT];
+ n->t_flushc = s[C_DISCARD];
+ n->t_werasc = s[C_WERASE];
+ n->t_lnextc = s[C_LNEXT];
+ }
+#endif /* TIOCGLTC */
+
+#if defined(POSIX) || defined(TERMIO)
+ {
+# ifdef POSIX
+ struct termios *n = &td->d_t;
+# else
+ struct termio *n = &td->d_t;
+# endif /* POSIX */
+
+# ifdef VINTR
+ n->c_cc[VINTR] = s[C_INTR];
+# endif /* VINTR */
+# ifdef VQUIT
+ n->c_cc[VQUIT] = s[C_QUIT];
+# endif /* VQUIT */
+# ifdef VERASE
+ n->c_cc[VERASE] = s[C_ERASE];
+# endif /* VERASE */
+# ifdef VKILL
+ n->c_cc[VKILL] = s[C_KILL];
+# endif /* VKILL */
+# ifdef VEOF
+ n->c_cc[VEOF] = s[C_EOF];
+# endif /* VEOF */
+# ifdef VEOL
+ n->c_cc[VEOL] = s[C_EOL];
+# endif /* VEOL */
+# ifdef VEOL2
+ n->c_cc[VEOL2] = s[C_EOL2];
+# endif /* VEOL2 */
+# ifdef VSWTCH
+ n->c_cc[VSWTCH] = s[C_SWTCH];
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+ n->c_cc[VDSWTCH] = s[C_DSWTCH];
+# endif /* VDSWTCH */
+# ifdef VERASE2
+ n->c_cc[VERASE2] = s[C_ERASE2];
+# endif /* VERASE2 */
+# ifdef VSTART
+ n->c_cc[VSTART] = s[C_START];
+# endif /* VSTART */
+# ifdef VSTOP
+ n->c_cc[VSTOP] = s[C_STOP];
+# endif /* VSTOP */
+# ifdef VWERASE
+ n->c_cc[VWERASE] = s[C_WERASE];
+# endif /* VWERASE */
+# ifdef VSUSP
+ n->c_cc[VSUSP] = s[C_SUSP];
+# endif /* VSUSP */
+# ifdef VDSUSP
+ n->c_cc[VDSUSP] = s[C_DSUSP];
+# endif /* VDSUSP */
+# ifdef VREPRINT
+ n->c_cc[VREPRINT] = s[C_REPRINT];
+# endif /* WREPRINT */
+# ifdef VDISCARD
+ n->c_cc[VDISCARD] = s[C_DISCARD];
+# endif /* VDISCARD */
+# ifdef VLNEXT
+ n->c_cc[VLNEXT] = s[C_LNEXT];
+# endif /* VLNEXT */
+# ifdef VSTATUS
+ n->c_cc[VSTATUS] = s[C_STATUS];
+# endif /* VSTATUS */
+# ifdef VPAGE
+ n->c_cc[VPAGE] = s[C_PAGE];
+# endif /* VPAGE */
+# ifdef VPGOFF
+ n->c_cc[VPGOFF] = s[C_PGOFF];
+# endif /* VPGOFF */
+# ifdef VKILL2
+ n->c_cc[VKILL2] = s[C_KILL2];
+# endif /* VKILL2 */
+# ifdef VMIN
+ n->c_cc[VMIN] = s[C_MIN];
+# endif /* VMIN */
+# ifdef VTIME
+ n->c_cc[VTIME] = s[C_TIME];
+# endif /* VTIME */
+ }
+
+#else /* GSTTY */
+
+# ifdef TIOCGPAGE
+ {
+ struct ttypagestat *n = &td->d_pc;
+
+ n->tps_length = 0;
+ n->tps_lpos = 0;
+ n->tps_statc = s[C_STATUS];
+ n->tps_pagec = s[C_PAGE];
+ n->tps_pgoffc = s[C_PGOFF];
+ n->tps_flag = 0;
+ }
+# endif /* TIOCGPAGE */
+
+# ifdef TIOCGETC
+ {
+ struct tchars *n = &td->d_tc;
+ n->t_intrc = s[C_INTR];
+ n->t_quitc = s[C_QUIT];
+ n->t_startc = s[C_START];
+ n->t_stopc = s[C_STOP];
+ n->t_eofc = s[C_EOF];
+ n->t_brkc = s[C_BRK];
+ }
+# endif /* TIOCGETC */
+
+# ifdef TIOCGETP
+ {
+ struct sgttyb *n = &td->d_t;
+
+ n->sg_erase = s[C_ERASE];
+ n->sg_kill = s[C_KILL];
+ }
+# endif /* TIOCGETP */
+#endif /* !POSIX || TERMIO */
+
+} /* tty_setchar */
+
+speed_t
+tty_getspeed(td)
+ ttydata_t *td;
+{
+ speed_t spd;
+
+#ifdef POSIX
+ if ((spd = cfgetispeed(&td->d_t)) == 0)
+ spd = cfgetospeed(&td->d_t);
+#else /* ! POSIX */
+# ifdef TERMIO
+# ifdef CBAUD
+ spd = td->d_t.c_cflag & CBAUD;
+# else
+ spd = 0;
+# endif
+# else /* SGTTY */
+ spd = td->d_t.sg_ispeed;
+# endif /* TERMIO */
+#endif /* POSIX */
+
+ return spd;
+} /* end tty_getspeed */
+
+int
+tty_gettabs(td)
+ ttydata_t *td;
+{
+#if defined(POSIX) || defined(TERMIO)
+ return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1;
+#else /* SGTTY */
+ return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1;
+#endif /* POSIX || TERMIO */
+} /* end tty_gettabs */
+
+int
+tty_geteightbit(td)
+ ttydata_t *td;
+{
+#if defined(POSIX) || defined(TERMIO)
+ return (td->d_t.c_cflag & CSIZE) == CS8;
+#else /* SGTTY */
+ return td->d_lb & (LPASS8 | LLITOUT);
+#endif /* POSIX || TERMIO */
+} /* end tty_geteightbit */
+
+int
+tty_cooked_mode(td)
+ ttydata_t *td;
+{
+#if defined(POSIX) || defined(TERMIO)
+ return (td->d_t.c_lflag & ICANON);
+#else /* SGTTY */
+ return !(td->d_t.sg_flags & (RAW | CBREAK));
+#endif /* POSIX || TERMIO */
+} /* end tty_cooked_mode */
+
+#ifdef _IBMR2
+void
+tty_setdisc(fd, dis)
+ int fd;
+ int dis;
+{
+ static bool edit_discipline = 0;
+ static union txname tx_disc;
+ extern char strPOSIX[];
+
+ switch (dis) {
+ case EX_IO:
+ if (edit_discipline) {
+ if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1)
+ return;
+ edit_discipline = 0;
+ }
+ return;
+
+ case ED_IO:
+ tx_disc.tx_which = 0;
+ if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1)
+ return;
+ if (strcmp(tx_disc.tx_name, strPOSIX) != 0) {
+ edit_discipline = 1;
+ if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1)
+ return;
+ }
+ return;
+
+ default:
+ return;
+ }
+} /* end tty_setdisc */
+#endif /* _IBMR2 */
+
+#ifdef DEBUG_TTY
+static void
+tty_printchar(s)
+ unsigned char *s;
+{
+ struct tcshmodes *m;
+ int i;
+
+ for (i = 0; i < C_NCC; i++) {
+ for (m = modelist; m->m_name; m++)
+ if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
+ break;
+ if (m->m_name)
+ xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1);
+ if (i % 5 == 0)
+ xputchar('\n');
+ }
+ xputchar('\n');
+}
+#endif /* DEBUG_TTY */
+#else /* WINNT */
+int
+tty_cooked_mode(td)
+ void *td;
+{
+ return do_nt_check_cooked_mode();
+}
+#endif /* !WINNT */
diff --git a/contrib/tcsh/ed.term.h b/contrib/tcsh/ed.term.h
new file mode 100644
index 0000000..bcd000b
--- /dev/null
+++ b/contrib/tcsh/ed.term.h
@@ -0,0 +1,492 @@
+/* $Header: /src/pub/tcsh/ed.term.h,v 1.13 1996/09/24 16:57:20 christos Exp $ */
+/*
+ * ed.term.h: Local terminal header
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_ed_term
+#define _h_ed_term
+
+#define TO_CONTROL(A) ((A) & 037)
+
+#if defined(TERMIO) || defined(POSIX)
+/*
+ * Aix compatible names
+ */
+# if defined(VWERSE) && !defined(VWERASE)
+# define VWERASE VWERSE
+# endif /* VWERSE && !VWERASE */
+
+# if defined(VDISCRD) && !defined(VDISCARD)
+# define VDISCARD VDISCRD
+# endif /* VDISCRD && !VDISCARD */
+
+# if defined(VFLUSHO) && !defined(VDISCARD)
+# define VDISCARD VFLUSHO
+# endif /* VFLUSHO && VDISCARD */
+
+# if defined(VSTRT) && !defined(VSTART)
+# define VSTART VSTRT
+# endif /* VSTRT && ! VSTART */
+
+# if defined(VSTAT) && !defined(VSTATUS)
+# define VSTATUS VSTAT
+# endif /* VSTAT && ! VSTATUS */
+
+# ifndef ONLRET
+# define ONLRET 0
+# endif /* ONLRET */
+
+# ifndef TAB3
+# ifdef OXTABS
+# define TAB3 OXTABS
+# else
+# define TAB3 0
+# endif /* OXTABS */
+# endif /* !TAB3 */
+
+# if defined(OXTABS) && !defined(XTABS)
+# define XTABS OXTABS
+# endif /* OXTABS && !XTABS */
+
+# ifndef ONLCR
+# define ONLCR 0
+# endif /* ONLCR */
+
+# ifndef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN */
+
+/*
+ * emx garbage
+ */
+# ifndef IDEFAULT
+# define IDEFAULT 0
+# endif /* IDEFAULT */
+
+# ifndef IDELETE
+# define IDELETE 0
+# endif /* IDELETE */
+
+# ifndef ECHOCTL
+# define ECHOCTL 0
+# endif /* ECHOCTL */
+
+# ifndef PARENB
+# define PARENB 0
+# endif /* PARENB */
+
+# ifndef EXTPROC
+# define EXTPROC 0
+# endif /* EXTPROC */
+
+# ifndef FLUSHO
+# define FLUSHO 0
+# endif /* FLUSHO */
+
+
+# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
+# define _POSIX_VDISABLE VDISABLE
+# endif /* VDISABLE && ! _POSIX_VDISABLE */
+
+/*
+ * Work around ISC's definition of IEXTEN which is
+ * XCASE!
+ */
+# ifdef ISC
+# if defined(IEXTEN) && defined(XCASE)
+# if IEXTEN == XCASE
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN == XCASE */
+# endif /* IEXTEN && XCASE */
+# if defined(IEXTEN) && !defined(XCASE)
+# define XCASE IEXTEN
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN && !XCASE */
+# endif /* ISC */
+
+/*
+ * Work around convex weirdness where turning off IEXTEN makes us
+ * lose all postprocessing!
+ */
+#ifdef convex
+# if defined(IEXTEN) && IEXTEN != 0
+# undef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN != 0 */
+#endif /* convex */
+
+
+# else /* SGTTY */
+
+# ifndef LPASS8
+# define LPASS8 0
+# endif /* LPASS8 */
+
+#endif /* TERMIO || POSIX */
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) -1)
+#endif /* _POSIX_VDISABLE */
+
+
+#if !defined(CREPRINT) && defined(CRPRNT)
+# define CREPRINT CRPRNT
+#endif /* !CREPRINT && CRPRNT */
+#if !defined(CDISCARD) && defined(CFLUSH)
+# define CDISCARD CFLUSH
+#endif /* !CDISCARD && CFLUSH */
+#if !defined(CDISCARD) && defined(CFLUSHO)
+# define CDISCARD CFLUSHO
+#endif /* !CDISCARD && CFLUSHO */
+
+/*
+ * IRIX4.0 control macro is broken!
+ * Ignore and undef all default tty chars defined and redefine only
+ * the ones that are different in the IRIX file.
+ */
+#if __STDC__ && defined(IRIS4D)
+# undef CINTR
+# define CINTR 0177 /* ^? */
+# undef CQUIT
+# undef CERASE
+# define CERASE TO_CONTROL('h')
+# undef CKILL
+# undef CEOF
+# undef CEOL
+# undef CEOL2
+# undef CSWTCH
+# define CSWTCH TO_CONTROL('z')
+# undef CDSWTCH
+# undef CERASE2
+# undef CSTART
+# undef CSTOP
+# undef CWERASE
+# undef CSUSP
+# undef CDSUSP
+# undef CREPRINT
+# undef CDISCARD
+# undef CLNEXT
+# undef CSTATUS
+# undef CPAGE
+# undef CPGOFF
+# undef CKILL2
+# undef CBRK
+# undef CMIN
+# undef CTIME
+#endif /* __STDC__ && IRIS4D */
+
+
+#ifndef CINTR
+# define CINTR TO_CONTROL('c')
+#endif /* CINTR */
+#ifndef CQUIT
+# define CQUIT 034 /* ^\ */
+#endif /* CQUIT */
+#ifndef CERASE
+# define CERASE 0177 /* ^? */
+#endif /* CERASE */
+#ifndef CKILL
+# define CKILL TO_CONTROL('u')
+#endif /* CKILL */
+#ifndef CEOF
+# define CEOF TO_CONTROL('d')
+#endif /* CEOF */
+#ifndef CEOL
+# define CEOL _POSIX_VDISABLE
+#endif /* CEOL */
+#ifndef CEOL2
+# define CEOL2 _POSIX_VDISABLE
+#endif /* CEOL2 */
+#ifndef CSWTCH
+# define CSWTCH _POSIX_VDISABLE
+#endif /* CSWTCH */
+#ifndef CDSWTCH
+# define CDSWTCH _POSIX_VDISABLE
+#endif /* CDSWTCH */
+#ifndef CERASE2
+# define CERASE2 _POSIX_VDISABLE
+#endif /* CERASE2 */
+#ifndef CSTART
+# define CSTART TO_CONTROL('q')
+#endif /* CSTART */
+#ifndef CSTOP
+# define CSTOP TO_CONTROL('s')
+#endif /* CSTOP */
+#ifndef CSUSP
+# define CSUSP TO_CONTROL('z')
+#endif /* CSUSP */
+#ifndef CDSUSP
+# define CDSUSP TO_CONTROL('y')
+#endif /* CDSUSP */
+
+#ifdef hpux
+
+# ifndef CREPRINT
+# define CREPRINT _POSIX_VDISABLE
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD _POSIX_VDISABLE
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT _POSIX_VDISABLE
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE _POSIX_VDISABLE
+# endif /* CWERASE */
+
+#else /* !hpux */
+
+# ifndef CREPRINT
+# define CREPRINT TO_CONTROL('r')
+# endif /* CREPRINT */
+# ifndef CDISCARD
+# define CDISCARD TO_CONTROL('o')
+# endif /* CDISCARD */
+# ifndef CLNEXT
+# define CLNEXT TO_CONTROL('v')
+# endif /* CLNEXT */
+# ifndef CWERASE
+# define CWERASE TO_CONTROL('w')
+# endif /* CWERASE */
+
+#endif /* hpux */
+
+#ifndef CSTATUS
+# define CSTATUS TO_CONTROL('t')
+#endif /* CSTATUS */
+#ifndef CPAGE
+# define CPAGE ' '
+#endif /* CPAGE */
+#ifndef CPGOFF
+# define CPGOFF TO_CONTROL('m')
+#endif /* CPGOFF */
+#ifndef CKILL2
+# define CKILL2 _POSIX_VDISABLE
+#endif /* CKILL2 */
+#ifndef CBRK
+# ifndef masscomp
+# define CBRK 0377
+# else
+# define CBRK '\0'
+# endif /* masscomp */
+#endif /* CBRK */
+#ifndef CMIN
+# define CMIN CEOF
+#endif /* CMIN */
+#ifndef CTIME
+# define CTIME CEOL
+#endif /* CTIME */
+
+/*
+ * Fix for sun inconsistency. On termio VSUSP and the rest of the
+ * ttychars > NCC are defined. So we undefine them.
+ */
+#if defined(TERMIO) || defined(POSIX)
+# if defined(POSIX) && defined(NCCS)
+# define NUMCC NCCS
+# else
+# ifdef NCC
+# define NUMCC NCC
+# endif /* NCC */
+# endif /* POSIX && NCCS */
+# ifdef NUMCC
+# ifdef VINTR
+# if NUMCC <= VINTR
+# undef VINTR
+# endif /* NUMCC <= VINTR */
+# endif /* VINTR */
+# ifdef VQUIT
+# if NUMCC <= VQUIT
+# undef VQUIT
+# endif /* NUMCC <= VQUIT */
+# endif /* VQUIT */
+# ifdef VERASE
+# if NUMCC <= VERASE
+# undef VERASE
+# endif /* NUMCC <= VERASE */
+# endif /* VERASE */
+# ifdef VKILL
+# if NUMCC <= VKILL
+# undef VKILL
+# endif /* NUMCC <= VKILL */
+# endif /* VKILL */
+# ifdef VEOF
+# if NUMCC <= VEOF
+# undef VEOF
+# endif /* NUMCC <= VEOF */
+# endif /* VEOF */
+# ifdef VEOL
+# if NUMCC <= VEOL
+# undef VEOL
+# endif /* NUMCC <= VEOL */
+# endif /* VEOL */
+# ifdef VEOL2
+# if NUMCC <= VEOL2
+# undef VEOL2
+# endif /* NUMCC <= VEOL2 */
+# endif /* VEOL2 */
+# ifdef VSWTCH
+# if NUMCC <= VSWTCH
+# undef VSWTCH
+# endif /* NUMCC <= VSWTCH */
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+# if NUMCC <= VDSWTCH
+# undef VDSWTCH
+# endif /* NUMCC <= VDSWTCH */
+# endif /* VDSWTCH */
+# ifdef VERASE2
+# if NUMCC <= VERASE2
+# undef VERASE2
+# endif /* NUMCC <= VERASE2 */
+# endif /* VERASE2 */
+# ifdef VSTART
+# if NUMCC <= VSTART
+# undef VSTART
+# endif /* NUMCC <= VSTART */
+# endif /* VSTART */
+# ifdef VSTOP
+# if NUMCC <= VSTOP
+# undef VSTOP
+# endif /* NUMCC <= VSTOP */
+# endif /* VSTOP */
+# ifdef VWERASE
+# if NUMCC <= VWERASE
+# undef VWERASE
+# endif /* NUMCC <= VWERASE */
+# endif /* VWERASE */
+# ifdef VSUSP
+# if NUMCC <= VSUSP
+# undef VSUSP
+# endif /* NUMCC <= VSUSP */
+# endif /* VSUSP */
+# ifdef VDSUSP
+# if NUMCC <= VDSUSP
+# undef VDSUSP
+# endif /* NUMCC <= VDSUSP */
+# endif /* VDSUSP */
+# ifdef VREPRINT
+# if NUMCC <= VREPRINT
+# undef VREPRINT
+# endif /* NUMCC <= VREPRINT */
+# endif /* VREPRINT */
+# ifdef VDISCARD
+# if NUMCC <= VDISCARD
+# undef VDISCARD
+# endif /* NUMCC <= VDISCARD */
+# endif /* VDISCARD */
+# ifdef VLNEXT
+# if NUMCC <= VLNEXT
+# undef VLNEXT
+# endif /* NUMCC <= VLNEXT */
+# endif /* VLNEXT */
+# ifdef VSTATUS
+# if NUMCC <= VSTATUS
+# undef VSTATUS
+# endif /* NUMCC <= VSTATUS */
+# endif /* VSTATUS */
+# ifdef VPAGE
+# if NUMCC <= VPAGE
+# undef VPAGE
+# endif /* NUMCC <= VPAGE */
+# endif /* VPAGE */
+# ifdef VPGOFF
+# if NUMCC <= VPGOFF
+# undef VPGOFF
+# endif /* NUMCC <= VPGOFF */
+# endif /* VPGOFF */
+# ifdef VKILL2
+# if NUMCC <= VKILL2
+# undef VKILL2
+# endif /* NUMCC <= VKILL2 */
+# endif /* VKILL2 */
+# ifdef VBRK
+# if NUMCC <= VBRK
+# undef VBRK
+# endif /* NUMCC <= VBRK */
+# endif /* VBRK */
+# ifdef VMIN
+# if NUMCC <= VMIN
+# undef VMIN
+# endif /* NUMCC <= VMIN */
+# endif /* VMIN */
+# ifdef VTIME
+# if NUMCC <= VTIME
+# undef VTIME
+# endif /* NUMCC <= VTIME */
+# endif /* VTIME */
+# endif /* NUMCC */
+#endif /* !POSIX */
+
+/*
+ * fix for hpux10 inconsistency: it has VWERASE, but TIOCSLTC returns
+ * EINVAL if one tries to change it
+ */
+#if defined(hpux) && defined(VSUSP) && defined(VDSUSP) && defined(VWERASE) && d
+efined(VLNEXT)
+# undef TIOCGLTC /* not really needed */
+# undef TIOCSLTC
+#endif
+
+#define C_INTR 0
+#define C_QUIT 1
+#define C_ERASE 2
+#define C_KILL 3
+#define C_EOF 4
+#define C_EOL 5
+#define C_EOL2 6
+#define C_SWTCH 7
+#define C_DSWTCH 8
+#define C_ERASE2 9
+#define C_START 10
+#define C_STOP 11
+#define C_WERASE 12
+#define C_SUSP 13
+#define C_DSUSP 14
+#define C_REPRINT 15
+#define C_DISCARD 16
+#define C_LNEXT 17
+#define C_STATUS 18
+#define C_PAGE 19
+#define C_PGOFF 20
+#define C_KILL2 21
+#define C_BRK 22
+#define C_MIN 23
+#define C_TIME 24
+#define C_NCC 25
+#define C_SH(A) (1 << (A))
+
+#endif /* _h_ed_term */
diff --git a/contrib/tcsh/ed.xmap.c b/contrib/tcsh/ed.xmap.c
new file mode 100644
index 0000000..d4d9bd6
--- /dev/null
+++ b/contrib/tcsh/ed.xmap.c
@@ -0,0 +1,844 @@
+/* $Header: /src/pub/tcsh/ed.xmap.c,v 3.21 1999/06/01 20:01:32 christos Exp $ */
+/*
+ * ed.xmap.c: This module contains the procedures for maintaining
+ * the extended-key map.
+ *
+ * An extended-key (Xkey) is a sequence of keystrokes
+ * introduced with an sequence introducer and consisting
+ * of an arbitrary number of characters. This module maintains
+ * a map (the Xmap) to convert these extended-key sequences
+ * into input strings (XK_STR), editor functions (XK_CMD), or
+ * unix commands (XK_EXE). It contains the
+ * following externally visible functions.
+ *
+ * int GetXkey(ch,val);
+ * CStr *ch;
+ * XmapVal *val;
+ *
+ * Looks up *ch in map and then reads characters until a
+ * complete match is found or a mismatch occurs. Returns the
+ * type of the match found (XK_STR, XK_CMD, or XK_EXE).
+ * Returns NULL in val.str and XK_STR for no match.
+ * The last character read is returned in *ch.
+ *
+ * void AddXkey(Xkey, val, ntype);
+ * CStr *Xkey;
+ * XmapVal *val;
+ * int ntype;
+ *
+ * Adds Xkey to the Xmap and associates the value in val with it.
+ * If Xkey is already is in Xmap, the new code is applied to the
+ * existing Xkey. Ntype specifies if code is a command, an
+ * out string or a unix command.
+ *
+ * int DeleteXkey(Xkey);
+ * CStr *Xkey;
+ *
+ * Delete the Xkey and all longer Xkeys staring with Xkey, if
+ * they exists.
+ *
+ * Warning:
+ * If Xkey is a substring of some other Xkeys, then the longer
+ * Xkeys are lost!! That is, if the Xkeys "abcd" and "abcef"
+ * are in Xmap, adding the key "abc" will cause the first two
+ * definitions to be lost.
+ *
+ * void ResetXmap();
+ *
+ * Removes all entries from Xmap and resets the defaults.
+ *
+ * void PrintXkey(Xkey);
+ * CStr *Xkey;
+ *
+ * Prints all extended keys prefixed by Xkey and their associated
+ * commands.
+ *
+ * Restrictions:
+ * -------------
+ * 1) It is not possible to have one Xkey that is a
+ * substring of another.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: ed.xmap.c,v 3.21 1999/06/01 20:01:32 christos Exp $")
+
+#include "ed.h"
+#include "ed.defns.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Internal Data types and declarations */
+
+/* The Nodes of the Xmap. The Xmap is a linked list of these node
+ * elements
+ */
+typedef struct Xmapnode {
+ Char ch; /* single character of Xkey */
+ int type;
+ XmapVal val; /* command code or pointer to string, if this
+ * is a leaf */
+ struct Xmapnode *next; /* ptr to next char of this Xkey */
+ struct Xmapnode *sibling; /* ptr to another Xkey with same prefix */
+} XmapNode;
+
+static XmapNode *Xmap = NULL; /* the current Xmap */
+#define MAXXKEY 100 /* max length of a Xkey for print putposes */
+static Char printbuf[MAXXKEY]; /* buffer for printing */
+
+
+/* Some declarations of procedures */
+static int TraverseMap __P((XmapNode *, CStr *, XmapVal *));
+static int TryNode __P((XmapNode *, CStr *, XmapVal *, int));
+static XmapNode *GetFreeNode __P((CStr *));
+static void PutFreeNode __P((XmapNode *));
+static int TryDeleteNode __P((XmapNode **, CStr *));
+static int Lookup __P((CStr *, XmapNode *, int));
+static int Enumerate __P((XmapNode *, int));
+static int unparsech __P((int, Char *));
+
+
+XmapVal *
+XmapCmd(cmd)
+ int cmd;
+{
+ static XmapVal xm;
+ xm.cmd = (KEYCMD) cmd;
+ return &xm;
+}
+
+XmapVal *
+XmapStr(str)
+ CStr *str;
+{
+ static XmapVal xm;
+ xm.str.len = str->len;
+ xm.str.buf = str->buf;
+ return &xm;
+}
+
+/* ResetXmap():
+ * Takes all nodes on Xmap and puts them on free list. Then
+ * initializes Xmap with arrow keys
+ */
+void
+ResetXmap()
+{
+ PutFreeNode(Xmap);
+ Xmap = NULL;
+
+ DefaultArrowKeys();
+ return;
+}
+
+
+/* GetXkey():
+ * Calls the recursive function with entry point Xmap
+ */
+int
+GetXkey(ch, val)
+ CStr *ch;
+ XmapVal *val;
+{
+ return (TraverseMap(Xmap, ch, val));
+}
+
+/* TraverseMap():
+ * recursively traverses node in tree until match or mismatch is
+ * found. May read in more characters.
+ */
+static int
+TraverseMap(ptr, ch, val)
+ XmapNode *ptr;
+ CStr *ch;
+ XmapVal *val;
+{
+ Char tch;
+
+ if (ptr->ch == *(ch->buf)) {
+ /* match found */
+ if (ptr->next) {
+ /* Xkey not complete so get next char */
+ if (GetNextChar(&tch) != 1) { /* if EOF or error */
+ val->cmd = F_SEND_EOF;
+ return XK_CMD;/* PWP: Pretend we just read an end-of-file */
+ }
+ *(ch->buf) = tch;
+ return (TraverseMap(ptr->next, ch, val));
+ }
+ else {
+ *val = ptr->val;
+ if (ptr->type != XK_CMD)
+ *(ch->buf) = '\0';
+ return ptr->type;
+ }
+ }
+ else {
+ /* no match found here */
+ if (ptr->sibling) {
+ /* try next sibling */
+ return (TraverseMap(ptr->sibling, ch, val));
+ }
+ else {
+ /* no next sibling -- mismatch */
+ val->str.buf = NULL;
+ val->str.len = 0;
+ return XK_STR;
+ }
+ }
+}
+
+void
+AddXkey(Xkey, val, ntype)
+ CStr *Xkey;
+ XmapVal *val;
+ int ntype;
+{
+ CStr cs;
+ cs.buf = Xkey->buf;
+ cs.len = Xkey->len;
+ if (Xkey->len == 0) {
+ xprintf(CGETS(9, 1, "AddXkey: Null extended-key not allowed.\n"));
+ return;
+ }
+
+ if (ntype == XK_CMD && val->cmd == F_XKEY) {
+ xprintf(CGETS(9, 2, "AddXkey: sequence-lead-in command not allowed\n"));
+ return;
+ }
+
+ if (Xmap == NULL)
+ /* tree is initially empty. Set up new node to match Xkey[0] */
+ Xmap = GetFreeNode(&cs); /* it is properly initialized */
+
+ /* Now recurse through Xmap */
+ (void) TryNode(Xmap, &cs, val, ntype);
+ return;
+}
+
+static int
+TryNode(ptr, str, val, ntype)
+ XmapNode *ptr;
+ CStr *str;
+ XmapVal *val;
+ int ntype;
+{
+ /*
+ * Find a node that matches *string or allocate a new one
+ */
+ if (ptr->ch != *(str->buf)) {
+ XmapNode *xm;
+
+ for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+ if (xm->sibling->ch == *(str->buf))
+ break;
+ if (xm->sibling == NULL)
+ xm->sibling = GetFreeNode(str); /* setup new node */
+ ptr = xm->sibling;
+ }
+
+ str->buf++;
+ str->len--;
+ if (str->len == 0) {
+ /* we're there */
+ if (ptr->next != NULL) {
+ PutFreeNode(ptr->next); /* lose longer Xkeys with this prefix */
+ ptr->next = NULL;
+ }
+
+ switch (ptr->type) {
+ case XK_STR:
+ case XK_EXE:
+ if (ptr->val.str.buf != NULL)
+ xfree((ptr_t) ptr->val.str.buf);
+ ptr->val.str.len = 0;
+ break;
+ case XK_NOD:
+ case XK_CMD:
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ switch (ptr->type = ntype) {
+ case XK_CMD:
+ ptr->val = *val;
+ break;
+ case XK_STR:
+ case XK_EXE:
+ ptr->val.str.len = (val->str.len + 1) * sizeof(Char);
+ ptr->val.str.buf = (Char *) xmalloc((size_t) ptr->val.str.len);
+ (void) memmove((ptr_t) ptr->val.str.buf, (ptr_t) val->str.buf,
+ (size_t) ptr->val.str.len);
+ ptr->val.str.len = val->str.len;
+ break;
+ default:
+ abort();
+ break;
+ }
+ }
+ else {
+ /* still more chars to go */
+ if (ptr->next == NULL)
+ ptr->next = GetFreeNode(str); /* setup new node */
+ (void) TryNode(ptr->next, str, val, ntype);
+ }
+ return (0);
+}
+
+void
+ClearXkey(map, in)
+ KEYCMD *map;
+ CStr *in;
+{
+ unsigned char c = (unsigned char) *(in->buf);
+ if ((map[c] == F_XKEY) &&
+ ((map == CcKeyMap && CcAltMap[c] != F_XKEY) ||
+ (map == CcAltMap && CcKeyMap[c] != F_XKEY)))
+ (void) DeleteXkey(in);
+}
+
+int
+DeleteXkey(Xkey)
+ CStr *Xkey;
+{
+ if (Xkey->len == 0) {
+ xprintf(CGETS(9, 3, "DeleteXkey: Null extended-key not allowed.\n"));
+ return (-1);
+ }
+
+ if (Xmap == NULL)
+ return (0);
+
+ (void) TryDeleteNode(&Xmap, Xkey);
+ return (0);
+}
+
+static int
+TryDeleteNode(inptr, str)
+ XmapNode **inptr;
+ CStr *str;
+{
+ XmapNode *ptr;
+ XmapNode *prev_ptr = NULL;
+
+ ptr = *inptr;
+ /*
+ * Find a node that matches *string or allocate a new one
+ */
+ if (ptr->ch != *(str->buf)) {
+ XmapNode *xm;
+
+ for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+ if (xm->sibling->ch == *(str->buf))
+ break;
+ if (xm->sibling == NULL)
+ return (0);
+ prev_ptr = xm;
+ ptr = xm->sibling;
+ }
+
+ str->buf++;
+ str->len--;
+
+ if (str->len == 0) {
+ /* we're there */
+ if (prev_ptr == NULL)
+ *inptr = ptr->sibling;
+ else
+ prev_ptr->sibling = ptr->sibling;
+ ptr->sibling = NULL;
+ PutFreeNode(ptr);
+ return (1);
+ }
+ else if (ptr->next != NULL && TryDeleteNode(&ptr->next, str) == 1) {
+ if (ptr->next != NULL)
+ return (0);
+ if (prev_ptr == NULL)
+ *inptr = ptr->sibling;
+ else
+ prev_ptr->sibling = ptr->sibling;
+ ptr->sibling = NULL;
+ PutFreeNode(ptr);
+ return (1);
+ }
+ else {
+ return (0);
+ }
+}
+
+/* PutFreeNode():
+ * Puts a tree of nodes onto free list using free(3).
+ */
+static void
+PutFreeNode(ptr)
+ XmapNode *ptr;
+{
+ if (ptr == NULL)
+ return;
+
+ if (ptr->next != NULL) {
+ PutFreeNode(ptr->next);
+ ptr->next = NULL;
+ }
+
+ PutFreeNode(ptr->sibling);
+
+ switch (ptr->type) {
+ case XK_CMD:
+ case XK_NOD:
+ break;
+ case XK_EXE:
+ case XK_STR:
+ if (ptr->val.str.buf != NULL)
+ xfree((ptr_t) ptr->val.str.buf);
+ break;
+ default:
+ abort();
+ break;
+ }
+ xfree((ptr_t) ptr);
+}
+
+
+/* GetFreeNode():
+ * Returns pointer to an XmapNode for ch.
+ */
+static XmapNode *
+GetFreeNode(ch)
+ CStr *ch;
+{
+ XmapNode *ptr;
+
+ ptr = (XmapNode *) xmalloc((size_t) sizeof(XmapNode));
+ ptr->ch = ch->buf[0];
+ ptr->type = XK_NOD;
+ ptr->val.str.buf = NULL;
+ ptr->val.str.len = 0;
+ ptr->next = NULL;
+ ptr->sibling = NULL;
+ return (ptr);
+}
+
+
+/* PrintXKey():
+ * Print the binding associated with Xkey key.
+ * Print entire Xmap if null
+ */
+void
+PrintXkey(key)
+ CStr *key;
+{
+ CStr cs;
+
+ if (key) {
+ cs.buf = key->buf;
+ cs.len = key->len;
+ }
+ else {
+ cs.buf = STRNULL;
+ cs.len = 0;
+ }
+ /* do nothing if Xmap is empty and null key specified */
+ if (Xmap == NULL && cs.len == 0)
+ return;
+
+ printbuf[0] = '"';
+ if (Lookup(&cs, Xmap, 1) <= -1)
+ /* key is not bound */
+ xprintf(CGETS(9, 4, "Unbound extended key \"%S\"\n"), cs.buf);
+ return;
+}
+
+/* Lookup():
+ * look for the string starting at node ptr.
+ * Print if last node
+ */
+static int
+Lookup(str, ptr, cnt)
+ CStr *str;
+ XmapNode *ptr;
+ int cnt;
+{
+ int ncnt;
+
+ if (ptr == NULL)
+ return (-1); /* cannot have null ptr */
+
+ if (str->len == 0) {
+ /* no more chars in string. Enumerate from here. */
+ (void) Enumerate(ptr, cnt);
+ return (0);
+ }
+ else {
+ /* If match put this char into printbuf. Recurse */
+ if (ptr->ch == *(str->buf)) {
+ /* match found */
+ ncnt = unparsech(cnt, &ptr->ch);
+ if (ptr->next != NULL) {
+ /* not yet at leaf */
+ CStr tstr;
+ tstr.buf = str->buf + 1;
+ tstr.len = str->len - 1;
+ return (Lookup(&tstr, ptr->next, ncnt + 1));
+ }
+ else {
+ /* next node is null so key should be complete */
+ if (str->len == 1) {
+ CStr pb;
+ printbuf[ncnt + 1] = '"';
+ printbuf[ncnt + 2] = '\0';
+ pb.buf = printbuf;
+ pb.len = ncnt + 2;
+ (void) printOne(&pb, &ptr->val, ptr->type);
+ return (0);
+ }
+ else
+ return (-1);/* mismatch -- string still has chars */
+ }
+ }
+ else {
+ /* no match found try sibling */
+ if (ptr->sibling)
+ return (Lookup(str, ptr->sibling, cnt));
+ else
+ return (-1);
+ }
+ }
+}
+
+static int
+Enumerate(ptr, cnt)
+ XmapNode *ptr;
+ int cnt;
+{
+ int ncnt;
+
+ if (cnt >= MAXXKEY - 5) { /* buffer too small */
+ printbuf[++cnt] = '"';
+ printbuf[++cnt] = '\0';
+ xprintf(CGETS(9, 5,
+ "Some extended keys too long for internal print buffer"));
+ xprintf(" \"%S...\"\n", printbuf);
+ return (0);
+ }
+
+ if (ptr == NULL) {
+#ifdef DEBUG_EDIT
+ xprintf(CGETS(9, 6, "Enumerate: BUG!! Null ptr passed\n!"));
+#endif
+ return (-1);
+ }
+
+ ncnt = unparsech(cnt, &ptr->ch); /* put this char at end of string */
+ if (ptr->next == NULL) {
+ CStr pb;
+ /* print this Xkey and function */
+ printbuf[++ncnt] = '"';
+ printbuf[++ncnt] = '\0';
+ pb.buf = printbuf;
+ pb.len = ncnt;
+ (void) printOne(&pb, &ptr->val, ptr->type);
+ }
+ else
+ (void) Enumerate(ptr->next, ncnt + 1);
+
+ /* go to sibling if there is one */
+ if (ptr->sibling)
+ (void) Enumerate(ptr->sibling, cnt);
+ return (0);
+}
+
+
+/* PrintOne():
+ * Print the specified key and its associated
+ * function specified by val
+ */
+int
+printOne(key, val, ntype)
+ CStr *key;
+ XmapVal *val;
+ int ntype;
+{
+ struct KeyFuncs *fp;
+ unsigned char unparsbuf[200];
+ static char *fmt = "%s\n";
+
+ xprintf("%-15S-> ", key->buf);
+ if (val != NULL)
+ switch (ntype) {
+ case XK_STR:
+ case XK_EXE:
+ xprintf(fmt, unparsestring(&val->str, unparsbuf,
+ ntype == XK_STR ? STRQQ : STRBB));
+ break;
+ case XK_CMD:
+ for (fp = FuncNames; fp->name; fp++)
+ if (val->cmd == fp->func)
+ xprintf(fmt, fp->name);
+ break;
+ default:
+ abort();
+ break;
+ }
+ else
+ xprintf(fmt, key, CGETS(9, 7, "no input"));
+ return (0);
+}
+
+static int
+unparsech(cnt, ch)
+ int cnt;
+ Char *ch;
+{
+ if (ch == 0) {
+ printbuf[cnt++] = '^';
+ printbuf[cnt] = '@';
+ return cnt;
+ }
+
+ if (Iscntrl(*ch)) {
+#ifndef _OSD_POSIX
+ printbuf[cnt++] = '^';
+ if (*ch == CTL_ESC('\177'))
+ printbuf[cnt] = '?';
+ else
+ printbuf[cnt] = *ch | 0100;
+#else /*_OSD_POSIX*/
+ if (*ch == CTL_ESC('\177'))
+ {
+ printbuf[cnt++] = '^';
+ printbuf[cnt] = '?';
+ }
+ else if (Isupper(_toebcdic[_toascii[*ch]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[*ch]|0100]) != NULL)
+ {
+ printbuf[cnt++] = '^';
+ printbuf[cnt] = _toebcdic[_toascii[*ch]|0100];
+ }
+ else
+ {
+ printbuf[cnt++] = '\\';
+ printbuf[cnt++] = ((*ch >> 6) & 7) + '0';
+ printbuf[cnt++] = ((*ch >> 3) & 7) + '0';
+ printbuf[cnt] = (*ch & 7) + '0';
+ }
+#endif /*_OSD_POSIX*/
+ }
+ else if (*ch == '^') {
+ printbuf[cnt++] = '\\';
+ printbuf[cnt] = '^';
+ }
+ else if (*ch == '\\') {
+ printbuf[cnt++] = '\\';
+ printbuf[cnt] = '\\';
+ }
+ else if (*ch == ' ' || (Isprint(*ch) && !Isspace(*ch))) {
+ printbuf[cnt] = *ch;
+ }
+ else {
+ printbuf[cnt++] = '\\';
+ printbuf[cnt++] = ((*ch >> 6) & 7) + '0';
+ printbuf[cnt++] = ((*ch >> 3) & 7) + '0';
+ printbuf[cnt] = (*ch & 7) + '0';
+ }
+ return cnt;
+}
+
+int
+parseescape(ptr)
+ const Char **ptr;
+{
+ const Char *p;
+ Char c;
+
+ p = *ptr;
+
+ if ((p[1] & CHAR) == 0) {
+ xprintf(CGETS(9, 8, "Something must follow: %c\n"), *p);
+ return -1;
+ }
+ if ((*p & CHAR) == '\\') {
+ p++;
+ switch (*p & CHAR) {
+ case 'a':
+ c = CTL_ESC('\007'); /* Bell */
+ break;
+ case 'b':
+ c = CTL_ESC('\010'); /* Backspace */
+ break;
+ case 'e':
+ c = CTL_ESC('\033'); /* Escape */
+ break;
+ case 'f':
+ c = CTL_ESC('\014'); /* Form Feed */
+ break;
+ case 'n':
+ c = CTL_ESC('\012'); /* New Line */
+ break;
+ case 'r':
+ c = CTL_ESC('\015'); /* Carriage Return */
+ break;
+ case 't':
+ c = CTL_ESC('\011'); /* Horizontal Tab */
+ break;
+ case 'v':
+ c = CTL_ESC('\013'); /* Vertical Tab */
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int cnt, val, ch;
+
+ for (cnt = 0, val = 0; cnt < 3; cnt++) {
+ ch = *p++ & CHAR;
+ if (ch < '0' || ch > '7') {
+ p--;
+ break;
+ }
+ val = (val << 3) | (ch - '0');
+ }
+ if ((val & 0xffffff00) != 0) {
+ xprintf(CGETS(9, 9,
+ "Octal constant does not fit in a char.\n"));
+ return 0;
+ }
+#ifdef _OSD_POSIX
+ if (CTL_ESC(val) != val && adrof(STRwarnebcdic))
+ xprintf(/*CGETS(9, 9, no NLS-String yet!*/
+ "Warning: Octal constant \\%3.3o is interpreted as EBCDIC value.\n", val/*)*/);
+#endif
+ c = (Char) val;
+ --p;
+ }
+ break;
+ default:
+ c = *p;
+ break;
+ }
+ }
+ else if ((*p & CHAR) == '^' && (Isalpha(p[1] & CHAR) ||
+ strchr("@^_?\\|[{]}", p[1] & CHAR))) {
+ p++;
+#ifndef _OSD_POSIX
+ c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : ((*p & CHAR) & 0237);
+#else /*_OSD_POSIX*/
+ c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*p & CHAR] & 0237];
+ if (adrof(STRwarnebcdic))
+ xprintf(/*CGETS(9, 9, no NLS-String yet!*/
+ "Warning: Control character ^%c may be interpreted differently in EBCDIC.\n", *p & CHAR /*)*/);
+#endif /*_OSD_POSIX*/
+ }
+ else
+ c = *p;
+ *ptr = p;
+ return (c);
+}
+
+
+unsigned char *
+unparsestring(str, buf, sep)
+ CStr *str;
+ unsigned char *buf;
+ Char *sep;
+{
+ unsigned char *b;
+ Char p;
+ int l;
+
+ b = buf;
+ if (sep[0])
+#ifndef WINNT
+ *b++ = sep[0];
+#else /* WINNT */
+ *b++ = CHAR & sep[0];
+#endif /* !WINNT */
+
+ for (l = 0; l < str->len; l++) {
+ p = str->buf[l];
+ if (Iscntrl(p)) {
+#ifndef _OSD_POSIX
+ *b++ = '^';
+ if (p == CTL_ESC('\177'))
+ *b++ = '?';
+ else
+ *b++ = (unsigned char) (p | 0100);
+#else /*_OSD_POSIX*/
+ if (_toascii[p] == '\177' || Isupper(_toebcdic[_toascii[p]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[p]|0100]) != NULL)
+ {
+ *b++ = '^';
+ *b++ = (_toascii[p] == '\177') ? '?' : _toebcdic[_toascii[p]|0100];
+ }
+ else
+ {
+ *b++ = '\\';
+ *b++ = ((p >> 6) & 7) + '0';
+ *b++ = ((p >> 3) & 7) + '0';
+ *b++ = (p & 7) + '0';
+ }
+#endif /*_OSD_POSIX*/
+ }
+ else if (p == '^' || p == '\\') {
+ *b++ = '\\';
+ *b++ = (unsigned char) p;
+ }
+ else if (p == ' ' || (Isprint(p) && !Isspace(p))) {
+ *b++ = (unsigned char) p;
+ }
+ else {
+ *b++ = '\\';
+ *b++ = ((p >> 6) & 7) + '0';
+ *b++ = ((p >> 3) & 7) + '0';
+ *b++ = (p & 7) + '0';
+ }
+ }
+ if (sep[0] && sep[1])
+#ifndef WINNT
+ *b++ = sep[1];
+#else /* WINNT */
+ *b++ = CHAR & sep[1];
+#endif /* !WINNT */
+ *b++ = 0;
+ return buf; /* should check for overflow */
+}
diff --git a/contrib/tcsh/eight-bit.me b/contrib/tcsh/eight-bit.me
new file mode 100644
index 0000000..466f011
--- /dev/null
+++ b/contrib/tcsh/eight-bit.me
@@ -0,0 +1,143 @@
+.\" $Id: eight-bit.me,v 3.1 1991/09/12 09:25:57 christos Exp $
+How to use 8 bit characters
+by
+Johan Widen
+(jw@sics.se)
+and
+Per Hedeland
+(per@erix.ericsson.se)
+
+.pp
+(Disclaimer: This is really a sketch of an approach rather
+than a "how-to" document.
+Also, it is mostly relevant to Swedish X Window users...)
+
+.pp
+The way I use this facility at present is to add lines such as the following
+to my .cshrc:
+
+.nf
+setenv NOREBIND
+setenv LC_CTYPE iso_8859_1
+foreach key ( \\\\304 \\\\305 \\\\326 \\\\344 \\\\345 \\\\366 )
+ bindkey $key self-insert-command
+end
+.fi
+
+.pp
+Note that if I used a system with a reasonably complete NLS
+(and a tcsh compiled to use it),
+all of the above could be replaced with simply setting the LANG environment
+variable to an appropriate value - the NLS would then indicate exactly which
+characters should be considered printable, and tcsh would do the rebinding
+of these automatically. The above works for tcsh's simulated NLS and for
+the NLS in SunOS 4.1 - without the NOREBIND setting, all of the
+Meta-<non-control-character> bindings would be undone in these cases.
+
+.pp
+These keybindings are the codes for my national characters, but the bindings
+(M-d, M-e etc) are not conveniently placed.
+They are however consistent with what other programs will see.
+
+.pp
+Now: I actually want the character \\304 to be inserted when I press say '{'
+together with a modifier key. I want the behavior to be the same not only
+in tcsh but in say cat, an editor and all other programs. I fix this by
+performing a keyboard remapping with the
+.i xmodmap
+program (I use X Windows).
+
+.pp
+I give xmodmap an input something like the following:
+
+.nf
+keycode 26 = Mode_switch
+add mod2 = Mode_switch
+! if you want Mode_switch to toggle, at the expense of losing
+! Caps- or whatever Lock you currently have, add the two lines below
+! clear Lock
+! add Lock = Mode_switch
+! Binds swedish characters on ][\\
+!
+keycode 71 = bracketleft braceleft adiaeresis Adiaeresis
+keycode 72 = bracketright braceright aring Aring
+keycode 95 = backslash bar odiaeresis Odiaeresis
+.fi
+
+or:
+
+.nf
+keysym Alt_R = Mode_switch
+add mod2 = Mode_switch
+keysym bracketleft = bracketleft braceleft Adiaeresis adiaeresis
+keysym bracketright = bracketright braceright Aring aring
+keysym backslash = backslash bar Odiaeresis odiaeresis
+.fi
+
+Another, more portable way of doing the same thing is:
+
+.nf
+#!/bin/sh
+# Make Alt-] etc produce the "appropriate" Swedish iso8859/1 keysym values
+# Should handle fairly strange initial mappings
+
+xmodmap -pk | sed -e 's/[()]//g' | \\
+awk 'BEGIN {
+ alt["bracketright"] = "Aring"; alt["braceright"] = "aring";
+ alt["bracketleft"] = "Adiaeresis"; alt["braceleft"] = "adiaeresis";
+ alt["backslash"] = "Odiaeresis"; alt["bar"] = "odiaeresis";
+}
+NF >= 5 && (alt[$3] != "" || alt[$5] != "") {
+ printf "keycode %s = %s %s ", $1, $3, $5;
+ if (alt[$3] != "") printf "%s ", alt[$3];
+ else printf "%s ", $3;
+ printf "%s\\n", alt[$5];
+ next;
+}
+alt[$3] != "" {
+ printf "keycode %s = %s %s %s\\n", $1, $3, $3, alt[$3];
+}
+NF >= 5 && ($3 ~ /^Alt_[LR]$/ || $5 ~ /^Alt_[LR]$/) {
+ printf "keycode %s = %s %s Mode_switch\\n", $1, $3, $5;
+ if ($3 ~ /^Alt_[LR]$/) altkeys = altkeys " " $3;
+ else altkeys = altkeys " " $5;
+ next;
+}
+$3 ~ /^Alt_[LR]$/ {
+ printf "keycode %s = %s %s Mode_switch\\n", $1, $3, $3;
+ altkeys = altkeys " " $3;
+}
+END {
+ if (altkeys != "") printf "clear mod2\\nadd mod2 =%s\\n", altkeys;
+}' | xmodmap -
+.fi
+
+.pp
+Finally, with the binding of the codes of my national characters to
+self-insert-command, I lost the ability to use the Meta key to call the
+functions previously bound to M-d, M-e, and M-v (<esc>d etc still works).
+However, with the assumption that
+most of my input to tcsh will be through the
+.i xterm
+terminal emulator, I can get that ability back via xterm bindings!
+Since M-d is the only one of the "lost" key combinations that was
+actually bound to a function in my case,
+and it had the same binding as M-D, I can use the following in
+my .Xdefaults file:
+
+.nf
+XTerm*VT100.Translations: #override \\n\\
+ Meta ~Ctrl<Key>d: string(0x1b) string(d)
+.fi
+
+- or, if I really want a complete mapping:
+
+.nf
+XTerm*VT100.Translations: #override \\n\\
+ :Meta ~Ctrl<Key>d: string(0x1b) string(d) \\n\\
+ :Meta ~Ctrl<Key>D: string(0x1b) string(D) \\n\\
+ :Meta ~Ctrl<Key>e: string(0x1b) string(e) \\n\\
+ :Meta ~Ctrl<Key>E: string(0x1b) string(E) \\n\\
+ :Meta ~Ctrl<Key>v: string(0x1b) string(v) \\n\\
+ :Meta ~Ctrl<Key>V: string(0x1b) string(V)
+.fi
diff --git a/contrib/tcsh/gethost.c b/contrib/tcsh/gethost.c
new file mode 100644
index 0000000..236be59
--- /dev/null
+++ b/contrib/tcsh/gethost.c
@@ -0,0 +1,344 @@
+/* $Header: /src/pub/tcsh/gethost.c,v 1.7 1997/10/28 22:34:19 christos Exp $ */
+/*
+ * gethost.c: Create version file from prototype
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: gethost.c,v 1.7 1997/10/28 22:34:19 christos Exp $")
+
+#ifdef SCO
+# define perror __perror
+# define rename __rename
+# define getopt __getopt
+# define system __system
+#endif
+#include <stdio.h>
+#ifdef SCO
+# undef perror
+# undef rename
+# undef getopt
+# undef system
+#endif
+
+#include <ctype.h>
+
+/* Some people don't bother to declare these */
+#if defined(SUNOS4) || defined(ibm032)
+extern int fprintf();
+extern int fclose();
+#endif /* SUNOS4 || ibm032 */
+
+#define ISSPACE(p) (isspace((unsigned char) (p)) && (p) != '\n')
+
+/*
+ * We cannot do that, because some compilers like #line and others
+ * like # <lineno>
+ * #define LINEDIRECTIVE
+ */
+
+static const char *keyword[] =
+{
+ "vendor",
+#define T_VENDOR 0
+ "hosttype",
+#define T_HOSTTYPE 1
+ "machtype",
+#define T_MACHTYPE 2
+ "ostype",
+#define T_OSTYPE 3
+ "newdef",
+#define T_NEWDEF 4
+ "enddef",
+#define T_ENDDEF 5
+ "newcode",
+#define T_NEWCODE 6
+ "endcode",
+#define T_ENDCODE 7
+ "comment",
+#define T_COMMENT 8
+ "macro",
+#define T_MACRO 9
+ NULL
+#define T_NONE 10
+};
+
+#define S_DISCARD 0
+#define S_COMMENT 1
+#define S_CODE 2
+#define S_KEYWORD 3
+
+static int findtoken __P((char *));
+static char *gettoken __P((char **, char *));
+
+int main __P((int, char *[]));
+
+/* findtoken():
+ * Return the token number of the given token
+ */
+static int
+findtoken(ptr)
+ char *ptr;
+{
+ int i;
+
+ if (ptr == NULL || *ptr == '\0')
+ return T_NONE;
+
+ for (i = 0; keyword[i] != NULL; i++)
+ if (strcmp(keyword[i], ptr) == 0)
+ return i;
+
+ return T_NONE;
+}
+
+
+/* gettoken():
+ * Get : delimited token and remove leading/trailing blanks/newlines
+ */
+static char *
+gettoken(pptr, token)
+ char **pptr;
+ char *token;
+{
+ char *ptr = *pptr;
+ char *tok = token;
+
+ for (; *ptr && ISSPACE(*ptr); ptr++)
+ continue;
+
+ for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
+ continue;
+
+ if (*ptr == ':')
+ ptr++;
+ else
+ tok--;
+
+ for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
+ continue;
+
+ *++tok = '\0';
+
+ *pptr = ptr;
+ return token;
+}
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char line[INBUFSIZE];
+ char *pname;
+ char *fname = "stdin";
+ char *ptr, *tok;
+ char defs[INBUFSIZE];
+ char stmt[INBUFSIZE];
+ FILE *fp = stdin;
+ int lineno = 0;
+ int inprocess = 0;
+ int token, state;
+ int errs = 0;
+
+ if ((pname = strrchr(argv[0], '/')) == NULL)
+ pname = argv[0];
+ else
+ pname++;
+
+ if (argc > 2) {
+ (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
+ return 1;
+ }
+
+ if (argc == 2)
+ if ((fp = fopen(fname = argv[1], "r")) == NULL) {
+ (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
+ return 1;
+ }
+
+ state = S_DISCARD;
+
+ while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
+ lineno++;
+ switch (token = findtoken(gettoken(&ptr, defs))) {
+ case T_NEWCODE:
+ state = S_CODE;
+ break;
+
+ case T_ENDCODE:
+ state = S_DISCARD;
+ break;
+
+ case T_COMMENT:
+ state = S_COMMENT;
+ break;
+
+ case T_NEWDEF:
+ state = S_KEYWORD;
+ break;
+
+ case T_ENDDEF:
+ state = S_DISCARD;
+ break;
+
+ case T_VENDOR:
+ state = S_KEYWORD;
+ break;
+
+ case T_HOSTTYPE:
+ state = S_KEYWORD;
+ break;
+
+ case T_MACHTYPE:
+ state = S_KEYWORD;
+ break;
+
+ case T_OSTYPE:
+ state = S_KEYWORD;
+ break;
+
+ case T_MACRO:
+ if (gettoken(&ptr, defs) == NULL) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
+ pname, fname, lineno);
+ break;
+ }
+ if (gettoken(&ptr, stmt) == NULL) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
+ pname, fname, lineno);
+ break;
+ }
+ (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
+ defs);
+ break;
+
+ case T_NONE:
+ if (state != S_CODE && defs && *defs != '\0') {
+ (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
+ pname, fname, lineno);
+ if (++errs == 30) {
+ (void) fprintf(stderr, "%s: Too many errors\n", pname);
+ return 1;
+ }
+ break;
+ }
+ (void) fprintf(stdout, "%s", line);
+ break;
+
+ default:
+ (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
+ pname, fname, lineno);
+ return 1;
+ }
+
+ switch (state) {
+ case S_DISCARD:
+ if (inprocess) {
+ inprocess = 0;
+ (void) fprintf(stdout, "#endif\n");
+ }
+ break;
+
+ case S_KEYWORD:
+ tok = gettoken(&ptr, defs);
+ if (token == T_NEWDEF) {
+ if (inprocess) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
+ pname, fname, lineno);
+ return 1;
+ }
+ if (tok == NULL) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
+ pname, fname, lineno);
+ return 1;
+ }
+ (void) fprintf(stdout, "\n\n");
+#ifdef LINEDIRECTIVE
+ (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
+#endif /* LINEDIRECTIVE */
+ (void) fprintf(stdout, "#if %s\n", defs);
+ inprocess = 1;
+ }
+ else {
+ if (tok && *tok)
+ (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
+ defs, keyword[token]);
+ else
+ (void) fprintf(stdout, "# if !defined(_%s_)\n",
+ keyword[token]);
+
+ if (gettoken(&ptr, stmt) == NULL) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
+ pname, fname, lineno);
+ return 1;
+ }
+ (void) fprintf(stdout, "# define _%s_\n", keyword[token]);
+ (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt);
+ (void) fprintf(stdout, "# endif\n");
+ }
+ break;
+
+ case S_COMMENT:
+ if (gettoken(&ptr, defs))
+ (void) fprintf(stdout, " /* %s */\n", defs);
+ break;
+
+ case S_CODE:
+ if (token == T_NEWCODE) {
+#ifdef LINEDIRECTIVE
+ (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
+#endif /* LINEDIRECTIVE */
+ }
+ break;
+
+ default:
+ (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
+ pname, fname, lineno);
+ return 1;
+ }
+ }
+
+ if (inprocess) {
+ (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
+ pname, fname, lineno);
+ return 1;
+ }
+
+ if (fp != stdin)
+ (void) fclose(fp);
+
+ return 0;
+}
diff --git a/contrib/tcsh/glob.3 b/contrib/tcsh/glob.3
new file mode 100644
index 0000000..2fc84e0
--- /dev/null
+++ b/contrib/tcsh/glob.3
@@ -0,0 +1,326 @@
+.\" Copyright (c) 1989 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Guido van Rossum.
+.\"
+.\" Redistribution and use in source and binary forms are permitted provided
+.\" that: (1) source distributions retain this entire copyright notice and
+.\" comment, and (2) distributions including binaries display the following
+.\" acknowledgement: ``This product includes software developed by the
+.\" University of California, Berkeley and its contributors'' in the
+.\" documentation or other materials provided with the distribution and in
+.\" all advertising materials mentioning features or use of this software.
+.\" Neither the name of the University nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)glob.3 5.3 (Berkeley) 3/19/91
+.\"
+.TH GLOB 3 "March 19, 1991"
+.UC 7
+.SH NAME
+glob, globfree \- generate pathnames matching a pattern
+.SH SYNOPSIS
+.nf
+#include <glob.h>
+
+glob(const char *pattern, int flags,
+ const int (*errfunc)(char *, int), glob_t *pglob);
+
+void globfree(glob_t *pglob);
+.fi
+.SH DESCRIPTION
+.I Glob
+is a pathname generator that implements the rules for file name pattern
+matching used by the shell.
+.PP
+The include file
+.I glob.h
+defines the structure type
+.IR glob_t ,
+which contains at least the following fields:
+.sp
+.RS
+.nf
+.ta .5i +\w'char **gl_pathv;\0\0\0'u
+typedef struct {
+ int gl_pathc; /* count of total paths so far */
+ int gl_matchc; /* count of paths matching pattern */
+ int gl_offs; /* reserved at beginning of gl_pathv */
+ int gl_flags; /* returned flags */
+ char **gl_pathv; /* list of paths matching pattern */
+} glob_t;
+.fi
+.RE
+.PP
+The argument
+.I pattern
+is a pointer to a pathname pattern to be expanded.
+.I Glob
+matches all accessible pathnames against the pattern and creates
+a list of the pathnames that match.
+In order to have access to a pathname,
+.I glob
+requires search permission on every component of a path except the last
+and read permission on each directory of any filename component of
+.I pattern
+that contains any of the special characters ``*'', ``?'' or ``[''.
+.PP
+.I Glob
+stores the number of matched pathnames into the
+.I gl_pathc
+field, and a pointer to a list of pointers to pathnames into the
+.I gl_pathv
+field.
+The first pointer after the last pathname is NULL.
+If the pattern does not match any pathnames, the returned number of
+matched paths is set to zero.
+.PP
+It is the caller's responsibility to create the structure pointed to by
+.IR pglob .
+The
+.I glob
+function allocates other space as needed, including the memory pointed
+to by
+.IR gl_pathv .
+.PP
+The argument
+.I flags
+is used to modify the behavior of
+.IR glob .
+The value of
+.I flags
+is the bitwise inclusive OR of any of the following
+values defined in
+.IR glob.h :
+.TP
+GLOB_APPEND
+Append pathnames generated to the ones from a previous call (or calls)
+to
+.IR glob .
+The value of
+.I gl_pathc
+will be the total matches found by this call and the previous call(s).
+The pathnames are appended to, not merged with the pathnames returned by
+the previous call(s).
+Between calls, the caller must not change the setting of the
+GLOB_DOOFFS flag, nor change the value of
+.I gl_offs
+when
+GLOB_DOOFFS is set, nor (obviously) call
+.I globfree
+for
+.I pglob.
+.TP
+GLOB_DOOFFS
+Make use of the
+.I gl_offs
+field.
+If this flag is set,
+.I gl_offs
+is used to specify how many NULL pointers to prepend to the beginning
+of the
+.I gl_pathv
+field.
+In other words,
+.I gl_pathv
+will point to
+.I gl_offs
+NULL pointers,
+followed by
+.I gl_pathc
+pathname pointers, followed by a NULL pointer.
+.TP
+GLOB_ERR
+Causes
+.I glob
+to return when it encounters a directory that it cannot open or read.
+Ordinarily,
+.I glob
+continues to find matches.
+.TP
+GLOB_MARK
+Each pathname that is a directory that matches
+.I pattern
+has a slash
+appended.
+.TP
+GLOB_NOSORT
+By default, the pathnames are sorted in ascending ASCII order;
+this flag prevents that sorting (speeding up
+.IR glob ).
+.TP
+GLOB_NOCHECK
+If
+.I pattern
+does not match any pathname, then
+.I glob
+returns a list
+consisting of only
+.IR pattern ,
+with the number of total pathnames is set to 1, and the number of matched
+pathnames set to 0.
+If
+.I GLOB_QUOTE
+is set, its effect is present in the pattern returned.
+.TP
+GLOB_QUOTE
+Use the backslash (``\e'') character for quoting: every occurrence of
+a backslash followed by a character in the pattern is replaced by that
+character, avoiding any special interpretation of the character.
+.TP
+GLOB_NOMAGIC
+Is the same as GLOB_NOCHECK but it only appends the
+.IR pattern
+if it does not contain any of the special characters ``*'', ``?'' or ``[''.
+GLOB_NOMAGIC is used to simplify implementing the globbing behavior in
+.IR csh(1).
+.PP
+If, during the search, a directory is encountered that cannot be opened
+or read and
+.I errfunc
+is non-NULL,
+.I glob
+calls (*\fIerrfunc\fP)(\fIpath\fP, \fIerrno\fP).
+This may be unintuitive: a pattern like ``*/Makefile'' will try to
+.IR stat (2)
+``foo/Makefile'' even if ``foo'' is not a directory, resulting in a
+call to
+.IR errfunc .
+The error routine can suppress this action by testing for ENOENT and
+ENOTDIR; however, the GLOB_ERR flag will still cause an immediate
+return when this happens.
+.PP
+If
+.I errfunc
+returns non-zero,
+.I glob
+stops the scan and returns
+.I GLOB_ABEND
+after setting
+.I gl_pathc
+and
+.I gl_pathv
+to reflect any paths already matched.
+This also happens if an error is encountered and
+.I GLOB_ERR
+is set in
+.IR flags ,
+regardless of the return value of
+.IR errfunc ,
+if called.
+If
+.I GLOB_ERR
+is not set and either
+.I errfunc
+is NULL or
+.I errfunc
+returns zero, the error is ignored.
+.PP
+The
+.I globfree
+function frees any space associated with
+.I pglob
+from a previous call(s) to
+.IR glob .
+.SH RETURNS
+On successful completion,
+.I glob
+returns zero.
+In addition the fields of
+.I pglob
+contain the values described below:
+.TP
+.I gl_pathc
+contains the total number of matched pathnames so far.
+This includes other matches from previous invocations of
+.I glob
+if
+.I GLOB_APPEND
+was specified.
+.TP
+.I gl_matchc
+contains the number of matched pathnames in the current invocation of
+.I glob.
+.TP
+.I gl_flags
+contains a copy of the
+.I flags
+parameter with the bit GLOB_MAGCHAR set if
+.I pattern
+contained any of the special characters ``*'', ``?'' or ``['', cleared
+if not.
+.TP
+.I gl_pathv
+contains a pointer to a NULL-terminated list of matched pathnames.
+However, if
+.I gl_pathc
+is zero, the contents of
+.I gl_pathv
+are undefined.
+.PP
+If
+.I glob
+terminates due to an error, it sets errno and returns one of the
+following non-zero constants, which are defined in the include
+file <glob.h>:
+.TP
+GLOB_NOSPACE
+An attempt to allocate memory failed.
+.TP
+GLOB_ABEND
+The scan was stopped because an error was encountered and either
+GLOB_ERR was set or (*\fIerrfunc\fR)() returned non-zero.
+.PP
+The arguments
+.I pglob->gl_pathc
+and
+.I pglob->gl_pathv
+are still set as specified above.
+.SH STANDARDS
+The
+.I glob
+function is expected to be POSIX 1003.2 compatible with the exception
+that the flag
+.I GLOB_QUOTE
+and the fields
+.I gl_matchc
+and
+.I gl_flags
+should not be used by applications striving for strict POSIX conformance.
+.SH EXAMPLE
+A rough equivalent of ``ls -l *.c *.h'' can be obtained with the
+following code:
+.sp
+.nf
+.RS
+glob_t g;
+
+g.gl_offs = 2;
+glob("*.c", GLOB_DOOFFS, NULL, &g);
+glob("*.h", GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
+g.gl_pathv[0] = "ls";
+g.gl_pathv[1] = "-l";
+execvp("ls", g.gl_pathv);
+.RE
+.fi
+.SH SEE ALSO
+sh(1), fnmatch(3), wordexp(3), regexp(3)
+.SH BUGS
+Patterns longer than MAXPATHLEN may cause unchecked errors.
+.PP
+.I Glob
+may fail and set errno for any of the errors specified for the
+library routines
+.I stat (2),
+.I closedir (3),
+.I opendir (3),
+.I readdir (3),
+.I malloc (3),
+and
+.I free (3).
+
diff --git a/contrib/tcsh/glob.c b/contrib/tcsh/glob.c
new file mode 100644
index 0000000..01dee4d
--- /dev/null
+++ b/contrib/tcsh/glob.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)glob.c 5.12 (Berkeley) 6/24/91";
+#endif /* LIBC_SCCS and not lint */
+/*
+ * Glob: the interface is a superset of the one defined in POSIX 1003.2,
+ * draft 9.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_ALTNOT:
+ * Use ^ instead of ! for "not".
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+#ifdef notdef
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <ctype.h>
+typedef void * ptr_t;
+#endif
+#ifdef WINNT
+ #pragma warning(disable:4244)
+#endif /* WINNT */
+
+#define Char __Char
+#include "sh.h"
+#undef Char
+#undef QUOTE
+#undef TILDE
+#undef META
+#undef CHAR
+#undef ismeta
+#undef Strchr
+
+#include "glob.h"
+
+#ifndef S_ISDIR
+#define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+#endif
+
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+#endif
+
+#if !defined(S_ISLNK) && !defined(lstat)
+#define lstat stat
+#endif
+
+typedef unsigned short Char;
+
+static int glob1 __P((Char *, glob_t *, int));
+static int glob2 __P((Char *, Char *, Char *, glob_t *, int));
+static int glob3 __P((Char *, Char *, Char *, Char *,
+ glob_t *, int));
+static int globextend __P((Char *, glob_t *));
+static int match __P((Char *, Char *, Char *, int));
+#ifndef __clipper__
+static int compare __P((const ptr_t, const ptr_t));
+#endif
+static DIR *Opendir __P((Char *));
+#ifdef S_IFLNK
+static int Lstat __P((Char *, struct stat *));
+#endif
+static int Stat __P((Char *, struct stat *sb));
+static Char *Strchr __P((Char *, int));
+#ifdef DEBUG
+static void qprintf __P((Char *));
+#endif
+
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define ALTNOT '^'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+
+#define M_META 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+#define CHAR(c) ((c)&M_ASCII)
+#define META(c) ((c)|M_META)
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ALTNOT META('^')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_META) != 0)
+
+#ifndef BUFSIZE
+#define GLOBBUFLEN MAXPATHLEN
+#else
+#define GLOBBUFLEN BUFSIZE
+#endif
+
+int
+globcharcoll(c1, c2)
+ int c1, c2;
+{
+#if defined(NLS) && defined(LC_COLLATE) && !defined(NOSTRCOLL)
+ char s1[2], s2[2];
+
+ if (c1 == c2)
+ return (0);
+ s1[0] = c1;
+ s2[0] = c2;
+ s1[1] = s2[1] = '\0';
+ return strcoll(s1, s2);
+#else
+ return (c1 - c2);
+#endif
+}
+
+/*
+ * Need to dodge two kernel bugs:
+ * opendir("") != opendir(".")
+ * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels.
+ * POSIX specifies that they should be ignored in directories.
+ */
+
+static DIR *
+Opendir(str)
+ register Char *str;
+{
+ char buf[GLOBBUFLEN];
+ register char *dc = buf;
+#if defined(hpux) || defined(__hpux)
+ struct stat st;
+#endif
+
+ if (!*str)
+ return (opendir("."));
+ while ((*dc++ = *str++) != '\0')
+ continue;
+#if defined(hpux) || defined(__hpux)
+ /*
+ * Opendir on some device files hangs, so avoid it
+ */
+ if (stat(buf, &st) == -1 || !S_ISDIR(st.st_mode))
+ return NULL;
+#endif
+ return (opendir(buf));
+}
+
+#ifdef S_IFLNK
+static int
+Lstat(fn, sb)
+ register Char *fn;
+ struct stat *sb;
+{
+ char buf[GLOBBUFLEN];
+ register char *dc = buf;
+
+ while ((*dc++ = *fn++) != '\0')
+ continue;
+# ifdef NAMEI_BUG
+ {
+ int st;
+
+ st = lstat(buf, sb);
+ if (*buf)
+ dc--;
+ return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
+ }
+# else
+ return (lstat(buf, sb));
+# endif /* NAMEI_BUG */
+}
+#else
+#define Lstat Stat
+#endif /* S_IFLNK */
+
+static int
+Stat(fn, sb)
+ register Char *fn;
+ struct stat *sb;
+{
+ char buf[GLOBBUFLEN];
+ register char *dc = buf;
+
+ while ((*dc++ = *fn++) != '\0')
+ continue;
+#ifdef NAMEI_BUG
+ {
+ int st;
+
+ st = stat(buf, sb);
+ if (*buf)
+ dc--;
+ return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
+ }
+#else
+ return (stat(buf, sb));
+#endif /* NAMEI_BUG */
+}
+
+static Char *
+Strchr(str, ch)
+ Char *str;
+ int ch;
+{
+ do
+ if (*str == ch)
+ return (str);
+ while (*str++);
+ return (NULL);
+}
+
+#ifdef DEBUG
+static void
+qprintf(s)
+Char *s;
+{
+ Char *p;
+
+ for (p = s; *p; p++)
+ printf("%c", *p & 0xff);
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", *p & M_PROTECT ? '"' : ' ');
+ printf("\n");
+ for (p = s; *p; p++)
+ printf("%c", *p & M_META ? '_' : ' ');
+ printf("\n");
+}
+#endif /* DEBUG */
+
+static int
+compare(p, q)
+ const ptr_t p, q;
+{
+#if defined(NLS) && !defined(NOSTRCOLL)
+ errno = 0; /* strcoll sets errno, another brain-damage */
+
+ return (strcoll(*(char **) p, *(char **) q));
+#else
+ return (strcmp(*(char **) p, *(char **) q));
+#endif /* NLS && !NOSTRCOLL */
+}
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+int
+glob(pattern, flags, errfunc, pglob)
+ const char *pattern;
+ int flags;
+ int (*errfunc) __P((const char *, int));
+ glob_t *pglob;
+{
+ int err, oldpathc;
+ Char *bufnext, *bufend, *compilebuf, m_not;
+ const unsigned char *compilepat, *patnext;
+ int c, not;
+ Char patbuf[GLOBBUFLEN + 1], *qpatnext;
+ int no_match;
+
+ patnext = (unsigned char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ oldpathc = pglob->gl_pathc;
+ pglob->gl_matchc = 0;
+
+ if (pglob->gl_flags & GLOB_ALTNOT) {
+ not = ALTNOT;
+ m_not = M_ALTNOT;
+ }
+ else {
+ not = NOT;
+ m_not = M_NOT;
+ }
+
+ bufnext = patbuf;
+ bufend = bufnext + GLOBBUFLEN;
+ compilebuf = bufnext;
+ compilepat = patnext;
+
+ no_match = *patnext == not;
+ if (no_match)
+ patnext++;
+
+ if (flags & GLOB_QUOTE) {
+ /* Protect the quoted characters */
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ if (c == QUOTE) {
+ if ((c = *patnext++) == EOS) {
+ c = QUOTE;
+ --patnext;
+ }
+ *bufnext++ = (Char) (c | M_PROTECT);
+ }
+ else
+ *bufnext++ = (Char) c;
+ }
+ else
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ *bufnext++ = (Char) c;
+ *bufnext = EOS;
+
+ bufnext = patbuf;
+ qpatnext = patbuf;
+ /* we don't need to check for buffer overflow any more */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == not)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ Strchr(qpatnext + 1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == not)
+ --qpatnext;
+ break;
+ }
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_SET;
+ if (c == not)
+ *bufnext++ = m_not;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one, to avoid
+ * exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf(patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob, no_match)) != 0)
+ return (err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc &&
+ ((flags & GLOB_NOCHECK) ||
+ ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) {
+ if (!(flags & GLOB_QUOTE)) {
+ Char *dp = compilebuf;
+ const unsigned char *sp = compilepat;
+
+ while ((*dp++ = *sp++) != '\0')
+ continue;
+ }
+ else {
+ /*
+ * copy pattern, interpreting quotes; this is slightly different
+ * than the interpretation of quotes above -- which should prevail?
+ */
+ while (*compilepat != EOS) {
+ if (*compilepat == QUOTE) {
+ if (*++compilepat == EOS)
+ --compilepat;
+ }
+ *compilebuf++ = (unsigned char) *compilepat++;
+ }
+ *compilebuf = EOS;
+ }
+ return (globextend(patbuf, pglob));
+ }
+ else if (!(flags & GLOB_NOSORT))
+ qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc),
+ pglob->gl_pathc - oldpathc, sizeof(char *),
+ (int (*) __P((const void *, const void *))) compare);
+ return (0);
+}
+
+static int
+glob1(pattern, pglob, no_match)
+ Char *pattern;
+ glob_t *pglob;
+ int no_match;
+{
+ Char pathbuf[GLOBBUFLEN + 1];
+
+ /*
+ * a null pathname is invalid -- POSIX 1003.1 sect. 2.4.
+ */
+ if (*pattern == EOS)
+ return (0);
+ return (glob2(pathbuf, pathbuf, pattern, pglob, no_match));
+}
+
+/*
+ * functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or
+ * more meta characters.
+ */
+static int
+glob2(pathbuf, pathend, pattern, pglob, no_match)
+ Char *pathbuf, *pathend, *pattern;
+ glob_t *pglob;
+ int no_match;
+{
+ struct stat sbuf;
+ int anymeta;
+ Char *p, *q;
+
+ /*
+ * loop over pattern segments until end of pattern or until segment with
+ * meta character found.
+ */
+ anymeta = 0;
+ for (;;) {
+ if (*pattern == EOS) { /* end of pattern? */
+ *pathend = EOS;
+
+ if (Lstat(pathbuf, &sbuf))
+ return (0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != SEP) &&
+ (S_ISDIR(sbuf.st_mode)
+#ifdef S_IFLNK
+ || (S_ISLNK(sbuf.st_mode) &&
+ (Stat(pathbuf, &sbuf) == 0) &&
+ S_ISDIR(sbuf.st_mode))
+#endif
+ )) {
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return (globextend(pathbuf, pglob));
+ }
+
+ /* find end of next segment, copy tentatively to pathend */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && *p != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* no expansion, do next segment */
+ pathend = q;
+ pattern = p;
+ while (*pattern == SEP)
+ *pathend++ = *pattern++;
+ }
+ else /* need expansion, recurse */
+ return (glob3(pathbuf, pathend, pattern, p, pglob, no_match));
+ }
+ /* NOTREACHED */
+}
+
+
+static int
+glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match)
+ Char *pathbuf, *pathend, *pattern, *restpattern;
+ glob_t *pglob;
+ int no_match;
+{
+ extern int errno;
+ DIR *dirp;
+ struct dirent *dp;
+ int err;
+ Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT;
+ char cpathbuf[GLOBBUFLEN], *ptr;;
+
+ *pathend = EOS;
+ errno = 0;
+
+ if (!(dirp = Opendir(pathbuf))) {
+ /* todo: don't call for ENOENT or ENOTDIR? */
+ for (ptr = cpathbuf; (*ptr++ = (char) *pathbuf++) != EOS;)
+ continue;
+ if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (cpathbuf, errno)) ||
+ (pglob->gl_flags & GLOB_ERR))
+ return (GLOB_ABEND);
+ else
+ return (0);
+ }
+
+ err = 0;
+
+ /* search directory for matching names */
+ while ((dp = readdir(dirp)) != NULL) {
+ register unsigned char *sc;
+ register Char *dc;
+
+ /* initial DOT must be matched literally */
+ if (dp->d_name[0] == DOT && *pattern != DOT)
+ continue;
+ for (sc = (unsigned char *) dp->d_name, dc = pathend;
+ (*dc++ = *sc++) != '\0';)
+ continue;
+ if (match(pathend, pattern, restpattern, (int) m_not) == no_match) {
+ *pathend = EOS;
+ continue;
+ }
+ err = glob2(pathbuf, --dc, restpattern, pglob, no_match);
+ if (err)
+ break;
+ }
+ /* todo: check error from readdir? */
+ (void) closedir(dirp);
+ return (err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(path, pglob)
+ Char *path;
+ glob_t *pglob;
+{
+ register char **pathv;
+ register int i;
+ unsigned int newsize;
+ char *copy;
+ Char *p;
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = (char **) (pglob->gl_pathv ?
+ xrealloc((ptr_t) pglob->gl_pathv, (size_t) newsize) :
+ xmalloc((size_t) newsize));
+ if (pathv == NULL)
+ return (GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0;)
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ if ((copy = (char *) xmalloc((size_t) (p - path))) != NULL) {
+ register char *dc = copy;
+ register Char *sc = path;
+
+ while ((*dc++ = *sc++) != '\0')
+ continue;
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return ((copy == NULL) ? GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(name, pat, patend, m_not)
+ register Char *name, *pat, *patend;
+ int m_not;
+{
+ int ok, negate_range;
+ Char c, k;
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ do
+ if (match(name, pat, patend, m_not))
+ return (1);
+ while (*name++ != EOS);
+ return (0);
+ case M_ONE:
+ if (*name++ == EOS)
+ return (0);
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ return (0);
+ if ((negate_range = ((*pat & M_MASK) == m_not)) != 0)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END) {
+ if ((*pat & M_MASK) == M_RNG) {
+ if (globcharcoll(CHAR(c), CHAR(k)) <= 0 &&
+ globcharcoll(CHAR(k), CHAR(pat[1])) <= 0)
+ ok = 1;
+ pat += 2;
+ }
+ else if (c == k)
+ ok = 1;
+ }
+ if (ok == negate_range)
+ return (0);
+ break;
+ default:
+ k = *name++;
+ if (samecase(k) != samecase(c))
+ return (0);
+ break;
+ }
+ }
+ return (*name == EOS);
+}
+
+/* free allocated data belonging to a glob_t structure */
+void
+globfree(pglob)
+ glob_t *pglob;
+{
+ register int i;
+ register char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ xfree((ptr_t) *pp), *pp = NULL;
+ xfree((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL;
+ }
+}
diff --git a/contrib/tcsh/glob.h b/contrib/tcsh/glob.h
new file mode 100644
index 0000000..bed9c4c
--- /dev/null
+++ b/contrib/tcsh/glob.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 5.6 (Berkeley) 4/3/91
+ */
+
+#ifndef _GLOB_H_
+#define _GLOB_H_
+
+typedef struct {
+ int gl_pathc; /* count of total paths so far */
+ int gl_matchc; /* count of paths matching pattern */
+ int gl_offs; /* reserved at beginning of gl_pathv */
+ int gl_flags; /* copy of flags parameter to glob() */
+ /* copy of errfunc parameter to glob() */
+ int (*gl_errfunc) __P((const char *, int));
+ char **gl_pathv; /* list of paths matching pattern */
+} glob_t;
+
+#define GLOB_APPEND 0x001 /* append to output from previous call */
+#define GLOB_DOOFFS 0x002 /* use gl_offs */
+#define GLOB_ERR 0x004 /* return on error */
+#define GLOB_MAGCHAR 0x008 /* pattern had globbing characters */
+#define GLOB_MARK 0x010 /* append / to matching directories */
+#define GLOB_NOCHECK 0x020 /* return pattern itself if nothing matches */
+#define GLOB_NOSORT 0x040 /* don't sort */
+#define GLOB_QUOTE 0x080 /* quote special chars with \ */
+#define GLOB_NOMAGIC 0x100 /* like GLOB_NOCHECK but only if the pattern
+ * did not have any magic characters */
+#define GLOB_ALTNOT 0x200 /* use alternate glob character [^ not !] */
+
+#define GLOB_NOSPACE (-1) /* malloc call failed */
+#define GLOB_ABEND (-2) /* unignored error */
+
+int glob __P((const char *, int, int (*)(const char *, int), glob_t *));
+void globfree __P((glob_t *));
+int globcharcoll __P((int, int));
+
+#endif /* !_GLOB_H_ */
diff --git a/contrib/tcsh/host.defs b/contrib/tcsh/host.defs
new file mode 100644
index 0000000..6f25601
--- /dev/null
+++ b/contrib/tcsh/host.defs
@@ -0,0 +1,1121 @@
+newcode :
+/* $Header: /src/pub/tcsh/host.defs,v 1.25 1999/04/20 07:48:41 christos Exp $ */
+/*
+ * host.defs: Hosttype/Machtype etc.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: host.defs,v 1.25 1999/04/20 07:48:41 christos Exp $")
+
+endcode :
+
+macro : M_mipsel : (defined(mips) || defined(__mips)) && (defined(MIPSEL) || defined(__MIPSEL))
+macro : M_mipseb : (defined(mips) || defined(__mips)) && (defined(MIPSEB) || defined(__MIPSEB))
+macro : M_i386 : (defined(i386) || defined(__i386__))
+macro : M_i486 : (defined(i486) || defined(__i486__))
+macro : M_i586 : (defined(i586) || defined(__i586__))
+macro : M_intel : (defined(M_i386) || defined(M_i486) || defined(M_i586))
+
+newdef : defined(ns32000)
+newcode :
+static char *
+isamultimax(flag)
+ int flag;
+{
+ if (access("/Umax.image", F_OK) == 0)
+ return "multimax";
+ else
+ return flag ? "mach" : "ns32000";
+}
+endcode :
+enddef :
+
+
+newdef : defined(cray)
+newcode :
+/*
+ * On crays, find the current machine type via the target() syscall
+ * We need ctype.h to convert the name returned to lower case
+ */
+# include <sys/target.h>
+# include <ctype.h>
+# include <string.h>
+
+/* From: hpa@hook.eecs.nwu.edu (H. Peter Anvin) */
+static char *
+getcray()
+{
+# ifdef MC_GET_SYSTEM /* If we have target() */
+ struct target data;
+
+ if (target(MC_GET_SYSTEM, &data) != -1) {
+ static char hosttype_buf[sizeof(data.mc_pmt)+1];
+ char *p = (char *) &(data.mc_pmt);
+ char *q = hosttype_buf;
+ int n;
+
+ /*
+ * Copy to buffer and convert to lower case
+ * String may not be null-terminated, so keep a counter
+ */
+ for (n = 0; *p && n < sizeof(data.mc_pmt); n++)
+ *q++ = tolower(p[n]);
+
+ *q = '\0';
+
+ /* replace dashes with underscores if present */
+ while ((q = strchr(hosttype_buf, '-')) != NULL)
+ *q = '_';
+ return hosttype_buf; /* Return in static buffer */
+ }
+ else
+# endif /* MC_GET_SYSTEM */
+ return "cray"; /* target() failed */
+}
+endcode :
+enddef :
+
+
+newdef : defined(convex)
+newcode :
+/*
+ * On convex, find the current machine type via the getsysinfo() syscall
+ */
+#include <sys/sysinfo.h>
+
+/* From: fox@convex.com (David DeSimone) */
+static char *
+getconvex()
+{
+ struct system_information sysinfo;
+ static char result[8];
+
+ if (getsysinfo(SYSINFO_SIZE, &sysinfo) == -1)
+ return "convex";
+
+ switch(sysinfo.cpu_type) {
+#ifdef SI_CPUTYPE_C1
+ case SI_CPUTYPE_C1:
+ return "c1";
+#endif
+
+#ifdef SI_CPUTYPE_C2
+ case SI_CPUTYPE_C2:
+ return "c2";
+#endif
+
+#ifdef SI_CPUTYPE_C2MP
+ case SI_CPUTYPE_C2MP:
+ (void) strcpy(result, "c2X0");
+ result[2] = sysinfo.cpu_count + '0';
+ return result;
+#endif
+
+#ifdef SI_CPUTYPE_C34
+ case SI_CPUTYPE_C34:
+ (void) strcpy(result, "c34X0");
+ result[3] = sysinfo.cpu_count + '0';
+ return result;
+#endif
+
+#ifdef SI_CPUTYPE_C38
+ case SI_CPUTYPE_C38:
+ (void) strcpy(result, "c38X0");
+ result[3] = sysinfo.cpu_count + '0';
+ return result;
+#endif
+
+#ifdef SI_CPUTYPE_C46
+ case SI_CPUTYPE_C46:
+ (void) strcpy(result, "c46X0");
+ result[3] = sysinfo.cpu_count + '0';
+ return result;
+#endif
+
+ default:
+ return "convex";
+ }
+}
+endcode :
+enddef :
+
+
+newcode :
+void
+getmachine()
+{
+ char *hosttype;
+ char *ostype;
+ char *vendor;
+ char *machtype;
+
+endcode :
+
+
+newdef : defined(__PARAGON__)
+comment : Intel Paragon running OSF/1
+vendor : : "intel"
+hosttype: : "paragon"
+ostype : : "osf1"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(AMIX)
+comment : Amiga running Amix 2.02
+vendor : : "commodore"
+hosttype: : "amiga"
+ostype : : "Amix"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(accel)
+comment : celerity Accel
+vendor : : "celerity"
+hosttype: : "celerityACCEL"
+ostype : : "unix"
+machtype: : "accel"
+enddef :
+
+
+newdef : defined(_VMS_POSIX)
+comment : digital vax or alpha running vms posix
+vendor : : "dec"
+hosttype: : "VMS-POSIX"
+ostype : : "vms"
+machtype: defined(__alpha) : "alpha"
+machtype: defined(__vax) || defined(vax) : "vax"
+machtype: defined(__vax__) : "vax"
+enddef :
+
+
+newdef : defined(__hp_osf)
+comment : Hewlett Packard running OSF/1
+vendor : : "hp"
+hosttype: defined(__pa_risc) : "hp9000s700-osf1"
+hosttype: : "hp-osf1"
+ostype : : "osf1"
+machtype: defined(__pa_risc) : "pa_risc"
+enddef :
+
+
+newdef : defined(hp9000)
+comment : Hewlett Packard running MORE/bsd
+vendor : : "hp"
+hosttype: defined(hp300) : "hp300"
+hosttype: defined(hp800) : "hp800"
+hosttype: : "hp9000"
+ostype : defined(BSD4_4) : "bsd44"
+ostype : : "mtXinu"
+machtype: defined(hp300) : "m68k"
+machtype: defined(hp800) : "pa_risc"
+enddef :
+
+
+newdef : defined(hpux) || defined(__hpux)
+comment : Hewlett Packard running HP/UX
+vendor : : "hp"
+hosttype: defined(__hp9000s700) : "hp9000s700"
+hosttype: defined(__hp9000s800) || defined(hp9000s800) : "hp9000s800"
+hosttype: defined(hp9000s500) : "hp9000s500"
+hosttype: defined(__hp9000s300) || defined(hp9000s300) : "hp9000s300"
+hosttype: : "hp"
+ostype : : "hpux"
+machtype: defined(__hp9000s700) : "pa_risc"
+machtype: defined(__hp9000s800) || defined(hp9000s800) : "pa_risc"
+machtype: defined(hp9000s500) : "m68k"
+machtype: defined(__hp9000s300) || defined(hp9000s300) : "m68k"
+enddef :
+
+
+newdef : defined(apollo)
+comment : Hewlett Packard apollo running Domain/OS
+vendor : : "hp"
+hosttype: : "apollo"
+ostype : : "DomainOS"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(sun) || defined(__sun__)
+comment : Sun Microsystems series 2 workstation (68010 based)
+comment : Sun Microsystems series 3 workstation (68020 based)
+comment : Sun Microsystems 386i workstation (386 based)
+comment : Sun Microsystems series 4 workstation (SPARC based)
+vendor : : "sun"
+hosttype: defined(M_i386) && !defined(__SVR4) : "sun386i"
+hosttype: defined(M_i386) && defined(__SVR4) : "i86pc"
+hosttype: defined(mc68010) || defined(__mc68010__) : "sun2"
+hosttype: defined(mc68020) || defined(__mc68020__) : "sun3"
+hosttype: defined(sparc) || defined(__sparc__) : "sun4"
+hosttype: : "sun"
+ostype : defined(SUNOS3) : "sunos3"
+ostype : defined(SUNOS4) : "sunos4"
+ostype : defined(SOLARIS2) : "solaris"
+machtype: defined(mc68010) || defined(__mc68010__) : "m68k"
+machtype: defined(mc68020) || defined(__mc68020__) : "m68k"
+machtype: defined(sparc) || defined(__sparc__) : "sparc"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(pyr)
+comment : Pyramid Technology
+vendor : : "pyramid"
+hosttype: : "pyramid"
+machtype: : "pyramid"
+enddef :
+
+
+newdef : defined(hcx) || defined(_CX_UX)
+comment : Harris Tahoe running CX/UX
+vendor : : "harris"
+hosttype: : "hcx"
+ostype : : "hcx"
+machtype: : "tahoe"
+enddef :
+
+
+newdef : defined(tahoe)
+comment : Harris Tahoe
+vendor : : "harris"
+hosttype: : "tahoe"
+machtype: : "tahoe"
+enddef :
+
+
+newdef : defined(ibm032)
+comment : RT running IBM AOS4.3 or MACH
+vendor : : "ibm"
+hosttype: : "rt"
+ostype : defined(MACH) : "mach"
+ostype : : "aos"
+machtype: : "ibm032"
+enddef :
+
+
+newdef : defined(aiws)
+comment : RT running IBM aix2.x
+vendor : : "ibm"
+hosttype: : "rtpc"
+ostype : : "aix"
+machtype: : "ibm032"
+enddef :
+
+
+newdef : defined(_AIX370)
+comment : IBM/370 running aix
+vendor : : "ibm"
+hosttype: : "aix370"
+ostype : : "aix"
+machtype: : "ibm370"
+enddef :
+
+
+newdef : defined(_IBMESA)
+comment : IBM/ESA running aix
+vendor : : "ibm"
+hosttype: : "aixESA"
+ostype : : "aix"
+machtype: : "esa"
+enddef :
+
+
+newdef : defined(_IBMR2)
+comment : IBM/RS6000 running aix
+vendor : : "ibm"
+hosttype: : "rs6000"
+ostype : : "aix"
+machtype: : "rs6000"
+enddef :
+
+
+newdef : defined(_AIXPS2)
+comment : IBM/PS2 running aix
+vendor : : "ibm"
+hosttype: : "ps2"
+ostype : : "aix"
+machtype: : "i386"
+enddef :
+
+
+newdef : defined(OREO)
+comment : Macintosh running AU/X
+vendor : : "apple"
+hosttype: : "mac2"
+ostype : : "aux"
+machtype: defined(mc68020) : "m68k"
+enddef :
+
+
+newdef : defined(u3b20d)
+comment : AT&T 3B/20 series running SVR2/3
+vendor : : "att"
+hosttype: : "att3b20"
+machtype: : "u3b20"
+enddef :
+
+
+newdef : defined(u3b15)
+comment : AT&T 3B/15 series running SVR2/3
+vendor : : "att"
+hosttype: : "att3b15"
+machtype: : "u3b15"
+enddef :
+
+
+newdef : defined(u3b5)
+comment : AT&T 3B/5 series running SVR2/3
+vendor : : "att"
+hosttype: : "att3b5"
+machtype: : "u3b5"
+enddef :
+
+
+newdef : defined(u3b2)
+comment : AT&T 3B/2 series running SVR2/3
+vendor : : "att"
+hosttype: : "att3b2"
+machtype: : "u3b2"
+enddef :
+
+
+newdef : defined(UNIXPC)
+comment : AT&T UnixPC att3b1/att7300
+vendor : : "att"
+hosttype: : "unixpc"
+machtype: defined(u3b1) : "u3b1"
+machtype: defined(att7300) : "att7300"
+enddef :
+
+
+newdef : defined(_MINIX)
+comment : Andy Tanenbaum's minix
+vendor : defined(M_i386) : "intel"
+hosttype: defined(M_i386) : "minix386"
+hosttype: : "minix"
+ostype : : "minix"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(linux)
+comment : Linus Torvalds's linux
+vendor : defined(M_intel) : "intel"
+hosttype: defined(M_i586) : "i586-linux"
+hosttype: defined(M_i486) : "i486-linux"
+hosttype: defined(M_i386) : "i386-linux"
+ostype : !defined(PPC) : "linux"
+ostype : defined(PPC) : "mklinux"
+machtype: defined(M_i586) : "i586"
+machtype: defined(M_i486) : "i486"
+machtype: defined(M_i386) : "i386"
+vendor : defined(__alpha) : "dec"
+vendor : defined(PPC) : "apple"
+hosttype: defined(__alpha) : "alpha"
+hosttype: defined(PPC) : "powerpc"
+machtype: defined(__alpha) : "alpha"
+machtype: defined(PPC) : "powerpc"
+enddef :
+
+
+newdef : defined(__EMX__)
+comment : OS/2 EMX [unix emulation under OS/2]
+vendor : defined(M_intel) : "intel"
+hosttype: defined(M_i386) : "i386-emx"
+ostype : : "os2"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(__NetBSD__)
+comment : NetBSD
+vendor : defined(arm32) : "acorn"
+vendor : defined(alpha) : "digital"
+vendor : defined(amiga) : "commodore"
+vendor : defined(atari) : "atari"
+vendor : defined(hp300) : "hp"
+vendor : defined(M_intel) : "intel"
+vendor : defined(m68k) : "motorola"
+vendor : defined(mac68k) : "apple"
+vendor : defined(pc532) : "national-semi"
+vendor : defined(pmax) || defined(mips) : "dec"
+vendor : defined(M_mipsel) : "dec"
+vendor : defined(sparc) : "sun"
+vendor : defined(sun3) : "sun"
+vendor : defined(vax) : "digital"
+hosttype: : "NetBSD"
+ostype : : "NetBSD"
+machtype: defined(arm32) : "arm32"
+machtype: defined(sparc) : "sparc"
+machtype: defined(mc68020) : "m68k"
+machtype: defined(M_i386) : "i386"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+machtype: defined(mips) : "mips"
+machtype: defined(pc532) : "pc532"
+machtype: defined(vax) : "vax"
+machtype: defined(alpha) : "alpha"
+enddef :
+
+
+newdef : defined(__FreeBSD__)
+comment : FreeBSD
+vendor : defined(M_intel) : "intel"
+hosttype: : "FreeBSD"
+ostype : : "FreeBSD"
+machtype: : "i386"
+enddef :
+
+
+newdef : defined(__386BSD__)
+comment : Bill Jolitz's 386BSD
+vendor : defined(M_intel) : "intel"
+hosttype: : "386BSD"
+ostype : : "386BSD"
+machtype: : "i386"
+enddef :
+
+
+newdef : defined(bsdi)
+comment : BSDI's unix
+vendor : defined(M_intel) : "intel"
+vendor : defined(sparc) : "sun"
+vendor : defined(__powerpc__) : "motorola"
+hosttype: defined(M_intel) : "bsd386"
+hosttype: defined(sparc) : "bsd-sparc"
+hosttype: defined(__powerpc__) : "bsd-powerpc"
+ostype : : "bsdi"
+machtype: defined(M_i386) : "i386"
+machtype: defined(sparc) : "sparc"
+machtype: defined(__powerpc__) : "powerpc"
+enddef :
+
+
+newdef : defined(COHERENT)
+comment : COHERENT's unix
+vendor : defined(_I386) : "intel"
+hosttype: : "coh386"
+hosttype: : "coherent"
+ostype : : "coherent"
+machtype: defined(_I386) : "i386"
+enddef :
+
+newdef : defined(SCO)
+comment : SCO UNIX System V/386 Release 3.2
+vendor : : "sco"
+hosttype: : "sco386"
+ostype : : "sco_unix"
+machtype: : "i386"
+enddef :
+
+newdef : defined(M_XENIX) && !defined(M_UNIX)
+comment : SCO XENIX
+vendor : : "sco"
+hosttype: : "sco_xenix"
+ostype : : "sco_xenix"
+machtype: defined(M_I386) : "i386"
+machtype: defined(M_I286) : "i286"
+enddef :
+
+
+newdef : defined(ISC) || defined(ISC202)
+comment : Interactive Unix
+vendor : : "isc"
+hosttype: : "isc386"
+ostype : defined(POSIX) : "POSIX"
+ostype : : "SVR3"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(INTEL)
+comment : Intel Unix
+vendor : : "intel"
+hosttype: : "intel386"
+ostype : : "intel_unix"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(MACH)
+comment : cmu's mach
+vendor : : "cmu"
+hosttype: defined(M_i386) : "i386-mach"
+ostype : : "mach"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(alliant)
+comment : Alliants FSX
+vendor : : "alliant"
+hosttype: defined(mc68000) : "alliant-fx80"
+hosttype: defined(i860) : "alliant-fx2800"
+hosttype: : "alliant"
+ostype : : "fsx"
+machtype: defined(mc68000) : "mc68000"
+machtype: defined(i860) : "i860"
+enddef :
+
+
+newdef : defined(_FTX)
+comment : Stratus Computer, Inc FTX2 (i860 based)
+comment : Stratus Computer, Inc FTX3 (HPPA based)
+vendor : : "stratus"
+hosttype: defined(i860) && defined(_FTX) : "atlantic"
+hosttype: defined(__hppa) && defined(_FTX) : "continuum"
+ostype : defined(i860) && defined(_FTX) : "ftx2"
+ostype : defined(__hppa) && defined(_FTX) : "ftx3"
+machtype: defined(i860) : "i860"
+machtype: defined(__hppa) : "hppa"
+enddef :
+
+
+newdef : defined(sequent) || defined(_SEQUENT_)
+comment : Sequent Balance (32000 based)
+comment : Sequent Symmetry running DYNIX/ptx (386/486 based)
+comment : Sequent Symmetry running DYNIX 3 (386/486 based)
+vendor : : "sequent"
+hosttype: defined(M_i386) && defined(sequent) : "symmetry"
+hosttype: defined(M_i386) : "ptx"
+hosttype: : "balance"
+ostype : defined(M_i386) && !defined(sequent) : "ptx"
+ostype : : "dynix3"
+machtype: defined(M_i386) : "i386"
+machtype: defined(ns32000) : "ns32000"
+enddef :
+
+
+newdef : defined(ns32000)
+comment : Encore Computer Corp. Multimax (32000 based)
+vendor : : "encore"
+hosttype: defined(CMUCS) : "multimax"
+hosttype: : isamultimax(0)
+ostype : defined(CMUCS) : "mach"
+ostype : : isamultimax(1)
+machtype: : "ns32000"
+enddef :
+
+
+newdef : defined(iconuxv)
+comment : Icon 88k running Unix
+vendor : : "icon"
+hosttype: : "icon"
+ostype : : "iconuxv"
+machtype: defined(m88k) || defined(__m88k__) : "m88k"
+enddef :
+
+
+newdef : defined(_CRAY) && defined(_CRAYCOM)
+comment : Cray Computer Corp. running CSOS
+vendor : : "ccc"
+hosttype: defined(_CRAY2) : "cray"
+hosttype: defined(_CRAY3) : "cray"
+hosttype: defined(_CRAY4) : "cray"
+ostype : : "CSOS"
+machtype: defined(_CRAY2) : "cray2"
+machtype: defined(_CRAY3) : "cray3"
+machtype: defined(_CRAY4) : "cray4"
+enddef :
+
+
+newdef : defined(cray) && !defined(_CRAYMPP)
+comment : Cray Research Inc. PVP running UNICOS
+vendor : : "cri"
+hosttype: : getcray()
+ostype : : "unicos"
+machtype: : getcray()
+enddef :
+
+
+newdef : defined(cray) && defined(_CRAYT3D)
+comment : Cray Research Inc. running UNICOS MAX
+vendor : : "cri"
+hosttype: : getcray()
+ostype : : "unicosmax"
+machtype: : getcray()
+enddef :
+
+
+newdef : defined(cray) && defined(_CRAYT3E)
+comment : Cray Research Inc. running UNICOS/mk
+vendor : : "cri"
+hosttype: : getcray()
+ostype : : "unicosmk"
+machtype: : getcray()
+enddef :
+
+
+newdef : defined(convex)
+comment : Convex
+vendor : : "convex"
+hosttype: : "convex"
+ostype : : "convexos"
+machtype: : getconvex()
+enddef :
+
+
+newdef : defined(butterfly)
+comment : BBN Butterfly 1000
+vendor : : "bbn"
+hosttype: : "butterfly"
+machtype: defined(mc68020) || defined(__mc68020__) : "m68k"
+enddef :
+
+
+newdef : defined(NeXT)
+comment : NeXTStep
+vendor : : "next"
+hosttype: defined(mc68020) || defined(__mc68020__) : "next"
+hosttype: defined(M_i386) || defined(__i386__) : "intel-pc"
+hosttype: defined(hppa) || defined(__hppa__) : "hp"
+hosttype: defined(sparc) || defined(__sparc__) : "sun"
+ostype : : "nextstep"
+machtype: defined(mc68020) || defined(__mc68020__) : "m68k"
+machtype: defined(M_i386) || defined(__i386__) : "i386"
+machtype: defined(hppa) || defined(__hppa__) : "hppa"
+machtype: defined(sparc) || defined(__sparc__) : "sparc"
+enddef :
+
+
+newdef : defined(__APPLE__)
+comment : Rhapsody
+vendor : : "apple"
+hosttype: defined(__i386__) : "intel-pc"
+hosttype: defined(__ppc__) : "macintosh"
+ostype : : "rhapsody"
+machtype: defined(__i386__) : "i386"
+machtype: defined(__ppc__) : "powerpc"
+enddef :
+
+
+newdef : defined(sony_news)
+comment : Sony NEWS 800 or 1700 workstation
+vendor : : "sony"
+hosttype: defined(mips) : "news_mips"
+hosttype: defined(mc68020) || defined(__mc68020__) : "news_m68k"
+ostype : : "News"
+machtype: defined(mc68020) || defined(__mc68020__) : "m68k"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+enddef :
+
+
+newdef : defined(sgi)
+comment : Silicon Graphics
+vendor : : "sgi"
+hosttype: defined(M_mipsel) : "iris4d"
+hosttype: defined(M_mipseb) : "iris4d"
+hosttype: defined(mc68000) : "iris3d"
+ostype : : "irix"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+machtype: defined(mc68000) : "mc68000"
+enddef :
+
+
+newdef : defined(ultrix) || defined(__ultrix)
+comment : Digital's Ultrix
+vendor : : "dec"
+hosttype: defined(M_mipsel) : "decstation"
+hosttype: defined(M_mipseb) : "decmips"
+hosttype: defined(vax) || defined(__vax) : "vax"
+hosttype: defined(__vax__) : "vax"
+ostype : : "ultrix"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+machtype: defined(vax) || defined (__vax) : "vax"
+hosttype: defined(__vax__) : "vax"
+enddef :
+
+
+newdef : defined(MIPS)
+comment : Mips OS
+vendor : : "mips"
+hosttype: defined(M_mipsel) : "mips"
+hosttype: defined(M_mipseb) : "mips"
+ostype : : "mips"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+enddef :
+
+
+newdef : defined(DECOSF1)
+comment : Digital's alpha running osf1
+vendor : : "dec"
+ostype : : "osf1"
+hosttype: defined(__alpha) : "alpha"
+machtype: defined(__alpha) : "alpha"
+enddef :
+
+
+newdef : defined(Lynx)
+comment : Lynx OS 2.1
+vendor : : "Lynx"
+hosttype: defined(M_mipsel) : "lynxos-mips"
+hosttype: defined(M_mipseb) : "lynxos-mips"
+hosttype: defined(M_i386) : "lynxos-i386"
+hosttype: defined(i860) || defined(__i860__) : "lynxos-i860"
+hosttype: defined(m68k) : "lynxos-m68k"
+hosttype: defined(m88k) : "lynxos-m88k"
+hosttype: defined(sparc) : "lynxos-sparc"
+hosttype: : "lynxos-unknown"
+ostype : : "LynxOS"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+machtype: defined(M_i386) : "i386"
+machtype: defined(i860) || defined(__i860__) : "i860"
+machtype: defined(m68k) : "m68k"
+machtype: defined(m88k) : "m88k"
+machtype: defined(sparc) : "sparc"
+enddef :
+
+
+newdef : defined(masscomp)
+comment : Masscomp
+vendor : : "masscomp"
+hosttype: : "masscomp"
+ostype : : "masscomp"
+enddef :
+
+newdef : defined(__MACHTEN__)
+comment : Machintosh
+vendor : : "Tenon"
+hosttype: : "Macintosh"
+ostype : : "MachTen"
+machtype: : "Macintosh"
+enddef :
+
+
+
+newdef : defined(GOULD_NP1)
+comment : Gould
+vendor : : "gould"
+hosttype: : "gould_np1"
+machtype: : "gould"
+enddef :
+
+
+newdef : defined(MULTIFLOW)
+comment : Multiflow running 4.3BSD
+vendor : : "multiflow"
+hosttype: : "multiflow"
+machtype: : "multiflow"
+ostype : : "bsd43"
+enddef :
+
+
+newdef : defined(SXA)
+comment : PFU/Fujitsu A-xx computer
+vendor : : "sxa"
+hosttype: : "pfa50"
+ostype : defined(_BSDX_) : "e60-bsdx"
+ostype : : "e60"
+machtype: : "pfa50"
+enddef :
+
+
+newdef : defined(titan)
+comment : (St)Ardent Titan
+vendor : : "ardent"
+hosttype: : "titan"
+enddef :
+
+
+newdef : defined(stellar)
+comment : Stellar
+vendor : : "stellar"
+hosttype: : "stellar"
+ostype : : "stellix"
+enddef :
+
+
+newdef : defined(atari)
+comment : Atari TT running SVR4. This machine was never
+comment : commercially available.
+vendor : : "atari"
+hosttype: : "atari"
+ostype : : "asv"
+enddef :
+
+
+newdef : defined(OPUS)
+comment : ???
+vendor : : "opus"
+hosttype: : "opus"
+enddef :
+
+
+newdef : defined(eta10)
+comment : ETA running SVR3
+vendor : : "eta"
+hosttype: : "eta10"
+enddef :
+
+
+newdef : defined(hk68)
+comment : Heurikon HK68 running Uniplus+ 5.0
+vendor : : "heurikon"
+hosttype: : "hk68"
+ostype : : "uniplus"
+enddef :
+
+
+newdef : defined(NDIX)
+comment : Norsk Data ND 500/5000 running Ndix
+vendor : : "norsk"
+hosttype: : "nd500"
+ostype : : "ndix"
+enddef :
+
+
+newdef : defined(AMIGA)
+comment : Amiga running AmigaOS+GG
+vendor : : "commodore"
+hosttype: : "amiga"
+ostype : : "AmigaOS"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(uts)
+comment : Amdahl running uts 2.1
+vendor : : "amdahl"
+hosttype: : "amdahl"
+ostype : : "uts"
+machtype: : "amdahl"
+enddef :
+
+
+newdef : defined(UTek)
+comment : Tektronix 4300 running UTek (BSD 4.2 / 68020 based)
+vendor : : "tektronix"
+hosttype: : "tek4300"
+enddef :
+
+
+newdef : defined(UTekV)
+comment : Tektronix XD88/10 running UTekV 3.2e (SVR3/88100 based)
+vendor : : "tektronix"
+hosttype: : "tekXD88"
+enddef :
+
+
+newdef : defined(__DGUX__)
+comment : Data-General AViiON running DGUX
+hosttype: : "aviion"
+ostype : : "dgux"
+vendor : : "dg"
+machtype: defined(__m88k__) : "m88k"
+machtype: defined(__i386__) : "pentium"
+enddef :
+
+
+newdef : defined(sysV68)
+comment : Motorola MPC running System V/68 R32V2 (SVR3/68020 based)
+vendor : : "motorola"
+hosttype: : "sysV68"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(supermax)
+comment : DDE Supermax running System V/68 R3 (SVR3/68020 based)
+vendor : : "supermax"
+hosttype: : "supermax"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(sysV88)
+comment : Motorola MPC running System V/88 R32V2 (SVR3/88100 based)
+vendor : : "motorola"
+hosttype: : "sysV88"
+machtype: : "m88k"
+enddef :
+
+
+newdef : defined(__clipper__)
+comment : Clipper Chipset (Intergraph)
+vendor : : "intergraph"
+hosttype: : "clipper"
+machtype: : "clipper"
+enddef :
+
+
+newdef : defined(SNI) || defined(sinix)
+comment : Siemens Nixdorf Informationssysteme SINIX
+vendor : : "sni"
+hosttype: defined(M_intel) : "wx200i"
+hosttype: defined(MIPSEB) : "rm400"
+ostype : defined(sinix) : "sinix"
+machtype: defined(M_i586) : "i586"
+machtype: defined(M_i486) : "i486"
+machtype: defined(M_i386) : "i386"
+machtype: defined(M_mipsel) : "mipsel"
+machtype: defined(M_mipseb) : "mipseb"
+machtype: : "mips"
+enddef :
+
+newdef : defined(_OSD_POSIX)
+comment : Siemens Nixdorf Informationssysteme BS2000 POSIX (mainframe, EBCDIC)
+vendor : : "sni"
+hosttype: defined(M_intel) : "bs2000"
+ostype : : "posix"
+machtype: : "bs2000"
+enddef :
+
+newdef : defined(_SX)
+comment : NEC Corporation (SX-4)
+vendor : : "nec"
+ostype : : "superux"
+hosttype: : "sx4"
+machtype: : "sx4"
+enddef :
+
+newdef : !defined(SOLARIS2) && (SYSVREL == 4)
+comment : Unix System V Release 4.0
+vendor : defined(DELL) : "dell"
+hosttype: defined(M_i386) : "i386"
+ostype : : "svr4"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+newdef : defined(__uxp__) || defined(__uxps__)
+comment : FUJITSU DS/90 7000
+vendor : : "fujitsu"
+hosttype: : "ds90"
+ostype : : "sysv4"
+machtype: : "sparc"
+enddef :
+
+newdef : defined(_UWIN)
+comment : AT&T Research Unix for Windows
+vendor : : "att"
+hosttype: : "win32.i386"
+machtype: : "i386"
+enddef :
+
+
+newdef : defined(mc68000) || defined(__mc68000__) || defined(mc68k32) || defined(m68k) || defined(mc68010) || defined(mc68020)
+hosttype: : "m68k"
+vendor : defined(m68k) : "motorola"
+machtype: : "m68k"
+enddef :
+
+
+newdef : defined(m88k) || defined(__m88k__)
+hosttype: : "m88k"
+machtype: : "m88k"
+enddef :
+
+
+newdef : defined(M_intel)
+hosttype: defined(M_i586) : "i586"
+hosttype: defined(M_i486) : "i486"
+hosttype: defined(M_i386) : "i386"
+vendor : : "intel"
+machtype: defined(M_i586) : "i586"
+machtype: defined(M_i486) : "i486"
+machtype: defined(M_i386) : "i386"
+enddef :
+
+
+newdef : defined(sparc) || defined(__sparc__)
+hosttype: : "sparc"
+machtype: : "sparc"
+enddef :
+
+
+newdef : defined(i860) || defined(__i860__)
+hosttype: : "i860"
+machtype: : "i860"
+enddef :
+
+
+newdef : defined(osf1)
+ostype : : "osf1"
+enddef :
+
+
+newdef : SYSVREL == 0
+ostype : defined(BSD4_4) : "bsd44"
+ostype : defined(BSD) : "bsd"
+ostype : defined(POSIX) : "posix"
+ostype : defined(unix) || defined(__unix__) : "unix"
+enddef :
+
+
+newdef : SYSVREL == 1
+ostype : : "svr1"
+enddef :
+
+
+newdef : SYSVREL == 2
+ostype : : "svr2"
+enddef :
+
+
+newdef : SYSVREL == 3
+ostype : : "svr3"
+enddef :
+
+
+newdef : SYSVREL == 4
+ostype : : "svr4"
+enddef :
+
+
+newcode :
+#ifndef _hosttype_
+ hosttype = "unknown";
+#endif
+#ifndef _ostype_
+ ostype = "unknown";
+#endif
+#ifndef _vendor_
+ vendor = "unknown";
+#endif
+#ifndef _machtype_
+ machtype = "unknown";
+#endif
+ tsetenv(STRHOSTTYPE, str2short(hosttype));
+ tsetenv(STRVENDOR, str2short(vendor));
+ tsetenv(STROSTYPE, str2short(ostype));
+ tsetenv(STRMACHTYPE, str2short(machtype));
+} /* end setmachine */
+endcode :
diff --git a/contrib/tcsh/imake.config b/contrib/tcsh/imake.config
new file mode 100644
index 0000000..4278a46
--- /dev/null
+++ b/contrib/tcsh/imake.config
@@ -0,0 +1,65 @@
+/*
+ * $Id: imake.config,v 1.4 1995/03/05 03:18:09 christos Exp $
+ *
+ * config.Imakefile for for tcsh 6.00
+ * Marc Horowitz, MIT SIPB
+ */
+
+/* installed location of tcsh, if different than the default in
+ pathnames.h */
+/* #define TcshPath /afs/sipb/project/tcsh/tcsh */
+
+/* The following #define's may be used to cause tcsh to link against
+these libraries. If you have one of the machines which is defined in
+the Imakefile, the correct libraries will automatically be used. It's
+better to set up new definitions in the Imakefile than to put them
+here if you're defining support for a new machine, rather than
+configuring for local hacks. */
+/* #define UseLibTermcap */
+/* #define UseLibCurses */
+/* #define UseLibNet */
+/* #define UseLibSocket */
+/* #define UseLibBsd */
+/* #define UseLibC_S */
+/* #define UseLibSun */
+/* #define UseLibCposix */
+/* #define UseLibInet */
+/* #define UseLibDir */
+/* #define UseLibX */
+/* #define UseLibIntl */
+/* #define UseLibPosix */
+/* #define UseLibDirent */
+
+/* define if you want to use gcc. Your site.def file may already do
+this, but it shouldn't hurt. */
+/* #define HasGcc */
+
+/* define if you have some different compiler than cc or gcc */
+/* #define MyCC xlc */
+
+/* define if you have Hesiod passwd information, and want tcsh to use it */
+/* #define HESIOD */
+
+/* define if you have AFS and want to use kerberos passwd authentication */
+/* #define AFS */
+/* define as well if your version of AFS is 3.3 or higher */
+/* #define AFS33 */
+
+/* defines installation dir if different from /usr/local. The
+executable will be put in TcshTop/bin/tcsh, and the man page in
+TcshTop/man/man1/tcsh.1 */
+/* #define TcshTop /afs/sipb/project/tcsh */
+
+/* define any of the following if you want to change the compiler flags */
+/* #define MyCflags */
+/* #define MyDefines */
+/* #define MyIncludes */
+/* #define MyLibs */
+
+/* By default, the compiler debug flags are -O. Define this if you
+want them to be something else. */
+/* #define CDebugFlags -g -O */
+
+/* If you want HOSTTYPE to be something other than the default in
+tc.vers.c, define it here */
+/* #define HostType decmips */
diff --git a/contrib/tcsh/install-sh b/contrib/tcsh/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/contrib/tcsh/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/tcsh/ma.setp.c b/contrib/tcsh/ma.setp.c
new file mode 100644
index 0000000..d515d0f
--- /dev/null
+++ b/contrib/tcsh/ma.setp.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
+ * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Users of this software agree to return to Carnegie Mellon any
+ * improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * Export of this software is permitted only after complying with the
+ * regulations of the U.S. Deptartment of Commerce relating to the
+ * Export of Technical Data.
+ */
+/*
+ * setpath --- smart interface for setting path variables
+ *
+ * usage: setpath(paths, cmds, localsyspath, dosuffix, printerrors)
+ * char **paths, **cmds, *localsyspath;
+ * int dosuffix, printerrors;
+ *
+ * The 'paths' argument is a list of pointers to path lists of the
+ * form "name=value" where name is the name of the path and value
+ * is a colon separated list of directories. There can never be
+ * more than MAXDIRS (64) directories in a path.
+ *
+ * The 'cmds' argument may be a sequence of any of the following:
+ * -r reset path to default
+ * -i newpath insert newpath before localsyspath
+ * -ia oldpath newpath insert newpath after oldpath
+ * -ib oldpath newpath insert newpath before oldpath
+ * -i# newpath insert newpath at position #
+ * -d oldpath delete oldpath
+ * -d# delete path at position #
+ * -c oldpath newpath change oldpath to newpath
+ * -c# newpath change position # to newpath
+ *
+ * The "-i newpath" command is equivilent to "-ib 'localsyspath' newpath".
+ *
+ * If 'dosuffix' is true, the appropriate suffix will be added to
+ * all command operands for any system path in 'paths'.
+ *
+ * Both of the 'paths' and 'cmds' lists are terminated by a NULL
+ * entry.
+ *
+ * if 'printerrors' is true, setpath will printf error diagnostics.
+ *
+ * WARNING !!!: Under no circumstances should anyone change this
+ * module without fully understanding the impact on the C shell.
+ * The C shell has it's own malloc and printf routines and this
+ * module was carefully written taking that into account. Do not
+ * use any stdio routines from this module except printf.
+ *
+ **********************************************************************
+ * HISTORY
+ *
+ * Revision 1.4 90/12/11 17:58:44 mja
+ * Add copyright/disclaimer for distribution.
+ *
+ * 05-Jun-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Make all non-entry points static.
+ *
+ * 30-Apr-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added -r switch to reset paths to their default values.
+ *
+ * 06-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created from old setpath program for the shell.
+ *
+ **********************************************************************
+ */
+#include "sh.h"
+RCSID("$Id: ma.setp.c,v 1.12 1996/04/26 19:18:36 christos Exp $")
+
+#ifdef MACH
+
+#define MAXDIRS 64 /* max directories on a path */
+#ifndef NULL
+# define NULL 0
+#endif
+
+static int npaths; /* # pathlist arguments */
+
+static struct pelem {
+ struct pelem *pnext; /* pointer to next path */
+ char *pname; /* name of pathlist */
+ char *psuf; /* suffix for pathlist */
+ char *pdef; /* default for pathlist */
+ int pdirs; /* # directories on each pathlist */
+ char *pdir[MAXDIRS]; /* directory names for each pathlist */
+} *pathhead = NULL;
+
+static struct {
+ char *name;
+ char *suffix;
+ char *defalt;
+} syspath[] = {
+ "PATH", "/bin", ":/usr/ucb:/bin:/usr/bin",
+ "CPATH", "/include", ":/usr/include",
+ "LPATH", "/lib", ":/lib:/usr/lib",
+ "MPATH", "/man", ":/usr/man",
+ "EPATH", "/maclib", "",
+ 0, 0, 0
+};
+
+static int sflag;
+static int eflag;
+
+#define INVALID { \
+ if (eflag) xprintf(CGETS(10, 1, \
+ "setpath: invalid command '%s'.\n"), cmd); \
+ freepaths(); \
+ return(-1); \
+}
+
+#define TOOFEW { \
+ if (eflag) xprintf(CGETS(10, 2, \
+ "setpath: insufficient arguments to command '%s'.\n"), cmd); \
+ freepaths(); \
+ return(-1); \
+}
+
+static int initpaths __P((char **));
+static void savepaths __P((char **));
+static void freepaths __P((void));
+static void rcmd __P((char *));
+static void icmd __P((char *, char *));
+static void iacmd __P((char *, char *));
+static void ibcmd __P((char *, char *));
+static void incmd __P((char *, int));
+static void insert __P((struct pelem *, int, char *));
+static void dcmd __P((char *));
+static void dncmd __P((int));
+static void delete __P((struct pelem *, int));
+static void ccmd __P((char *, char *));
+static void cncmd __P((char *, int));
+static void change __P((struct pelem *, int, char *));
+static int locate __P((struct pelem *, char *));
+
+
+
+int
+setpath(paths, cmds, localsyspath, dosuffix, printerrors)
+register char **paths, **cmds, *localsyspath;
+int dosuffix, printerrors;
+{
+ register char *cmd, *cmd1, *cmd2;
+ register int ncmd;
+
+ sflag = dosuffix;
+ eflag = printerrors;
+ if (initpaths(paths) < 0)
+ return(-1);
+ if (npaths == 0)
+ return(0);
+ for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) {
+ if (cmd[0] != '-')
+ INVALID;
+ cmd1 = cmds[ncmd+1];
+ cmd2 = cmds[ncmd+2];
+ switch (cmd[1]) {
+ case 'r':
+ if (cmd[2] != '\0')
+ INVALID;
+ rcmd(localsyspath);
+ break;
+ case 'i':
+ if (cmd[2] == '\0') {
+ ncmd++;
+ if (cmd1 == NULL) TOOFEW;
+ icmd(cmd1, localsyspath);
+ } else if (isdigit(cmd[2])) {
+ ncmd++;
+ if (cmd1 == NULL) TOOFEW;
+ incmd(cmd1, atoi(cmd+2));
+ } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) {
+ INVALID;
+ } else {
+ ncmd += 2;
+ if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
+ if (cmd[2] == 'a')
+ iacmd(cmd1, cmd2);
+ else
+ ibcmd(cmd1, cmd2);
+ }
+ break;
+ case 'd':
+ if (cmd[2] == '\0') {
+ ncmd++;
+ if (cmd1 == NULL) TOOFEW;
+ dcmd(cmd1);
+ } else if (isdigit(cmd[2]))
+ dncmd(atoi(cmd+2));
+ else {
+ INVALID;
+ }
+ break;
+ case 'c':
+ if (cmd[2] == '\0') {
+ ncmd += 2;
+ if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
+ ccmd(cmd1, cmd2);
+ } else if (isdigit(cmd[2])) {
+ ncmd++;
+ if (cmd1 == NULL) TOOFEW;
+ cncmd(cmd1, atoi(cmd+2));
+ } else {
+ INVALID;
+ }
+ break;
+ default:
+ INVALID;
+ }
+ }
+ savepaths(paths);
+ freepaths();
+ return(0);
+}
+
+static int
+initpaths(paths)
+register char **paths;
+{
+ register char *path, *val, *p, *q;
+ register int i, done;
+ register struct pelem *pe, *pathend;
+
+ freepaths();
+ for (npaths = 0; path = paths[npaths]; npaths++) {
+ val = index(path, '=');
+ if (val == NULL) {
+ if (eflag)
+ xprintf(CGETS(10, 3,
+ "setpath: value missing in path '%s'\n"), path);
+ freepaths();
+ return(-1);
+ }
+ *val++ = '\0';
+ pe = (struct pelem *)xmalloc((unsigned)(sizeof(struct pelem)));
+ setzero((char *) pe, sizeof(struct pelem));
+ if (pathhead == NULL)
+ pathhead = pathend = pe;
+ else {
+ pathend->pnext = pe;
+ pathend = pe;
+ }
+ p = strsave(path);
+ pe->pname = p;
+ pe->psuf = "";
+ pe->pdef = "";
+ for (i = 0; syspath[i].name; i++)
+ if (strcmp(pe->pname, syspath[i].name) == 0) {
+ pe->psuf = syspath[i].suffix;
+ pe->pdef = syspath[i].defalt;
+ break;
+ }
+ q = val;
+ for (;;) {
+ q = index(p = q, ':');
+ done = (q == NULL);
+ if (!done)
+ *q++ = '\0';
+ p = strsave(p);
+ pe->pdir[pe->pdirs] = p;
+ pe->pdirs++;
+ if (done)
+ break;
+ }
+ }
+ return(0);
+}
+
+static void
+savepaths(paths)
+register char **paths;
+{
+ register char *p, *q;
+ register int npath, i, len;
+ register struct pelem *pe;
+
+ for (npath = 0, pe = pathhead; pe; npath++, pe = pe->pnext) {
+ len = strlen(pe->pname) + 1;
+ if (pe->pdirs == 0)
+ len++;
+ else for (i = 0; i < pe->pdirs; i++)
+ len += strlen(pe->pdir[i]) + 1;
+ p = xmalloc((unsigned)len);
+ paths[npath] = p;
+ for (q = pe->pname; *p = *q; p++, q++);
+ *p++ = '=';
+ if (pe->pdirs != 0) {
+ for (i = 0; i < pe->pdirs; i++) {
+ for (q = pe->pdir[i]; *p = *q; p++, q++);
+ *p++ = ':';
+ }
+ p--;
+ }
+ *p = '\0';
+ }
+}
+
+static void
+freepaths()
+{
+ register char *p;
+ register int i;
+ register struct pelem *pe;
+
+ if (npaths == 0 || pathhead == NULL)
+ return;
+ while (pe = pathhead) {
+ if (pe->pname) {
+ for (i = 0; i < pe->pdirs; i++) {
+ if (pe->pdir[i] == NULL)
+ continue;
+ p = pe->pdir[i];
+ pe->pdir[i] = NULL;
+ xfree((ptr_t) p);
+ }
+ pe->pdirs = 0;
+ p = pe->pname;
+ pe->pname = NULL;
+ xfree((ptr_t) p);
+ }
+ pathhead = pe->pnext;
+ xfree((ptr_t) pe);
+ }
+ npaths = 0;
+}
+
+/***********************************************
+ *** R E S E T A P A T H N A M E ***
+ ***********************************************/
+
+static void
+rcmd(localsyspath) /* reset path with localsyspath */
+char *localsyspath;
+{
+ register int n, done;
+ register char *new, *p;
+ register struct pelem *pe;
+ char newbuf[MAXPATHLEN+1];
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ new = newbuf;
+ *new = '\0';
+ if (localsyspath != NULL) {
+ *new = ':';
+ (void) strcpy(new + 1, localsyspath);
+ (void) strcat(new, pe->psuf);
+ }
+ (void) strcat(new, pe->pdef);
+ for (n = 0; n < pe->pdirs; n++) {
+ if (pe->pdir[n] == NULL)
+ continue;
+ p = pe->pdir[n];
+ pe->pdir[n] = NULL;
+ xfree((ptr_t) p);
+ }
+ pe->pdirs = 0;
+ for (;;) {
+ new = index(p = new, ':');
+ done = (new == NULL);
+ if (!done)
+ *new++ = '\0';
+ p = strsave(p);
+ pe->pdir[pe->pdirs] = p;
+ pe->pdirs++;
+ if (done)
+ break;
+ }
+ }
+}
+
+/***********************************************
+ *** I N S E R T A P A T H N A M E ***
+ ***********************************************/
+
+static void
+icmd(path, localsyspath) /* insert path before localsyspath */
+char *path, *localsyspath;
+{
+ register int n;
+ register char *new;
+ register struct pelem *pe;
+ char newbuf[MAXPATHLEN+1];
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ if (sflag)
+ new = localsyspath;
+ else {
+ new = newbuf;
+ (void) strcpy(new, localsyspath);
+ (void) strcat(new, pe->psuf);
+ }
+ n = locate(pe, new);
+ if (n >= 0)
+ insert(pe, n, path);
+ else
+ insert(pe, 0, path);
+ }
+}
+
+static void
+iacmd(inpath, path) /* insert path after inpath */
+char *inpath, *path;
+{
+ register int n;
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ n = locate(pe, inpath);
+ if (n >= 0)
+ insert(pe, n + 1, path);
+ else
+ xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
+ inpath, pe->pname);
+ }
+}
+
+static void
+ibcmd(inpath, path) /* insert path before inpath */
+char *inpath, *path;
+{
+ register int n;
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ n = locate(pe, inpath);
+ if (n >= 0)
+ insert(pe, n, path);
+ else
+ xprintf(CGETS(10, 4, "setpath: %s not found in %s\n",
+ inpath, pe->pname));
+ }
+}
+
+static void
+incmd(path, n) /* insert path at position n */
+char *path;
+int n;
+{
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext)
+ insert(pe, n, path);
+}
+
+static void
+insert(pe, loc, key)
+register struct pelem *pe;
+register int loc;
+register char *key;
+{
+ register int i;
+ register char *new;
+ char newbuf[2000];
+
+ if (sflag) { /* add suffix */
+ new = newbuf;
+ (void) strcpy(new, key);
+ (void) strcat(new, pe->psuf);
+ } else
+ new = key;
+ new = strsave(new);
+ for (i = pe->pdirs; i > loc; --i)
+ pe->pdir[i] = pe->pdir[i-1];
+ if (loc > pe->pdirs)
+ loc = pe->pdirs;
+ pe->pdir[loc] = new;
+ pe->pdirs++;
+}
+
+/***********************************************
+ *** D E L E T E A P A T H N A M E ***
+ ***********************************************/
+
+static void
+dcmd(path) /* delete path */
+char *path;
+{
+ register int n;
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ n = locate(pe, path);
+ if (n >= 0)
+ delete(pe, n);
+ else
+ xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
+ path, pe->pname);
+ }
+}
+
+static void
+dncmd(n) /* delete at position n */
+int n;
+{
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ if (n < pe->pdirs)
+ delete(pe, n);
+ else
+ xprintf(CGETS(10, 5,
+ "setpath: %d not valid position in %s\n"),
+ n, pe->pname);
+ }
+}
+
+static void
+delete(pe, n)
+register struct pelem *pe;
+int n;
+{
+ register int d;
+
+ xfree((ptr_t) (pe->pdir[n]));
+ for (d = n; d < pe->pdirs - 1; d++)
+ pe->pdir[d] = pe->pdir[d+1];
+ --pe->pdirs;
+}
+
+/***********************************************
+ *** C H A N G E A P A T H N A M E ***
+ ***********************************************/
+
+static void
+ccmd(inpath, path) /* change inpath to path */
+char *inpath, *path;
+{
+ register int n;
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ n = locate(pe, inpath);
+ if (n >= 0)
+ change(pe, n, path);
+ else
+ xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
+ inpath, pe->pname);
+ }
+}
+
+static void
+cncmd(path, n) /* change at position n to path */
+char *path;
+int n;
+{
+ register struct pelem *pe;
+
+ for (pe = pathhead; pe; pe = pe->pnext) {
+ if (n < pe->pdirs)
+ change(pe, n, path);
+ else
+ xprintf(CGETS(10, 5,
+ "setpath: %d not valid position in %s\n"),
+ n, pe->pname);
+ }
+}
+
+static void
+change(pe, loc, key)
+register struct pelem *pe;
+register int loc;
+register char *key;
+{
+ register char *new;
+ char newbuf[MAXPATHLEN+1];
+
+ if (sflag) { /* append suffix */
+ new = newbuf;
+ (void) strcpy(new, key);
+ (void) strcat(new, pe->psuf);
+ } else
+ new = key;
+ new = strsave(new);
+ xfree((ptr_t) (pe->pdir[loc]));
+ pe->pdir[loc] = new;
+}
+
+/***************************************
+ *** F I N D P A T H N A M E ***
+ ***************************************/
+
+static int
+locate(pe, key)
+register struct pelem *pe;
+register char *key;
+{
+ register int i;
+ register char *realkey;
+ char keybuf[MAXPATHLEN+1];
+
+ if (sflag) {
+ realkey = keybuf;
+ (void) strcpy(realkey, key);
+ (void) strcat(realkey, pe->psuf);
+ } else
+ realkey = key;
+ for (i = 0; i < pe->pdirs; i++)
+ if (strcmp(pe->pdir[i], realkey) == 0)
+ break;
+ return((i < pe->pdirs) ? i : -1);
+}
+#endif
diff --git a/contrib/tcsh/mi.termios.c b/contrib/tcsh/mi.termios.c
new file mode 100644
index 0000000..b4834b6
--- /dev/null
+++ b/contrib/tcsh/mi.termios.c
@@ -0,0 +1,393 @@
+/* $Header: /src/pub/tcsh/mi.termios.c,v 1.3 1996/04/26 19:18:38 christos Exp $ */
+/* termios.c - fake termios interface using sgtty interface
+ * by Magnus Doell and Bruce Evans.
+ *
+ */
+#include "sh.h"
+RCSID("$Id: mi.termios.c,v 1.3 1996/04/26 19:18:38 christos Exp $")
+
+#ifdef _MINIX
+
+
+/* Undefine everything that clashes with sgtty.h. */
+#undef B0
+#undef B50
+#undef B75
+#undef B110
+#undef B134
+#undef B150
+#undef B200
+#undef B300
+#undef B600
+#undef B1200
+#undef B1800
+#undef B2400
+#undef B4800
+#undef B9600
+#undef B19200
+#undef B28800
+#undef B38400
+#undef B57600
+#undef B115200
+/* Do not #undef CRMOD. We want a warning when they differ! */
+#undef ECHO
+/* Do not #undef XTABS. We want a warning when they differ! */
+
+/* Redefine some of the termios.h names just undefined with 'T_' prefixed
+ * to the name. Don't bother with the low speeds - Minix does not support
+ * them. Add support for higher speeds (speeds are now easy and don't need
+ * defines because they are not encoded).
+ */
+#define T_ECHO 000001
+
+#include <errno.h>
+#include <sgtty.h>
+
+static _PROTOTYPE( int tc_to_sg_speed, (speed_t speed) );
+static _PROTOTYPE( speed_t sg_to_tc_speed, (int speed) );
+#define B19200 192
+
+/* The speed get/set functions could be macros in the Minix implementation
+ * because there are speed fields in the structure with no fancy packing
+ * and it is not practical to check the values outside the driver.
+ * Where tests are necessary because the driver acts different from what
+ * POSIX requires, they are done in tcsetattr.
+ */
+
+speed_t cfgetispeed(termios_p)
+struct termios *termios_p;
+{
+ return termios_p->c_ispeed;
+}
+
+speed_t cfgetospeed(termios_p)
+struct termios *termios_p;
+{
+ return termios_p->c_ospeed;
+}
+
+speed_t cfsetispeed(termios_p, speed)
+struct termios *termios_p;
+speed_t speed;
+{
+ termios_p->c_ispeed = speed;
+ return 0;
+}
+
+speed_t cfsetospeed(termios_p, speed)
+struct termios *termios_p;
+speed_t speed;
+{
+ termios_p->c_ospeed = speed;
+ return 0;
+}
+
+static speed_t sg_to_tc_speed(speed)
+int speed;
+{
+ /* The speed encodings in sgtty.h and termios.h are different. Both are
+ * inflexible. Minix doesn't really support B0 but we map it through
+ * anyway. It doesn't support B50, B75 or B134.
+ */
+ switch (speed) {
+ case B0: return 0;
+ case B110: return 110;
+ case B200: return 200;
+ case B300: return 300;
+ case B600: return 600;
+ case B1200: return 1200;
+ case B1800: return 1800;
+ case B2400: return 2400;
+ case B4800: return 4800;
+ case B9600: return 9600;
+ case B19200: return 19200;
+#ifdef B28800
+ case B28800: return 28800;
+#endif
+#ifdef B38400
+ case B38400: return 38400;
+#endif
+#ifdef B57600
+ case B57600: return 57600;
+#endif
+#ifdef B115200
+ case B115200: return 115200;
+#endif
+ default: return (speed_t)-1;
+ }
+}
+
+static int tc_to_sg_speed(speed)
+speed_t speed;
+{
+ /* Don't use a switch here in case the compiler is 16-bit and doesn't
+ * properly support longs (speed_t's) in switches. It turns out the
+ * switch is larger and slower for most compilers anyway!
+ */
+ if (speed == 0) return 0;
+ if (speed == 110) return B110;
+ if (speed == 200) return B200;
+ if (speed == 300) return B300;
+ if (speed == 600) return B600;
+ if (speed == 1200) return B1200;
+ if (speed == 1800) return B1800;
+ if (speed == 2400) return B2400;
+ if (speed == 4800) return B4800;
+ if (speed == 9600) return B9600;
+ if (speed == 19200) return B19200;
+#ifdef B28800
+ if (speed == 28800) return B28800;
+#endif
+#ifdef B38400
+ if (speed == 38400) return B38400;
+#endif
+#ifdef B57600
+ if (speed == 57600) return B57600;
+#endif
+#ifdef B115200
+ if (speed == 115200) return B115200;
+#endif
+ return -1;
+}
+
+int tcgetattr(filedes, termios_p)
+int filedes;
+struct termios *termios_p;
+{
+ struct sgttyb sgbuf;
+ struct tchars tcbuf;
+
+ if (ioctl(filedes, TIOCGETP, &sgbuf) < 0
+ || ioctl(filedes, TIOCGETC, (struct sgttyb *) &tcbuf) < 0)
+ {
+ return -1;
+ }
+
+ /* Minix input flags:
+ * BRKINT: forced off (break is not recognized)
+ * IGNBRK: forced on (break is not recognized)
+ * ICRNL: set if CRMOD is set and not RAW (CRMOD also controls output)
+ * IGNCR: forced off (ignoring cr's is not supported)
+ * INLCR: forced off (mapping nl's to cr's is not supported)
+ * ISTRIP: forced off (should be off for consoles, on for rs232 no RAW)
+ * IXOFF: forced off (rs232 uses CTS instead of XON/XOFF)
+ * IXON: forced on if not RAW
+ * PARMRK: forced off (no '\377', '\0', X sequence on errors)
+ * ? IGNPAR: forced off (input with parity/framing errors is kept)
+ * ? INPCK: forced off (input parity checking is not supported)
+ */
+ termios_p->c_iflag = IGNBRK;
+ if (!(sgbuf.sg_flags & RAW))
+ {
+ termios_p->c_iflag |= IXON;
+ if (sgbuf.sg_flags & CRMOD)
+ {
+ termios_p->c_iflag |= ICRNL;
+ }
+ }
+
+ /* Minix output flags:
+ * OPOST: set if CRMOD or XTABS is set
+ * XTABS: copied from sg_flags
+ * CRMOD: copied from sg_flags
+ */
+ termios_p->c_oflag = sgbuf.sg_flags & (CRMOD | XTABS);
+ if (termios_p->c_oflag)
+ {
+ termios_p->c_oflag |= OPOST;
+ }
+
+ /* Minix local flags:
+ * ECHO: set if ECHO is set
+ * ECHOE: set if ECHO is set (ERASE echoed as error-corecting backspace)
+ * ECHOK: set if ECHO is set ('\n' echoed after KILL char)
+ * ECHONL: forced off ('\n' not echoed when ECHO isn't set)
+ * ICANON: set if neither CBREAK nor RAW
+ * IEXTEN: forced off
+ * ISIG: set if not RAW
+ * NOFLSH: forced off (input/output queues are always flushed)
+ * TOSTOP: forced off (no job control)
+ */
+ termios_p->c_lflag = 0;
+ if (sgbuf.sg_flags & ECHO)
+ {
+ termios_p->c_lflag |= T_ECHO | ECHOE | ECHOK;
+ }
+ if (!(sgbuf.sg_flags & RAW))
+ {
+ termios_p->c_lflag |= ISIG;
+ if (!(sgbuf.sg_flags & CBREAK))
+ {
+ termios_p->c_lflag |= ICANON;
+ }
+ }
+
+ /* Minix control flags:
+ * CLOCAL: forced on (ignore modem status lines - not quite right)
+ * CREAD: forced on (receiver is always enabled)
+ * CSIZE: CS5-CS8 correspond directly to BITS5-BITS8
+ * CSTOPB: set for B110 (driver will generate 2 stop-bits than)
+ * HUPCL: forced off
+ * PARENB: set if EVENP or ODDP is set
+ * PARODD: set if ODDP is set
+ */
+ termios_p->c_cflag = CLOCAL | CREAD;
+ switch (sgbuf.sg_flags & BITS8)
+ {
+ case BITS5: termios_p->c_cflag |= CS5; break;
+ case BITS6: termios_p->c_cflag |= CS6; break;
+ case BITS7: termios_p->c_cflag |= CS7; break;
+ case BITS8: termios_p->c_cflag |= CS8; break;
+ }
+ if (sgbuf.sg_flags & ODDP)
+ {
+ termios_p->c_cflag |= PARENB | PARODD;
+ }
+ if (sgbuf.sg_flags & EVENP)
+ {
+ termios_p->c_cflag |= PARENB;
+ }
+ if (sgbuf.sg_ispeed == B110)
+ {
+ termios_p->c_cflag |= CSTOPB;
+ }
+
+ /* Minix may give back different input and output baudrates,
+ * but only the input baudrate is valid for both.
+ * As our termios emulation will fail, if input baudrate differs
+ * from output baudrate, force them to be equal.
+ * Otherwise it would be very suprisingly not to be able to set
+ * the terminal back to the state returned by tcgetattr :).
+ */
+ termios_p->c_ospeed =
+ termios_p->c_ispeed =
+ sg_to_tc_speed((unsigned char) sgbuf.sg_ispeed);
+
+ /* Minix control characters correspond directly except VSUSP and the
+ * important VMIN and VTIME are not really supported.
+ */
+ termios_p->c_cc[VEOF] = tcbuf.t_eofc;
+ termios_p->c_cc[VEOL] = tcbuf.t_brkc;
+ termios_p->c_cc[VERASE] = sgbuf.sg_erase;
+ termios_p->c_cc[VINTR] = tcbuf.t_intrc;
+ termios_p->c_cc[VKILL] = sgbuf.sg_kill;
+ termios_p->c_cc[VQUIT] = tcbuf.t_quitc;
+ termios_p->c_cc[VSTART] = tcbuf.t_startc;
+ termios_p->c_cc[VSTOP] = tcbuf.t_stopc;
+ termios_p->c_cc[VMIN] = 1;
+ termios_p->c_cc[VTIME] = 0;
+ termios_p->c_cc[VSUSP] = 0;
+
+ return 0;
+}
+
+int tcsetattr(filedes, opt_actions, termios_p)
+int filedes;
+int opt_actions;
+struct termios *termios_p;
+{
+ struct sgttyb sgbuf;
+ struct tchars tcbuf;
+ int sgspeed;
+
+ /* Posix 1003.1-1988 page 135 says:
+ * Attempts to set unsupported baud rates shall be ignored, and it is
+ * implementation-defined whether an error is returned by any or all of
+ * cfsetispeed(), cfsetospeed(), or tcsetattr(). This refers both to
+ * changes to baud rates not supported by the hardware, and to changes
+ * setting the input and output baud rates to different values if the
+ * hardware does not support it.
+ * Ignoring means not to change the existing settings, doesn't it?
+ */
+ if ((termios_p->c_ispeed != 0 && termios_p->c_ispeed != termios_p->c_ospeed)
+ || (sgspeed = tc_to_sg_speed(termios_p->c_ospeed)) < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sgbuf.sg_ispeed = sgbuf.sg_ospeed = sgspeed;
+ sgbuf.sg_flags = 0;
+
+ /* I don't know what should happen with requests that are not supported by
+ * old Minix drivers and therefore cannot be emulated.
+ * Returning an error may confuse the application (the values aren't really
+ * invalid or unsupported by the hardware, they just couldn't be satisfied
+ * by the driver). Not returning an error might be even worse because the
+ * driver will act different to what the application requires it to act
+ * after sucessfully setting the attributes as specified.
+ * Settings that cannot be emulated fully include:
+ * c_ospeed != 110 && c_cflag & CSTOPB
+ * c_ospeed == 110 && ! c_cflag & CSTOPB
+ * (c_cc[VMIN] != 1 || c_cc[VTIME] != 0) && ! c_lflag & ICANON
+ * c_lflag & ICANON && ! c_lflag & ISIG
+ * For the moment I just ignore these conflicts.
+ */
+
+ if (termios_p->c_oflag & OPOST)
+ {
+ /* CRMOD isn't Posix and may conflict with ICRNL, which is Posix,
+ * so we just ignore it.
+ */
+ if (termios_p->c_oflag & XTABS)
+ {
+ sgbuf.sg_flags |= XTABS;
+ }
+ }
+
+ if (termios_p->c_iflag & ICRNL)
+ {
+ /* We couldn't do it better :-(. */
+ sgbuf.sg_flags |= CRMOD;
+ }
+
+ if (termios_p->c_lflag & T_ECHO)
+ {
+ sgbuf.sg_flags |= ECHO;
+ }
+ if (!(termios_p->c_lflag & ICANON))
+ {
+ if (termios_p->c_lflag & ISIG)
+ {
+ sgbuf.sg_flags |= CBREAK;
+ }
+ else
+ {
+ sgbuf.sg_flags |= RAW;
+ }
+ }
+
+ switch (termios_p->c_cflag & CSIZE)
+ {
+ case CS5: sgbuf.sg_flags |= BITS5; break;
+ case CS6: sgbuf.sg_flags |= BITS6; break;
+ case CS7: sgbuf.sg_flags |= BITS7; break;
+ case CS8: sgbuf.sg_flags |= BITS8; break;
+ }
+ if (termios_p->c_cflag & PARENB)
+ {
+ if (termios_p->c_cflag & PARODD)
+ {
+ sgbuf.sg_flags |= ODDP;
+ }
+ else
+ {
+ sgbuf.sg_flags |= EVENP;
+ }
+ }
+
+ sgbuf.sg_erase = termios_p->c_cc[VERASE];
+ sgbuf.sg_kill = termios_p->c_cc[VKILL];
+
+ tcbuf.t_intrc = termios_p->c_cc[VINTR];
+ tcbuf.t_quitc = termios_p->c_cc[VQUIT];
+ tcbuf.t_startc = termios_p->c_cc[VSTART];
+ tcbuf.t_stopc = termios_p->c_cc[VSTOP];
+ tcbuf.t_eofc = termios_p->c_cc[VEOF];
+ tcbuf.t_brkc = termios_p->c_cc[VEOL];
+
+ return ioctl(filedes, TIOCSETP, &sgbuf) < 0 &&
+ ioctl(filedes, TIOCSETC, (struct sgttyb *) &tcbuf) < 0 ?
+ -1 : 0;
+}
+#endif /* _MINIX */
diff --git a/contrib/tcsh/mi.varargs.h b/contrib/tcsh/mi.varargs.h
new file mode 100644
index 0000000..7377075
--- /dev/null
+++ b/contrib/tcsh/mi.varargs.h
@@ -0,0 +1,15 @@
+/* $Header: /src/pub/tcsh/mi.varargs.h,v 1.2 1996/04/26 19:18:39 christos Exp $ */
+/*
+ * mi.varargs.h: Correct varargs for minix
+ */
+#ifndef _h_mi_varargs
+#define _h_mi_varargs
+
+typedef char *va_list;
+
+#define va_dcl int va_alist;
+#define va_start(p) (p) = (va_list) &va_alist;
+#define va_arg(p,type) ( (type *) ((p)+=sizeof(type)) )[-1]
+#define va_end(p)
+
+#endif /* _h_mi_varargs */
diff --git a/contrib/tcsh/mi.wait.h b/contrib/tcsh/mi.wait.h
new file mode 100644
index 0000000..205ac68
--- /dev/null
+++ b/contrib/tcsh/mi.wait.h
@@ -0,0 +1,44 @@
+/* The <sys/wait.h> header contains macros related to wait(). The value
+ * returned by wait() and waitpid() depends on whether the process
+ * terminated by an exit() call, was killed by a signal, or was stopped
+ * due to job control, as follows:
+ *
+ * High byte Low byte
+ * +---------------------+
+ * exit(status) | status | 0 |
+ * +---------------------+
+ * killed by signal | 0 | signal |
+ * +---------------------+
+ * stopped (job control) | signal | 0177 |
+ * +---------------------+
+ */
+
+#ifndef _WAIT_H
+#define _WAIT_H
+
+#ifndef _TYPES_H /* not quite right */
+#include <sys/types.h>
+#endif
+
+#define __LOW(v) ((v) & 0377)
+#define __HIGH(v) (((v) >> 8) & 0377)
+
+#define WNOHANG 1 /* do not wait for child to exit */
+#define WUNTRACED 2 /* for job control; not implemented */
+
+#define WIFEXITED(s) (__LOW(s) == 0) /* normal exit */
+#define WEXITSTATUS(s) (__HIGH(s)) /* exit status */
+#define WTERMSIG(s) (__LOW(s) & 0177) /* sig value */
+#define WIFSIGNALED(s) ((((unsigned int)(s)-1) & 0xFFFF) < 0xFF) /* signaled */
+#define WIFSTOPPED(s) (__LOW(s) == 0177) /* stopped */
+#define WSTOPSIG(s) (__HIGH(s) & 0377) /* stop signal */
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( pid_t wait, (int *_stat_loc) );
+_PROTOTYPE( pid_t waitpid, (pid_t _pid, int *_stat_loc, int _options) );
+
+#endif /* _WAIT_H */
diff --git a/contrib/tcsh/nls/C/set1 b/contrib/tcsh/nls/C/set1
new file mode 100644
index 0000000..6053155
--- /dev/null
+++ b/contrib/tcsh/nls/C/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.5 1998/06/27 12:27:55 christos Exp $
+$ Error messages
+$set 1
+1 Syntax Error
+2 %s is not allowed
+3 Word too long
+4 $< line too long
+5 No file for $0
+6 Incomplete [] modifier
+7 $ expansion must end before ]
+8 Bad : modifier in $ (%c)
+9 Subscript error
+10 Badly formed number
+11 No more words
+12 Missing file name
+13 Internal glob error
+14 Command not found
+15 Too few arguments
+16 Too many arguments
+17 Too dangerous to alias that
+18 Empty if
+19 Improper then
+20 Words not parenthesized
+21 %s not found
+22 Improper mask
+23 No such limit
+24 Argument too large
+25 Improper or unknown scale factor
+26 Undefined variable
+27 Directory stack not that deep
+28 Bad signal number
+29 Unknown signal; kill -l lists signals
+30 Variable name must begin with a letter
+31 Variable name too long
+32 Variable name must contain alphanumeric characters
+33 No job control in this shell
+34 Expression Syntax
+35 No home directory
+36 Can't change to home directory
+37 Invalid null command
+38 Assignment missing expression
+39 Unknown operator
+40 Ambiguous
+41 %s: File exists
+42 Argument for -c ends in backslash
+43 Interrupted
+44 Subscript out of range
+45 Line overflow
+46 No such job
+47 Can't from terminal
+48 Not in while/foreach
+49 No more processes
+50 No match
+51 Missing %c
+52 Unmatched %c
+53 Out of memory
+54 Can't make pipe
+55 %s: %s
+56 %s
+57 Usage: jobs [ -l ]
+58 Arguments should be jobs or process id's
+59 No current job
+60 No previous job
+61 No job matches pattern
+62 Fork nesting > %d; maybe `...` loop
+63 No job control in subshells
+64 Sync fault: Process %d not found
+65 %sThere are suspended jobs
+66 %sThere are stopped jobs
+67 No other directory
+68 Directory stack empty
+69 Bad directory
+70 Usage: %s [-%s]%s
+71 No operand for -h flag
+72 Not a login shell
+73 Division by 0
+74 Mod by 0
+75 Bad scaling; did you mean "%s"?
+76 Can't suspend a login shell (yet)
+77 Unknown user: %s
+78 No $home variable set
+79 Usage: history [-%s] [# number of events]
+80 $, ! or < not allowed with $# or $?
+81 Newline in variable name
+82 * not allowed with $# or $?
+83 $?<digit> or $#<digit> not allowed
+84 Illegal variable name
+85 Newline in variable index
+86 Expansion buffer overflow
+87 Variable syntax
+88 Bad ! form
+89 No previous substitute
+90 Bad substitute
+91 No previous left hand side
+92 Right hand side too long
+93 Bad ! modifier: %c
+94 Modifier failed
+95 Substitution buffer overflow
+96 Bad ! arg selector
+97 No prev search
+98 %s: Event not found
+99 Too many )'s
+100 Too many ('s
+101 Badly placed (
+102 Missing name for redirect
+103 Ambiguous output redirect
+104 Can't << within ()'s
+105 Ambiguous input redirect
+106 Badly placed ()'s
+107 Alias loop
+108 No $watch variable set
+109 No scheduled events
+110 Usage: sched -<item#>.\nUsage: sched [+]hh:mm <command>
+111 Not that many scheduled events
+112 No command to run
+113 Invalid time for event
+114 Relative time inconsistent with am/pm
+115 Out of termcap string space
+116 Usage: settc %s [yes|no]
+117 Unknown capability `%s'
+118 Unknown termcap parameter `%%%c'
+119 Too many arguments for `%s' (%d)
+120 `%s' requires %d arguments
+121 Usage: echotc [-v|-s] [<capability> [<args>]]
+122 %s: %s. Wrong Architecture
+123 !# History loop
+124 Malformed file inquiry
+125 Selector overflow
+126 Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX -Dname[=value] ] [ argument ... ]
+127 Unknown option: `-%s'\nUsage: %s [ -bcdefFilmnqstvVxX ] [ argument ... ]
+128 Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX ] [ argument ... ]
+129 \nInvalid completion: "%s"
+130 \nInvalid %s: '%c'
+131 \nMissing separator '%c' after %s "%s"
+132 \nIncomplete %s: "%s"
+133 No operand for -m flag
+134 Usage: unlimit [-fh] [limits]
+135 $%S is read-only
+136 No such job
+137 Unknown colorls variable `%c%c'
diff --git a/contrib/tcsh/nls/C/set10 b/contrib/tcsh/nls/C/set10
new file mode 100644
index 0000000..56a96b2
--- /dev/null
+++ b/contrib/tcsh/nls/C/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: invalid command '%s'.\n
+2 setpath: insufficient arguments to command '%s'.\n
+3 setpath: value missing in path '%s'\n
+4 setpath: %s not found in %s\n
+5 setpath: %d not valid position in %s\n
diff --git a/contrib/tcsh/nls/C/set11 b/contrib/tcsh/nls/C/set11
new file mode 100644
index 0000000..312a9c9
--- /dev/null
+++ b/contrib/tcsh/nls/C/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ sh.c
+$set 11
+1 Warning: no access to tty (%s).\n
+2 Thus no job control in this shell.\n
+3 You have %d mail messages.\n
+4 You have %d mail messages in %s.\n
+5 You have %smail.\n
+6 new
+7 You have %smail in %s.\n
diff --git a/contrib/tcsh/nls/C/set12 b/contrib/tcsh/nls/C/set12
new file mode 100644
index 0000000..e0b44a7
--- /dev/null
+++ b/contrib/tcsh/nls/C/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.3 1996/04/26 20:31:52 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: Trying to start from "%s"\n
diff --git a/contrib/tcsh/nls/C/set13 b/contrib/tcsh/nls/C/set13
new file mode 100644
index 0000000..af1de4e
--- /dev/null
+++ b/contrib/tcsh/nls/C/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d hash buckets of %d bits each\n
+3 debug mask = 0x%08x\n
+4 %d hits, %d misses, %d%%\n
+5 %S: shell built-in command.\n
+6 %S: Command not found.\n
+7 where: / in command makes no sense\n
+8 %S is aliased to
+9 %S is a shell built-in\n
+10 hash miss:
diff --git a/contrib/tcsh/nls/C/set14 b/contrib/tcsh/nls/C/set14
new file mode 100644
index 0000000..d1b86a8
--- /dev/null
+++ b/contrib/tcsh/nls/C/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.3 1998/11/24 18:18:06 christos Exp $
+$ sh.file.c
+$set 14
+1 \nYikes!! Too many %s!!\n
+2 names in password file
+3 files
diff --git a/contrib/tcsh/nls/C/set15 b/contrib/tcsh/nls/C/set15
new file mode 100644
index 0000000..1fb8912
--- /dev/null
+++ b/contrib/tcsh/nls/C/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.3 1996/10/19 17:52:32 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: Can't %s%s limit\n
+2 remove
+3 set
+4 \040hard
diff --git a/contrib/tcsh/nls/C/set16 b/contrib/tcsh/nls/C/set16
new file mode 100644
index 0000000..67b1eb8
--- /dev/null
+++ b/contrib/tcsh/nls/C/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.3 1996/04/26 20:31:55 christos Exp $
+$ sh.lex.c
+$set 16
+1 Reset tty pgrp from %d to %d\n
+2 \nUse "logout" to logout.\n
+3 \nUse "exit" to leave %s.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Bad seek type %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/C/set17 b/contrib/tcsh/nls/C/set17
new file mode 100644
index 0000000..fa4fd20
--- /dev/null
+++ b/contrib/tcsh/nls/C/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.3 1996/10/19 17:52:33 christos Exp $
+$ sh.proc.c
+$set 17
+1 BUG: waiting for background job!\n
+2 Exit %d\n
+3 BUG: process flushed twice
+4 Running
+5 Signal
+6 Exit %-25d
+7 Done
+8 BUG: status=%-9o
+9 \040(core dumped)
+10 \040(wd:
+11 wd now:
+12 %S: Already suspended\n
+13 %S: Already stopped\n
diff --git a/contrib/tcsh/nls/C/set18 b/contrib/tcsh/nls/C/set18
new file mode 100644
index 0000000..f00c4f6
--- /dev/null
+++ b/contrib/tcsh/nls/C/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ sh.set.c
+$set 18
+1 Warning: ridiculously long PATH truncated\n
diff --git a/contrib/tcsh/nls/C/set19 b/contrib/tcsh/nls/C/set19
new file mode 100644
index 0000000..15e17ee
--- /dev/null
+++ b/contrib/tcsh/nls/C/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.3 1996/04/26 20:31:58 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: Out of memory\n
+2 free(%lx) called before any allocations.
+3 free(%lx) above top of memory.
+4 free(%lx) below bottom of memory.
+5 free(%lx) bad block.
+6 free(%lx) bad range check.
+7 free(%lx) bad block index.
+8 %s current memory allocation:\nfree:\t
+9 \nused:\t
+10 \n\tTotal in use: %d, total free: %d\n
+11 \tAllocated memory from 0x%lx to 0x%lx. Real top at 0x%lx\n
+12 Allocated memory from 0x%lx to 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/C/set2 b/contrib/tcsh/nls/C/set2
new file mode 100644
index 0000000..8fff30c
--- /dev/null
+++ b/contrib/tcsh/nls/C/set2
@@ -0,0 +1,111 @@
+$ $Id: set2,v 1.4 1998/10/25 15:12:38 christos Exp $
+$ Signal names
+$set 2
+1 Null signal
+2 Hangup
+3 Interrupt
+4 Quit
+5 Illegal instruction
+6 Trace/BPT trap
+7 Abort
+8 IOT trap
+9 System Crash Imminent
+10 Error exit
+11 EMT trap
+12 Floating exception
+13 Killed
+14 User signal 1
+15 User signal 2
+16 Segmentation fault
+17 Bus error
+18 Program range error
+19 Operand range error
+20 Bad system call
+21 Broken pipe
+22 Alarm clock
+23 Terminated
+24 Child status change
+25 Death of child
+26 Apollo-specific fault
+27 Child stopped or exited
+28 Child exited
+29 Power failure
+30 Resource Lost
+31 Break (Ctrl-Break)
+32 Input/output possible signal
+33 Asynchronous I/O (select)
+34 Urgent condition on I/O channel
+35 Multitasking wake-up
+36 Multitasking kill
+37 Fortran asynchronous I/O completion
+38 Recovery
+39 Uncorrectable memory error
+40 CPU time limit exceeded
+41 System shutdown imminent
+42 micro-tasking group-no wakeup flag set
+43 Thread error - (use cord -T for detailed info)
+44 CRAY Y-MP register parity error
+45 Information request
+46 Suspended (signal)
+47 Stopped (signal)
+48 Suspended
+49 Stopped
+50 Continued
+51 Suspended (tty input)
+52 Stopped (tty input)
+53 Suspended (tty output)
+54 Stopped (tty output)
+55 Window status changed
+56 Window size changed
+57 Phone status changed
+58 Cputime limit exceeded
+59 Filesize limit exceeded
+60 Virtual time alarm
+61 Profiling time alarm
+62 DIL signal
+63 Pollable event occured
+64 Process's lwps are blocked
+65 Special LWP signal
+66 Special CPR Signal
+67 Special CPR Signal
+68 First Realtime Signal
+69 Second Realtime Signal
+70 Third Realtime Signal
+71 Fourth Realtime Signal
+72 Fourth Last Realtime Signal
+73 Third Last Realtime Signal
+74 Second Last Realtime Signal
+75 Last Realtime Signal
+76 LAN Asyncronous I/O
+77 PTY read/write availability
+78 I/O intervention required
+79 HFT monitor mode granted
+80 HFT monitor mode should be relinguished
+81 HFT sound control has completed
+82 Data in HFT ring buffer
+83 Migrate process
+84 Secure attention key
+85 Reschedule
+86 Signaling SS$_DEBUG
+87 Priority changed
+88 True deadlock detected
+89 New input character
+90 Stack limit exceeded
+91 Unused signal
+92 LM overlay
+93 system freeze
+94 system defreeze
+95 dead lock
+96 exceeded memory size limit
+97 exceeded data size limit
+98 exceeded memory size limit of 32KB
+99 exce error for no memory
+100 check point start
+101 check point start of kernel
+102 restart start
+103 restart of kernel
+104 exeeded XMU size limit
+105 exeeded RLG0 limit
+106 exeeded RLG1 limit
+107 exeeded RLG2 limit
+108 exeeded RLG3 limit
diff --git a/contrib/tcsh/nls/C/set20 b/contrib/tcsh/nls/C/set20
new file mode 100644
index 0000000..1be2714
--- /dev/null
+++ b/contrib/tcsh/nls/C/set20
@@ -0,0 +1,41 @@
+$ $Id: set20,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.bind.c
+$set 20
+1 Invalid key name `%S'\n
+2 Bad key name: %S\n
+3 Bad command name: %S\n
+4 Bad key spec %S\n
+5 Null string specification\n
+6 Standard key bindings\n
+7 Alternative key bindings\n
+8 Multi-character bindings\n
+9 Arrow key bindings\n
+10 %-15s-> is undefined\n
+11 BUG!!! %s isn't bound to anything.\n
+12 Usage: bindkey [options] [--] [KEY [COMMAND]]\n
+13 -a list or bind KEY in alternative key map\n
+14 -b interpret KEY as a C-, M-, F- or X- key name\n
+15 -s interpret COMMAND as a literal string to be output\n
+16 -c interpret COMMAND as a builtin or external command\n
+17 -v bind all keys to vi bindings\n
+18 -e bind all keys to emacs bindings\n
+19 -d bind all keys to default editor's bindings\n
+20 -l list editor commands with descriptions\n
+21 -r remove KEY's binding\n
+22 -k interpret KEY as a symbolic arrow-key name\n
+23 -- force a break from option processing\n
+24 -u (or any invalid option) this message\n
+25 Without KEY or COMMAND, prints all bindings\n
+26 Without COMMAND, prints the binding for KEY.\n
+27 bad key specification -- null string\n
+28 bad key specification -- empty string\n
+29 Bad function-key specification. Null key not allowed\n
+30 bad key specification -- malformed hex number\n
+31 bad key specification -- malformed octal number\n
+32 bad key specification -- malformed decimal number\n
+33 Bad function-key specification.\n
+34 Null key not allowed\n
+35 bad key specification -- unknown name "%S"\n
+36 usage: bind [KEY | COMMAND KEY | "emacs" | "vi" | "-a"]\n
+37 Invalid function
+38 %s\t\tis undefined\n
diff --git a/contrib/tcsh/nls/C/set21 b/contrib/tcsh/nls/C/set21
new file mode 100644
index 0000000..9484ba0
--- /dev/null
+++ b/contrib/tcsh/nls/C/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.disc.c
+$set 21
+1 Couldn't get local chars.\n
+2 Couldn't set local chars.\n
diff --git a/contrib/tcsh/nls/C/set22 b/contrib/tcsh/nls/C/set22
new file mode 100644
index 0000000..6aa8a29
--- /dev/null
+++ b/contrib/tcsh/nls/C/set22
@@ -0,0 +1,17 @@
+$ $Id: set22,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t aliased to
+2 \nIncorrect passwd for %s\n
+3 Faulty alias 'precmd' removed.\n
+4 Faulty alias 'cwdcmd' removed.\n
+5 Faulty alias 'beepcmd' removed.\n
+6 Faulty alias 'periodic' removed.\n
+7 parsing command line\n
+8 Do you really want to delete all files? [n/y]
+9 skipping deletion of files!\n
+10 command line now is:\n
+11 parsing command line\n
+12 in one of the lists\n
+13 command line now is:\n
+14 yY
diff --git a/contrib/tcsh/nls/C/set23 b/contrib/tcsh/nls/C/set23
new file mode 100644
index 0000000..4f8e560
--- /dev/null
+++ b/contrib/tcsh/nls/C/set23
@@ -0,0 +1,34 @@
+$ $Id: set23,v 1.3 1996/04/26 20:32:00 christos Exp $
+$ tc.os.c
+$set 23
+1 Bad cpu/site name
+2 Site path too long
+3 unknown
+4 site: %s\n
+5 %d: Site not found\n
+6 setlocal: %s: %s\n
+7 Site not found
+8 You're trapped in a universe you never made
+9 Getwarp failed
+10 Invalid warp
+11 Setwarp failed
+12 Illegal universe
+13 Unknown Error: %d
+14 sysname: %s\n
+15 nodename: %s\n
+16 release: %s\n
+17 version: %s\n
+18 machine: %s\n
+19 getwd: Cannot open ".." (%s)
+20 getwd: Cannot chdir to ".." (%s)
+21 getwd: Read error in ".." (%s)
+22 getwd: Cannot change back to "." (%s)
+23 getwd: Cannot stat "/" (%s)
+24 getwd: Cannot stat "." (%s)
+25 getwd: Cannot stat directory "%s" (%s)
+26 getwd: Cannot open directory "%s" (%s)
+27 getwd: Cannot find "." in ".." (%s)
+28 Invalid system type
+29 System type is not set
+30 Too many arguments
+31 Invalid argument
diff --git a/contrib/tcsh/nls/C/set24 b/contrib/tcsh/nls/C/set24
new file mode 100644
index 0000000..2896947
--- /dev/null
+++ b/contrib/tcsh/nls/C/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.sched.c
+$set 24
+1 kludge
diff --git a/contrib/tcsh/nls/C/set25 b/contrib/tcsh/nls/C/set25
new file mode 100644
index 0000000..063e8d6
--- /dev/null
+++ b/contrib/tcsh/nls/C/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.sig.c
+$set 25
+1 our wait %d\n
+2 error: bsd_signal(%d) signal out of range\n
+3 error: bsd_signal(%d) - sigaction failed, errno %d\n
diff --git a/contrib/tcsh/nls/C/set26 b/contrib/tcsh/nls/C/set26
new file mode 100644
index 0000000..aa854ad
--- /dev/null
+++ b/contrib/tcsh/nls/C/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tc.who.c
+$set 26
+1 cannot stat %s. Please "unset watch".\n
+2 %s cannot be opened. Please "unset watch".\n
+3 BUG! last element is not whotail!\n
+4 backward:
+5 BUG! first element is not whohead!\n
+6 new: %s/%s\n
+7 %n has %a %l from %m.
+8 %n has %a %l.
+9 logged on
+10 logged off
+11 replaced %s on
+12 local
diff --git a/contrib/tcsh/nls/C/set27 b/contrib/tcsh/nls/C/set27
new file mode 100644
index 0000000..52664d9
--- /dev/null
+++ b/contrib/tcsh/nls/C/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tw.comp.c
+$set 27
+1 command
+2 separator
+3 pattern
+4 range
+5 completion
diff --git a/contrib/tcsh/nls/C/set29 b/contrib/tcsh/nls/C/set29
new file mode 100644
index 0000000..040e881
--- /dev/null
+++ b/contrib/tcsh/nls/C/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ tw.help.c
+$set 29
+1 No help file for %S\n
diff --git a/contrib/tcsh/nls/C/set3 b/contrib/tcsh/nls/C/set3
new file mode 100644
index 0000000..9f83760
--- /dev/null
+++ b/contrib/tcsh/nls/C/set3
@@ -0,0 +1,117 @@
+$ $Id: set3,v 1.3 1995/04/24 14:12:51 christos Exp $
+$ Editor function descriptions
+$set 3
+1 Move back a character
+2 Delete the character behind cursor
+3 Cut from beginning of current word to cursor - saved in cut buffer
+4 Cut from beginning of line to cursor - save in cut buffer
+5 Move to beginning of current word
+6 Move to beginning of line
+7 Capitalize the characters from cursor to end of current word
+8 Vi change case of character under cursor and advance one character
+9 Vi change to end of line
+10 Clear screen leaving current line on top
+11 Complete current word
+12 Tab forward through files
+13 Tab backward through files
+14 Complete current word ignoring programmable completions
+15 Copy current word to cursor
+16 Copy area between mark and cursor to cut buffer
+17 Expand to preceding word for which this is a prefix
+18 Delete character under cursor
+19 Delete character under cursor or signal end of file on an empty line
+20 Delete character under cursor or list completions if at end of line
+21 Delete character under cursor, list completions or signal end of file
+22 Cut from cursor to end of current word - save in cut buffer
+23 Adds to argument if started or enters digit
+24 Digit that starts argument
+25 Move to next history line
+26 Lowercase the characters from cursor to end of current word
+27 Indicate end of file
+28 Move cursor to end of line
+29 Exchange the cursor and mark
+30 Expand file name wildcards
+31 Expand history escapes
+32 Expand the history escapes in a line
+33 Expand variables
+34 Move forward one character
+35 Move forward to end of current word
+36 Exchange the two characters before the cursor
+37 Search in history backward for line beginning as current
+38 Search in history forward for line beginning as current
+39 Insert last item of previous command
+40 Incremental search forward
+41 Incremental search backward
+42 Clear line
+43 Cut to end of line and save in cut buffer
+44 Cut area between mark and cursor and save in cut buffer
+45 Cut the entire line and save in cut buffer
+46 List choices for completion
+47 List choices for completion overriding programmable completion
+48 List file name wildcard matches
+49 List choices for completion or indicate end of file if empty line
+50 Display load average and current process status
+51 Expand history escapes and insert a space
+52 Execute command
+53 Expand pathnames, eliminating leading .'s and ..'s
+54 Expand commands to the resulting pathname or alias
+55 Switch from insert to overwrite mode or vice versa
+56 Add 8th bit to next character typed
+57 Add the next character typed to the line verbatim
+58 Redisplay everything
+59 Restart stopped editor
+60 Look for help on current command
+61 This character is added to the line
+62 This character is the first in a character sequence
+63 Set the mark at cursor
+64 Correct the spelling of current word
+65 Correct the spelling of entire line
+66 Send character to tty in cooked mode
+67 Toggle between literal and lexical current history line
+68 Exchange the character to the left of the cursor with the one under
+69 Exchange the two characters before the cursor
+70 Tty delayed suspend character
+71 Tty flush output character
+72 Tty interrupt character
+73 Tty quit character
+74 Tty suspend character
+75 Tty allow output character
+76 Tty disallow output character
+77 Indicates unbound character
+78 Emacs universal argument (argument times 4)
+79 Move to previous history line
+80 Uppercase the characters from cursor to end of current word
+81 Vi goto the beginning of next word
+82 Vi enter insert mode after the cursor
+83 Vi enter insert mode at end of line
+84 Vi change case of character under cursor and advance one character
+85 Vi change prefix command
+86 Vi change to end of line
+87 Enter vi command mode (use alternative key bindings)
+88 Vi command mode complete current word
+89 Vi move to previous character (backspace)
+90 Vi delete prefix command
+91 Vi move to the end of the current space delimited word
+92 Vi move to the end of the current word
+93 Vi move to the character specified backward
+94 Vi move to the character specified forward
+95 Vi move up to the character specified backward
+96 Vi move up to the character specified forward
+97 Enter vi insert mode
+98 Enter vi insert mode at beginning of line
+99 Vi repeat current character search in the same search direction
+100 Vi repeat current character search in the opposite search direction
+101 Vi repeat current search in the same search direction
+102 Vi repeat current search in the opposite search direction
+103 Vi replace character under the cursor with the next character typed
+104 Vi replace mode
+105 Vi search history backward
+106 Vi search history forward
+107 Vi replace character under the cursor and enter insert mode
+108 Vi replace entire line
+109 Vi move to the previous word
+110 Vi move to the next word
+111 Vi undo last change
+112 Vi goto the beginning of line
+113 Perform which of current command
+114 Paste cut buffer at cursor position
diff --git a/contrib/tcsh/nls/C/set30 b/contrib/tcsh/nls/C/set30
new file mode 100644
index 0000000..b9e6216
--- /dev/null
+++ b/contrib/tcsh/nls/C/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.4 1996/10/19 17:52:34 christos Exp $
+$ tw.parse.c
+$set 30
+1 starting_a_command %d\n
+2 complete %d
+3 complete %d %S\n
+4 %s: Internal match error.\n
+5 items
+6 rows
+7 There are %d %s, list them anyway? [n/y]
+8 looking = %d\n
+9 \ntcsh internal error: I don't know what I'm looking for!\n
+10 not a directory
+11 not found
+12 unreadable
+13 yY
diff --git a/contrib/tcsh/nls/C/set31 b/contrib/tcsh/nls/C/set31
new file mode 100644
index 0000000..3641251
--- /dev/null
+++ b/contrib/tcsh/nls/C/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ vms.termcap.c
+$set 31
+1 Can't open TERMCAP: [%s]\n
+2 Can't open %s.\n
+3 Found %s in %s.\n
+4 No match found for %s in file %s\n
diff --git a/contrib/tcsh/nls/C/set4 b/contrib/tcsh/nls/C/set4
new file mode 100644
index 0000000..a7d289c
--- /dev/null
+++ b/contrib/tcsh/nls/C/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ Termcap strings
+$set 4
+1 add new blank line
+2 audible bell
+3 clear to bottom
+4 clear to end of line
+5 cursor to horiz pos
+6 clear screen
+7 delete a character
+8 delete a line
+9 start delete mode
+10 end delete mode
+11 end insert mode
+12 cursor from status line
+13 home cursor
+14 insert character
+15 start insert mode
+16 insert padding
+17 sends cursor down
+18 sends cursor left
+19 sends cursor right
+20 sends cursor up
+21 begin bold
+22 end attributes
+23 non destructive space
+24 end standout
+25 begin standout
+26 cursor to status line
+27 cursor up one
+28 begin underline
+29 end underline
+30 visible bell
+31 delete multiple chars
+32 cursor down multiple
+33 insert multiple chars
+34 cursor left multiple
+35 cursor right multiple
+36 cursor up multiple
+37 Has automatic margins
+38 Can use physical tabs
+39 Number of lines
+40 Number of columns
+41 Has meta key
+42 Newline ignored at right margin
diff --git a/contrib/tcsh/nls/C/set5 b/contrib/tcsh/nls/C/set5
new file mode 100644
index 0000000..b684bb8
--- /dev/null
+++ b/contrib/tcsh/nls/C/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ ed.chared.c
+$set 5
+1 Load average unavailable\n
diff --git a/contrib/tcsh/nls/C/set6 b/contrib/tcsh/nls/C/set6
new file mode 100644
index 0000000..03206ad
--- /dev/null
+++ b/contrib/tcsh/nls/C/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ERROR: illegal command from key 0%o\r\n
+2 yes\n
+3 edit\n
+4 abort\n
+5 no\n
+6 No matching command\n
+7 Ambiguous command\n
+8 *** editor fatal ERROR ***\r\n\n
diff --git a/contrib/tcsh/nls/C/set7 b/contrib/tcsh/nls/C/set7
new file mode 100644
index 0000000..26e14132
--- /dev/null
+++ b/contrib/tcsh/nls/C/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.3 1996/04/26 20:32:04 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tTcsh thinks your terminal has the\n
+2 \tfollowing characteristics:\n\n
+3 \tIt has %d columns and %d lines\n
+4 \tIt has %s meta key\n
+5 a
+6 no
+7 \tIt can%s use tabs\n
+8 not
+9 \tIt %s automatic margins\n
+10 has
+11 does not have
+12 \tIt %s magic margins\n
+13 (empty)
+14 yes
+15 no
+16 ERROR: cannot delete\r\n
+17 DeleteChars: num is riduculous: %d\r\n
+18 ERROR: cannot insert\r\n
+19 StartInsert: num is riduculous: %d\r\n
+20 %s: Cannot open /etc/termcap.\n
+21 %s: No entry for terminal type "%s"\n
+22 %s: using dumb terminal settings.\n
+23 %s: WARNING: Your terminal cannot move up.\n
+24 Editing may be odd for long lines.\n
+25 no clear EOL capability.\n
+26 no delete char capability.\n
+27 no insert char capability.\n
diff --git a/contrib/tcsh/nls/C/set8 b/contrib/tcsh/nls/C/set8
new file mode 100644
index 0000000..36cb350
--- /dev/null
+++ b/contrib/tcsh/nls/C/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ ed.term.c
+$set 8
+1 Unknown switch
+2 Invalid argument
diff --git a/contrib/tcsh/nls/C/set9 b/contrib/tcsh/nls/C/set9
new file mode 100644
index 0000000..72511b4
--- /dev/null
+++ b/contrib/tcsh/nls/C/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.2 1995/03/19 18:07:15 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: Null extended-key not allowed.\n
+2 AddXkey: sequence-lead-in command not allowed\n
+3 DeleteXkey: Null extended-key not allowed.\n
+4 Unbound extended key "%S"\n
+5 Some extended keys too long for internal print buffer
+6 Enumerate: BUG!! Null ptr passed\n!
+7 no input
+8 Something must follow: %c\n
+9 Octal constant does not fit in a char.\n
diff --git a/contrib/tcsh/nls/Makefile b/contrib/tcsh/nls/Makefile
new file mode 100644
index 0000000..43a23fa
--- /dev/null
+++ b/contrib/tcsh/nls/Makefile
@@ -0,0 +1,21 @@
+
+SUBDIRS= C german french italian ja greek spanish
+#GENCAT= gencat -new
+GENCAT= gencat
+
+catalogs:
+ @for i in ${SUBDIRS} ; \
+ do \
+ echo "$$i"; \
+ cd $$i; \
+ cat set[0-9] set[0-9][0-9] > ../../tcsh.$$i.m; \
+ cd ..; \
+ ${GENCAT} ../tcsh.$$i.cat ../tcsh.$$i.m; \
+ done
+
+clean:
+ @for i in ${SUBDIRS} ; \
+ do \
+ rm -f $$i/*~; \
+ rm -f ../tcsh.$$i.cat ../tcsh.$$i.m; \
+ done
diff --git a/contrib/tcsh/nls/french/set1 b/contrib/tcsh/nls/french/set1
new file mode 100644
index 0000000..9d8764ac
--- /dev/null
+++ b/contrib/tcsh/nls/french/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.3 1998/06/27 12:27:57 christos Exp $
+$ Messages d 'erreur
+$set 1
+1 Erreur de syntaxe
+2 %s n'est pas autorisé
+3 Mot trop long
+4 $< ligne trop longue
+5 Pas de fichier pour $0
+6 Modificateur [] incomplet
+7 $ l'expansion doit se terminer avant ]
+8 Mauvais : modificateur dans $ (%c)
+9 Erreur d'indice
+10 Numéro mal formé
+11 Plus de mots
+12 Nom de fichier manquant
+13 Erreur globale interne
+14 Commande introuvable
+15 Trop peu d'arguments
+16 Trop d'arguments
+17 Trop dangereux d'attribuer un alias à cela
+18 `If' vide
+19 `Then' incorrect
+20 Les mots ne sont pas placés entre parenthèses
+21 %s introuvable
+22 Masque incorrect
+23 Pas de limite de ce type
+24 Argument trop long
+25 Facteur d'échelle incorrect ou inconnu
+26 Variable pas définie
+27 La pile de répertoires n'a pas cette taille
+28 Mauvais numéro de signal
+29 Signal inconnu; "kill -l" permet de lister les signaux
+30 Le nom de la variable doit commencer par une lettre
+31 Le nom de la variable est trop long
+32 Le nom de la variable ne doit contenir que des caractères alphanumériques
+33 Pas de gestion des travaux dans ce shell
+34 Syntaxe de l'expression
+35 Pas de répertoire personnel
+36 Impossible de passer dans le répertoire personnel
+37 Commande nulle incorrecte
+38 Il manque l'affectation dans l'expression
+39 Opérateur inconnu
+40 ambigu
+41 %s: Le fichier existe
+42 L'argument pour -c se termine avec un anti-slash
+43 Interrompu
+44 Indice hors limites
+45 Dépassement de capacité de ligne
+46 Pas de travail de ce type
+47 Impossible à partir d'un terminal
+48 Vous n'êtes pas dans une boucle while ou foreach
+49 Plus de processus
+50 Pas de correspondance
+51 %c manquant
+52 %c sans correspondance
+53 Mémoire insuffisante
+54 Impossible de créer un tube
+55 %s: %s
+56 %s
+57 Syntaxe: jobs [ -l ]
+58 Les arguments doivent être des ID de processus ou des numéros de travaux
+59 Pas de travail en cours
+60 Pas de travail précédent
+61 Pas de travail de cette forme
+62 Emboîtement des `Fork' > %d; peut-être une boucle `...`
+63 Pas de gestion des travaux dans les sous-shells
+64 Faute `Sync': Processus %d pas trouvé
+65 %s Il y a des travaux interrompus
+66 %s Il y a des travaux arrêtés
+67 Pas d'autre répertoire
+68 La pile de répertoires est vide
+69 Répertoire incorrect
+70 Syntaxe: %s [-%s]%s
+71 Pas d'opérande pour l'indicateur -h
+72 Ce n'est pas un shell de connexion
+73 Division par zéro
+74 Modulo par zéro
+75 Mise à l'échelle incorrecte ; cela signifie-t-il ``%s'' ?
+76 Impossible d'interrompre un shell de connexion
+77 Utilisateur inconnu : %s
+78 Pas de variable `$home' définie
+79 Syntaxe: history [-%s] [# nombre d'évènements]
+80 $, ! ou < pas autorisés avec $# or $?
+81 Retour-chariot dans un nom de variable
+82 * pas autorisé avec $# or $?
+83 $?<digit> ou $#<digit> pas autorisé
+84 Nom de variable incorrect
+85 Retour-chariot dans l'index de variable
+86 Dépassement de capacité de la mémoire tampon d'expansion
+87 Syntaxe de variable
+88 Forme ! incorrecte
+89 Pas de remplacement précédent
+90 Remplacement incorrect
+91 Pas de partie gauche précédente
+92 Partie droite trop longue
+93 Modificateur ! incorrect: %c
+94 Echec du modificateur
+95 Dépassement de capacité de la mémoire tampon de substitution
+96 Sélecteur d'argument ! incorrect
+97 Pas de recherche précédente
+98 %s: événement introuvable
+99 Trop de caractères )
+100 Trop de caractères (
+101 Caractère ( mal placé
+102 Il manque un nom pour rediriger
+103 Redirection de sortie ambigue
+104 Pas de << entre les caractères ( et )
+105 Redirection d'entrée ambigue
+106 Caractères () mal placés
+107 Boucle dans les alias
+108 Pas de variable `$watch' définie
+109 Pas d'évènement prévu
+110 Syntaxe: sched -<#numéro>.\nSyntaxe: sched [+]hh:mm <commande>
+111 Pas tant d'évènements prévus
+112 Pas de commande à lancer
+113 Temps incorrect pour l'évènement
+114 Temps relatif incompatible avec am/pm
+115 Pas assez de place pour la chaine termcap
+116 Syntaxe: settc %s [yes|no]
+117 Capacité `%s' inconnue
+118 Paramètre termcap inconnu `%%%c'
+119 Trop d'arguments pour `%s' (%d)
+120 `%s' nécessite %d arguments
+121 Syntaxe: echotc [-v|-s] [<capacité> [<args>]]
+122 %s: %s. Mauvaise Architecture
+123 !# Boucle dans l'historique
+124 Mauvaise recherche de fichier
+125 Dépassement de capacité de sélecteur
+126 Option inconnue: `-%s'\nSyntaxe: %s [ -bcdefilmnqstvVxX -Dnom[=valeur] ] [ argument ... ]
+127 Option inconnue: `-%s'\nSyntaxe: %s [ -bcdefFilmnqstvVxX ] [ argument ... ]
+128 Option inconnue: `-%s'\nSyntaxe: %s [ -bcdefilmnqstvVxX ] [ argument ... ]
+129 \nComplément incorrect: "%s"
+130 \n%s incorrect: '%c'
+131 \nIl manque le séparateur '%c' après %s "%s"
+132 \n%s incomplet: "%s"
+133 Pas d'opérande pour l'indicateur -m
+134 Syntaxe: unlimit [-fh] [limites]
+135 $%S est en lecture seule
+136 Pas de travail de ce type
+137 Unknown colorls variable `%c%c'
diff --git a/contrib/tcsh/nls/french/set10 b/contrib/tcsh/nls/french/set10
new file mode 100644
index 0000000..191462a
--- /dev/null
+++ b/contrib/tcsh/nls/french/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: commande incorrecte '%s'.\n
+2 setpath: pas assez d'arguments pour la commande '%s'.\n
+3 setpath: donnée manquante dans le chemin '%s'\n
+4 setpath: %s pas trouvé dans %s\n
+5 setpath: %d pas une position correcte dans %s\n
diff --git a/contrib/tcsh/nls/french/set11 b/contrib/tcsh/nls/french/set11
new file mode 100644
index 0000000..421b99c
--- /dev/null
+++ b/contrib/tcsh/nls/french/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ sh.c
+$set 11
+1 Attention: pas d'accès au tty (%s).\n
+2 Ainsi pas de contrôle de job dans ce shell.\n
+3 Vous avez%d messages courrier (mail).\n
+4 Vous avez %d messages courrier (mail) dans %s.\n
+5 Vous avez du %scourrier.\n
+6 nouveau
+7 Vous avez du %scourrier dans %s.\n
diff --git a/contrib/tcsh/nls/french/set12 b/contrib/tcsh/nls/french/set12
new file mode 100644
index 0000000..ccc1396
--- /dev/null
+++ b/contrib/tcsh/nls/french/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.2 1996/04/26 20:45:51 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: Essaie de démarrer à partir de "%s"\n
diff --git a/contrib/tcsh/nls/french/set13 b/contrib/tcsh/nls/french/set13
new file mode 100644
index 0000000..aeefa40
--- /dev/null
+++ b/contrib/tcsh/nls/french/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d groupes de hashage de %d bits chacun\n
+3 masque de déboguage = 0x%08x\n
+4 %d réussis, %d manqués, %d%%\n
+5 %S: commande intégrée au shell.\n
+6 %S: Commande pas trouvée.\n
+7 où: / dans la commande n'a pas de sens\n
+8 %S est un alias avec
+9 %S est intégré(e) au shell\n
+10 hashage manqués:
diff --git a/contrib/tcsh/nls/french/set14 b/contrib/tcsh/nls/french/set14
new file mode 100644
index 0000000..dd16890
--- /dev/null
+++ b/contrib/tcsh/nls/french/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ sh.file.c
+$set 14
+1 \nTrop de %s !!\n
+2 noms dans le fichier des mots de passe
+3 fichiers
diff --git a/contrib/tcsh/nls/french/set15 b/contrib/tcsh/nls/french/set15
new file mode 100644
index 0000000..4a59b54
--- /dev/null
+++ b/contrib/tcsh/nls/french/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: ne peut %s la limite%s\n
+2 enlever
+3 positionner
+4 matérielle
diff --git a/contrib/tcsh/nls/french/set16 b/contrib/tcsh/nls/french/set16
new file mode 100644
index 0000000..0ce1081
--- /dev/null
+++ b/contrib/tcsh/nls/french/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.2 1996/04/26 20:45:55 christos Exp $
+$ sh.lex.c
+$set 16
+1 Réinitialise le groupe de processus des terminaux de %d à %d\n
+2 \nUtilisez "logout" pour vous déconnecter.\n
+3 \nUtilisez "exit" pour quitter %s.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Mauvais type pour seek %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/french/set17 b/contrib/tcsh/nls/french/set17
new file mode 100644
index 0000000..a343157
--- /dev/null
+++ b/contrib/tcsh/nls/french/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.2 1996/10/19 17:52:38 christos Exp $
+$ sh.proc.c
+$set 17
+1 BUG: attente de travail en tâche de fond !\n
+2 Sortie %d\n
+3 BUG: processus vidé deux fois
+4 Tourne
+5 Signal
+6 Sortie %-25d
+7 Fait
+8 BUG: état=%-9o
+9 \040(core dumped)
+10 \040(wd:
+11 wd maintenant:
+12 %S: Déjà suspendu\n
+13 %S: Déjà arrêté\n
diff --git a/contrib/tcsh/nls/french/set18 b/contrib/tcsh/nls/french/set18
new file mode 100644
index 0000000..0d6c50f
--- /dev/null
+++ b/contrib/tcsh/nls/french/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ sh.set.c
+$set 18
+1 Attention: le PATH exagérément long est tronqué\n
diff --git a/contrib/tcsh/nls/french/set19 b/contrib/tcsh/nls/french/set19
new file mode 100644
index 0000000..c24da8a
--- /dev/null
+++ b/contrib/tcsh/nls/french/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.2 1996/04/26 20:45:59 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: Plus de mémoire\n
+2 free(%lx) appelé avant allocation.
+3 free(%lx) au delà de la limite memoire.
+4 free(%lx) en deçà de la limite memoire.
+5 free(%lx) mauvais bloc.
+6 free(%lx) limites incorrectes.
+7 free(%lx) index de bloc incorrect.
+8 %s allocation mémoire actuelle:\nfree:\t
+9 \nutilisé:\t
+10 \n\tTotal utilisé: %d, total libre: %d\n
+11 \tMémoire allouée de 0x%lx à 0x%lx. Limite réelle supérieure à 0x%lx\n
+12 Mémoire allouée de 0x%lx à 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/french/set2 b/contrib/tcsh/nls/french/set2
new file mode 100644
index 0000000..e5bf617
--- /dev/null
+++ b/contrib/tcsh/nls/french/set2
@@ -0,0 +1,94 @@
+$ $Id: set2,v 1.2 1997/10/27 23:33:53 christos Exp $
+$ Messages Signaux
+$set 2
+1 Signal nul
+2 Interrompu
+3 Arrêté
+4 Sortie
+5 Instruction interdite
+6 Piège Trace/BPT
+7 Abandon
+8 Piège IOT
+9 Plantage système imminent
+10 Sortie erreur
+11 Piège EMT
+12 Exception de calcul en virgule flottante
+13 Supprimé
+14 Signal utilisateur 1
+15 Signal utilisateur 2
+16 Incident de segmentation
+17 Erreur de bus
+18 Program range error
+19 Operand range error
+20 Appel système incorrect
+21 Tube détruit
+22 Alarme
+23 Terminé
+24 L'état du fils a changé
+25 Mort du fils
+26 Faute spécifique Apollo
+27 Fils arrêté ou sorti
+28 Fils sorti
+29 Coupure d'alimentation
+30 Ressource perdue
+31 Break (Ctrl-Break)
+32 Signal d'E-S possible
+33 Entrée-Sortie asynchrone (select)
+34 Condition urgente sur canal d'E-S
+35 Reprise multi-tâche
+36 Terminaison multi-tâche
+37 Achèvement d'E-S asynchrone Fortran
+38 Reprise
+39 Erreur mémoire irrécupérable
+40 Limite temps CPU dépassée
+41 Arrêt du système imminent
+42 Groupe micro-tasking-pas d'option de réveil définie
+43 Erreur de thread - (utilisez cord -T pour plus d'infos)
+44 Erreur de parité de registre du CRAY Y-MP
+45 Demande d'information
+46 Interrompu (Signal)
+47 Stoppé (Signal)
+48 Interrompu
+49 Stoppé
+50 Continue
+51 Entrée tty suspendue
+52 Entrée tty arrêtée
+53 Sortie tty suspendue
+54 Sortie tty arrêtée
+55 Etat de la fenêtre modifié
+56 Taille de la fenêtre modifiée
+57 Etat du téléphone modifié
+58 Limite temps CPU dépassée
+59 Taille limite de fichier dépassée
+60 Signal de l'horloge virtuelle
+61 Signal de profil
+62 Signal DIL
+63 Un évènement à scruter est arrivé
+64 Process's lwps are blocked
+65 Signal Special LWP
+66 Signal Special CPR
+67 Signal Special CPR
+68 Premier signal temps réel
+69 Deuxième signal temps réel
+70 Troisième signal temps réel
+71 Quatrième signal temps réel
+72 Quatrième signal temps réel avant la fin
+73 Antépénultième signal temps réel
+74 Avant-dernier signal temps réel
+75 Dernier signal temps réel
+76 E-S asynchrone LAN
+77 Lecture/Ecriture PTY disponible
+78 Intervention E-S nécessaire
+79 Mode moniteur HFT accordé
+80 Le mode moniteur HFT doit être abandonné
+81 Le contrôle du son HFT est terminé
+82 Données en buffer circulaire HFT
+83 Processus de transfert
+84 Touche d'attention sécurisée
+85 Re-séquencement
+86 Signal SS$_DEBUG
+87 Priorité modifiée
+88 detecté
+89 Nouveau caractère d'entrée
+90 Stack limit exceeded
+91 Unused signal
diff --git a/contrib/tcsh/nls/french/set20 b/contrib/tcsh/nls/french/set20
new file mode 100644
index 0000000..0f26862
--- /dev/null
+++ b/contrib/tcsh/nls/french/set20
@@ -0,0 +1,41 @@
+$ $Id: set20,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.bind.c
+$set 20
+1 Nom de touche incorrect `%S'\n
+2 Mauvais nom de touche: %S\n
+3 Mauvais nom de commande: %S\n
+4 Mauvaise touche spécifiée %S\n
+5 Chaine nulle spécifiée\n
+6 Définition de touches standard\n
+7 Définition de touches alternatives\n
+8 Définition Multi-caractères\n
+9 Définition des touches de direction\n
+10 %-15s-> n'est pas défini\n
+11 BUG!!! %s n'est lié à rien.\n
+12 Usage: bindkey [options] [--] [TOUCHE [COMMANDE]]\n
+13 -a liste ou définit la TOUCHE dans la table des touches alternatives\n
+14 -b interprète TOUCHE comme un nom de touche C-, M-, F- or X-\n
+15 -s interprète COMMANDE comme une chaine littérale devant être sortie\n
+16 -c interprète COMMANDE comme une commande intégrée ou externe\n
+17 -v redéfinit toutes les touches pour vi\n
+18 -e redéfinit toutes les touches pour emacs\n
+19 -d redéfinit toutes les touches pour de l'éditeur par defaut\n
+20 -l liste les commandes de l'éditeur avec descriptions\n
+21 -r enlève la correspondance pour la TOUCHE\n
+22 -k interprète TOUCHE comme un nom de touche de direction symbolique\n
+23 -- force un arrêt dans le traitement de l'option\n
+24 -u (ou toute option incorrecte) ce message\n
+25 Sans TOUCHE ni COMMANDE, imprime toutes les associations\n
+26 Sans COMMANDE, imprime l'association pour TOUCHE.\n
+27 mauvaise spécification de touche -- chaine nulle\n
+28 mauvaise spécification de touche -- chaine vide\n
+29 mauvaise spécification de touche de fonction. Touche nulle pas autorisé\n
+30 mauvaise spécification de touche -- nombre hexa mal formé\n
+31 mauvaise spécification de touche -- nombre octal mal formé\n
+32 mauvaise spécification de touche -- nombre décimal mal formé\n
+33 Mauvaise spécification de touche de fonction.\n
+34 Touche nulle pas autorisé\n
+35 Mauvaise spécification de touche -- nom inconnu "%S"\n
+36 Syntaxe: bind [TOUCHE | COMMANDE TOUCHE | "emacs" | "vi" | "-a"]\n
+37 Fonction incorrecte
+38 %s\t\tn'est pas défini\n
diff --git a/contrib/tcsh/nls/french/set21 b/contrib/tcsh/nls/french/set21
new file mode 100644
index 0000000..78c8c1a
--- /dev/null
+++ b/contrib/tcsh/nls/french/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.disc.c
+$set 21
+1 ne peut obtenir les caractères locaux.\n
+2 ne peut définir les catactères locaux.\n
diff --git a/contrib/tcsh/nls/french/set22 b/contrib/tcsh/nls/french/set22
new file mode 100644
index 0000000..94f4131
--- /dev/null
+++ b/contrib/tcsh/nls/french/set22
@@ -0,0 +1,17 @@
+$ $Id: set22,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t a comme alias
+2 \nMot de passe incorrect pour %s\n
+3 Erreur alias 'precmd' enlevé.\n
+4 Erreur alias 'cwdcmd' enlevé.\n
+5 Erreur alias 'beepcmd' enlevé.\n
+6 Erreur alias 'periodic' enlevé.\n
+7 étude de la ligne de commande\n
+8 Voulez vous vraiment supprimer tous les fichiers? [n/y]
+9 passe la suppression des fichiers!\n
+10 la ligne de commande est maintenant :\n
+11 étude de la ligne de commande\n
+12 dans une des listes\n
+13 la ligne de commande est maintenant :\n
+14 OoyY
diff --git a/contrib/tcsh/nls/french/set23 b/contrib/tcsh/nls/french/set23
new file mode 100644
index 0000000..187db0f
--- /dev/null
+++ b/contrib/tcsh/nls/french/set23
@@ -0,0 +1,34 @@
+$ $Id: set23,v 1.2 1996/04/26 20:46:04 christos Exp $
+$ tc.os.c
+$set 23
+1 Mauvais nom de cpu/site
+2 Chemin du site trop mong
+3 inconnu
+4 site: %s\n
+5 %d: Site pas trouvé\n
+6 setlocal: %s: %s\n
+7 Site pas trouvé
+8 Vous êtes piégé dans un univers que vous n'avez jamais créé
+9 Getwarp a échoué
+10 warp invalide
+11 Setwarp a échoué
+12 Univers incorrect
+13 Erreur inconnue : %d
+14 sysname: %s\n
+15 nodename: %s\n
+16 release: %s\n
+17 version: %s\n
+18 machine: %s\n
+19 getwd: Ne peut ouvrir ".." (%s)
+20 getwd: Ne peut effectuer chdir vers ".." (%s)
+21 getwd: Erreur en lecture dans ".." (%s)
+22 getwd: Ne peut revenir à "." (%s)
+23 getwd: Ne peut effectuer stat "/" (%s)
+24 getwd: Ne peut effectuer stat "." (%s)
+25 getwd: Ne peut effectuer stat sur répertoire "%s" (%s)
+26 getwd: Ne peut ouvrir le répertoire "%s" (%s)
+27 getwd: Ne peut trouver "." dans ".." (%s)
+28 Type de système incorrect
+29 Le type de système n'est pas défini
+30 XXX: Too many arguments
+31 XXX: Invalid argument
diff --git a/contrib/tcsh/nls/french/set24 b/contrib/tcsh/nls/french/set24
new file mode 100644
index 0000000..4c89c35
--- /dev/null
+++ b/contrib/tcsh/nls/french/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.sched.c
+$set 24
+1 kludge
diff --git a/contrib/tcsh/nls/french/set25 b/contrib/tcsh/nls/french/set25
new file mode 100644
index 0000000..f5efff5
--- /dev/null
+++ b/contrib/tcsh/nls/french/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.sig.c
+$set 25
+1 notre attente %d\n
+2 erreur: bsd_signal(%d) signal hors limites\n
+3 erreur: bsd_signal(%d) - sigaction a échoué, errno %d\n
diff --git a/contrib/tcsh/nls/french/set26 b/contrib/tcsh/nls/french/set26
new file mode 100644
index 0000000..c42cb3c
--- /dev/null
+++ b/contrib/tcsh/nls/french/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tc.who.c
+$set 26
+1 ne peut effectuer stat %s. S.V.P effectuez "unset watch".\n
+2 %s ne peut être ouvert. S.V.P effectuez "unset watch".\n
+3 BUG! le dernier élément n'est pas whotail!\n
+4 arrière:
+5 BUG! le premier élément n'est pas whohead!\n
+6 nouveau: %s/%s\n
+7 %n a %a %l from %m.
+8 %n a %a %l.
+9 connecté
+10 déconnecté
+11 remplacé %s
+12 local
diff --git a/contrib/tcsh/nls/french/set27 b/contrib/tcsh/nls/french/set27
new file mode 100644
index 0000000..3f29321
--- /dev/null
+++ b/contrib/tcsh/nls/french/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tw.comp.c
+$set 27
+1 commande
+2 séparateur
+3 motif
+4 intervalle
+5 complément
diff --git a/contrib/tcsh/nls/french/set29 b/contrib/tcsh/nls/french/set29
new file mode 100644
index 0000000..7309fe4
--- /dev/null
+++ b/contrib/tcsh/nls/french/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ tw.help.c
+$set 29
+1 Pas de fichier d'aide pour %S\n
diff --git a/contrib/tcsh/nls/french/set3 b/contrib/tcsh/nls/french/set3
new file mode 100644
index 0000000..acf6f80
--- /dev/null
+++ b/contrib/tcsh/nls/french/set3
@@ -0,0 +1,117 @@
+$ $Id: set3,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ Description des fonctions éditeur
+$set 3
+1 Recule d'un caractère
+2 Efface le caractère derrière le curseur
+3 Coupe depuis le début du mot jusqu'au curseur - sauvegardé dans le tampon de copie
+4 Coupe depuis le début de la ligne jusqu'au curseur - sauvegardé dans le tampon de copie
+5 Va au début du mot courant
+6 Va au début de la ligne
+7 Met en majuscules les caractères depuis le curseur jusqu'à la fin du mot
+8 Vi change la casse du caractère sous le curseur et avance d'un caractère
+9 Vi change jusqu'à la fin de la ligne
+10 Efface l'écran en laissant la ligne courant au dessus
+11 Complète le mot courant
+12 Tab avance parmi les fichiers
+13 Tab recule parmi les fichiers
+14 Complète le mot courant en ignorant les compléments programmables
+15 Copie le mot courant jusqu'au curseur
+16 Copie la zone entre la marque et le curseur dans le tampon de copie
+17 Développe vers le mot précédent pour lequel c'est un préfixe
+18 Efface le caractère sous le curseur
+19 Efface le caractère sous le curseur, ou signale la fin de fichier si ligne vide
+20 Efface le caractère sous le curseur, ou liste les compléments si fin de ligne
+21 Efface le caractère sous le curseur, liste les compléments ou signale la fin de fichier
+22 Coupe depuis le curseur jusqu'à la fin du mot courant - sauvegardé dans le tampon de copie
+23 Ajoute aux arguments si démarré ou entre le chiffre
+24 Chiffre au début de l'argument
+25 Va à la prochaine ligne de l'historique
+26 Met en minuscules les caractères depuis le curseur jusqu'à la fin du mot
+27 Indique la fin de fichier
+28 Déplace le curseur à la fin de la ligne
+29 Echange le curseur et la marque
+30 Développe les jokers du nom de fichier
+31 Développe les échappements de l'historique
+32 Développe les échappements de l'historique en une ligne
+33 Développe les variables
+34 Avance d'un caractère
+35 Avance à la fin du mot courant
+36 Echange les deux caractères avant le curseur
+37 Cherche en arrière dans l'historique une ligne commençant comme la ligne courante
+38 Cherche en avant dans l'historique une ligne commençant comme la ligne courante
+39 Insère le dernier elément de la commande précédente
+40 Recherche en avant incrémentale
+41 Recherche en arrière incrémentale
+42 Efface la ligne
+43 Coupe jusqu'à la fin de la ligne et sauvegarde dans le tampon de copie
+44 Coupe la zone entre la marque et le curseur et sauvegarde dans le tampon de copie
+45 Coupe toute la ligne et sauvegarde dans le tampon de copie
+46 Liste les choix pour le complément
+47 Liste les choix pour le complément sur-définissant le complément programmable
+48 Liste les correspondances pour le nom de fichier avec joker
+49 Liste les choix pour le complément ou indique la fin de fichier si ligne vide
+50 Affiche la charge moyenne et l'état courant des processus
+51 Développe les échappements de l'historique et insère une espace
+52 Exécute la commande
+53 Développe les nom de répertoires, éliminant les `.' et `..' en tête
+54 Développe les commandes pour le chemin ou l'alias résultant
+55 Passe du mode insertion au mode recouvrement et vice-versa
+56 Ajoute le 8ième bit au prochain caractère saisi
+57 Ajoute le prochain caractère saisi à la ligne
+58 Réaffiche tout
+59 Redémarre l'éditeur
+60 Cherche de l'aide pour la commande courante
+61 Ce caractère est ajouté à la ligne
+62 Ca caractère est le premier dans une séquence de caractères
+63 Définit la marque à la position du curseur
+64 Corrige la syntaxe du mot courant
+65 Corrige la syntaxe de la ligne complète
+66 Envoie le caractère au tty en mode
+67 Bascule la ligne courante de l'historique entre le mode littéral et lexical
+68 Echange le caractère à la gauche du curseur avec celui en dessous du curseur
+69 Echange les deux caractères avant le curseur
+70 Caractère tty de suspension différé
+71 Caractère tty de vidage de sortie
+72 Caractère tty d'interruption
+73 Caractère tty de sortie
+74 Caractère tty de suspension
+75 Caractère tty de validation de sortie
+76 Caractère tty d'invalidation de sortie
+77 Indique un caractère pas attaché
+78 Argument universel Emacs (argument x 4)
+79 Va à la ligne précédente de l'historique
+80 Met en majuscule les caractères depuis le curseur jusqu'à la fin du mot courant
+81 Vi va au début du prochain mot
+82 Vi passe en mode insertion après le curseur
+83 Vi passe en mode insertion à la fin de la ligne
+84 Vi change la casse du caractère sous le curseur et avance d'un caractère
+85 Vi change la commande `prefix'
+86 Vi change jusqu'à la fin de la ligne
+87 Passe au mode de commande Vi (redéfinition des touches alternatives)
+88 Le mode commande de Vi complète le mot courant
+89 Vi va au caractère précédent (retour-arrière)
+90 Vi efface la commande `prefix'
+91 Vi va à la fin du mot courant délimité par des espaces
+92 Vi va à la fin du mot courant
+93 Vi va vers le caractère spécifié avant
+94 Vi va vers le caractère spécifié après
+95 Vi remonte vers le caractère spécifié avant
+96 Vi remonte vers le caractère spécifié après
+97 Passe en mode insertion Vi
+98 Passe en mode insertion Vi au début de la ligne
+99 Vi répète la recherche du caractère en cours dans la même direction
+100 Vi répète la recherche du caractère en cours dans la direction opposée
+101 Vi répète la recherche en cours dans la même direction
+102 Vi répète la recherche en cours dans la direction opposée
+103 Vi remplace le caractère sous le curseur avec le prochain caractère saisi
+104 Mode de remplacement Vi
+105 Vi cherche dans l'historique en arrière
+106 Vi cherche dans l'historique en avant
+107 Vi remplace le caractère sous le curseur et passe en mode insertion
+108 Vi remplace la ligne entière
+109 Vi va au mot précédent
+110 Vi va au prochain mot
+111 Vi défait la dernière modification
+112 Vi va au début de la ligne
+113 Exécute quelle commande en cours
+114 Colle le tampon de copie à la position du curseur
diff --git a/contrib/tcsh/nls/french/set30 b/contrib/tcsh/nls/french/set30
new file mode 100644
index 0000000..27ab9c9
--- /dev/null
+++ b/contrib/tcsh/nls/french/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.2 1996/04/26 20:46:09 christos Exp $
+$ tw.parse.c
+$set 30
+1 démarre une commande %d\n
+2 complete %d
+3 complete %d %S\n
+4 %s: Erreur interne de correspondance.\n
+5 éléments
+6 colonnes
+7 Il y a %d %s, les lister quand même ? [n/y]
+8 looking = %d\n
+9 \nerreur interne %s: Je ne sais pas ce que je recherche !\n
+10 pas un répertoire
+11 pas trouvé
+12 pas lisible
+13 oOyY
diff --git a/contrib/tcsh/nls/french/set31 b/contrib/tcsh/nls/french/set31
new file mode 100644
index 0000000..211c5bf
--- /dev/null
+++ b/contrib/tcsh/nls/french/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ vms.termcap.c
+$set 31
+1 Ne peut ouvrir TERMCAP: [%s]\n
+2 Ne peut ouvrir %s.\n
+3 Trouvé %s dans %s.\n
+4 Pas de correspondance trouvée pour %s dans le fichier %s\n
diff --git a/contrib/tcsh/nls/french/set4 b/contrib/tcsh/nls/french/set4
new file mode 100644
index 0000000..bff6be3
--- /dev/null
+++ b/contrib/tcsh/nls/french/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ Termcap strings
+$set 4
+1 ajoute une nouvelle ligne vide
+2 bip audible
+3 efface jusqu'en bas
+4 efface jusqu'à la fin de la ligne
+5 curseur vers un position horizontale
+6 efface l'écran
+7 efface un caractère
+8 efface une ligne
+9 commence le mode d'effacement
+10 termine le mode d'effacement
+11 termine le mode d'insertion
+12 curseur de la ligne d'état
+13 curseur origine
+14 insère caractère
+15 commence le mode insertion
+16 insère du remplissage
+17 curseur vers le bas
+18 curseur vers la gauche
+19 curseur vers la droite
+20 curseur vers le haut
+21 commence le gras
+22 fin attributs
+23 espaces non-destructives
+24 fin mise en évidence
+25 commence mise en évidence
+26 curseur à la ligne d'état
+27 curseur d'une vers le haut
+28 commence souligné
+29 fin souligné
+30 bip `visible'
+31 efface plusiseurs caractères
+32 curseur vers le bas (plusieurs)
+33 insert plusieurs caractères
+34 curseur vers la gauche (plusieurs)
+35 curseur vers la droite (plusieurs)
+36 curseur vers le haut (plusieurs)
+37 A les marge automatiques
+38 Peut utiliser les tabulations physiques
+39 Nombre de lignes
+40 Nombre de colonnes
+41 A les touches `alternatives'
+42 retoure-chariot ignoré à la droite de la marge
diff --git a/contrib/tcsh/nls/french/set5 b/contrib/tcsh/nls/french/set5
new file mode 100644
index 0000000..d2caaea
--- /dev/null
+++ b/contrib/tcsh/nls/french/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ ed.chared.c
+$set 5
+1 Charge moyenne indisponible\n
diff --git a/contrib/tcsh/nls/french/set6 b/contrib/tcsh/nls/french/set6
new file mode 100644
index 0000000..f766687e
--- /dev/null
+++ b/contrib/tcsh/nls/french/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ERREUR: commande interdite de la touche 0%o\r\n
+2 oui\n
+3 edit\n
+4 arrête\n
+5 non\n
+6 Pas de commande correspondante\n
+7 Commande ambigue\n
+8 *** ERREUR fatale de l'éditeur ***\r\n\n
diff --git a/contrib/tcsh/nls/french/set7 b/contrib/tcsh/nls/french/set7
new file mode 100644
index 0000000..104eb4b
--- /dev/null
+++ b/contrib/tcsh/nls/french/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.2 1996/04/26 20:46:12 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tTcsh a déterminé que votre terminal a les\n
+2 \tcaractéristiques suivantes :\n\n
+3 \tIl a %d colonnes et %d lignes\n
+4 \tIl %s touche `alternative'\n
+5 a une
+6 n'a pas de
+7 \tIl %speut utiliser les tabulations\n
+8 ne
+9 \tIl %s les marges automatiques\n
+10 a
+11 n'a pas
+12 \tIl %s les marges magiques\n
+13 (vide)
+14 oui
+15 non
+16 ERREUR: ne peut pas effacer\r\n
+17 DeleteChars: num est ridicule: %d\r\n
+18 ERREUR: ne peut insérer\r\n
+19 StartInsert: num est ridicule: %d\r\n
+20 %s: Ne peut ouvrir /etc/termcap.\n
+21 %s: Pas d'entrée pour le type de terminal "%s"\n
+22 %s: utilise la configuration d'un terminal banal.\n
+23 %s: ATTENTION: Votre terminal ne peut effectuer de déplacement vers le haut.\n
+24 L'édition peut être incorrecte pour les longues lignes.\n
+25 pas de capacité d'effacement jusqu'à fin de ligne.\n
+26 pas de capacité d'effacement de caractère.\n
+27 pas de capacité d'insertion de caractère.\n
diff --git a/contrib/tcsh/nls/french/set8 b/contrib/tcsh/nls/french/set8
new file mode 100644
index 0000000..3c089f8
--- /dev/null
+++ b/contrib/tcsh/nls/french/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ ed.term.c
+$set 8
+1 Sélecteur inconnu
+2 Argument incorrect
diff --git a/contrib/tcsh/nls/french/set9 b/contrib/tcsh/nls/french/set9
new file mode 100644
index 0000000..b776d6b
--- /dev/null
+++ b/contrib/tcsh/nls/french/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.1 1995/04/25 14:04:35 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: touche d'extension nulle pas autorisé.\n
+2 AddXkey: commande séquence d'introduction (sequence-lead-in) pas autorisé\n
+3 DeleteXkey: touche d'extension nulle pas autorisé.\n
+4 Touche d'extension pas définie "%S"\n
+5 Certaines touches d'extension trop longues pour tampon d'impression interne
+6 Enumerate: BUG!! Pointeur Null passé!\n
+7 pas d'entrée
+8 Quelque chose doit suivre: %c\n
+9 Une constante Octale ne peut pas tenir dans un caractère.\n
diff --git a/contrib/tcsh/nls/german/set1 b/contrib/tcsh/nls/german/set1
new file mode 100644
index 0000000..616e5a1
--- /dev/null
+++ b/contrib/tcsh/nls/german/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.5 1998/06/27 12:27:59 christos Exp $
+$ Error messages
+$set 1
+1 Syntaxfehler
+2 %s nicht erlaubt
+3 Word zu lang
+4 $< Zeile zu lang
+5 Keine Datei für $0
+6 Unvollständiger [] Modifizierer
+7 $ Ausweitung muß vor ] enden
+8 Falscher : Modifizierer in $ (%c)
+9 Indexfehler
+10 Falsche Nummer
+11 Keine Worte mehr
+12 Dateiname fehlt
+13 Interner Fehler (glob)
+14 Befehl nicht gefunden
+15 Zu wenig Argumente
+16 Zu viele Argumente
+17 Zu gefährlich für ein Alias
+18 Leeres If
+19 Unpassendes Then
+20 Worte nicht in Klammern
+21 %s nicht gefunden
+22 Ungeeignete Maske
+23 Keine bekannte Begrenzung
+24 Argument zu groß
+25 Ungeeigneter oder unbekannter Vergrößerungsfaktor
+26 Undefinierte Variable
+27 Verzeichnisstapel nicht so tief
+28 Falscher Signalname
+29 Unbekanntes Signal; kill -l listet Signale auf
+30 Variablenname muß mit einem Buchstaben beginnen
+31 Variablenname zu lang
+32 Variablenname muß Buchstaben oder Ziffern enthalten
+33 Keine Jobkontrolle in dieser Shell
+34 Ausdruck nicht korrekt
+35 Kein Startverzeichnis
+36 Kann nicht in das Startverzeichnis wechseln
+37 Ungültiger leerer Befehl
+38 Zuweisung ohne Ausdruck
+39 Unbekannter Operator
+40 Mehrdeutig
+41 %s: Datei existiert
+42 Argument für -c endet mit einem Backslash (\\)
+43 Abgebrochen
+44 Index nicht im gültigen Bereich
+45 Zeilenüberlauf
+46 Kein solcher Job
+47 Kann nicht vom Terminal
+48 Nicht in while/foreach
+49 Keine Prozesse mehr
+50 Kein Treffer
+51 Fehlendes %c
+52 Überflüssiges %c
+53 Kein Speicher mehr
+54 Kann keine Pipe erzeugen
+55 %s: %s
+56 %s
+57 Benutzung: jobs [ -l ]
+58 Argumente können Job- oder Prozeß-ID's sein
+59 Kein aktueller Job
+60 Kein vorhergehender Job
+61 Kein Job entspricht dem Muster
+62 Fork-Ebene > %d; evtl. `...` Schleife?
+63 Keine Jobkontrolle in Unter-Shells
+64 Sync-Fehler: Prozeß %d nicht gefunden
+65 %sEs gibt noch angehaltene Jobs
+66 %sEs gibt noch angehaltene Jobs
+67 Kein anderes Verzeichnis
+68 Verzeichnisstapel leer
+69 Ungültiges Verzeichnis
+70 Benutzung: %s [-%s]%s
+71 Kein Operand für -h
+72 Nicht in einer Login-Shell
+73 Division durch 0
+74 Mod durch 0
+75 Bad scaling; did you mean "%s"?
+76 Kann Login-Shell (noch) nicht anhalten
+77 Unbekannter Benutzer: %s
+78 Keine $home-Variable gesetzt
+79 Benutzung: history [-%s] [# Anzahl der Befehle]
+80 $, ! oder < nicht erlaubt mit $# or $?
+81 Zeilenumbruch in Variablenname
+82 * nicht erlaubt bei $# or $?
+83 $?<digit> or $#<digit> nicht erlaubt
+84 Ungültiger Variablenname
+85 Zeilenumbruch in Variablenindex
+86 Überlauf des Erweiterungspuffers
+87 Variablen-Syntax
+88 Falsche ! Form
+89 Keine vorhergehende Ersetzung
+90 Falsche Ersetzung
+91 Keine vorhergehende linke Seite
+92 Rechte Seite zu lang
+93 Falscher ! Modifizierer: %c
+94 Modifizierer fehlgeschlagen
+95 Überlauf des Ersetzungspuffers
+96 Falscher ! Argumentbezeichner
+97 Keine vorhergehende Suche
+98 %s: Befehl nicht gefunden
+99 Zu viele ')'
+100 Zu viele '('
+101 Falsch plazierte '('
+102 Fehlender Name für Umlenkung
+103 Mehrdeutige Ausgabeumlenkung
+104 Kann keine << innerhalb von ()
+105 Mehrdeutige Eingabeumlenkung
+106 Falsch plazierte ()
+107 Alias-Schleife
+108 Keine $watch-Variable gesetzt
+109 Keine vorgemerkten Befehle
+110 Benutzung: sched -<item#>.\nBenutzung: sched [+]hh:mm <Befehl>
+111 Nicht so viele vorgemerkte Befehle
+112 Kein auszuführender Befehl
+113 Ungültige Zeit für Befehl
+114 Relative Zeit inkonsistent mit am/pm
+115 Kein Platz mehr für Termcap-Eintrag
+116 Benutzung: settc %s [yes|no]
+117 Unbekannte Fähigkeit `%s'
+118 Unbekannter Termcap-Parameter `%%%c'
+119 Zu viele Argumente für `%s' (%d)
+120 `%s' erfordert %d Argumente
+121 Benutzung: echotc [-v|-s] [<Fähigkeit> [<Argumente>]]
+122 %s: %s. Falsche Architektur
+123 !# History-Schleife
+124 Falsche Dateianforderung
+125 Selector-Überlauf
+126 Unbekannte Option: `-%s'\nBenutzung: %s [ -bcdefilmnqstvVxX -Dname[=Wert] ] [ Argument ... ]
+127 Unbekannte Option: `-%s'\nBenutzung: %s [ -bcdefFilmnqstvVxX ] [ Argument ... ]
+128 Unbekannte Option: `-%s'\nBenutzung: %s [ -bcdefilmnqstvVxX ] [ Argument ... ]
+129 \nUngültige Vervollständigung: "%s"
+130 \nUngültiger %s: '%c'
+131 \nFehlende Trennung '%c' nach %s "%s"
+132 \nUnvollständiger/-ges %s: "%s"
+133 Kein Operand für -m Option
+134 Benutzung: unlimit [-fh] [Grenzen]
+135 $%S ist nur lesbar
+136 Kein solcher Job
+137 Unknown colorls variable `%c%c'
diff --git a/contrib/tcsh/nls/german/set10 b/contrib/tcsh/nls/german/set10
new file mode 100644
index 0000000..ae50ffb
--- /dev/null
+++ b/contrib/tcsh/nls/german/set10
@@ -0,0 +1,9 @@
+$ $Id: set10,v 1.3 1996/10/19 17:52:48 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: ungültiger Befehl '%s'.\n
+2 setpath: unzureichende Argumente für Befehl '%s'.\n
+3 setpath: Wert fehlt in Pfad '%s'\n
+4 setpath: %s nicht in %s gefunden\n
+5 setpath: %d keine gültige Position in %s\n
+
diff --git a/contrib/tcsh/nls/german/set11 b/contrib/tcsh/nls/german/set11
new file mode 100644
index 0000000..793e4d4
--- /dev/null
+++ b/contrib/tcsh/nls/german/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.4 1996/10/19 17:52:49 christos Exp $
+$ sh.c
+$set 11
+1 Warnung: kein Zugriff auf Tty (%s).\n
+2 Daher keine Job Control in dieser Shell.\n
+3 Sie haben %d Mails.\n
+4 Sie haben %d Mails in %s.\n
+5 Sie haben %sMail.\n
+6 neue\040
+7 Sie haben %sMail in %s.\n
diff --git a/contrib/tcsh/nls/german/set12 b/contrib/tcsh/nls/german/set12
new file mode 100644
index 0000000..fefab67
--- /dev/null
+++ b/contrib/tcsh/nls/german/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.3 1996/04/26 20:54:21 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: Versuche von "%s" zu starten.\n
diff --git a/contrib/tcsh/nls/german/set13 b/contrib/tcsh/nls/german/set13
new file mode 100644
index 0000000..e03203a
--- /dev/null
+++ b/contrib/tcsh/nls/german/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d Hash-Buckets mit jeweils %d Bits\n
+3 debug mask = 0x%08x\n
+4 %d Treffer, %d Fehler, %d%%\n
+5 %S: Befehl in Shell eingebaut.\n
+6 %S: Befehl nicht gefunden.\n
+7 where: / in Befehl ist nicht sinnvoll\n
+8 %S ist ein Alias für
+9 %S ist ein eingebauter Shell-Befehl\n
+10 Hash-Fehler:
diff --git a/contrib/tcsh/nls/german/set14 b/contrib/tcsh/nls/german/set14
new file mode 100644
index 0000000..e882877
--- /dev/null
+++ b/contrib/tcsh/nls/german/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.3 1996/10/19 17:52:50 christos Exp $
+$ sh.file.c
+$set 14
+1 \nAuweia!! Zu viele %s!!\n
+2 Namen in Passwort-Datei
+3 Dateien
diff --git a/contrib/tcsh/nls/german/set15 b/contrib/tcsh/nls/german/set15
new file mode 100644
index 0000000..3113808
--- /dev/null
+++ b/contrib/tcsh/nls/german/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.3 1996/10/19 17:52:51 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: Kann Begrenzung nicht %s%s\n
+2 löschen
+3 setzen
+4 \040(hard limit)
diff --git a/contrib/tcsh/nls/german/set16 b/contrib/tcsh/nls/german/set16
new file mode 100644
index 0000000..e43d5a8
--- /dev/null
+++ b/contrib/tcsh/nls/german/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ sh.lex.c
+$set 16
+1 Setze Prozeßgruppe des Terminals von %d auf %d\n
+2 \nBitte "logout" zum Abmelden benutzen.\n
+3 \nBitte "exit" zum Verlassen der Tcsh benutzen.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Falscher Typ für seek: %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/german/set17 b/contrib/tcsh/nls/german/set17
new file mode 100644
index 0000000..36a6e76
--- /dev/null
+++ b/contrib/tcsh/nls/german/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.3 1996/10/19 17:52:51 christos Exp $
+$ sh.proc.c
+$set 17
+1 FEHLER: Warte auf Hintergrund-Job!\n
+2 Exitcode %d\n
+3 FEHLER: Prozeß "flushed" zum zweitenmal
+4 Läuft
+5 Signal
+6 Exitcode %-25d
+7 Fertig
+8 FEHLER: Status=%-9o
+9 \040(core dumped)
+10 \040(Verz:\040
+11 (Verz jetzt:
+12 %S: Bereits angehalten\n
+13 %S: Bereits angehalten\n
diff --git a/contrib/tcsh/nls/german/set18 b/contrib/tcsh/nls/german/set18
new file mode 100644
index 0000000..016e670
--- /dev/null
+++ b/contrib/tcsh/nls/german/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ sh.set.c
+$set 18
+1 Warnung: lächerlich langer PATH abgeschnitten\n
diff --git a/contrib/tcsh/nls/german/set19 b/contrib/tcsh/nls/german/set19
new file mode 100644
index 0000000..376ce30
--- /dev/null
+++ b/contrib/tcsh/nls/german/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: Out of memory\n
+2 free(%lx) aufgerufen vor irgendeiner Allokation.
+3 free(%lx) vor dem Start des Speichers.
+4 free(%lx) hinter dem Ende des Speichers.
+5 free(%lx) falschen Block.
+6 free(%lx) falscher Bereichs-Check.
+7 free(%lx) falscher Block-Index.
+8 Tcsh's augenblickliche Speicherbelegung:\nfrei:\t
+9 \nbenutzt:\t
+10 \n\tInsgesamt in Benutzung: %d, insgesamt frei: %d\n
+11 \tAllokierter Speicher von 0x%lx bis 0x%lx. Wirklicher Anfang 0x%lx\n
+12 Allokierter Speicher von 0x%lx bis 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/german/set2 b/contrib/tcsh/nls/german/set2
new file mode 100644
index 0000000..08af0c7
--- /dev/null
+++ b/contrib/tcsh/nls/german/set2
@@ -0,0 +1,94 @@
+$ $Id: set2,v 1.4 1997/10/27 23:33:55 christos Exp $
+$ Signal names
+$set 2
+1 Null signal
+2 Aufgelegt
+3 Unterbrochen
+4 Verlassen
+5 Fehlerhafte Prozessoranweisung
+6 Trace/BPT trap
+7 Abbruch
+8 IOT trap
+9 Systemabsturz steht bevor
+10 Fehlerhaft beendet
+11 EMT trap
+12 Fließkommafehler
+13 Abgebrochen
+14 Benutzersignal 1
+15 Benutzersignal 2
+16 Speicherschutzverletzung
+17 Bus error
+18 Programmbereichsfehler
+19 Operandenbereichsfehler
+20 Falscher Systemaufruf
+21 Ausgabeweitergabe abgebrochen
+22 Alarm clock
+23 Beendet
+24 Kindprozeß hat Zustand geändert
+25 Abbruch eines Kindprozesses
+26 Apollo-spezifischer Fehler
+27 Kindprozeß angehalten oder beendet
+28 Kindprozeß beendet
+29 Stromunterbrechung
+30 Ressource verloren
+31 Unterbrechung (Ctrl-Break)
+32 Mögliches Ein-/Ausgabesignal
+33 Asynchrone I/O (select)
+34 Dringende Anfrage von Ein-/Ausgabekanal
+35 Multitasking wake-up
+36 Multitasking kill
+37 Fortran asynchrones Ein-Ausgabeende
+38 Wiederaufsetzen
+39 Nicht korrigierbarer Speicherfehler
+40 CPU-Zeitbeschränkung überschritten
+41 Systembeendigung absehbar
+42 micro-tasking group-no wakeup flag set
+43 Thread error - (use cord -T for detailed info)
+44 CRAY Y-MP register parity error
+45 Information request
+46 Angehalten (Signal)
+47 Angehalten (Signal)
+48 Angehalten
+49 Angehalten
+50 Fortsetzen
+51 Angehalten (Tty-Eingabe)
+52 Angehalten (Tty-Eingabe)
+53 Angehalten (Tty-Ausgabe)
+54 Angehalten (Tty-Ausgabe)
+55 Fensterzustand hat sich geändert
+56 Fenstergröße hat sich geändert
+57 Phone status changed
+58 CPU-Zeitbeschränkung überschritten
+59 Beschränkung der Dateigröße überschritten
+60 Virtueller Zeitalarm
+61 Profiling time alarm
+62 DIL signal
+63 Pollable event occured
+64 Process's lwps are blocked
+65 Special LWP signal
+66 Special CPR Signal
+67 Special CPR Signal
+68 First Realtime Signal
+69 Second Realtime Signal
+70 Third Realtime Signal
+71 Fourth Realtime Signal
+72 Fourth Last Realtime Signal
+73 Third Last Realtime Signal
+74 Second Last Realtime Signal
+75 Last Realtime Signal
+76 LAN Asyncronous I/O
+77 PTY read/write availability
+78 I/O intervention required
+79 HFT monitor mode granted
+80 HFT monitor mode should be relinguished
+81 HFT sound completed
+82 Data in HFT ring buffer
+83 Migrate process
+84 Secure attention key
+85 Reschedule
+86 Signaling SS$_DEBUG
+87 Priority changed
+88 Echte Verklemmung entdeckt
+89 New input character
+90 Stack limit exceeded
+91 Unused signal
diff --git a/contrib/tcsh/nls/german/set20 b/contrib/tcsh/nls/german/set20
new file mode 100644
index 0000000..8773671
--- /dev/null
+++ b/contrib/tcsh/nls/german/set20
@@ -0,0 +1,41 @@
+$ $Id: set20,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.bind.c
+$set 20
+1 Ungültiger Tastenname `%S'\n
+2 Falsche Tastenname: %S\n
+3 Falsche Befehlsname: %S\n
+4 Falsche Tastenangabe %S\n
+5 Leere Zeichenkette angegeben\n
+6 Standard Tastenbelegung\n
+7 Alternative Tastenbelegung\n
+8 Belegungen mit mehreren Zeichen\n
+9 Belegungen der Pfeiltasten\n
+10 %-15s-> ist undefiniert\n
+11 BUG!!! %s ist mit nichts belegt.\n
+12 Benutzung: bindkey [Optionen] [--] [TASTE [BEFEHL]]\n
+13 -a belege Taste in alternativer Tastenbelegung\n
+14 -b akzeptiere symbolische Tastendefinitionen\n
+15 -s belege einen Out-String anstelle eines Befehls\n
+16 -c belege einen Unix-Befehl anstelle eines Befehls\n
+17 -v initialisiere Belegungen mit Standard-Vi-Belegungen\n
+18 -e initialisiere Belegungen mit Standard-Emacs-Belegungen\n
+19 -d initialisiere Belegungen mit Standard-Belegungen\n
+20 -l zeige verfügbare Funktionen mit Beschreibungen an\n
+21 -r entferne Belegung eines Tastes\n
+22 -k belege Pfeiltaste mit Namen in In-String\n
+23 -- force a break from option processing\n
+24 -u (or any invalid option) this message\n
+25 Wenn kein Out-String oder Befehl angegeben wurde, wir die Belegung für\n
+26 den In-String ausgegeben oder alle Belegungen, falls kein in-String gegeben.\n
+27 Falsche Tastenangabe -- nicht definierte Zeichenkette\n
+28 Falsche Tastenangabe -- leere Zeichenkette\n
+29 Falsche Funktionstastenangabe. Leere Taste nicht erlaubt\n
+30 Falsche Tastenangabe -- nicht korrekte Hex-Zahl\n
+31 Falsche Tastenangabe -- nicht korrekte Oktal-Zahl\n
+32 Falsche Tastenangabe -- nicht korrekte Dezimal-Zahl\n
+33 Falsche Funktionstastenangabe.\n
+34 Leere Taste nicht erlaubt\n
+35 Falsche Tastenangabe -- unbeannter Name "%S"\n
+36 Benutzung: bind [TASTE | BEFEHL TASTE | "emacs" | "vi" | "-a"]\n
+37 Ungültige Funktion
+38 %s\t\tist undefiniert\n
diff --git a/contrib/tcsh/nls/german/set21 b/contrib/tcsh/nls/german/set21
new file mode 100644
index 0000000..509887f
--- /dev/null
+++ b/contrib/tcsh/nls/german/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.disc.c
+$set 21
+1 Kann lokale Sonderzeichen nicht auslesen.\n
+2 Kann lokale Sonderzeichen nicht setzen.\n
diff --git a/contrib/tcsh/nls/german/set22 b/contrib/tcsh/nls/german/set22
new file mode 100644
index 0000000..d7521bd
--- /dev/null
+++ b/contrib/tcsh/nls/german/set22
@@ -0,0 +1,17 @@
+$ $Id: set22,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t ein Alias für
+2 \nPasswort nicht korrekt für %s\n
+3 Fehlerhafter Alias 'precmd' entfernt.\n
+4 Fehlerhafter Alias 'cwdcmd' entfernt.\n
+5 Fehlerhafter Alias 'beepcmd' entfernt.\n
+6 Fehlerhafter Alias 'periodic' entfernt.\n
+7 zerteile Kommandozeile\n
+8 Wollen Sie wirklich alle Dateien löschen? [n/j]
+9 Übergehe das Löschen der Dateien!\n
+10 Kommandozeile ist nun:\n
+11 zerteile Kommandozeile\n
+12 in einer der Listen\n
+13 Kommandozeile ist nun:\n
+14 jJyY
diff --git a/contrib/tcsh/nls/german/set23 b/contrib/tcsh/nls/german/set23
new file mode 100644
index 0000000..f2bd825
--- /dev/null
+++ b/contrib/tcsh/nls/german/set23
@@ -0,0 +1,34 @@
+$ $Id: set23,v 1.3 1996/04/26 20:54:22 christos Exp $
+$ tc.os.c
+$set 23
+1 Falscher Cpu/Site-Name
+2 Site-Pfad zu lang
+3 unbekannt
+4 Site: %s\n
+5 %d: Site nicht gefunden\n
+6 setlocal: %s: %s\n
+7 Site nicht gefunden
+8 Sie sind in einem Universum gefangen, daß Sie nie gemacht haben
+9 Getwarp fehlgeschlagen
+10 Ungültiger Warp
+11 Setwarp fehlgeschlagen
+12 Ungültiges Universum
+13 Unbekannter Fehler: %d
+14 sysname: %s\n
+15 nodename: %s\n
+16 release: %s\n
+17 version: %s\n
+18 machine: %s\n
+19 getwd: Kann ".." nicht öffnen (%s)
+20 getwd: Kann nicht in ".." wechseln (%s)
+21 getwd: Lesefehler in ".." (%s)
+22 getwd: Kann nicht zurück zu "." wechseln (%s)
+23 getwd: Kann kein stat auf "/" machen (%s)
+24 getwd: Kann kein stat auf "." machen (%s)
+25 getwd: Kann kein stat auf Verzeichnis "%s" machen (%s)
+26 getwd: Kann Verzeichnis "%s" nicht öffnen (%s)
+27 getwd: Kann "." nicht in ".." finden (%s)
+28 Ungültiger Systemtyp
+29 Systemtyp ist nicht gesetzt
+30 Too many arguments
+31 Invalid argument
diff --git a/contrib/tcsh/nls/german/set24 b/contrib/tcsh/nls/german/set24
new file mode 100644
index 0000000..96ecbb4
--- /dev/null
+++ b/contrib/tcsh/nls/german/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.sched.c
+$set 24
+1 Hack!
diff --git a/contrib/tcsh/nls/german/set25 b/contrib/tcsh/nls/german/set25
new file mode 100644
index 0000000..443104a
--- /dev/null
+++ b/contrib/tcsh/nls/german/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tc.sig.c
+$set 25
+1 unser wait %d\n
+2 Fehler: bsd_signal(%d) Signal außerhalb der Grenzen\n
+3 Fehler: bsd_signal(%d) - sigaction fehlerhaft, errno %d\n
diff --git a/contrib/tcsh/nls/german/set26 b/contrib/tcsh/nls/german/set26
new file mode 100644
index 0000000..548b534
--- /dev/null
+++ b/contrib/tcsh/nls/german/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.3 1996/10/19 17:52:52 christos Exp $
+$ tc.who.c
+$set 26
+1 Kein Zugriff auf %s. Bitte "unset watch" eingeben.\n
+2 %s kann nicht geöffnet werden. Bitte "unset watch" eingeben.\n
+3 FEHLER! letztes Element ist nicht whotail!\n
+4 Zurück:
+5 FEHLER! erstes Element ist nicht whohead!\n
+6 neu: %s/%s\n
+7 %n hat %a an %l von %m.
+8 %n hat %a an %l.
+9 sich angemeldet
+10 sich abgemeldet
+11 %s ersetzt
+12 lokal
diff --git a/contrib/tcsh/nls/german/set27 b/contrib/tcsh/nls/german/set27
new file mode 100644
index 0000000..d5a6460
--- /dev/null
+++ b/contrib/tcsh/nls/german/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tw.comp.c
+$set 27
+1 Befehl
+2 Trenner
+3 Muster
+4 Bereichs
+5 Vervollständigung
diff --git a/contrib/tcsh/nls/german/set29 b/contrib/tcsh/nls/german/set29
new file mode 100644
index 0000000..490b532
--- /dev/null
+++ b/contrib/tcsh/nls/german/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ tw.help.c
+$set 29
+1 Keine Hilfe-Datei für %S\n
diff --git a/contrib/tcsh/nls/german/set3 b/contrib/tcsh/nls/german/set3
new file mode 100644
index 0000000..c19ea2a
--- /dev/null
+++ b/contrib/tcsh/nls/german/set3
@@ -0,0 +1,117 @@
+$ $Id: set3,v 1.4 1995/04/25 14:08:04 christos Exp $
+$ Editor function descriptions
+$set 3
+1 Ein Zeichen zurück
+2 Lösche Zeichen hinter Cursor
+3 Lösche vom Anfang des aktuellen Worts bis zum Cursor - in Cut-Puffer
+4 Lösche vom Anfang der Zeile bis zum Cursor - in Cut-Puffer
+5 Gehe an den Anfang des aktuellen Worts
+6 Gehe zum Anfang der Zeile
+7 Wandele vom Cursor bis zum Ende des aktuellen Worts in Großbuchstaben um
+8 Vi: Ändere Groß/Kleinschreibung des Zeichen unter dem Cursor und bewege Cursor eins nach vorn
+9 Vi: Ändere bis zum Ende der Zeile
+10 Lösche Bildschirm (aktuelle Zeile oben)
+11 Vervollständige aktuelles Wort
+12 Gehe mit Tab vorwärts durch die Dateiliste
+13 Gehe mit Tab rückwärts durch die Dateiliste
+14 Vervollständige Wort (ignoriere programmierbare Vervollständigungen)
+15 Kopiere aktuelles Wort zum Cursor
+16 Kopiere Area zwischen Marke und Cursor in Cut-Puffer
+17 Erweitere zu früherem Wort für das dies ein Anfang ist
+18 Lösche Zeichen unter Cursor
+19 Lösche Zeichen unter Cursor oder gib EOF-Signal am Ende der Zeile
+20 Lösche Zeichen unter Cursor oder zeige Vervollständigungen am Ende der Zeile an
+21 Lösche Zeichen unter Cursor oder zeige Vervollständigungen oder gib EOF-Signal
+22 Lösche von Cursor bis zum Ende des aktuellen Worts - in Cut-Puffer
+23 Füge Argument hinzu, wenn gestartet, oder gib zahl ein
+24 Ziffer, die ein Argument beginnt
+25 Gehe zur nächsten History-Zeile
+26 Wandele vom Cursor bis zum Ende des aktuellen Worts in Kleinbuchstaben um
+27 Melde Ende der Datei
+28 Gehe zum Ende der Zeile
+29 Tausche Cursor und Marke aus
+30 Expandiere Wildcards in Dateinamen
+31 Expandiere History-Escapes
+32 Expandiere History-Escapes in einer Zeile
+33 Expandiere Variablen
+34 Gehe ein Zeichen vor
+35 Gehe vor bis zum Ende des akutellen Worts
+36 Vertausche zwei Zeichen vor dem Cursor
+37 Suche rückwärts in History nach Zeile mit gleichem Anfang
+38 Suche vorwärts in History nach Zeile mit gleichem Anfang
+39 Setze letzten Teil des vorherigen Befehls ein
+40 Incrementelle Suche (vorwärts)
+41 Incrementelle Suche (rückwärts)
+42 Lösche Zeile
+43 Lösche bis zum Ende der Zeile - in Cut-Puffer
+44 Lösche Area zwischen Marke und Cursor - in Cut-Puffer
+45 Lösche gesamte Zeile - in Cut-Puffer
+46 Zeige Möglichkeiten der Vervollständigung
+47 Zeige Möglichkeiten der Vervollständigung (ignoriere programmierbare Vervollständigungen)
+48 Zeige Treffer der Dateinamen-Wildcards
+49 Zeige Möglichkeiten der Vervollständigung oder gib EOF, falls Zeile leer
+50 Zeige durchschnittliche Last und augenblickl. Prozeßzustand
+51 Expandiere History-Escape und füge Leerzeichen ein
+52 Führe Befehl aus
+53 Expandiere Pfadnamen, eliminiere führende . und ..
+54 Expandiere Befehle in den entsprechenden Pfadnamen oder Alias
+55 Schalte von Insert- auf Einfügemodus oder umgekehrt
+56 Füge das achte Bit zu dem nächsten eingegebenen Zeichen hinzu
+57 Füge das nächste Eingabezeichen unverändert ein
+58 Baue Anzeige neu auf
+59 Starte angehaltenen Editor wieder
+60 Suche nach Hilfe für den aktuellen Befehl
+61 Dieses Zeichen wird zur Zeile hinzugefügt
+62 Dieses Zeichen ist das erste einer Folge von Zeichen
+63 Setze die Marke an der Stelle des Cursors
+64 Korrigiere die Schreibweise des aktuellen Wortes
+65 Korrigiere die Schreibweise der gesamten Zeile
+66 Sende Zeichen an Tty im "cooked mode"
+67 Schalte um zwischen literaler und lexicalischer aktueller History-Zeile
+68 Tausche das Zeichen links des Cursors mit dem unter dem Cursor
+69 Tausche die zwei Zeichen vor dem Cursor
+70 Tty delayed suspend Zeichen
+71 Tty flush output Zeichen
+72 Tty interrupt Zeichen
+73 Tty quit Zeichen
+74 Tty suspend Zeichen
+75 Tty allow output Zeichen
+76 Tty disallow output Zeichen
+77 Indicates unbound Zeichen
+78 Emacs universelles Argument (Argument mal 4)
+79 Gehe zur vorhergehenden History-Zeile
+80 Wandele die Zeichen vom Cursor bis zum Ende des akt. Worts in Großbuchst. um
+81 Vi gehe zum Anfang des nächsten Wortes
+82 Vi gehe in Einfügemodus hinter dem Cursor
+83 Vi gehe in Einfügemodus am Ende der Zeile
+84 Vi ändere Groß/Kleinschreibung des Zeichens unter dem Cursor und gehe ien vor
+85 Vi ändere Prefix-Befehl
+86 Vi ändere bis zum Ende der Zeile
+87 Vi gehe in Befehlsmodus (benutze alternative Tastenbelegung)
+88 Vi Befehlsmodus vervollständige aktuelles Wort
+89 Vi gehe zum vorhergehenden Zeichen (Backspace)
+90 Vi lösche Prefix-Befehl
+91 Vi gehe zum Ende des aktuellen Worts (durch Leerzeichen begrenzt)
+92 Vi gehe zum Ende des aktuellen Worts
+93 Vi gehe zum angegebenen Zeichen rückwärts
+94 Vi gehe zum angegebenen Zeichen vorwärts
+95 Vi gehe hoch zum angegebenen Zeichen rückwärts
+96 Vi gehe hoch zum angegebenen Zeichen vorwärts
+97 Vi gehe in Einfügemodus
+98 Vi gehe in Einfügemodus am Anfang der Zeile
+99 Vi wiederhole aktuelle Suche in dieselbe Richtung
+100 Vi wiederhole aktuelle Suche in entgegengesetzte Richtung
+101 Vi wiederhole aktuelle Suche in dieselbe Richtung
+102 Vi wiederhole aktuelle Suche in entgegengesetzte Richtung
+103 Vi ersetze Zeichen unter dem Cursor mit dem nächsten eingegebenen Zeichen
+104 Vi Ersetzungsmodus
+105 Vi suche History vorwärts
+106 Vi suche History rückwärts
+107 Vi ersetze Zeichen unter dem Cursor und gehe in Einfügemodus
+108 Vi ersetze gesamte Zeile
+109 Vi gehe zum verhergehenden Wort
+110 Vi gehe zum nächsten Wort
+111 Vi mache letzte Änderung rückgängig
+112 Vi gehe zum Anfang der Zeile
+113 Mache ein 'which' von dem aktuellen Befehl
+114 Füge den Cut-Puffer an der Cursor-Position ein
diff --git a/contrib/tcsh/nls/german/set30 b/contrib/tcsh/nls/german/set30
new file mode 100644
index 0000000..0657670
--- /dev/null
+++ b/contrib/tcsh/nls/german/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.3 1996/04/26 20:54:24 christos Exp $
+$ tw.parse.c
+$set 30
+1 Anfangsbefehl %d\n
+2 vervollständige %d
+3 vervollständige %d %S\n
+4 %s: Interner Abgleichsfehler.\n
+5 Objekte
+6 Spalten
+7 Es gibt %d %s, trotzdem anzeigen? [n/j]
+8 looking = %d\n
+9 \n%s interner Fehler: Ich weiß nicht, wonach ich suche!\n
+10 kein Verzeichnis
+11 nicht gefunden
+12 nicht lesbar
+13 jJyY
diff --git a/contrib/tcsh/nls/german/set31 b/contrib/tcsh/nls/german/set31
new file mode 100644
index 0000000..88f3dcc
--- /dev/null
+++ b/contrib/tcsh/nls/german/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ vms.termcap.c
+$set 31
+1 Kann TERMCAP nicht öffnen: [%s]\n
+2 Kann %s nicht öffnen.\n
+3 Fand %s in %s.\n
+4 Kein Eintrag für %s in Datei %s gefunden\n
diff --git a/contrib/tcsh/nls/german/set4 b/contrib/tcsh/nls/german/set4
new file mode 100644
index 0000000..c11e712
--- /dev/null
+++ b/contrib/tcsh/nls/german/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ Termcap strings
+$set 4
+1 füge neue, leere Zeile hinzu
+2 hörbare Pieps
+3 lösche bis zum Ende der Anzeige
+4 lösche bis zum Ende der Zeile
+5 Cursor zu horizontaler Position
+6 lösche Bildschirm
+7 lösche ein Zeichen
+8 lösche eine Zeile
+9 starte Löschemodus
+10 beende Löschmodus
+11 beende Einfügemodus
+12 Cursor aus Statuszeile
+13 Cursor in Ursprungsposition
+14 füge Zeichen ein
+15 starte Einfügemodus
+16 setze Füllzeichen ein
+17 Cursor nach unten
+18 Cursor nach links
+19 Cursor nach rechts
+20 Cursor nach oben
+21 starte Fettschrift
+22 beende Attribute
+23 nicht zerstörendes Leerzeichen
+24 beende hervorgehobene Darstellung
+25 beginne hervorgehobene Darstellung
+26 Cursor in Statuszeile
+27 Cursor eins hoch
+28 beginne Unterstreichung
+29 beende Unterstreichung
+30 sichtbarer Pieps
+31 lösche mehrere Zeichen
+32 Cursor mehrere Zeichen nach unten
+33 füge mehrere Zeichen ein
+34 Cursor mehrere Zeichen nach links
+35 Cursor mehrere Zeichen nach rechts
+36 Cursor mehrere Zeichen nach oben
+37 hat automatische Ränder
+38 kann physikalische Tabulatoren benutzen
+39 Anzahl Zeilen
+40 Anzahl Spalten
+41 hat Meta-Taste
+42 Zeilenumbruch am rechten Rand wird ignoriert
diff --git a/contrib/tcsh/nls/german/set5 b/contrib/tcsh/nls/german/set5
new file mode 100644
index 0000000..195c72e
--- /dev/null
+++ b/contrib/tcsh/nls/german/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ ed.chared.c
+$set 5
+1 Durchschnittliche Last nicht verfügbar\n
diff --git a/contrib/tcsh/nls/german/set6 b/contrib/tcsh/nls/german/set6
new file mode 100644
index 0000000..df99266
--- /dev/null
+++ b/contrib/tcsh/nls/german/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ ed.inputl.c
+$set 6
+1 FEHLER: Illegaler Befehl von Taste 0%o\r\n
+2 ja\n
+3 ediere\n
+4 brich ab\n
+5 nein\n
+6 Kein entsprechender Befehl\n
+7 Mehrdeutiger Befehl\n
+8 *** Editor fataler FEHLER ***\r\n\n
diff --git a/contrib/tcsh/nls/german/set7 b/contrib/tcsh/nls/german/set7
new file mode 100644
index 0000000..188bf64
--- /dev/null
+++ b/contrib/tcsh/nls/german/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.4 1996/10/19 17:52:53 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tTcsh meint, Ihr Endgerät hat die\n
+2 \tfolgenden Eigenschaften:\n\n
+3 \tEs hat %d Spalten und %d Zeilen\n
+4 \tEs hat %s Meta-Taste\n
+5 eine
+6 keine
+7 \tEs kann%s Tabulatoren benutzen\n
+8 \040keine
+9 \tEs %s automatische Ränder\n
+10 hat
+11 hat nicht
+12 \tEs %s magische Ränder\n
+13 (leer)
+14 ja
+15 nein
+16 FEHLER: kann nicht löschen\r\n
+17 DeleteChars: num ist lächerlich: %d\r\n
+18 FEHLER: kann nicht einfügen\r\n
+19 StartInsert: num ist lächerlich: %d\r\n
+20 %s: Kann /etc/termcap nicht öffnen.\n
+21 %s: Kein Eintrag für Terminaltyp "%s"\n
+22 %s: benutze minimale Terminaleigenschaften.\n
+23 %s: WARNUNG: Ihr Terminal kann den Cursor nicht aufwärts bewegen.\n
+24 Lange Zeilen könnten etwas komisch aussehen.\n
+25 keine Fähigkeit, bis Zeilenende zu löschen.\n
+26 keine Fähigkeit, Zeichen zu löschen.\n
+27 keine Fähigkeit, Zeichen einzufügen.\n
diff --git a/contrib/tcsh/nls/german/set8 b/contrib/tcsh/nls/german/set8
new file mode 100644
index 0000000..ba7f030
--- /dev/null
+++ b/contrib/tcsh/nls/german/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.2 1995/03/19 18:09:24 christos Exp $
+$ ed.term.c
+$set 8
+1 Unbekannter Schalter
+2 Ungültiges Argument
diff --git a/contrib/tcsh/nls/german/set9 b/contrib/tcsh/nls/german/set9
new file mode 100644
index 0000000..b987d11
--- /dev/null
+++ b/contrib/tcsh/nls/german/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.3 1996/10/19 17:52:54 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: Null extended-key not allowed.\n
+2 AddXkey: sequence-lead-in command not allowed\n
+3 DeleteXkey: Null extended-key not allowed.\n
+4 Unbound extended key "%S"\n
+5 Some extended keys too long for internal print buffer
+6 Enumerate: BUG!! Null ptr passed\n!
+7 keine Eingabe
+8 Es muß noch etwas folgen: %c\n
+9 Oktal-Konstante paßt nicht in ein Zeichen.\n
diff --git a/contrib/tcsh/nls/greek/set1 b/contrib/tcsh/nls/greek/set1
new file mode 100644
index 0000000..17c8573
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.3 1998/09/18 15:31:57 christos Exp $
+$ Error messages
+$set 1
+1 ËÜèïò óýíôáîç
+2 Tï %s äåí åðéôñÝðåôáé
+3 ÕðåñâïëéêÜ ìåãÜëç ëÝîç
+4 $< ÕðåñâïëéêÜ ìåãÜëç ãñáììÞ
+5 Äåí õðÜñ÷åé áñ÷åßï ãéÜ ôï $0
+6 ÅëëéðÞò ìåôáôñïðÝáò []
+7 Ç áíÜðôõîç ôïõ $ ðñÝðåé íá ôåëåéþíåé ðñéí ôï ]
+8 ËÜèïò ìåôáôñïðÝáò : óôï $ (%c)
+9 ËÜèïò üñéóìá
+10 Êáêïó÷çìáôéóìÝíïò áñéèìüò
+11 Äåí õðÜñ÷ïõí Üëëåò ëÝîåéò
+12 Áðüí üíïìá áñ÷åßïõ
+13 Åóùôåñéêü ëÜèïò globbing
+14 Ç åíôïëÞ äå âñÝèçêå
+15 ÕðåñâïëéêÜ ëßãá ïñßóìáôá
+16 ÕðåñâïëéêÜ ðïëëÜ ïñßóìáôá
+17 ÕðåñâïëéêÜ åðéêßíäõíï øåõäþíõìï
+18 Áäåéï if
+19 ÁêáôÜëëçëï then
+20 Ïé ëÝîåéò äåí åßíáé åíôüò ðáñåíèÝóåùí
+21 Tï %s äåí âñÝèçêå
+22 ÁêáôÜëëçëç ìÜóêá
+23 Äåí õðÜñ÷åé ôÝôïéï üñéï
+24 ÕðåñâïëéêÜ ìåãÜëï üñéóìá
+25 ÁêáôÜëëçëïò Þ Üãíùóôïò ðáñÜãïíôáò ìåãÝèïõò
+26 Ìç ïñéóìÝíç ìåôáâëçôÞ
+27 Tï stack êáôáëüãùí äåí åßíáé ôüóï âáèý
+28 ËÜèïò áñéèìüò signal
+29 ¶ãíùóôï signal·äþóôå kill -l ãéÜ ëßóôá signals
+30 Tá ïíüìáôá ìåôáâëçôþí ðñÝðåé íá áñ÷ßæïõí ìå ãñÜììá
+31 ÕðåñâïëéêÜ ìåãÜëï üíïìá ìåôáâëçôÞò
+32 Tá ïíüìáôá ìåôáâëçôþí ðñÝðåé íá ðåñéÝ÷ïõí áëöáñçèìçôéêïýò ÷áñáêôÞñåò
+33 Äåí õðÜñ÷åé Ýëåã÷ïò åñãáóéþí óå áõôü ôï shell
+34 ËÜèïò óýíôáîç Ýêöñáóçò
+35 Äåí õðÜñ÷åé ðñïóùðéêüò êáôÜëïãïò (home directory)
+36 Äåí ìðïñþ íá ðñïóðåëÜóù ôïí ðñïóùðéêü êáôÜëïãï (home directory)
+37 Áêõñç êåíÞ åíôïëÞ
+38 Åê÷þñçóç ÷ùñßò Ýêöñáóç
+39 Áãíùóôïò ôåëåóôÞò
+40 Äéöïñïýìåíï
+41 %s: ôï áñ÷åßï õðÜñ÷åé
+42 Tï üñéóìá ôïõ -c ôåëåéþíåé óå backslash
+43 ÄéáêïðÞ
+44 Äåßêôçò åêôüò ïñßùí
+45 Õðåñ÷åßëéóç ãñáììÞò
+46 Äåí õðÜñ÷åé ôÝôïéá åñãáóßá
+47 Äåí ãßíåôáé áðü ôï ôåñìáôéêü
+48 Åêôüò while/foreach
+49 Äåí õðÜñ÷ïõí Üëëåò äéåñãáóßåò
+50 Äåí õðÜñ÷åé ôáßñéáóìá
+51 Áðüí %c
+52 Ìç ôáéñéáóìÝíï %c
+53 Äåí õðÜñ÷åé Üëëç ìíÞìç
+54 Äåí ìðïñþ íá äçìéïõñãÞóù pipe
+55 %s: %s
+56 %s
+57 ×ñÞóç: jobs [ -l ]
+58 Tá ïñßóìáôá ðñÝðåé íá åßíáé åñãáóßåò Þ ôáõôüôçôåò äéåñãáóéþí
+59 Äåí õðÜñ÷åé ôñÝ÷ïõóá åñãáóßá
+60 Äåí õðÜñ÷åé ðñïçãïýìåíç åñãáóßá
+61 ÊáììéÜ åñãáóßá äåí ôáéñéÜæåé ìå ôï pattern
+62 Tï fork nesting åßíáé ìåãáëýôåñï áðü %d; ðéèáíü `...` loop
+63 Ï Ýëåã÷ïò åñãáóéþí äåí åßíáé äéáèÝóéìïò óôá êáôþôåñá shells
+64 ËÜèïò sunc: ç äéåñãáóßá %d äå âñÝèçêå
+65 %sÕðÜñ÷ïõí áíáâëçèåßóåò åñãáóßåò
+66 %sÕðÜñ÷ïõí óôáìáôçìÝíåò åñãáóßåò
+67 Äåí õðÜñ÷åé Üëëïò êáôÜëïãïò
+68 Tï stack êáôáëüãùí åßíáé Üäåéï
+69 ËÜèïò êáôÜëïãïò
+70 ×ñÞóç: %s [-%s]%s
+71 Äåí õðÜñ÷åé üñéóìá ãéÜ ôï flag -h
+72 Äåí Ý÷åé ãßíåé login ìå áõôü ôï shell
+73 Äéáßñåóç ìå 0
+74 Modulo ìå 0
+75 ËÜèïò ìåãÝèõíóç· åííïïýóáôå "%s"?
+76 Äåí ìðïñþ (áêüìá) íá áíáâÜëù ôï login shell
+77 Áãíùóôïò ÷ñÞóôçò: %s
+78 Äåí Ý÷åé äïèåß ôéìÞ óôç ìåôáâëçôÞ $home
+79 ×ñÞóç: history [-%s] [# áñéèìüò åíôïëþí]
+80 Tá $, ! êáé < äåí åðéôñÝðïíôáé ìå ôá $# êáé $?
+81 ÁëëáãÞ ãñáììÞò óå üíïìá ìåôáâëçôÞò
+82 Tï * äåí åðéôñÝðåôáé ìå ôá $# êáé $?
+83 Tá $?<øçößï> êáé $#<øçößï> äåí åðéôñÝðïíôáé
+84 Áêõñï üíïìá ìåôáâëçôÞò
+85 ÁëëáãÞ ãñáììÞò óå äåßêôç ìåôáâëçôÞò
+86 Õðåñ÷åßëéóç buffer åðÝêôáóçò
+87 ËÜèïò óýíôáîçò ìåôáâëçôÞò
+88 ËÜèïò ìïñöÞ !
+89 Äåí õðÜñ÷åé ðñïçãïýìåíç áíôéêáôÜóôáóç
+90 ËÜèïò áíôéêáôÜóôáóç
+91 Äåí õðÜñ÷åé ðñïçãïýìåíï áñéóôåñü ìÝñïò
+92 Tï äåîß ìÝñïò åßíáé ðïëý ìåãÜëï
+93 Êáêüò ìåôáôñïðÝáò !: %c
+94 Ï ìåôáôñïðÝáò áðÝôõ÷å
+95 Õðåñ÷åßëéóç ôïõ buffer áíôéêáôáóôÜóåùí
+96 ËÜèïò åðéëïãÝáò ïñßóìáôïò !
+97 Äåí õðÜñ÷åé ðñïçãïýìåíç áíáæÞôçóç
+98 %s: ç åíôïëÞ äå âñÝèçêå
+99 ÕðåñâïëéêÜ ðïëëÝò )
+100 ÕðåñâïëéêÜ ðïëëÝò (
+101 ËÜèïò ôïðïèåôçìÝíç (
+102 ÐáñÜëåéøç ïíüìáôïò ãéÜ áíáêáôåýèõíóç
+103 Äéöïñïýìåíç áíáêáôåýèõíóç åîüäïõ
+104 Äåí ãßíåôáé << ìÝóá óå ()
+105 Äéöïñïýìåíç áíáêáôåýèõíóç åéóüäïõ
+106 ËÜèïò ôïðïèåôçìÝíåò ()
+107 Âñü÷ïò øåõäùíýìùí
+108 Äåí Ý÷åé äïèåß ôéìÞ óôç ìåôáâëçôÞ $watch
+109 Äåí õðÜñ÷ïõí äñïìïëïãçìÝíåò åíôïëÝò
+110 ×ñÞóç: sched -<#áíôéêåéìÝíïõ>.\n×ñÞóç: sched [+]ùù:ëë <åíôïëÞ>
+111 Äåí õðÜñ÷ïõí ôüóåò äñïìïëïãçìÝíåò åíôïëÝò
+112 Äåí õðÜñ÷åé åíôïëÞ ãéÜ åêôÝëåóç
+113 Áêõñïò ÷ñüíïò ãéÜ ôçí åíôïëÞ
+114 Ï ó÷åôéêüò ÷ñüíïò äåí åßíáé óõíåðÞò ìå ôï am/pm
+115 Äåí õðÜñ÷åé ÷þñïò ãéÜ ôï termcap string
+116 ×ñÞóç: settc %s [yes|no]
+117 Áãíùóôç éêáíüôçôá `%s'
+118 Áãíùóôç ðáñÜìåôñïò ôïõ termcap `%%%c'
+119 ÕðåñâïëéêÜ ðïëëÜ ïñßóìáôá ãéÜ ôï `%s' (%d)
+120 Tï `%s' áðáéôåß %d ïñßóìáôá
+121 ×ñÞóç: echotc [-v|-s] [<éêáíüôçôá> [<ïñßóìáôá>]]
+122 %s: %s. ËÜèïò Áñ÷éôåêôïíéêÞ
+123 !# âñü÷ïò Éóôïñßáò åíôïëþí
+124 Êáêïó÷çìáôéóìÝíç åñþôçóç ãéÜ áñ÷åßï
+125 Õðåñ÷åßëéóç åðéëïãÝùí
+126 Áãíùóôç åðéëïãÞ: `-%s'\n×ñÞóç: %s [ -bcdefilmnqstvVxX -Dname[=value] ] [ üñéóìá ... ]
+127 Áãíùóôç åðéëïãÞ: `-%s'\nUsage: %s [ -bcdefFilmnqstvVxX ] [ üñéóìá ... ]
+128 Áãíùóôç åðéëïãÞ: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX ] [ üñéóìá ... ]
+129 \nËÜèïò óõìðëÞñùóç: "%s"
+130 \nËÜèïò %s: '%c'
+131 \nÐáñÜëçøç äéá÷ùñéóôÞ '%c' ìåôÜ ôï %s "%s"
+132 \nÌç ðëÞñåò %s: "%s"
+133 Äåí õðÜñ÷åé üñéóìá ãéÜ ôï flag -m
+134 ×ñÞóç: unlimit [-fh] [üñéá]
+135 Tï $%S åßíáé ìüíï ãéÜ äéÜâáóìá
+136 Äåí õðÜñ÷åé ôÝôïéá åñãáóßá
+137 Unknown colorls variable `%c%c'
diff --git a/contrib/tcsh/nls/greek/set10 b/contrib/tcsh/nls/greek/set10
new file mode 100644
index 0000000..33a00de
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.2 1998/09/18 15:31:58 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: Üêõñç åíôïëÞ '%s'.\n
+2 setpath: áíåðáñêÞò áñéèìüò ïñéóìÜôùí ãéÜ ôçí åíôïëÞ '%s'.\n
+3 setpath: êÜðïéá ôéìÞ ëåßðåé óôï path '%s'\n
+4 setpath: ôï %s äå âñÝèçêå óôï %s\n
+5 setpath: ç èÝóç %d äåí éó÷ýåé óôï %s\n
diff --git a/contrib/tcsh/nls/greek/set11 b/contrib/tcsh/nls/greek/set11
new file mode 100644
index 0000000..1ab3951
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.1 1996/04/26 19:24:11 christos Exp $
+$ sh.c
+$set 11
+1 Ðñïåéäïðïßçóç: äåí ìðïñþ íá ðñïóðåëÜóù ôï tty (%s).\n
+2 Óõíåðþò, äåí èá õðÜñ÷åé Ýëåã÷ïò åñãáóéþí óå áõôü ôï shell.\n
+3 ¸÷åôå %d ìçíýìáôá mail.\n
+4 Å÷åôå %d ìçíýìáôá mail óôï %s.\n
+5 Å÷åôå %smail.\n
+6 íÝï
+7 Å÷åôå %smail óôï %s.\n
diff --git a/contrib/tcsh/nls/greek/set12 b/contrib/tcsh/nls/greek/set12
new file mode 100644
index 0000000..09cfdc6
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.2 1998/09/18 15:31:59 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: ðñïóðáèþ íá áñ÷ßóù áðü ôï "%s"\n
diff --git a/contrib/tcsh/nls/greek/set13 b/contrib/tcsh/nls/greek/set13
new file mode 100644
index 0000000..6e6963a
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.1 1996/04/26 19:24:15 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d hash buckets ìå %d bits ôï êáèÝíá\n
+3 ìÜóêá debug = 0x%08x\n
+4 %d åðéôõ÷ßåò, %d áðïôõ÷ßåò, %d%%\n
+5 %S: åóùôåñéêÞ åíôïëÞ ôïõ shell.\n
+6 %S: ç åíôïëÞ äå âñÝèçêå.\n
+7 where: ôï / óôçí åíôïëÞ äåí Ý÷åé íüçìá\n
+8 Tï %S åßíáé øåõäþíõìï ãéÜ ôçí åíôïëÞ
+9 Tï %S åßíáé åóùôåñéêÞ åíôïëÞ ôïõ shell\n
+10 áðïôõ÷ßá ôïõ hash:
diff --git a/contrib/tcsh/nls/greek/set14 b/contrib/tcsh/nls/greek/set14
new file mode 100644
index 0000000..282f639
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.2 1998/11/24 18:18:11 christos Exp $
+$ sh.file.c
+$set 14
+1 \nÐööö!! ÕðåñâïëéêÜ ðïëëÜ %s!!\n
+2 ïíüìáôá óôï password file
+3 áñ÷åßá
diff --git a/contrib/tcsh/nls/greek/set15 b/contrib/tcsh/nls/greek/set15
new file mode 100644
index 0000000..f92fef4
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.1 1996/04/26 19:24:18 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: äå ìðïñþ íá %sôï%s üñéï\n
+2 ìçäåíßóù
+3 èÝóù
+4 \040áõóôçñü
diff --git a/contrib/tcsh/nls/greek/set16 b/contrib/tcsh/nls/greek/set16
new file mode 100644
index 0000000..18d92e2
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.2 1998/09/18 15:32:00 christos Exp $
+$ sh.lex.c
+$set 16
+1 Ìçäåíéóìüò ôïõ ãêñïõð äéåñãáóéþí ôïõ tty áðü %d óå %d\n
+2 \nÄþóôå "logout" ãéÜ íá âãåßôå.\n
+3 \nÄþóôå "exit" ãéÜ íá ôåñìáôßóåôå ôï %s.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Bad seek type %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/greek/set17 b/contrib/tcsh/nls/greek/set17
new file mode 100644
index 0000000..b0baa0e
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.1 1996/04/26 19:24:22 christos Exp $
+$ sh.proc.c
+$set 17
+1 BUG: wait ãéÜ åñãáóßá ðïõ ôñÝ÷åé óôï ðáñáóêÞíéï!\n
+2 Åîïäïò ìå status %d\n
+3 BUG: ç äéåñãáóßá åêêåíþèçêå äõü öïñÝò
+4 ÔñÝ÷åé
+5 ÓÞìá
+6 Åîïäïò ìå status %-25d
+7 Ïëïêëçñþèçêå
+8 BUG: status=%-9o
+9 \040(åããñáöÞ áñ÷åßïõ core)
+10 \040(wd:
+11 ôùñéíï wd:
+12 %S: Ý÷åé Þäç áíáâëçèåß\n
+13 %S: Ý÷åé Þäç óôáìáôÞóåé\n
diff --git a/contrib/tcsh/nls/greek/set18 b/contrib/tcsh/nls/greek/set18
new file mode 100644
index 0000000..ad0a5e6
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.1 1996/04/26 19:24:26 christos Exp $
+$ sh.set.c
+$set 18
+1 Ðñïåéäïðïßçóç: PATH ìå ôåñÜóôéï ìÝãåèïò, ðåñéêüðçêå\n
diff --git a/contrib/tcsh/nls/greek/set19 b/contrib/tcsh/nls/greek/set19
new file mode 100644
index 0000000..e1d1520
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.1 1996/04/26 19:24:27 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: ç ìíÞìç ôåëåßùóå\n
+2 free(%lx) êëÞèçêå ðñßí íá åê÷ùñçèåß ìíÞìç.
+3 free(%lx) ðñéí ôçí áñ÷Þ ôçò ìíÞìçò.
+4 free(%lx) ìåôÜ ôï ôÝëïò ôçò ìíÞìçò.
+5 free(%lx) åóöáëìÝíï block.
+6 free(%lx) åóöáëìÝíç êëßìáêá check.
+7 free(%lx) åóöáëìÝíïò äåßêôçò block.
+8 Ðáñïýóá åê÷þñçóç ìíÞìçò ôïõ %s:\nfree:\t
+9 \n÷ñçóéìïðïéåßôáé:\t
+10 \n\tÓõíïëéêÜ ÷ñçóéìïðïéåßôáé: %d, óõíïëéêÞ åëåýèåñç: %d\n
+11 \tÅ÷åé åê÷ùñçèåß ìíÞìç áðü 0x%lx ùò 0x%lx. ÐñáãìáôéêÞ áñ÷Þ 0x%lx\n
+12 Å÷åé åê÷ùñçèåß ìíÞìç áðü 0x%lx ùò 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/greek/set2 b/contrib/tcsh/nls/greek/set2
new file mode 100644
index 0000000..35a14b2
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set2
@@ -0,0 +1,94 @@
+$ $Id: set2,v 1.2 1997/10/27 23:33:56 christos Exp $
+$ Signal names
+$set 2
+1 Ìçäåíéêü signal
+2 ÄéáêïðÞ ãñáììÞò (hangup)
+3 ÄéáêïðÞ (interrupt)
+4 Ðáñáßôçóç (quit)
+5 ÐáñÜíïìç åíôïëÞ (Illegal instruction)
+6 Trace/BPT trap
+7 Abort
+8 IOT trap
+9 Åðéêåßìåíç êáôÜññåõóç óõóôÞìáôïò
+10 Tåñìáôéóìüò ìå ëÜèïò
+11 EMT trap
+12 Åîáßñåóç áñéèìçôéêÞò êéíçôÞò õðïäéáóôïëÞò
+13 Óêïôþèçêå
+14 User signal 1
+15 User signal 2
+16 ËÜèïò Segmentation
+17 ËÜèïò Bus
+18 ËÜèïò ðåäßïõ ôéìþí ðñïãñÜììáôïò
+19 ËÜèïò ðåäßïõ ôéìþí ïñßóìáôïò
+20 Áíýðáñêôï system call
+21 ÓðáóìÝíï pipe
+22 ÓÞìá alarm
+23 Tåñìáôßóôçêå
+24 ÁëëáãÞ êáôÜóôáóçò äéåñãáóßáò-ðáéäéïý
+25 ÈÜíáôïò äéåñãáóßáò-ðáéäéïý
+26 ÓöÜëìá Apollo
+27 Ç äéåñãáóßá-ðáéäß óôáìÜôçóå Þ ôåñìÜôéóå
+28 Ç äéåñãáóßá-ðáéäß ôåñìÜôéóå
+29 ÄéáêïðÞ ôÜóçò
+30 Áðþëåéá ðüñïõ
+31 Break (Ctrl-Break)
+32 ÓÞìá äõíáôüôçôáò input/output
+33 Áóýã÷ñïíï I/O (select)
+34 Åðåßãïõóá êáôÜóôáóç óå äßáõëï I/O
+35 Multitasking wake-up
+36 Multitasking kill
+37 ÐåñÜôùóç áóýã÷ñïíïõ I/O ôçò fortran
+38 ÁíÜêáìøç
+39 Ìç åðáíïñèþóéìï óöÜëìá ìíÞìçò
+40 ÕðÝñâáóç ïñßïõ ÷ñüíïõ CPU
+41 Åðéêåßìåíï shutdown óõóôÞìáôïò
+42 Tï wakeup flag ôïõ áñéè. ïìÜäáò micro-tasking Ýãéíå set
+43 Ðñüâëçìá thread - (÷ñçóéìïðïéÞóôå cord -T ãéÜ ëåðôïìåñåßò ðëçñïöïñßåò)
+44 ÓöÜëìá áñôéüôçôáò êáôá÷ùñçôÞ CRAY Y-MP
+45 Áßôçóç ðëçñïöïñßáò
+46 ÁíáâïëÞ (óÞìál)
+47 Ðáýóç (óÞìá)
+48 ÁíáâïëÞ
+49 Ðáýóç
+50 ÓõíÝ÷éóç
+51 ÁíáâïëÞ (åßóïäïò áðü ôåñìáôéêü)
+52 Ðáýóç (åßóïäïò áðü ôåñìáôéêü)
+53 ÁíáâïëÞ (Ýîïäïò óå ôåñìáôéêü)
+54 Ðáýóç (Ýîïäïò óå ôåñìáôéêü)
+55 Ç êáôÜóôáóç ôïõ ðáñáèýñïõ Üëëáîå
+56 Tï ìÝãåèïò ôïõ ðáñáèýñïõ Üëëáîå
+57 Ç êáôÜóôáóç ôçò ôçëåöùíéêÞò ãñáììÞò Üëëáîå
+58 ÕðÝñâáóç ïñßïõ ÷ñüíïõ CPU
+59 ÕðÝñâáóç ïñßïõ ìåãÝèïõò áñ÷åßïõ
+60 ÓÞìá alarm åéêïíéêïý ÷ñüíïõ
+61 ÓÞìá alarm ÷ñüíïõ Profiling
+62 ÓÞìá DIL
+63 ÐñïÝêõøå pollable event
+64 Tá lwp's ôçò äéåñãáóßáò åßíáé ìðëïêáñéóìÝíá
+65 Åéäéêü óÞìá LWP
+66 Åéäéêü óÞìá CPR
+67 Åéäéêü óÞìá CPR
+68 Ðñþôï óÞìá Ðñáãìáôéêïý ×ñüíïõ
+69 Äåýôåñï óÞìá Ðñáãìáôéêïý ×ñüíïõ
+70 Tñßôï óÞìá Ðñáãìáôéêïý ×ñüíïõ
+71 TÝôáñôï óÞìá Ðñáãìáôéêïý ×ñüíïõ
+72 TÝôáñôï áðü ôï ôÝëïò óÞìá Ðñáãìáôéêïý ×ñüíïõ
+73 Tñßôï áðü ôï ôÝëïò óÞìá Ðñáãìáôéêïý ×ñüíïõ
+74 Äåýôåñï áðü ôï ôÝëïò óÞìá Ðñáãìáôéêïý ×ñüíïõ
+75 Tåëåõôáßï óÞìá Ðñáãìáôéêïý ×ñüíïõ
+76 Áóýã÷ñïíï I/O ôïðéêïý äéêôýïõ
+77 Äéáèåóéìüôçôá PTY ãéÜ áíÜãíùóç/ãñÜøéìï
+78 Áðáéôåßôáé ðáñÝìâáóç óôï I/O
+79 Ç ëåéôïõñãßá HFT monitor ðáñá÷ùñÞèçêå
+80 Ç ëåéôïõñãßá HFT monitor ðñÝðåé íá ðáñá÷ùñçèåß
+81 Ï Ýëåã÷ïò Þ÷ïõ HFT Ý÷åé ðåñáôùèåß
+82 ÄåäïìÝíá óôïí HFT ring buffer
+83 ÌåôáíÜóóôåõóç äéåñãáóßáò
+84 ÁóöáëÝò attention key
+85 Åðáíáäñïìïëüãçóç
+86 ÓÞìá SS$_DEBUG
+87 ÁëëáãÞ ðñïôåñáéüôçôáò
+88 Áíé÷íåýèçêå ðñáãìáôéêü áäéÝîïäï
+89 ÍÝïò ÷áñáêôÞñáò åéóüäïõ
+90 Stack limit exceeded
+91 Unused signal
diff --git a/contrib/tcsh/nls/greek/set20 b/contrib/tcsh/nls/greek/set20
new file mode 100644
index 0000000..9ff678d
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set20
@@ -0,0 +1,41 @@
+$ $Id: set20,v 1.3 1998/09/18 15:32:01 christos Exp $
+$ tc.bind.c
+$set 20
+1 Áêõñï üíïìá ðëÞêôñïõ `%S'\n
+2 ÅóöáëìÝíï üíïìá ðëÞêôñïõ: %S\n
+3 ÅóöáëìÝíï üíïìá åíôïëÞò: %S\n
+4 ÅóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ %S\n
+5 ÌçäåíéêÞ ðåñéãñáöÞ string\n
+6 Standard óõó÷åôßóåéò ðëÞêôñùí\n
+7 ÅíáëëáêôéêÝò óõó÷åôßóåéò ðëÞêôñùí\n
+8 Óõó÷åôßóåéò ðïëëáðëþí ÷áñáêôÞñùí\n
+9 Óõó÷åôßóåéò ðëÞêôñùí âÝëïõò\n
+10 %-15s-> äåí Ý÷åé ïñéóôåß\n
+11 BUG!!! ôï %s äåí åßíáé óõó÷åôéóìÝíï ìå ôßðïôá.\n
+12 ×ñÞóç: bindkey [åðéëïãÝò] [--] [ÐËÇÊÔÑÏ [ÅÍÔÏËÇ]]\n
+13 -a åìöÜíéóç Þ óõó÷Ýôéóç ÐËÇÊÔÑÏõ óôïí åíáëëáêôéêü ÷Üñôç ðëÞêôñùí\n
+14 -b åñìçíåßá ÐËÇÊÔÑÏõ ùò C-, M-, F- or X- üíïìá ðëÞêôñïõ\n
+15 -s åñìçíåßá ÅÍÔÏËÇò ùò êõñéïëåêôéêïý string ãéÜ åìöÜíéóç\n
+16 -c åñìçíåßá ÅÍÔÏËÇò ùò åóùôåñéêÞò Þ åîùôåñéêÞò åíôïëÞò\n
+17 -v óõó÷Ýôéóç üëùí ôùí ðëÞêôñùí óå áíôéóôïé÷ßá vi\n
+18 -e óõó÷Ýôéóç üëùí ôùí ðëÞêôñùí óå áíôéóôïé÷ßá emacs\n
+19 -d óõó÷Ýôéóç üëùí ôùí ðëÞêôñùí óôçí default ôïõ editor\n
+20 -l åìöÜíéóç ôùí åíôïëþí ôïõ editor ìå ðåñéãñáöÝò\n
+21 -r êáôÜñãçóç óõó÷Ýôéóçò ôïõ ÐËÇÊÔÑÏõ\n
+22 -k åñìçíåßá ÐËÇÊÔÑÏõ ùò óõìâïëéêü üíïìá ðëÞêôñïõ âÝëïõò\n
+23 -- ôÝëïò åðåîåñãáóßáò åðéëïãþí\n
+24 -u (Þ ïðïéáäÞðïôå Üêõñç åðéëïãÞ) áõôü ôï ìÞíõìá\n
+25 ×ùñßò ÐËÇÊÔÑÏ Þ ÅÍÔÏËÇ, åìöáíßæåé üëåò ôéò óõó÷åôßóåéò\n
+26 ×ùñßò ÅÍÔÏËÇ, åìöáíßæåé ôç óõó÷Ýôéóç ãéÜ ôï ÐËÇÊÔÑÏ.\n
+27 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- ìçäåíéêü string\n
+28 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- Üäåéï string\n
+29 ÅóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ function. Ôï ìçäåíéêü string áðáãïñåýåôáé\n
+30 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- êáêïó÷çìáôéóìÝíïò äåêáåîáäéêüò áñéèìüò\n
+31 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- êáêïó÷çìáôéóìÝíïò ïêôáäéêüò áñéèìüò\n
+32 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- êáêïó÷çìáôéóìÝíïò äåêáäéêüò áñéèìüò\n
+33 ÅóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ function.\n
+34 Ôï ìçäåíéêü ðëÞêôñï äåí åðéôñÝðåôáé\n
+35 åóöáëìÝíç ðåñéãñáöÞ ðëÞêôñïõ -- Üãíùóôï üíïìá "%S"\n
+36 ÷ñÞóç: bind [ÐËÇÊÔÑÏ | ÐËÇÊÔÑÏ ÅÍÔÏËÇÓ | "emacs" | "vi" | "-a"]\n
+37 Áêõñç ëåéôïõñãßá
+38 Tï %s\t\täåí åßíáé ïñéóìÝíï\n
diff --git a/contrib/tcsh/nls/greek/set21 b/contrib/tcsh/nls/greek/set21
new file mode 100644
index 0000000..0e2933f
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.1 1996/04/26 19:24:32 christos Exp $
+$ tc.disc.c
+$set 21
+1 Äå ìðïñþ íá äéáâÜóù ôá local chars.\n
+2 Äå ìðïñþ íá ãñÜøù ôá local chars.\n
diff --git a/contrib/tcsh/nls/greek/set22 b/contrib/tcsh/nls/greek/set22
new file mode 100644
index 0000000..70d389a
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set22
@@ -0,0 +1,18 @@
+$ $Id: set22,v 1.1 1996/04/26 19:24:35 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t øåõäþíõìï ãéÜ ôï
+2 \nËÜèïò password ãéÜ ôï %s\n
+3 Tï åóöáëìÝíï øåõäþíõìï 'precmd' áöáéñÝèçêå.\n
+4 Ôï åóöáëìÝíï øåõäþíõìï 'cwdcmd' áöáéñÝèçêå.\n
+5 Ôï åóöáëìÝíï øåõäþíõìï 'beepcmd' áöáéñÝèçêå.\n
+6 Ôï åóöáëìÝíï øåõäþíõìï 'periodic' áöáéñÝèçêå.\n
+7 Ýëåã÷ïò óýíôáîçò ãñáììÞò\n
+8 ÈÝëåôå ðñáãìáôéêÜ íá óâÞóåôå üëá ôá áñ÷åßá? [n/y]
+9 áêýñùóç óâçóßìáôïò áñ÷åßùí!\n
+10 ç ãñáììÞ ôþñá Ýãéíå:\n
+11 Ýëåã÷ïò óýíôáîçò ãñáììÞò\n
+12 óå Ýíáí áðü ôïõò êáôáëüãïõò\n
+13 ç ãñáììÞ ôþñá Ýãéíå:\n
+14 yY
+
diff --git a/contrib/tcsh/nls/greek/set23 b/contrib/tcsh/nls/greek/set23
new file mode 100644
index 0000000..4fb2998
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set23
@@ -0,0 +1,31 @@
+$ $Id: set23,v 1.2 1998/09/18 15:32:02 christos Exp $
+$ tc.os.c
+$set 23
+1 Áêõñï üíïìá cpu/site
+2 Ôï site path åßíáé õðåñâïëéêÜ ìáêñý
+3 Üãíùóôï
+4 site: %s\n
+5 %d: ôï site äå âñÝèçêå\n
+6 setlocal: %s: %s\n
+7 Tï site äå âñÝèçêå
+8 Åßóôå ðáãéäåõìÝíïò óå Ýíá óýìðáí ðïõ äåí Ý÷åôå êáôáóêåõÜóåé
+9 Tï getwarp áðÝôõ÷å
+10 Áêõñï warp
+11 Tï setwarp áðÝôõ÷å
+12 Áêõñï óýìðáí
+13 Áãíùóôï ëÜèïò: %d
+14 üíïìá óõóôÞìáôïò: %s\n
+15 üíïìá êüìâïõ: %s\n
+16 release: %s\n
+17 version: %s\n
+18 machine: %s\n
+19 getwd: äå ìðïñþ íá áíïßîù ôï ".." (%s)
+20 getwd: äå ìðïñþ íá áëëÜîù ôïí êáôÜëïãï óå ".." (%s)
+21 getwd: óöÜëìá óôçí áíÜãíùóç ôïõ ".." (%s)
+22 getwd: äå ìðïñþ íá îáíáëëÜîù ôïí êáôÜëïãï óå "." (%s)
+23 getwd: äå ìðïñþ íá êÜíù stat ôï "/" (%s)
+24 getwd: äå ìðïñþ íá êÜíù stat ôïí êáôÜëïãï "%s" (%s)
+25 getwd: äå ìðïñþ íá áíïßîù ôïí êáôÜëïãï "%s" (%s)
+26 getwd: äå ìðïñþ íá âñþ ôï "." óôï ".." (%s)
+27 Áêõñïò ôýðïò óõóôÞìáôïò
+28 Äåí Ý÷åé äïèåß ôéìÞ óôïí ôýðï óõóôÞìáôïò
diff --git a/contrib/tcsh/nls/greek/set24 b/contrib/tcsh/nls/greek/set24
new file mode 100644
index 0000000..f1a811b
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.1 1996/04/26 19:24:44 christos Exp $
+$ tc.sched.c
+$set 24
+1 kludge
diff --git a/contrib/tcsh/nls/greek/set25 b/contrib/tcsh/nls/greek/set25
new file mode 100644
index 0000000..316c20f
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.1 1996/04/26 19:24:47 christos Exp $
+$ tc.sig.c
+$set 25
+1 our wait %d\n
+2 óöÜëìá: ôï bsd_signal(%d) åêôüò ïñßùí\n
+3 óöÜëìá: ç sigaction áðÝôõ÷å ãéÜ ôï bsd_signal(%d), errno %d\n
diff --git a/contrib/tcsh/nls/greek/set26 b/contrib/tcsh/nls/greek/set26
new file mode 100644
index 0000000..4449a65
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.2 1998/09/18 15:32:02 christos Exp $
+$ tc.who.c
+$set 26
+1 äå ìðïñþ íá êÜíù stat ôï %s. Ðáñáêáëþ äþóôå "unset watch".\n
+2 Tï %s äå ìðïñåß íá áíïé÷ôåß. Ðáñáêáëþ äþóôå "unset watch".\n
+3 BUG! ôï ôåëåõôáßï óôïé÷åßï äåí åßíáé whotail!\n
+4 ðñïò ôá ðßóù:
+5 BUG! ôï ôåëåõôáßï óôïé÷åßï äåí åßíáé whohead!\n
+6 íÝï: %s/%s\n
+7 Ï ÷ñÞóôçò %n Ýêáíå %a óôï ôåñìáôéêü %l áðü %m.
+8 Ï ÷ñÞóôçò %n Ýêáíå %a óôï ôåñìáôéêü %l.
+9 login
+10 logout
+11 áíôéêáôÝóôçóå ôïí %s óôï ôåñìáôéêü
+12 ôïðéêü
diff --git a/contrib/tcsh/nls/greek/set27 b/contrib/tcsh/nls/greek/set27
new file mode 100644
index 0000000..fba4644
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.1 1996/04/26 19:24:51 christos Exp $
+$ tw.comp.c
+$set 27
+1 åíôïëÞ
+2 separator
+3 pattern
+4 êëßìáêá ôéìþí
+5 óõìðëÞñùóç
diff --git a/contrib/tcsh/nls/greek/set29 b/contrib/tcsh/nls/greek/set29
new file mode 100644
index 0000000..6f30288
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.1 1996/04/26 19:24:55 christos Exp $
+$ tw.help.c
+$set 29
+1 Äåí õðÜñ÷åé áñ÷åßï ìå âïÞèåéá ãéÜ ôï %S\n
diff --git a/contrib/tcsh/nls/greek/set3 b/contrib/tcsh/nls/greek/set3
new file mode 100644
index 0000000..46b4364
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set3
@@ -0,0 +1,118 @@
+$ $Id: set3,v 1.2 1998/09/18 15:32:03 christos Exp $
+$ Editor function descriptions
+$set 3
+1 Ìåôáêßíçóç Ýíá ÷áñáêôÞñá üðéóèåí
+2 ÄéáãñáöÞ ÷áñáêôÞñá áñéóôåñÜ ôïõ äñïìÝá
+3 ÁðïêïðÞ áðü ôçí áñ÷Þ ôçò ôñÝ÷ïõóáò ëÝîçò ùò ôï äñïìÝá - öýëáîç óôï cut buffer
+4 ÁðïêïðÞ áðü ôçí áñ÷Þ ôçò ãñáììÞò - öýëáîç óôï cut buffer
+5 Ìåôáêßíçóç óôçí áñ÷Þ ôçò ôñÝ÷ïõóáò ëÝîçò
+6 Ìåôáêßíçóç óôçí áñ÷Þ ãñáììÞò
+7 ÌåôáôñïðÞ óå êåöáëáßá áðü ôï äñïìÝá ùò ôï ôÝëïò ôçò ôñÝ÷ïõóáò ëÝîçò
+8 (Vi) áëëáãÞ êåöáëáßùí/ìéêñþí óôç èÝóç ôïõ äñïìÝá êáé ìåôáêßíçóç ìéÜ èÝóç
+9 (Vi) áëëáãÞ êåöáëáßùí/ìéêñþí ùò ôï ôÝëïò ôçò ãñáììÞò
+10 ÊáèÜñéóìá ïèüíçò ìå ðáñáìïíÞ ôçò ôñÝ÷ïõóáò ãñáìÞò óôï ðÜíù ìÝñïò
+11 ÓõìðëÞñùóç ôñÝ÷ïõóáò ëÝîçò
+12 Tab forward ìåôáîý áñ÷åßùí
+13 Tab backward ìåôáîý áñ÷åßùí
+14 ÓõìðëÞñùóç ôñÝ÷ïõóáò ëÝîçò áãíïþíôáò ôéò ðñïãñáììáôéæüìåíåò óõìðëçñþóåéò
+15 ÁíôéãñáöÞ ôñÝ÷ïõóáò ëÝîçò óôçí èÝóç ôïõ äñïìÝá
+16 ÁíôéãñáöÞ ðåñéï÷Þò ìåôáîý óçìáäéïý êáé äñïìÝá óôï cut buffer
+17 ÁíÜðôõîç óå ðñïçãïýìåíç ëÝîç ìå ßäéï ðñüèåìá
+18 ÄéáãñáöÞ ÷áñáêôÞñá óôç èÝóç ôïõ äñïìÝá
+19 ÄéáãñáöÞ ÷áñáêôÞñá óôç èÝóç ôïõ äñïìÝá Þ end of file (ãéÜ Üäåéá ãñáììÞ)
+20 ÄéáãñáöÞ ÷áñáêôÞñá óôç èÝóç ôïõ äñïìÝá Þ óõìðëçñþóåéò (óôï ôÝëïò ãñáììÞò)
+21 ÄéáãñáöÞ ÷áñáêôÞñá óôç èÝóç ôïõ äñïìÝá, óõìðëçñþóåéò Þ end of file
+22 ÁðïêïðÞ áðü ôï äñïìÝá ùò ôï ôÝëïò ôçò ëÝîçò - öýëáîç óôï cut buffer
+23 Ðñüóèåóç óå üñéóìá óôçí áñ÷Þ Þ åßóïäïò øçößïõ
+24 Øçößï ðïõ áñ÷ßæåé üñéóìá
+25 Ìåôáêßíçóç óôçí åðüìåíç ãñáììÞ Éóôïñßáò
+26 ÌåôáôñïðÞ óå ìéêñÜ áðü ôï äñïìÝá ùò ôï ôÝëïò ôçò ëÝîçò
+27 Åíäåéîç end of file
+28 Ìåôáêßíçóç äñïìÝá óôï ôÝëïò ôçò ãñáììÞò
+29 ÁíôéìåôÜèåóç äñïìÝá - óçìáäéïý
+30 ÁíÜðôõîç wildcards óôï üíïìá áñ÷åßïõ
+31 ÁíÜðôõîç escapes Éóôïñßáò
+32 ÁíÜðôõîç escapes Éóôïñßáò óå ìéÜ ãñáììÞ
+33 ÁíÜðôõîç ìåôáâëçôþí
+34 Ìåôáêßíçóç äñïìÝá ìéÜ èÝóç åìðñüò
+35 Ìåôáêßíçóç ùò ôï ôÝëïò ôçò ëÝîçò
+36 ÁíôéìåôÜèåóç ôùí äýï ÷áñáêôÞñùí ðñéí ôï äñïìÝá
+37 ÁíáæÞôçóç ðñïçãïýìåíçò ãñáììÞò ôçò Éóôïñßáò ðïõ íá áñ÷ßæåé üðùò ç ôùñéíÞ
+38 ÁíáæÞôçóç åðüìåíçò ãñáììÞò ôçò Éóôïñßáò ðïõ íá áñ÷ßæåé üðùò ç ôùñéíÞ
+39 ÅéóáãùãÞ ôåëåõôáßïõ ôìÞìáôïò ðñïçãïýìåíçò åíôïëÞò
+40 ÓôáäéáêÞ áíáæÞôçóç óôá åðüìåíá
+41 ÓôáäéáêÞ áíáæÞôçóç óôá ðñïçãïýìåíá
+42 ÓâÞóéìï ãñáììÞò
+43 ÁðïêïðÞ ùò ôï ôÝëïò ôçò ãñáììÞò êáé öýëáîç óôï cut buffer
+44 ÁðïêïðÞ áðü ôï óçìÜäé ùò ôï äñïìÝá êáé öýëáîç óôï cut buffer
+45 ÁðïêïðÞ ïëüêëçñçò ôçò ãñáììÞò êáé öýëáîç óôï cut buffer
+46 ÅìöÜíéóç åðéëïãþí óõìðëÞñùóçò
+47 ÅìöÜíéóç åðéëïãþí óõìðëÞñùóçò áãíïþíôáò ôçí ðñïãñáììáôéæüìåíç óõìðëÞñùóç
+48 ÅìöÜíéóç ïíïìÜôùí áñ÷åßùí ðïõ ôáéñéÜæïõí ìå ôï wildcard
+49 ÅìöÜíéóç åðéëïãþí óõìðëÞñùóçò Þ end of file (óå Üäåéá ãñáììÞ)
+50 ÅìöÜíéóç ìÝóïõ üñïõ öïñôßïõ êáé êáôÜóôáóçò äéåñãáóéþí
+51 ÁíÜðôõîç escapes Éóôïñßáò êáé ðáñåìâïëÞ åíüò space
+52 ÅêôÝëåóç åíôïëÞò
+53 ÁíÜðôõîç pathnames, ìå áöáßñåóç ôùí áñ÷éêþí . êáé ..
+54 ÁíÜðôõîç åíôïëþí óôï ó÷åôéêü pathname Þ øåõäþíõìï
+55 ÅíáëëáãÞ áðü ðáñåìâïëÞ ÷áñáêôÞñùí óå áíôéêáôÜóôáóç êáé áíôßóôñïöá
+56 Ðñüóèåóç 8ïõ bit óôïí åðüìåíï ÷áñáêôÞñá ðïõ ðëçêôñïëïãåßôáé
+57 Ðñüóèåóç óôç ãñáììÞ ôïõ åðüìåíïõ ÷áñáêôÞñá ÷ùñßò åñìçíåßá (÷áñ. åëÝã÷ïõ)
+58 ÅðáíåìöÜíéóç
+59 Åðáíåêêßíçóç óôáìáôçìÝíïõ editor
+60 ÁíáæÞôçóç âïÞèåéáò ãéÜ ôçí ôñÝ÷ïõóá ãñáììÞ
+61 Ï ÷áñáêôÞñáò áõôüò ðñïóôßèåôáé óôç ãñáììÞ
+62 Ï ÷áñáêôÞñáò áõôüò åßíáé ï ðñþôïò ìéÜò áêïëïõèßáò ÷áñáêôÞñùí
+63 TïðïèÝôçóç óçìáäéïý óôç èÝóç ôïõ äñïìÝá
+64 Äéüñèùóç ïñèïãñáößáò ôçò ôñÝ÷ïõóáò ëÝîçò
+65 Äéüñèùóç ïñèïãñáößáò üëçò ôçò ãñáììÞò
+66 ÁðïóôïëÞ ÷áñáêôÞñá óôï ôåñìáôéêü óå cooked mode
+67 ÅíáëëáãÞ ìåôáîý êõñéïëåîßáò êáé ëåêôéêÞò ìïñöÞò ãñáììÞò Éóôïñßáò
+68 ÅíáëëáãÞ ôïõ ÷áñáêôÞñá óôç èÝóç ôïõ äñïìÝá ìå ôïí åðüìåíï
+69 ÅíáëëáãÞ ôùí äýï ÷áñáêôÞñùí áñéóôåñÜ ôïõ äñïìÝá
+70 ×áñáêôÞñáò ôåñìáôéêïý ãéá êáèõóôåñçìÝíç áíáâïëÞ äéåñãáóßáò
+71 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ åêêÝíùóç output
+72 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ åêêÝíùóç input
+73 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ ðáñáßôçóç (quit)
+74 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ áíáâïëÞ
+75 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ åíåñãïðïßçóç output
+76 ×áñáêôÞñáò ôåñìáôéêïý ãéÜ áðåíåñãïðïßçóç output
+77 Åíäåéîç ÷áñáêôÞñá ÷ùñßò áíôéóôïß÷éóç
+78 Universal üñéóìá ôïõ emcas (üñéóìá åðß 4)
+79 Ìåôáêßíçóç óôçí ðñïçãïýìåíç ãñáììÞ Éóôïñßáò
+80 ÌåôáôñïðÞ óå êåöáëáßá áðü ôç èÝóç ôïõ äñïìÝá ùò ôï ôÝëïò ôçò ëÝîçò
+81 (Vi) ìåôáêßíçóç óôçí áñ÷Þ ôçò åðüìåíçò ëÝîçò
+82 (Vi) ìåôÜâáóç óå ôñüðï ðáñåìâïëÞò ÷áñáêôÞñùí ìåôÜ ôï äñïìÝá
+83 (Vi) ìåôÜâáóç óå ôñüðï ðáñåìâïëÞò ÷áñáêôÞñùí óôï ôÝëïò ôçò ãñáììÞò
+84 (Vi) ìåôáôñïðÞ êåöáëáßùí/ìéêñþí óôç èÝóç äñïìÝá êáé ìåôáêßíçóç äåîéÜ
+85 (Vi) åíôïëÞ áëëáãÞò ðñïèÝìáôïò
+86 (Vi) áëëáãÞ ùò ôï ôÝëïò ôçò ãñáììÞò
+87 ÌåôÜâáóç óôïí ôñüðï åíôïëþí vi
+88 (Vi) óå ôñüðï åíôïëþí, óõìðëÞñùóç ëÝîçò
+89 (Vi) ìåôáêßíçóç óôïí ðñïçãïýìåíï ÷áñáêôÞñá (backspace)
+90 (Vi) åíôïëÞ äéáãñáöÞò ðñïèÝìáôïò
+91 (Vi) ìåôáêßíçóç óôï ôÝëïò ôçò ôñÝ÷ïõóáò ëÝîçò (÷ùñéóìÝíçò áðï space)
+92 (Vi) ìåôáêßíçóç óôï ôÝëïò ôçò ôñÝ÷ïõóáò ëÝîçò
+93 (Vi) ìåôáêßíçóç ðñïò ôá ðßóù ùò ôïí êáèïñéóìÝíï ÷áñáêôÞñá
+94 (Vi) ìåôáêßíçóç ðñïò ôá åìðñüò ùò ôïí êáèïñéóìÝíï ÷áñáêôÞñá
+95 (Vi) ìåôáêßíçóç ðñïò ôá ðßóù ùò êáé ôïí êáèïñéóìÝíï ÷áñáêôÞñá
+96 (Vi) ìåôáêßíçóç ðñïò ôá åìðñüò ùò êáé ôïí êáèïñéóìÝíï ÷áñáêôÞñá
+97 ÌåôÜâáóç óôïí ôñüðï ðáñåìâïëÞò ôïõ vi
+98 ÌåôÜâáóç óôïí ôñüðï ðáñåìâïëÞò ôïõ vi óôçí áñ÷Þ ôçò ãñáììÞò
+99 (Vi) åðáíÜëçøç ðñïçãïýìåíçò áíáæÞôçóçò ÷áñáêôÞñá óôçí ßäéá êáôåýèõíóç
+100 (Vi) åðáíÜëçøç ðñïçãïýìåíçò áíáæÞôçóçò ÷áñáêôÞñá óôçí áíôßèåôç êáôåýèõíóç
+101 (Vi) åðáíÜëçøç ðñïçãïýìåíçò áíáæÞôçóçò óôçí ßäéá êáôåýèõíóç
+102 (Vi) åðáíÜëçøç ðñïçãïýìåíçò áíáæÞôçóçò óôçí áíôßèåôç êáôåýèõíóç
+103 (Vi) áíôéêáôÜóôáóç ôñÝ÷ïíôá ÷áñáêôÞñá ìå ôïí åðüìåíï ðëçêôñïëïãïýìåíï
+104 (Vi) ôñüðïò áíôéêáôÜóôáóçò
+105 (Vi) áíáæÞôçóç Éóôïñßáò ðñïò ôá ðßóù
+106 (Vi) áíáæÞôçóç Éóôïñßáò ðñïò ôá ìðñïóôÜ
+107 (Vi) áíôéêáôÜóôáóç ôñÝ÷ïíôá ÷áñáêôÞñá êáé ìåôÜâáóç óå ôñüðï ðáñåìâïëÞò
+108 (Vi) áíôéêáôÜóôáóç ïëüêëçñçò ôçò ãñáììÞò
+109 (Vi) ìåôáêßíçóç óôçí ðñïçãïýìåíç ëÝîç
+110 (Vi) ìåôáêßíçóç óôçí åðüìåíç ëÝîç
+111 (Vi) áíáßñåóç ðñïçãïýìåíçò áëëáãÞò
+112 (Vi) ìåôáêßíçóç óôçí áñ÷Þ ôçò ãñáììÞò
+113 ÅêôÝëåóç "which" ôçò ôñÝ÷ïõóáò åíôïëÞò
+114 Åðéêüëëçóç ôïõ cut buffer óôçí ôñÝ÷ïõóá èÝóç
+
diff --git a/contrib/tcsh/nls/greek/set30 b/contrib/tcsh/nls/greek/set30
new file mode 100644
index 0000000..121cfc3
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.1 1996/04/26 19:25:06 christos Exp $
+$ tw.parse.c
+$set 30
+1 starting_a_command %d\n
+2 óõìðëÞñùóç %d
+3 óõìðëÞñùóç %d %S\n
+4 %s: åóùôåñéêü ëÜèïò ôáéñéÜóìáôïò.\n
+5 áíôéêåßìåíáitems
+6 óåéñÝò)
+7 ÕðÜñ÷ïõí %d %s, íá ôá åìöáíßóù ïýôùò Þ Üëëùò? [n/y]
+8 looking = %d\n
+9 \nåóùôåñéêü óöÜëìá ôïõ %s: äåí îÝñù ôé áíáæçôþ!\n
+10 äåí åßíáé êáôÜëïãïò áñ÷åßùí
+11 äå âñÝèçêå
+12 ìç áíáãíþóéìï
+13 yY
diff --git a/contrib/tcsh/nls/greek/set31 b/contrib/tcsh/nls/greek/set31
new file mode 100644
index 0000000..95f3e0d
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.1 1996/04/26 19:25:15 christos Exp $
+$ vms.termcap.c
+$set 31
+1 Äå ìðïñþ íá áíïßîù ôï TERMCAP: [%s]\n
+2 Äå ìðïñþ íá áíïßîù ôï %s.\n
+3 ÂñÞêá ôï %s óôï %s.\n
+4 Äå âñÞêá êÜôé ðïõ íá ôáéñéÜæåé ìå ôï %s óôï áñ÷åßï %s\n
diff --git a/contrib/tcsh/nls/greek/set4 b/contrib/tcsh/nls/greek/set4
new file mode 100644
index 0000000..b982ed1
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.2 1998/09/18 15:32:04 christos Exp $
+$ Termcap strings
+$set 4
+1 ðñüóèåóç íÝáò êåíÞò ãñáììÞò
+2 ç÷çôéêü óÞìá
+3 êáèÜñéóìá ùò ôï ôÝëïò ïèüíçò
+4 êáèÜñéóìá ùò ôï ôÝëïò ãñáììÞò
+5 äñïìÝáò óå ïñéæüíôéá èÝóç
+6 êáèÜñéóìá ïèüíçò
+7 äéáãñáöÞ åíüò ÷áñáêôÞñá
+8 äéáãñáöÞ ìéÜò ãñáììÞò
+9 Ýíáñîç ôñüðïõ äéáãñáöÞò
+10 ôåñìáôéóìüò ôñüðïõ äéáãñáöÞò
+11 ôåñìáôéóìüò ôñüðïõ ðáñåìâïëÞò
+12 äñïìÝáò áðü ãñáììÞ êáôÜóôáóçò
+13 äñïìÝáò óôçí áñ÷Þ
+14 åéóáãùãÞ ÷áñáêôÞñá
+15 Ýíáñîç ôñüðïõ ðáñåìâïëÞò
+16 ðáñåìâïëÞ padding
+17 áðïóôïëÞ ÊÜôù
+18 áðïóôïëÞ ÁñéóôåñÜ
+19 áðïóôïëÞ ÄåîéÜ
+20 áðïóôïëÞ ÅðÜíù
+21 Ýíáñîç bold
+22 ôÝëïò éäéïôÞôùí ÷áñáêôÞñùí
+23 ìç êáôáóôñåðôéêü space
+24 ôÝëïò Ýìöáóçò
+25 áñ÷Þ Ýìöáóçò
+26 ï äñïìÝáò óôç ãñáììÞ êáôÜóôáóçò
+27 ï äñïìÝáò ìéÜ èÝóç åðÜíù
+28 Ýíáñîç õðïãñÜììéóçò
+29 ôÝëïò õðïãñÜììéóçò
+30 ïñáôü óÞìá
+31 äéáãñáöÞ ðïëëáðëþí ÷áñáêôÞñùí
+32 äñïìÝáò ðïëëáðëÝò èÝóåéò êÜôù
+33 ðáñåìâïëÞ ðïëëáðëþí ÷áñáêôÞñùí
+34 äñïìÝáò ðïëëáðëÝò èÝóåéò áñéóôåñÜ
+35 äñïìÝáò ðïëëáðëÝò èÝóåéò äåîéÜ
+36 äñïìÝáò ðïëëáðëÝò èÝóåéò åðÜíù
+37 Äõíáôüôçôá áõôüìáôùí ðåñéèùñßùí
+38 Äõíáôüôçôá ÷ñÞóçò öõóéêþí tabs
+39 Áñéèìüò ãñáììþí
+40 Áñéèìüò óôçëþí
+41 Õðáñîç "ìåôá"-ðëÞêôñïõ
+42 Ôï newline áãíïåßôáé óôï äåîß ðåñéèþñéï
diff --git a/contrib/tcsh/nls/greek/set5 b/contrib/tcsh/nls/greek/set5
new file mode 100644
index 0000000..6d4834b
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.1 1996/04/26 19:25:27 christos Exp $
+$ ed.chared.c
+$set 5
+1 Ï ìÝóïò üñïò öïñôßïõ äåí åßíáé äéáèÝóéìïò\n
diff --git a/contrib/tcsh/nls/greek/set6 b/contrib/tcsh/nls/greek/set6
new file mode 100644
index 0000000..8d6da29
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.1 1996/04/26 19:25:29 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ÓÖÁËÌÁ: Üêõñç åíôïëÞ áðï ôï ðëÞêôñï 0%o\r\n
+2 íáé\n
+3 edit\n
+4 abort\n
+5 ü÷é\n
+6 Äåí õðÜñ÷åé åíôïëÞ ðïõ íá ôáéñéÜæåé\n
+7 Äéöïñïýìåíç åíôïëÞ\n
+8 *** ìïéñáßï ÓÖÁËÌÁ editor ***\r\n\n
diff --git a/contrib/tcsh/nls/greek/set7 b/contrib/tcsh/nls/greek/set7
new file mode 100644
index 0000000..4eea77f
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.2 1998/09/18 15:32:05 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tÔï %s îÝñåé ãéÜ ôï ôåñìáôéêü óáò ôá\n
+2 \tåîÞò ÷áñáêôçñéóôéêÜ:\n\n
+3 \tÅ÷åé %d óôÞëåò êáé %d ãñáììÝò\n
+4 \t%s÷åé "ìåôá"-ðëÞêôñï\n
+5 Å
+6 Äåí Ý
+7 \t%sìðïñåß íá ÷ñçóéìïðïéÞóåé tabs\n
+8 Äåí
+9 \t%s áõôüìáôá ðåñéèþñéá\n
+10 Å÷åé
+11 Äåí Ý÷åé
+12 \t%s "ìáãéêÜ" ðåñéèþñéá\n
+13 (Üäåéï)
+14 íáé
+15 ü÷é
+16 ÓÖÁËÌÁ: äå ìðïñþ íá óâÞóù\r\n
+17 DeleteChars: ï áñéèìüò åßíáé áðßèáíïò: %d\r\n
+18 ÓÖÁËÌÁ: äå ìðïñþ íá ðáñåìâÜëù\r\n
+19 StartInsert: ï áñéèìüò åßíáé áðßèáíïò: %d\r\n
+20 %s: Äå ìðïñþ íá áíïßîù ôï /etc/termcap.\n
+21 %s: Äåí õðÜñ÷åé åããñáöÞ ãéá ôïí ôýðï ôåñìáôéêïý "%s"\n
+22 %s: èá ÷ñçóéìïðïéÞóù ÷áñáêôçñéóôéêÜ "÷áæïý" ôåñìáôéêïý.\n
+23 %s: ÐÑÏÅÉÄÏÐÏÉÇÓÇ: Ôï ôåñìáôéêü äåí ìðïñåß íá ìåôáêéíÞóåé åðÜíù.\n
+24 Ôï editing ìðïñåß íá åßíáé ðåñßåñãï ãéÜ ìåãÜëåò ãñáììÝò.\n
+25 äåí õðÜñ÷åé äõíáôüôçôá êáèáñéóìïý ùò ôï ôÝëïò ãñáììÞò.\n
+26 äåí õðÜñ÷åé äõíáôüôçôá äéáãñáöÞò ÷áñáêôÞñá.\n
+27 äåí õðÜñ÷åé äõíáôüôçôá ðáñåìâïëÞò ÷áñáêôÞñá.\n
diff --git a/contrib/tcsh/nls/greek/set8 b/contrib/tcsh/nls/greek/set8
new file mode 100644
index 0000000..376a8cd
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.1 1996/04/26 19:25:32 christos Exp $
+$ ed.term.c
+$set 8
+1 Áãíùóôï switch
+2 Áêõñï üñéóìá
diff --git a/contrib/tcsh/nls/greek/set9 b/contrib/tcsh/nls/greek/set9
new file mode 100644
index 0000000..1ec0731
--- /dev/null
+++ b/contrib/tcsh/nls/greek/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.2 1998/09/18 15:32:06 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: äåí åðéôñÝðåôáé ìçäåíéêü extended-key.\n
+2 AddXkey: ç åíôïëÞ ìå áõôÞí ôçí áñ÷éêÞ áêïëïõèßá äåí åðéôñÝðåôáé\n
+3 DeleteXkey: äåí åðéôñÝðåôáé ìçäåíéêü extended-key.\n
+4 Áóõó÷Ýôéóôï extended key "%S"\n
+5 ÌåñéêÜ extended keys åßíáé ðïëý ìåãÜëá ãéÜ ôïí åóùôåñéêü print buffer
+6 Enumerate: BUG!! ÐÝñáóìá ìçäåíéêïý pointer!\n
+7 äåí õðÜñ÷åé åßóïäïò
+8 ÊÜôé ðñÝðåé íá áêïëïõèåß: %c\n
+9 Ç ïêôáäéêÞ óôáèåñÜ äå ÷ùñÜåé óôï ìÝãåèïò åíüò char.\n
diff --git a/contrib/tcsh/nls/italian/set1 b/contrib/tcsh/nls/italian/set1
new file mode 100644
index 0000000..0f772ec
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.1 1998/09/03 22:03:13 christos Exp $
+$ Error messages
+$set 1
+1 Errore di Sintassi
+2 %s non è permesso
+3 Parola troppo lunga
+4 $< linea troppo lunga
+5 Nessun file per $0
+6 Modificatore [] incompleto
+7 L'espansione $ deve terminare prima di ]
+8 Modificatore sbagliato in $ (%c)
+9 Errore di indice
+10 Numero non corretto
+11 Sono senza parole
+12 Nome di file mancante
+13 Errore interno di glob
+14 Comando non trovato
+15 Troppi pochi argomenti
+16 Troppi argomenti
+17 È troppo pericoloso creare un alias in questo caso
+18 `if' vuoto
+19 `then' sbagliato
+20 Parola non tra parentesi
+21 %s non trovato
+22 Maschera sbagliata
+23 limit non esistente
+24 Argomento troppo lungo
+25 Fattore di scala sbagliato o sconosciuto
+26 Variabile non definita
+27 Pila delle directory non così profonda
+28 Numero di segnale non corretto
+29 Segnale sconosciuto; utilizza kill -l per elencare i segnali
+30 Il nome della variabile deve iniziare con una lettera
+31 Il nome della variabile è troppo lungo
+32 Il nome della variabile deve contenere caratteri alfanumerici
+33 Non ho il controllo dei lavori in questa shell
+34 Errore di sintassi nell'espressione
+35 HOME directory non esistente
+36 Non posso entrare nella HOME directory
+37 Comando nullo non corretto
+38 Espressione mancante nell'assegnamento
+39 Operatore sconosciuto
+40 Ambiguo
+41 %s: il file esiste
+42 L'argomento di -c finisce con un backslash
+43 Interrotto
+44 Indice fuori scala
+45 Overflow di linea
+46 Lavoro non esistente
+47 Non posso dal terminale
+48 Non in un while/foreach
+49 Ho finito i processi
+50 Corrispondenza non esistente
+51 %c mancante
+52 %c non corrispondente
+53 Memoria esaurita
+54 Non posso creare una pipe
+55 %s: %s
+56 %s
+57 Utilizzo: jobs [ -l ]
+58 Gli argomenti devono essere lavori o identificativi di processo
+59 Non esiste un lavoro predefinito
+60 Non esiste un lavoro precedente
+61 Nessun lavoro corrisponde alla descrizione
+62 Annidamento del `fork' > %d; potrebbe causare `...` un ciclo chiuso
+63 Nessun controllo dei lavori nelle sottoshell
+64 Errore di sincronizzazione: processo %d non trovato
+65 %sCi sono dei lavori sospesi
+66 %sCi sono dei lavori fermi
+67 Nessun'altra directory
+68 Pila delle directory vuota
+69 Directory sbagliata
+70 Utilizzo: %s [-%s]%s
+71 Operando non esistente per l'opzione -h
+72 Shell non di login
+73 Divisione per 0
+74 Resto per 0
+75 Errore di scala; intendevi forse "%s"?
+76 Non posso sospendere una shell di login (o perlomeno non ancora)
+77 Utente sconosciuto: %s
+78 Variabile $home non definita
+79 Utilizzo: history [-%s] [# numero dei comandi]
+80 $, ! oppure < non utilizzabili con $# o $?
+81 A capo in un nome di variabile
+82 * non permesso con $# o $?
+83 $?<cifra> o $#<cifra> non permessi
+84 Nome di variabile non lecito
+85 A capo nell'indice di una variabile
+86 Errore di overflow nel buffer di espansione
+87 Errore di sintassi nella variabile
+88 Costrutto ! sbagliato
+89 Precedente sostituzione inesistente
+90 Sostituzione sbagliata
+91 Non esiste il precedente lato sinistro
+92 Lato destro troppo lungo
+93 Modificatore ! errato: %c
+94 Il modificatore non ha funzionato
+95 Overflow di buffer nella sostituzione
+96 Errato selettore ! di argomento
+97 Nessuna ricerca precedente
+98 %s: evento non trovato
+99 Troppe )
+100 Troppe (
+101 ( non posizionata correttamente
+102 Manca il nome per la redirezione
+103 Redirezione in uscita ambigua
+104 Non posso usare << dentro ()
+105 Redirezione in ingresso ambigua
+106 () non posizionate correttamente
+107 Ciclo chiuso nell'alias
+108 Variabile $watch non definita
+109 Nessun evento programmato
+110 Utilizzo: sched -<elemento#>.\nUtilizzo: sched [+]hh:mm <comando>
+111 Non ci sono così tanti eventi programmati
+112 Nessun comando da eseguire
+113 Istante non corretto per l'evento
+114 Istante relativo non consistente con am/pm
+115 Al di fuori dello spazio stringa del termcap
+116 Utilizzo: settc %s [yes|no]
+117 Capacità `%s' sconosciuta
+118 Parametro del termcap `%%%c' sconosciuto
+119 Troppi argomenti per `%s' (%d)
+120 `%s' richiede %d argomenti
+121 Utilizzo: echotc [-v|-s] [<capacità> [<argomenti>]]
+122 %s: %s. Architettura non corretta
+123 !# Ciclo chiuso nello storico
+124 Richiesta di file formulata incorrettamente
+125 Overflow di selettore
+126 Opzione sconosciuta: `-%s'\nUtilizzo: %s [ -bcdefilmnqstvVxX -Dnome[=valore] ] [ argomento ... ]
+127 Opzione sconosciuta: `-%s'\nUtilizzo: %s [ -bcdefFilmnqstvVxX ] [ argomento ... ]
+128 Opzione sconosciuta: `-%s'\nUtilizzo: %s [ -bcdefilmnqstvVxX ] [ argomento ... ]
+129 \nCompletamento non corretto: "%s"
+130 \n%s non corretto: '%c'
+131 \nManca il separatore '%c' dopo %s "%s"
+132 \n%s incompleto: "%s"
+133 Manca l'operando dell'opzione -m
+134 Utilizzo: unlimit [-fh] [limiti]
+135 $%S è a sola lettura
+136 Non esiste il lavoro
+137 Variabile `%c%c colorls' sconosciuta
diff --git a/contrib/tcsh/nls/italian/set10 b/contrib/tcsh/nls/italian/set10
new file mode 100644
index 0000000..1fcda24
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.1 1998/09/03 22:03:14 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: comando '%s' non valido.\n
+2 setpath: argomenti insufficienti per il comando '%s'.\n
+3 setpath: manca un valore nel percorso '%s'\n
+4 setpath: %s non trovato in %s\n
+5 setpath: posizione %d non valida in %s\n
diff --git a/contrib/tcsh/nls/italian/set11 b/contrib/tcsh/nls/italian/set11
new file mode 100644
index 0000000..a558b2c
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.1 1998/09/03 22:03:14 christos Exp $
+$ sh.c
+$set 11
+1 Attenzione: accesso negato al terminale (%s).\n
+2 Quindi il controllo dei lavori in questa shell non è possibile.\n
+3 Hai %d messaggi di posta elettronica.\n
+4 Hai %d messaggi di posta elettronica in %s.\n
+5 Hai %smessaggi di posta elettronica.\n
+6 nuovi
+7 Hai %smessaggi di posta elettronica in %s.\n
diff --git a/contrib/tcsh/nls/italian/set12 b/contrib/tcsh/nls/italian/set12
new file mode 100644
index 0000000..f07486b
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.1 1998/09/03 22:03:16 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: sto tentando di partire da "%s"\n
diff --git a/contrib/tcsh/nls/italian/set13 b/contrib/tcsh/nls/italian/set13
new file mode 100644
index 0000000..65b46bb
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.1 1998/09/03 22:03:17 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d gruppi di hash di %d bits ciascuno\n
+3 maschera di debug = 0x%08x\n
+4 %d giusti, %d errori, %d%%\n
+5 %S: comando interno della shell.\n
+6 %S: comando non trovato.\n
+7 where: / non ha senso all'interno di un comando\n
+8 %S è un alias per
+9 %S è un comando interno\n
+10 errore di hash:
diff --git a/contrib/tcsh/nls/italian/set14 b/contrib/tcsh/nls/italian/set14
new file mode 100644
index 0000000..0c95390
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.1 1998/09/03 22:03:18 christos Exp $
+$ sh.file.c
+$set 14
+1 \nAccipicchia!! Troppi %s!!\n
+2 nomi nel file della password
+3 file
diff --git a/contrib/tcsh/nls/italian/set15 b/contrib/tcsh/nls/italian/set15
new file mode 100644
index 0000000..8ed2234
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.1 1998/09/03 22:03:18 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: non si può %s il limite%s\n
+2 eliminare
+3 modificare
+4 \040fisico
diff --git a/contrib/tcsh/nls/italian/set16 b/contrib/tcsh/nls/italian/set16
new file mode 100644
index 0000000..1d11fbf
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.1 1998/09/03 22:03:19 christos Exp $
+$ sh.lex.c
+$set 16
+1 Reinizializzato il gruppo di processi di terminale da %d a %d\n
+2 \nUsa "logout" per uscire.\n
+3 \nUsa "exit" per lasciare %s.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Tipo di seek sbagliato %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/italian/set17 b/contrib/tcsh/nls/italian/set17
new file mode 100644
index 0000000..1361ffc
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.1 1998/09/03 22:03:20 christos Exp $
+$ sh.proc.c
+$set 17
+1 BACO: sto aspettando un lavoro in background!\n
+2 Uscito %d\n
+3 BACO: il processo è stato svuotato due volte
+4 In esecuzione
+5 Segnale
+6 Uscito %-25d
+7 Fatto
+8 BACO: stato=%-9o
+9 \040(creato file core)
+10 \040(directory di lavoro:
+11 directory di lavoro corrente:
+12 %S: già sospeso\n
+13 %S: già fermato\n
diff --git a/contrib/tcsh/nls/italian/set18 b/contrib/tcsh/nls/italian/set18
new file mode 100644
index 0000000..a8a80f2
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.1 1998/09/03 22:03:21 christos Exp $
+$ sh.set.c
+$set 18
+1 Attenzione: PATH indecorosamente lungo troncato\n
diff --git a/contrib/tcsh/nls/italian/set19 b/contrib/tcsh/nls/italian/set19
new file mode 100644
index 0000000..caa052d
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.1 1998/09/03 22:03:21 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: Memoria esaurita\n
+2 free(%lx) chiamata prima di qualsiasi allocazione.
+3 free(%lx) oltre il limite superiore della memoria.
+4 free(%lx) oltre il limite inferiore della memoria.
+5 free(%lx) blocco errato.
+6 free(%lx) intervallo di controllo sbagliato.
+7 free(%lx) indice di blocco sbagliato.
+8 %s attuale allocazione di memoria:\nlibera:\t
+9 \nutilizzata:\t
+10 \n\tTotale utilizzata: %d, totale libera: %d\n
+11 \tAllocata memoria da 0x%lx a 0x%lx. Limite superiore effettivo a 0x%lx\n
+12 Allocata memoria da 0x%lx a 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/italian/set2 b/contrib/tcsh/nls/italian/set2
new file mode 100644
index 0000000..07925f5
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set2
@@ -0,0 +1,94 @@
+$ $Id: set2,v 1.1 1998/09/03 22:03:22 christos Exp $
+$ Signal names
+$set 2
+1 Segnale nullo
+2 Interrotto
+3 Fermato
+4 Uscito
+5 Istruzione non esistente
+6 trap di tipo Trace/BPT
+7 Segnale di annullamento
+8 trap IOT
+9 Crash di sistema imminente
+10 Uscita per errore
+11 trap EMT
+12 Errore di calcolo in virgola mobile
+13 Ucciso
+14 Segnale utente numero 1
+15 Segnale utente numero 2
+16 Errore di accesso al segmento di memoria
+17 Errore di bus
+18 Errore nell'intervallo del programma
+19 Errore nell'intervallo dell'operando
+20 Chiamata di sistema sbagliata
+21 Pipe interrotta
+22 Allarme
+23 Terminato
+24 Cambio di stato nel figlio
+25 Morte del figlio
+26 Errore specifico dell'Apollo
+27 Figlio fermato o uscito
+28 Figlio uscito
+29 Errore di alimentazione
+30 Perdita della risorsa
+31 Interruzione (Ctrl-Break)
+32 Possibile segnale di I/O
+33 I/O asincrono (select)
+34 Urgenza su canale di I/O
+35 Interruzione del `multitasking'
+36 Termine del `multitasking'
+37 Completamento di I/O asincrono del Fortran
+38 Recupero
+39 Errore non correggibile di memoria
+40 Tempo di CPU a disposizione esaurito
+41 Spegnimento del sistema imminente
+42 micro-tasking group-no wakeup flag settato
+43 Errore di thread - (usa cord -T per avere informazioni dettagliate)
+44 Errore di parità di registro del CRAY Y-MP
+45 Richiesta di informazioni
+46 Sospeso (segnale)
+47 Fermato (segnale)
+48 Sospeso
+49 Fermato
+50 Continuato
+51 Sospeso (input da tty)
+52 Fermato (input da tty)
+53 Sospeso (output su tty)
+54 Fermato (output su tty)
+55 Cambio di stato della finestra
+56 Cambio di dimensioni della finestra
+57 Cambio di stato del telefono
+58 Tempo di CPU a disposizione esaurito
+59 Limite massimo delle dimensioni di un file superato
+60 Allarme dell'orologio virtuale
+61 Allarme di tempo di profiling
+62 Segnale DIL
+63 Si è verificato un evento interrogabile
+64 Gli lwps del processo sono bloccati
+65 Segnale speciale LWP
+66 Segnale speciale CPR
+67 Segnale speciale CPR
+68 Primo segnale di tempo reale
+69 Secondo segnale di tempo reale
+70 Terzo segnale di tempo reale
+71 Quarto segnale di tempo reale
+72 Quart'ultimo segnale di tempo reale
+73 Terz'ultimo segnale di tempo reale
+74 Penultimo segnale di tempo reale
+75 Ultimo segnale di tempo reale
+76 I/O asincrono di LAN
+77 Disponibilità di lettura/scrittura su pseudoterminale
+78 Richiesta di I/O
+79 Modalità di monitoraggio HFT disponibile
+80 La modalità di monitoraggio HFT deve essere abbandonata
+81 Il controllo sonoro HFT è stato completato
+82 Dati nel buffer circolare HFT
+83 Migrate process
+84 Tasto di attenzione assicurata
+85 Rischedulamento
+86 Segnale di SS$_DEBUG
+87 Cambio di priorità
+88 Identificato uno stallo
+89 Nuovo carattere in ingresso
+90 Oltrepassato lo spazio disponibile di stack
+91 Segnale non usato
diff --git a/contrib/tcsh/nls/italian/set20 b/contrib/tcsh/nls/italian/set20
new file mode 100644
index 0000000..25aadb7
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set20
@@ -0,0 +1,41 @@
+$ $Id: set20,v 1.1 1998/09/03 22:03:23 christos Exp $
+$ tc.bind.c
+$set 20
+1 Nome di tasto non corretto `%S'\n
+2 Nome di tasto sbagliato: %S\n
+3 Nome di comando sbagliato: %S\n
+4 Specificazione di tasto sbagliata %S\n
+5 Stringa di specificazione sbagliata\n
+6 Definizione dei tasti standard\n
+7 Definizione dei tasti alternativi\n
+8 Definizione delle combinazioni di più tasti\n
+9 Definizione dei tasti freccia\n
+10 %-15s-> non è definita\n
+11 BACO!!! %s non è definita da nessuna parte.\n
+12 Utilizzo: bindkey [opzioni] [--] [TASTO [COMANDO]]\n
+13 -a elenca o definisce un tasto nella tabella dei tasti alternativi\n
+14 -b interpreta TASTO come C-, M-, F- o X- tasto\n
+15 -s interpreta COMANDO come una sequenza di caratteri da mandare in uscita\n
+16 -c interpreta COMANDO come un comando interno o esterno\n
+17 -v definisce tutti i tasti alla 'vi'\n
+18 -e definisce tutti i tasti alla 'emacs'\n
+19 -d definisce tutti i tasti in base all'editor di default\n
+20 -l elenca i comandi di modifica testo con relativa descrizione\n
+21 -r rimuove la definizione per TASTO\n
+22 -k interpreta TASTO come un nome simbolico di tasto freccia\n
+23 -- forza un'interruzione nella interpretazione delle opzioni\n
+24 -u (o qualsiasi opzione non corretta) questo messaggio\n
+25 Senza TASTO o COMANDO, stampa tutte le definizioni\n
+26 Senza COMANDO, stampa la definizione di TASTO.\n
+27 specificazione di tasto sbagliata -- stringa nulla\n
+28 specificazione di tasto sbagliata -- stringa vuota\n
+29 Specificazione di tasto funzione sbagliata. Il tasto nullo non si può usare\n
+30 specificazione di tasto sbagliata -- numero esadecimale non corretto\n
+31 specificazione di tasto sbagliata -- numero ottale non corretto\n
+32 specificazione di tasto sbagliata -- numero decimale non corretto\n
+33 Specificazione di tasto funzione sbagliata.\n
+34 Il tasto nullo non si può usare\n
+35 specificazione di tasto sbagliata -- nome "%S" sconosciuto\n
+36 utilizzo: bind [TASTO | COMANDO TASTO | "emacs" | "vi" | "-a"]\n
+37 Funzione non corretta
+38 %s\t\tnon è definita\n
diff --git a/contrib/tcsh/nls/italian/set21 b/contrib/tcsh/nls/italian/set21
new file mode 100644
index 0000000..564e91a
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.2 1998/09/09 10:30:21 christos Exp $
+$ tc.disc.c
+$set 21
+1 Non si possono ottenere i caratteri locali\n
+2 Non si possono definire i caratteri locali\n
diff --git a/contrib/tcsh/nls/italian/set22 b/contrib/tcsh/nls/italian/set22
new file mode 100644
index 0000000..1187251
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set22
@@ -0,0 +1,17 @@
+$ $Id: set22,v 1.1 1998/09/03 22:03:24 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t è un alias per
+2 \nPassword non corretta per %s\n
+3 Alias non corretto 'precmd' rimosso.\n
+4 Alias non corretto 'cwdcmd' rimosso.\n
+5 Alias non corretto 'beepcmd' rimosso.\n
+6 Alias non corretto 'periodic' rimosso.\n
+7 sto esaminando la linea di comando\n
+8 Vuoi realmente cancellare tutti i file? [s/n]
+9 sto saltando la cancellazione dei file!\n
+10 la linea di comando adesso è:\n
+11 sto esaminando la linea di comando\n
+12 in uno degli elenchi\n
+13 la linea di comando ora è:\n
+14 sS
diff --git a/contrib/tcsh/nls/italian/set23 b/contrib/tcsh/nls/italian/set23
new file mode 100644
index 0000000..661e7e6
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set23
@@ -0,0 +1,34 @@
+$ $Id: set23,v 1.1 1998/09/03 22:03:25 christos Exp $
+$ tc.os.c
+$set 23
+1 Nome di cpu/macchina non corretto
+2 Percorso per la macchina troppo lungo
+3 sconosciuta
+4 macchina: %s\n
+5 %d: macchina non trovata\n
+6 setlocal: %s: %s\n
+7 Macchina non trovata
+8 Sei intrappolato in un universo che non creasti
+9 Getwarp fallita
+10 Warp non corretto
+11 Setwarp fallita
+12 Universo non corretto
+13 Errore sconosciuto: %d
+14 sysname: %s\n
+15 nodename: %s\n
+16 release: %s\n
+17 version: %s\n
+18 machine: %s\n
+19 getwd: non posso aprire ".." (%s)
+20 getwd: non posso entrare in ".." (%s)
+21 getwd: errore di lettura in ".." (%s)
+22 getwd: non posso tornare indietro in "." (%s)
+23 getwd: non posso usare la funzione stat in "/" (%s)
+24 getwd: non posso usare la funzione stat in "." (%s)
+25 getwd: non posso usare la funzione stat nella directory "%s" (%s)
+26 getwd: non posso aprire la directory "%s" (%s)
+27 getwd: non riesco a trovare "." in ".." (%s)
+28 Tipo di sistema non corretto
+29 Il tipo di sistema non è stato definito
+30 Troppi argomenti
+31 Argomento non corretto
diff --git a/contrib/tcsh/nls/italian/set24 b/contrib/tcsh/nls/italian/set24
new file mode 100644
index 0000000..d74e532
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.1 1998/09/03 22:03:26 christos Exp $
+$ tc.sched.c
+$set 24
+1 accrocchio
diff --git a/contrib/tcsh/nls/italian/set25 b/contrib/tcsh/nls/italian/set25
new file mode 100644
index 0000000..e20766a
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.1 1998/09/03 22:03:27 christos Exp $
+$ tc.sig.c
+$set 25
+1 ourwait %d\n
+2 errore: bsd_signal(%d) segnale fuori intervallo\n
+3 errore: bsd_signal(%d) - sigaction fallita, errno %d\n
diff --git a/contrib/tcsh/nls/italian/set26 b/contrib/tcsh/nls/italian/set26
new file mode 100644
index 0000000..f2ff82d
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.1 1998/09/03 22:03:28 christos Exp $
+$ tc.who.c
+$set 26
+1 non posso usare stat per %s. Per pietà dai un "unset watch".\n
+2 Non riesco ad aprire %s. Per pietà dai un "unset watch".\n
+3 BACO! l'ultimo elemento non è whotail!\n
+4 all'indietro:
+5 BACO! il primo elemento non è whohead!\n
+6 nuova entrata: %s/%s\n
+7 %n %a %l da %m.
+8 %n %a %l.
+9 si è loggato su
+10 si è sloggato da
+11 ha rimpiazzato %s su
+12 console
diff --git a/contrib/tcsh/nls/italian/set27 b/contrib/tcsh/nls/italian/set27
new file mode 100644
index 0000000..856c2cc
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.1 1998/09/03 22:03:28 christos Exp $
+$ tw.comp.c
+$set 27
+1 comando
+2 separatore
+3 disegno
+4 intervallo
+5 completamento
diff --git a/contrib/tcsh/nls/italian/set29 b/contrib/tcsh/nls/italian/set29
new file mode 100644
index 0000000..5bf6016
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.1 1998/09/03 22:03:29 christos Exp $
+$ tw.help.c
+$set 29
+1 Non esiste il file di aiuto per %S\n
diff --git a/contrib/tcsh/nls/italian/set3 b/contrib/tcsh/nls/italian/set3
new file mode 100644
index 0000000..733a36f
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set3
@@ -0,0 +1,117 @@
+$ $Id: set3,v 1.1 1998/09/03 22:03:30 christos Exp $
+$ Editor function descriptions
+$set 3
+1 Retrocede di un carattere
+2 Cancella il carattere dietro il cursore
+3 Taglia dall'inizio della parola corrente fino al cursore salvando nel buffer
+4 Taglia dall'inizio della linea sino al cursore salvando nel buffer
+5 Si sposta all'inizio della parola corrente
+6 Si sposta all'inizio della linea
+7 Converte in maiuscole le lettere dal cursore fino alla fine della parola corrente
+8 Vi: cambia in maiuscolo/minuscolo la lettera sotto il cursore e avanza di un carattere
+9 Vi: cambia fino alla fine della linea
+10 Cancella lo schermo lasciando la linea corrente in alto
+11 Completa la parola corrente
+12 Avanza con il tabulatore tra i file
+13 Retrocede con il tabulatore tra i file
+14 Completa la parola corrente ignorando le modalità di completamento programmabili
+15 Copia la parola corrente nella posizione del cursore
+16 Copia la zona tra il cursore e il segno nel buffer
+17 Espande nella precedente parola di cui questa è la parte iniziale
+18 Cancella il carattere sotto il cursore
+19 Cancella il carattere sotto il cursore o segnala la fine del file in una linea vuota
+20 Cancella il carattere sotto il cursore o elenca i completamenti se alla fine di una linea
+21 Cancella il carattere sotto il cursore, elenca completamenti o segnala la fine del file
+22 Taglia dal cursore fino alla fine della parola corrente salvando nel buffer
+23 Aggiunge all'argomento qualora iniziato, altrimenti inserisce la cifra
+24 Cifra che inizia l'argomento
+25 Si sposta alla linea seguente nello storico
+26 Converte in minuscole le lettere dal cursore fino alla fine della parola corrente
+27 Indica la fine di file
+28 Sposta il cursore alla fine della linea
+29 Scambia cursore e segno
+30 Espande i caratteri jolly nel nome del file
+31 Espande le sequenze di escape nello storico
+32 Espande le sequenze di escape nello storico in una linea
+33 Espande le variabili
+34 Avanza di un carattere
+35 Avanza alla fine della parola corrente
+36 Scambia i due caratteri prima del cursore
+37 Cerca all'indietro nello storico per una linea che inizia come la corrente
+38 Cerca in avanti nello storico per una linea che inizia come la corrente
+39 Inserisce l'ultimo elemento del precedente comando
+40 Ricerca incrementale in avanti
+41 Ricerca incrementale all'indietro
+42 Cancella la linea
+43 Taglia fino alla fine della linea salvando nel buffer
+44 Taglia la zona tra il cursore e il segno e la salva nel buffer
+45 Taglia l'intera linea salvandola nel buffer
+46 Elenca le possibili scelte per il completamento
+47 Elenca le possibili scelte per il completamento ignorando le modalità di completamento programmabili
+48 Elenca i file che corrispondono ai caratteri jolly
+49 Elenca le possibili scelte per il completamento o segnala la fine del file nel caso di linea vuota
+50 Mostra la media di carico macchina e lo stato del processo corrente
+51 Espande le sequenze di escape nello storico e inserisce uno spazio
+52 Esegue un comando
+53 Espande i percorsi eliminando i '.' e '..' iniziali
+54 Espande i comandi con il relativo percorso o alias
+55 Commuta tra le modalità di inserimento e di sovrascrittura
+56 Aggiunge l'ottavo bit al successivo carattere inserito
+57 Aggiunge nella linea il successivo carattere così com'è
+58 Ridisegna tutto
+59 Fa ripartire l'editor sospeso
+60 Cerca le spiegazioni del comando corrente
+61 Questo carattere è aggiunto alla linea
+62 Questo carattere è il primo in una sequenza di caratteri
+63 Fissa il segno nella posizione del cursore
+64 Corregge la sintassi della parola corrente
+65 Corregge la sintassi dell'intera linea
+66 Invia il carattere sul terminale in modalità `cooked'
+67 Commuta tra la corrente linea letterale e lessicale dello storico
+68 Scambia il carattere alla sinistra del cursore con quello sotto
+69 Scambia i due caratteri prima del cursore
+70 Carattere di sospensione del terminale ritardata
+71 Carattere di svuotamento dell'output del terminale
+72 Carattere di interruzione del terminale
+73 Carattere di uscita del terminale
+74 Carattere di sospensione del terminale
+75 Carattere di permesso di output del terminale
+76 Carattere di negazione dell'output del terminale
+77 Indica un carattere non assegnato
+78 Argomento Emacs universale
+79 Si sposta sulla precedente linea dello storico
+80 Converte in maiuscole le lettere dal cursore fino alla fine della parola corrente
+81 Vi: vai all'inizio della prossima parola
+82 Vi: commuta in modalità di inserimento dopo il cursore
+83 Vi: commuta in modalità di inserimento alla fine della linea
+84 Vi: cambia in da o in maiuscolo la lettera sotto il cursore e avanza di una posizione
+85 Vi: cambia il comando di prefisso
+86 Vi: modifica alla fine della linea
+87 Entra in modalità di comando vi (utilizza le definizioni di tasti alternative)
+88 Vi: modalità di comando a completamento di parola
+89 Vi: si sposta sul precedente carattere (backspace)
+90 Vi: cancella il comando di prefisso
+91 Vi: avanza sul primo carattere che precede uno spazio
+92 Vi: si sposta alla fine della parola corrente
+93 Vi: retrocede al carattere indicato
+94 Vi: avanza al carattere indicato
+95 Vi: si sposta sopra il carattere indicato all'indietro
+96 Vi: si sposta sopra il carattere indicato in avanti
+97 Commuta in modalità di inserimento vi
+98 Commuta in modalità di inserimento vi all'inizio della linea
+99 Vi: ripete la ricerca del carattere nella stessa direzione
+100 Vi: ripete la ricerca del carattere nella direzione opposta
+101 Vi: ripete la ricerca nella stessa direzione
+102 Vi: ripete la ricerca nella direzione opposta
+103 Vi: rimpiazza il carattere sotto il cursore con quello successivamente introdotto
+104 Vi: modalità di rimpiazzo
+105 Vi: ricerca nello storico all'indietro
+106 Vi: ricerca nello storico in avanti
+107 Vi: rimpiazza il carattere sotto il cursore e commuta in modalità di inserimento
+108 Vi: rimpiazza l'intera linea
+109 Vi: si sposta alla parola precedente
+110 Vi: si sposta alla parola successiva
+111 Vi: annulla la precedente modifica
+112 Vi: si sposta all'inizio della linea
+113 Esegue un `which' del comando corrente
+114 Inserisce il contenuto del buffer alla posizione del cursore
diff --git a/contrib/tcsh/nls/italian/set30 b/contrib/tcsh/nls/italian/set30
new file mode 100644
index 0000000..b5e7ee3
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.1 1998/09/03 22:03:31 christos Exp $
+$ tw.parse.c
+$set 30
+1 inizio_il_comando %d\n
+2 completo %d
+3 completo %d %S\n
+4 %s: Errore interno di corrispondenza.\n
+5 elementi, li
+6 righe, le
+7 Ci sono %d %selenco ugualmente? [n/s]
+8 sembra = %d\n
+9 \nerrore interno della tcsh: Non mi ricordo cosa stavo facendo!\n
+10 non è una directory
+11 non trovato
+12 non leggibile
+13 sS
diff --git a/contrib/tcsh/nls/italian/set31 b/contrib/tcsh/nls/italian/set31
new file mode 100644
index 0000000..07cdef2
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.1 1998/09/03 22:03:31 christos Exp $
+$ vms.termcap.c
+$set 31
+1 Non posso aprire il TERMCAP: [%s]\n
+2 Non posso aprire %s.\n
+3 Ho trovato %s in %s.\n
+4 Non esistono corrispondenze per %s nel file %s\n
diff --git a/contrib/tcsh/nls/italian/set4 b/contrib/tcsh/nls/italian/set4
new file mode 100644
index 0000000..fbd5604
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.1 1998/09/03 22:03:32 christos Exp $
+$ Termcap strings
+$set 4
+1 aggiunge una linea vuota
+2 segnale acustico
+3 cancella fino al margine inferiore
+4 cancella fino alla fine della linea
+5 cursore alla posizione orizzontale
+6 cancella lo schermo
+7 cancella un carattere
+8 cancella una riga
+9 mette in modalità di cancellazione
+10 fine della modalità di cancellazione
+11 fine della modalità di inserimento
+12 cursore dalla linea di stato
+13 cursore nella posizione iniziale
+14 inserisce un carattere
+15 mette in modalità di inserimento
+16 inserisce un carattere di riallineamento
+17 muove il cursore verso il basso
+18 muove il cursore verso sinistra
+19 muove il cursore verso destra
+20 muove il cursore verso l'alto
+21 inizio del grassetto
+22 fine degli attributi
+23 spazio non coprente
+24 fine dell'evidenziazione
+25 inizio dell'evidenziazione
+26 cursore nella linea di stato
+27 cursore su di uno
+28 inizio sottolineatura
+29 fine sottolineatura
+30 segnale ottico
+31 cancella più caratteri
+32 cursore verso il basso più volte
+33 inserisce più caratteri
+34 cursore verso sinistra più volte
+35 cursore verso destra più volte
+36 cursore verso l'alto più volte
+37 Ha margini automatizzati
+38 Può usare tabulatori fisici
+39 Numero di linee
+40 Numero di colonne
+41 Ha il tasto meta
+42 Ritorno a capo ignorato sul margine destro
diff --git a/contrib/tcsh/nls/italian/set5 b/contrib/tcsh/nls/italian/set5
new file mode 100644
index 0000000..788d52c
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.1 1998/09/03 22:03:33 christos Exp $
+$ ed.chared.c
+$set 5
+1 Media di carico non disponibile\n
diff --git a/contrib/tcsh/nls/italian/set6 b/contrib/tcsh/nls/italian/set6
new file mode 100644
index 0000000..6686b01
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.1 1998/09/03 22:03:34 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ERRORE: comando illegale per il tasto 0%o\r\n
+2 sì\n
+3 modificare\n
+4 annullare\n
+5 no\n
+6 Non esiste un comando corrispondente\n
+7 Comando ambiguo\n
+8 *** ERRORE fatale nell'editor ***\r\n\n
diff --git a/contrib/tcsh/nls/italian/set7 b/contrib/tcsh/nls/italian/set7
new file mode 100644
index 0000000..f09b3dd
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.1 1998/09/03 22:03:34 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tLa tcsh ipotizza che il tuo terminale abbia\n
+2 \tle seguenti caratteristiche:\n\n
+3 \t%d colonne e %d linee\n
+4 \t%s tasto meta\n
+5 il
+6 nessun
+7 \t%s può usare i tabulatori\n
+8 non
+9 \t%s i margini automatici\n
+10 ha
+11 non ha
+12 \t%s i margini magici\n
+13 (vuoto)
+14 sì
+15 no
+16 ERRORE: non posso cancellare\r\n
+17 DeleteChars: il valore num è ridicolo: %d\r\n
+18 ERRORE: non posso inserire\r\n
+19 StartInsert: il valore num è ridicolo: %d\r\n
+20 %s: Non riesco ad aprire /etc/termcap.\n
+21 %s: Nessuna definizione per un terminale di tipo "%s"\n
+22 %s: sto usando i settaggi relativi ad un terminale veramente stupido.\n
+23 %s: ATTENZIONE: Il terminale non può scrollare verso l'alto.\n
+24 La modifica delle linee lunghe potrebbe essere difficoltosa.\n
+25 non è possibile cancellare fino alla fine della linea.\n
+26 non è possibile cancellare caratteri.\n
+27 non è possibile inserire caratteri.\n
diff --git a/contrib/tcsh/nls/italian/set8 b/contrib/tcsh/nls/italian/set8
new file mode 100644
index 0000000..ca5ce8d
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.1 1998/09/03 22:03:35 christos Exp $
+$ ed.term.c
+$set 8
+1 Commutatore sconosciuto
+2 Argomento non valido
diff --git a/contrib/tcsh/nls/italian/set9 b/contrib/tcsh/nls/italian/set9
new file mode 100644
index 0000000..745aad2
--- /dev/null
+++ b/contrib/tcsh/nls/italian/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.1 1998/09/03 22:03:36 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: tasto esteso nullo non ammesso.\n
+2 AddXkey: comando `sequence-lead-in' non permesso\n
+3 DeleteXkey: tasto esteso nullo non ammesso.\n
+4 Tasto esteso "%S" non definito\n
+5 Alcuni tasti estesi sono troppo grandi per il buffer interno di stampa
+6 Enumerate: BACO!! ho ricevuto un puntatore nullo\n!
+7 niente in ingresso
+8 Qualcosa deve seguire: %c\n
+9 Costante ottale non adeguata per un char.\n
diff --git a/contrib/tcsh/nls/ja/set1 b/contrib/tcsh/nls/ja/set1
new file mode 100644
index 0000000..b999e07
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set1
@@ -0,0 +1,139 @@
+$ $Id: set1,v 1.3 1999/05/11 13:08:29 christos Exp $
+$ Error messages
+$set 1
+1 ʸˡ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+3 ʸ¾Ï¤¬Ä¹¤¹¤®¤Þ¤¹
+4 $< ¤Î¹Ô¤¬Ä¹¤¹¤®¤Þ¤¹
+5 $0 ÍѤΥե¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó
+6 [] ½¤¾þ»Ò¤¬ÉÔ´°Á´¤Ç¤¹
+7 $ Ÿ³«¤Ï ] ¤ÎÁ°¤Ë½ª¤ï¤ëɬÍפ¬¤¢¤ê¤Þ¤¹
+8 $ Æâ¤Î : ½¤¾þ»Ò¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ (%c)
+9 ÇÛÎó¤Îź¤¨»ú¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+10 ÉÔŬÀÚ¤ËÀ¸À®¤µ¤ì¤¿ÈÖ¹æ¤Ç¤¹
+11 ʸ»úÎó¤Ï¤â¤¦¤¢¤ê¤Þ¤»¤ó
+12 ¥Õ¥¡¥¤¥ë̾¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+13 glob¤ÎÆâÉô¥¨¥é¡¼¤Ç¤¹
+14 ¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó
+15 ¥¢¡¼¥®¥å¥á¥ó¥È¤¬ÉÔ­¤·¤Æ¤¤¤Þ¤¹
+16 ¥¢¡¼¥®¥å¥á¥ó¥È¤¬Â¿²á¤®¤Þ¤¹
+17 ´í¸±¤Ê¥¨¥¤¥ê¥¢¥¹ÄêµÁ¤Ç¤¹
+18 if¤¬¤¢¤ê¤Þ¤»¤ó
+19 ´Ö°ã¤Ã¤¿then¤Ç¤¹
+20 ʸ»úÎ󤬳ç¸ÌÆâ¤Ë¤¢¤ê¤Þ¤»¤ó
+21 %s ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó
+22 ´Ö°ã¤Ã¤¿mask¤Ç¤¹
+23 ¤½¤Î¤è¤¦¤ÊlimitÃͤϤ¢¤ê¤Þ¤»¤ó
+24 ¥¢¡¼¥®¥å¥á¥ó¥È¤¬Ä¹¤¹¤®¤Þ¤¹
+25 ¥ª¥×¥·¥ç¥óñ°Ì¤¬ÉÔÌÀ¤«´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+26 ÊÑ¿ô¤òÄêµÁ¤·¤Æ¤¤¤Þ¤»¤ó
+27 ¥Ç¥£¥ì¥¯¥È¥ê¡¼¥¹¥¿¥Ã¥¯¤ÎÈÖ¹æ»ØÄ꤬¿¼²á¤®¤Þ¤¹
+28 ¥·¥°¥Ê¥ëÈֹ椬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+29 ¥·¥°¥Ê¥ë¤Î̾Á°¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹ "kill -l"¤Ç¸«¤ë»ö¤¬½ÐÍè¤Þ¤¹
+30 ÊÑ¿ô̾¤Ï±Ñ»ú¤Ç»Ï¤á¤ëɬÍפ¬¤¢¤ê¤Þ¤¹
+31 ÊÑ¿ô¤Î̾Á°¤¬Ä¹¤¹¤®¤Þ¤¹
+32 ÊÑ¿ô̾¤Ï±Ñ¿ô»ú¤À¤±¤Ç¹½À®¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹
+33 ¤³¤Îshell¤Ç¤Ï¥¸¥ç¥Ö¥³¥ó¥È¥í¡¼¥ë¤Ï»ÈÍѤǤ­¤Þ¤»¤ó
+34 ¼°¹½Ê¸?
+35 ¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¡¼¤¬¤¢¤ê¤Þ¤»¤ó
+36 ¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¡¼¤ËÊѹ¹¤Ç¤­¤Þ¤»¤ó
+37 ÉÔÀµ¤Ê¥Ì¥ë¥³¥Þ¥ó¥É¤Ç¤¹
+38 ¼°¤¬´Ö°ã¤Ã¤Æ¤¤¤ë³äÅö¤¬¤¢¤ê¤Þ¤¹
+39 ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤±é»»»Ò¤Ç¤¹
+40 Û£Ëæ¤Ç¤¹
+41 %s¤È¸À¤¦¥Õ¥¡¥¤¥ë¤Ï¤¹¤Ç¤Ë¸ºß¤·¤Þ¤¹
+42 -cÍѤΰú¿ô¤Ï¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å¤Ç½ª¤ï¤ê¤Þ¤¹
+43 ³ä¤ê¹þ¤ß¤¬Æþ¤ê¤Þ¤·¤¿
+44 ÇÛÎó¤ËÆþ¤ì¤ëź¤¨»ú¤¬ÈϰϤòĶ¤¨¤Æ¤¤¤Þ¤¹
+45 ¹Ô¤Î¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¤Ç¤¹
+46 ¤½¤Î¤è¤¦¤Ê¥¸¥ç¥Ö¤Ï¤¢¤ê¤Þ¤»¤ó
+47 üËö¤«¤é¤Ï¤Ç¤­¤Þ¤»¤ó
+48 while/foreach¤ÎÃæ¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó
+49 ¥×¥í¥»¥¹¤òÀ¸À®¤Ç¤­¤Þ¤»¤ó
+50 ¾È¹ç¥Ñ¥¿¡¼¥ó¤Ë¹ç¤¤¤Þ¤»¤ó
+51 ´Ö°ã¤Ã¤¿ %c ¤Ç¤¹
+52 %c ¤¬°ìÃפ·¤Þ¤»¤ó
+53 ¥á¥â¥ê¤¬ÉÔ­¤·¤Æ¤¤¤Þ¤¹
+54 ¥Ñ¥¤¥×¤òºî¤ì¤Þ¤»¤ó
+55 %s: %s
+56 %s
+57 ·Á¼°: jobs [ -l ]
+58 ¥¢¡¼¥®¥å¥á¥ó¥È¤Ï¥¸¥ç¥Ö¤«¥×¥í¥»¥¹ID¤Ç¤¹.
+59 ¥«¥ì¥ó¥È¤Îjob¤Ï¤¢¤ê¤Þ¤»¤ó
+60 Á°¤Îjob¤Ï¤¢¤ê¤Þ¤»¤ó
+61 ¥¸¥ç¥Ö¤¬¥Ñ¥¿¡¼¥ó¤Ë°ìÃפ·¤Þ¤»¤ó
+62 Fork¤Î¿¼¤µ¤¬ %d¤òĶ¤¨¤Þ¤·¤¿; ¤ª¤½¤é¤¯¥ë¡¼¥×¤Ç¤¹
+63 ¤³¤Îsubshell¤Ç¤Ï¥¸¥ç¥Ö¥³¥ó¥È¥í¡¼¥ë¤Ï»ÈÍѤǤ­¤Þ¤»¤ó
+64 sync¼ºÇÔ: ¥×¥í¥»¥¹ %d ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó
+65 %sÃæÃǤ·¤¿job¤¬»Ä¤Ã¤Æ¤¤¤Þ¤¹
+66 %s»ß¤Þ¤Ã¤¿job¤¬»Ä¤Ã¤Æ¤¤¤Þ¤¹
+67 ¾¤Î¥Ç¥£¥ì¥¯¥È¥ê¡¼¤Ï¤¢¤ê¤Þ¤»¤ó
+68 ¥Ç¥£¥ì¥¯¥È¥ê¡¼¥¹¥¿¥Ã¥¯¤Ï¶õ¤Ç¤¹
+69 ¥Ç¥£¥ì¥¯¥È¥ê¡¼Ì¾¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+70 ·Á¼°: %s [-%s]%s
+71 -h¥Õ¥é¥°ÍѤΥª¥Ú¥é¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó
+72 ¥í¥°¥¤¥ó¥·¥§¥ë¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó
+73 0¤Ç³ä¤ê»»¤·¤Þ¤·¤¿
+74 0¤Ç³ä¤ê»»¤·¤Þ¤·¤¿(;¤ê·×»»)
+75 ´Ö°ã¤Ã¤¿¥ª¥×¥·¥ç¥óñ°Ì: "%s"¤Î°ÕÌ£¤Ï?
+76 ¥í¥°¥¤¥ó¥·¥§¥ë¤Ê¤Î¤ÇÃæÃǤǤ­¤Þ¤»¤ó
+77 %s¤È¤¤¤¦¥æ¡¼¥¶¡¼¤Ï¸ºß¤·¤Þ¤»¤ó
+78 $homeÊÑ¿ô¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó
+79 ·Á¼°: history [-%s] [# number of events]
+80 $, ! ¤â¤·¤¯¤Ï < ¤Ï $# ¤â¤·¤¯¤Ï $? ¤È°ì½ï¤Ë¤Ï»ÈÍѤǤ­¤Þ¤»¤ó
+81 ÊÑ¿ô̾¤Ë²þ¹Ô¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹
+82 * ¤Ï $# ¤â¤·¤¯¤Ï $? ¤È°ì½ï¤Ë¤Ï»ÈÍѤǤ­¤Þ¤»¤ó
+83 $?<digit> ¤â¤·¤¯¤Ï $#<digit> ¤Ï»ÈÍѤǤ­¤Þ¤»¤ó
+84 ÊÑ¿ô̾¤¬ÉÔÀµ¤Ç¤¹
+85 ÊÑ¿ô¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ë²þ¹Ô¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹
+86 ³ÈÄ¥¥Ð¥Ã¥Õ¥¡¡¼¥ª¡¼¥Ð¡¼¥Õ¥í¡¼
+87 ÊÑ¿ô¹½Ê¸?
+88 ´Ö°ã¤Ã¤¿ ! ·Á¼°¤Ç¤¹
+89 Á°¤ÎÃÖ´¹¤Ï¤¢¤ê¤Þ¤»¤ó
+90 ÉÔÀµ¤ÊÃÖ´¹¤Ç¤¹
+91 º¸¥µ¥¤¥É¤¬¤¢¤ê¤Þ¤»¤ó
+92 ±¦¥µ¥¤¥É¤¬Ä¹²á¤®¤Þ¤¹
+93 ´Ö°ã¤Ã¤¿ ! ½¤¾þ»Ò¤Ç¤¹: %c
+94 ½¤¾þ»Ò¤Î¼ºÇԤǤ¹
+95 ÃÖ´¹¥Ð¥Ã¥Õ¥¡¤¬¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¤·¤Þ¤·¤¿
+96 ´Ö°ã¤Ã¤¿ ! °ú¿ô¤Î¥»¥ì¥¯¥¿¡¼¤Ç¤¹
+97 Á°¤Î¸¡º÷·ë²Ì¤Ï¤¢¤ê¤Þ¤»¤ó
+98 %s: ¥¤¥Ù¥ó¥È¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó
+99 ")"¤¬Â¿¤¹¤®¤Þ¤¹
+100 "("¤¬Â¿¤¹¤®¤Þ¤¹
+101 ( ¤Î¾ì½ê¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+102 ¥ê¥À¥¤¥ì¥¯¥È¸þ¤±¤Î̾Á°¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+103 Û£Ëæ¤Ê¥ê¥À¥¤¥ì¥¯¥È½ÐÎϤǤ¹
+104 () ¤ËÂФ·¤Æ << ¤Ï»È¤¨¤Þ¤»¤ó
+105 Û£Ëæ¤Ê¥ê¥À¥¤¥ì¥¯¥ÈÆþÎϤǤ¹
+106 () ¤Î¾ì½ê¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+107 ¥¨¥¤¥ê¥¢¥¹¤Î̵¸Â¥ë¡¼¥×¤¬È¯À¸¤·¤Þ¤·¤¿
+108 ÊÑ¿ô"$watch"¤¬ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó
+109 ¥¹¥±¥¸¥å¡¼¥ë¤Ë¥¤¥Ù¥ó¥È¤ÏÀßÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó
+110 ·Á¼°: sched -<item#>.\nUsage: sched [+]hh:mm <command>
+111 ¥¹¥±¥¸¥å¡¼¥ë¤µ¤ì¤¿¥¤¥Ù¥ó¥È¤Ï¤¢¤ê¤Þ¤»¤ó
+112 ¼Â¹Ô¤Ç¤­¤ë¥³¥Þ¥ó¥É¤Ï¤¢¤ê¤Þ¤»¤ó
+113 ÉÔÀµ¤Ê¥¤¥Ù¥ó¥È³«»Ï»þ´Ö¤Ç¤¹
+114 am/pm»ØÄê¤ÇÁêÂÐŪ¤Ê»þ´Ö»ØÄê¤Ï¤Ç¤­¤Þ¤»¤ó
+115 termcap¤Îʸ»úÎóÎΰèÉÔ­¤Ç¤¹
+116 ·Á¼°: settc %s [yes|no]
+117 ÃΤé¤Ê¤¤capability `%s'
+118 ÃΤé¤Ê¤¤termcap¥Ñ¥é¥á¥¿ `%%%c'
+119 `%s' ¸þ¤±¤Î¥¢¡¼¥®¥å¥á¥ó¥È¤¬Â¿²á¤®¤Þ¤¹ (%d)
+120 `%s' ¤Ï %d ¥¢¡¼¥®¥å¥á¥ó¥È¤¬É¬ÍפǤ¹
+121 ·Á¼°: echotc [-v|-s] [<capability> [<args>]]
+122 %s: %s. ´Ö°ã¤Ã¤¿¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ç¤¹
+123 !# ¥Ò¥¹¥È¥ê¡¼¤Î¥ë¡¼¥×
+124 ÉÔ´°Á´¤Ê¥Õ¥¡¥¤¥ë¥Á¥§¥Ã¥¯¤Ç¤¹
+125 ¥»¥ì¥¯¥¿¡¼ ¥ª¡¼¥Ð¡¼¥Õ¥í¡¼
+126 ÉÔÌÀ¥ª¥×¥·¥ç¥ó: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX -Dname[=value] ] [ argument ... ]
+127 ÉÔÌÀ¥ª¥×¥·¥ç¥ó: `-%s'\nUsage: %s [ -bcdefFilmnqstvVxX ] [ argument ... ]
+128 ÉÔÌÀ¥ª¥×¥·¥ç¥ó: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX ] [ argument ... ]
+129 \nÉÔÀµ¤ÊÊä´°: "%s"
+130 \nÉÔÀµ¤Ê %s: '%c'
+131 \n'%c' ( %s ¤Î¸å¤í)¤Ï´Ö°ã¤Ã¤¿¥»¥Ñ¥ì¡¼¥¿¡¼¤Ç¤¹ "%s"
+132 \nÉÔ´°Á´¤Ê %s: "%s"
+133 -m¥Õ¥é¥°ÍѤΥª¥Ú¥é¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó
+134 ·Á¼°: unlimit [-fh] [limits]
+135 $%S ¤ÏÆɼèÀìÍѤǤ¹
+136 job¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó
+137 ÉÔÌÀ¤ÎcolorlsÀßÄê¤Ç¤¹ `%c%c'
diff --git a/contrib/tcsh/nls/ja/set10 b/contrib/tcsh/nls/ja/set10
new file mode 100644
index 0000000..d76ae2e
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.1 1998/09/03 22:04:03 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: ¥³¥Þ¥ó¥É¤¬ÉÔÀµ¤Ç¤¹ '%s'.\n
+2 setpath: '%s' ¥³¥Þ¥ó¥É¤Î¤¿¤á¤Î¥¢¡¼¥®¥å¥á¥ó¥È¤¬ÉÔ­¤·¤Æ¤¤¤Þ¤¹.\n
+3 setpath: ¥Ñ¥¹ '%s'¤ÎÆâÍƤ¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹\n
+4 setpath: %s ¤¬ %s ¤ÎÃæ¤Ë¤¢¤ê¤Þ¤»¤ó\n
+5 setpath: %d ¤Ï %s ¤ÎÃæ¤Ç¤Ï,´Ö°ã¤Ã¤¿°ÌÃ֤Ǥ¹\n
diff --git a/contrib/tcsh/nls/ja/set11 b/contrib/tcsh/nls/ja/set11
new file mode 100644
index 0000000..1e619ba
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.1 1998/09/03 22:04:04 christos Exp $
+$ sh.c
+$set 11
+1 ·Ù¹ð: tty¤Ë¥¢¥¯¥»¥¹¤¬¤Ç¤­¤Þ¤»¤ó (%s).\n
+2 ¤³¤Î¤¿¤á¤Ë,¤³¤Îshell¤Ë¤Ï¥¸¥ç¥Ö¥³¥ó¥È¥í¡¼¥ë¤¬¤¢¤ê¤Þ¤»¤ó.\n
+3 ¤¢¤Ê¤¿¤Ë %d Ä̤Υ᡼¥ë¥á¥Ã¥»¡¼¥¸¤¬¤¢¤ê¤Þ¤¹.\n
+4 ¤¢¤Ê¤¿¤Ë %d Ä̤Υ᡼¥ë¥á¥Ã¥»¡¼¥¸¤¬ %s ¤Ë¤¢¤ê¤Þ¤¹.\n
+5 ¤¢¤Ê¤¿¤Ë %s¥á¡¼¥ë¤¬¤¢¤ê¤Þ¤¹.\n
+6 ¿·¤·¤¤
+7 ¤¢¤Ê¤¿¤Ë %s¥á¡¼¥ë¤¬ %s¤Ë¤¢¤ê¤Þ¤¹.\n
diff --git a/contrib/tcsh/nls/ja/set12 b/contrib/tcsh/nls/ja/set12
new file mode 100644
index 0000000..ef990cf
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.1 1998/09/03 22:04:05 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: "%s"¤«¤é¤Î¼Â¹Ô¤ò»î¤·¤Þ¤¹\n
diff --git a/contrib/tcsh/nls/ja/set13 b/contrib/tcsh/nls/ja/set13
new file mode 100644
index 0000000..3f06441
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set13
@@ -0,0 +1,12 @@
+$ $Id: set13,v 1.1 1998/09/03 22:04:05 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d ¤Î¥Ï¥Ã¥·¥åÎΰè (%d ¥Ó¥Ã¥ÈËè)\n
+3 ¥Ç¥Ð¥Ã¥°¥Þ¥¹¥¯ = 0x%08x\n
+4 %d À®¸ù, %d ¼ºÇÔ, %d%%\n
+5 %S: ¥·¥§¥ë¤ËÆþ¤Ã¤Æ¤¤¤ë¥³¥Þ¥ó¥É¤Ç¤¹.\n
+6 %S: ¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó\n
+7 where: / ¤¬Æþ¤Ã¤Æ¤¤¤ë¾ì¹ç¤Ï»È¤¨¤Þ¤»¤ó\n
+8 %S ¤Ï¥¨¥¤¥ê¥¢¥¹ÄêµÁ¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹:
+9 %S ¤Ï¥·¥§¥ë¤ËÆþ¤Ã¤Æ¤¤¤Þ¤¹.\n
diff --git a/contrib/tcsh/nls/ja/set15 b/contrib/tcsh/nls/ja/set15
new file mode 100644
index 0000000..d0049cc
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.1 1998/09/03 22:04:06 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: %s ½ÐÍè¤Þ¤»¤ó. (%s À©¸Â)\n
+2 ²ò½ü
+3 ÀßÄê
+4 \040¥Ï¡¼¥É
diff --git a/contrib/tcsh/nls/ja/set16 b/contrib/tcsh/nls/ja/set16
new file mode 100644
index 0000000..644e388
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.2 1998/09/09 10:30:26 christos Exp $
+$ sh.lex.c
+$set 16
+1 tty pgrp ¤ò %d ¤«¤é %d¤ËºÆÀßÄꤷ¤Þ¤¹\n
+2 \n¥í¥°¥¢¥¦¥È¤Ï"logout"¤ò»ÈÍѤ·¤Æ²¼¤µ¤¤\n
+3 \n%s½ªÎ»¤Ï"exit"¤ò»ÈÍѤ·¤Æ²¼¤µ¤¤\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 ´Ö°ã¤Ã¤¿ seek ¥¿¥¤¥×¤Ç¤¹ %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/ja/set17 b/contrib/tcsh/nls/ja/set17
new file mode 100644
index 0000000..fe1550e
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set17
@@ -0,0 +1,15 @@
+$ $Id: set17,v 1.1 1998/09/03 22:04:08 christos Exp $
+$ sh.proc.c
+$set 17
+1 ¾ã³²: ¥Ð¥Ã¥°¥°¥é¥¦¥ó¥É¥¸¥ç¥Ö¤òÂԤäƤ¤¤Þ¤¹\n
+2 %d¤Ç½ªÎ»¤·¤Þ¤·¤¿\n
+3 ¾ã³²: ¥×¥í¥»¥¹¥Õ¥é¥Ã¥·¥å¤¬ÆóÅټ¹Ԥµ¤ì¤Þ¤·¤¿
+4 ¼Â¹ÔÃæ¤Ç¤¹
+5 ¥·¥°¥Ê¥ë
+6 %-d¤Ç½ªÎ»¤·¤Þ¤·¤¿
+7 ½ªÎ»
+8 ¾ã³²: ¾õÂÖ=%-9o
+9 \040(core¤ò½ÐÎϤ·¤Þ¤·¤¿)
+10 \040(wd:
+12 %S: ¤¹¤Ç¤ËÃæÃǤ·¤Æ¤¤¤Þ¤¹\n
+13 %S: ¤¹¤Ç¤ËÄä»ß¤·¤Æ¤¤¤Þ¤¹\n
diff --git a/contrib/tcsh/nls/ja/set18 b/contrib/tcsh/nls/ja/set18
new file mode 100644
index 0000000..9f29795
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.1 1998/09/03 22:04:09 christos Exp $
+$ sh.set.c
+$set 18
+1 ·Ù¹ð: ÉÔ¼«Á³¤ËŤ¤ PATH ¤ÏÀÚ¤ê¼Î¤Æ¤é¤ì¤Þ¤¹\n
diff --git a/contrib/tcsh/nls/ja/set2 b/contrib/tcsh/nls/ja/set2
new file mode 100644
index 0000000..c1e5ea2
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set2
@@ -0,0 +1,94 @@
+$ $Id: set2,v 1.1 1998/09/03 22:04:10 christos Exp $
+$ Signal names
+$set 2
+1 ¥Ì¥ë¥·¥°¥Ê¥ë
+2 ¥Ï¥ó¥°¥¢¥Ã¥×
+3 ³ä¤ê¹þ¤ß
+4 ̾ȧ
+5 ÉÔÀµ¤Êµ¡³£¸ì¤ÎÌ¿Îá
+6 ¥È¥ì¡¼¥¹¡¦¥Ö¥ì¡¼¥¯¥Ý¥¤¥ó¥È¥È¥é¥Ã¥×
+7 ¥¢¥Ü¡¼¥È
+8 IOT¥È¥é¥Ã¥×
+9 ¥·¥¹¥Æ¥à¥¯¥é¥Ã¥·¥å²ÄǽÀ­Áý
+10 ¥¨¥é¡¼½ªÎ»
+11 ¥¨¥ß¥å¥ì¡¼¥·¥ç¥ó¥È¥é¥Ã¥×
+12 ±é»»Îã³°
+13 ¶¯À©½ªÎ»
+14 ¥æ¡¼¥¶¡¼¥·¥°¥Ê¥ë1
+15 ¥æ¡¼¥¶¡¼¥·¥°¥Ê¥ë2
+16 ¥»¥°¥á¥ó¥È¥¨¥é¡¼
+17 ¥Ð¥¹¥¨¥é¡¼
+18 ¥×¥í¥°¥é¥àÈÏ°Ï¥¨¥é¡¼
+19 ¥ª¥Ú¥é¥ó¥ÉÈÏ°Ï¥¨¥é¡¼
+20 ÉÔÀµ¥·¥¹¥Æ¥à¥³¡¼¥ë
+21 ¥Ñ¥¤¥×Ç˲õ
+22 ¥¢¥é¡¼¥à¥·¥°¥Ê¥ë
+23 ½ªÎ»
+24 »Ò¥×¥í¥»¥¹¤Î¾õÂÖÊѹ¹
+25 »Ò¥×¥í¥»¥¹»àË´
+26 Apollo¸ÂÄꥨ¥é¡¼
+27 »Ò¥×¥í¥»¥¹Ää»ß¤â¤·¤¯¤Ï½ªÎ»
+28 »Ò¥×¥í¥»¥¹½ªÎ»
+29 ÅŸ»°Û¾ï
+30 ¥ê¥½¡¼¥¹¾ÃÌÇ
+31 ¥Ö¥ì¡¼¥¯ (Ctrl-Break)
+32 Æþ½ÐÎÏ ²Äǽ¥·¥°¥Ê¥ë
+33 ÈóƱ´ü I/O (select)
+34 ¥½¥±¥Ã¥È¶ÛµÞÍ×µá
+35 ¿½Å¥¿¥¹¥¯wake-up
+36 ¿½Å¥¿¥¹¥¯kill
+37 FortranÈóƱ´üI/O½ªÎ»
+38 ¥ê¥«¥Ð¥ê
+39 ÉÔÀµ¤Ê¥á¥â¥ê¡¼¥¨¥é¡¼
+40 CPU »þ´ÖÀ©¸Â¥ª¡¼¥Ð¡¼
+41 ¥·¥¹¥Æ¥àÄä»ß ²ÄǽÀ­Áý
+42 ¥Þ¥¤¥¯¥í¥¿¥¹¥­¥ó¥° group-no wakeup ¥Õ¥é¥°ÀßÄê
+43 ¥¹¥ì¥Ã¥É¥¨¥é¡¼ - (cord -T ¤ò»ÈÍѤ·¤Æ¾ÜºÙ¾ðÊó¤ò»²¾È¤·¤Æ²¼¤µ¤¤)
+44 CRAY Y-MP ¥ì¥¸¥¹¥¿¥Ñ¥ê¥Æ¥£¡¼¥¨¥é¡¼
+45 ¾ðÊóÍ×µá
+46 ÃæÃÇ(¥·¥°¥Ê¥ë)
+47 Ää»ß(¥·¥°¥Ê¥ë)
+48 ̾̂
+49 Ää»ß
+50 ·Ñ³
+51 ÃæÃÇ(ttyÆþÎÏ)
+52 Ää»ß(ttyÆþÎÏ)
+53 ÃæÃÇ(tty½ÐÎÏ)
+54 Ää»ß(tty½ÐÎÏ)
+55 ¥¦¥£¥ó¥É¥¦¾õÂÖÊѹ¹
+56 ¥¦¥£¥ó¥É¥¦¥µ¥¤¥ºÊѹ¹
+57 ÅÅÏòóÀþ¾õÂÖÊѹ¹
+58 CPU»þ´ÖÀ©¸Â¥ª¡¼¥Ð¡¼
+59 ¥Õ¥¡¥¤¥ë¥µ¥¤¥ºÀ©¸Â¥ª¡¼¥Ð¡¼
+60 ²¾ÁÛ»þ´Ö¥¢¥é¡¼¥à
+61 ¥×¥í¥Õ¥¡¥¤¥ê¥ó¥°»þ´Ö¥¢¥é¡¼¥à
+62 DIL¥·¥°¥Ê¥ë
+63 ´Æ»ë²Äǽ¥¤¥Ù¥ó¥ÈȯÀ¸
+64 ¥×¥í¥»¥¹¤ÎLWPS¤¬¥Ö¥í¥Ã¥¯¤µ¤ì¤Þ¤·¤¿
+65 ÆÃÊÌ LWP ¥·¥°¥Ê¥ë
+66 ÆÃÊÌ CPR ¥·¥°¥Ê¥ë
+67 ÆÃÊÌ CPR ¥·¥°¥Ê¥ë
+68 Â裱 ¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+69 Â裲 ¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+70 Â裳 ¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+71 Â裴 ¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+72 Â裴 ºÇ½ª¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+73 Â裳 ºÇ½ª¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+74 Â裲 ºÇ½ª¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+75 ºÇ½ª¥ê¥¢¥ë¥¿¥¤¥à¥·¥°¥Ê¥ë
+76 LAN ÈóƱ´ü I/O
+77 PTY read/write ²Äǽ
+78 I/O ²ðÆþÍ×µá
+79 HFT ¥â¥Ë¥¿¡¼¥â¡¼¥ÉÉÕÍ¿
+80 HFT ¥â¥Ë¥¿¡¼¥â¡¼¥É¤Ërelinguish?¤¬É¬Í×
+81 HFT ¥µ¥¦¥ó¥É¥³¥ó¥È¥í¡¼¥ë´°Î»
+82 HFT ring buffer¤Ë¥Ç¡¼¥¿¤¢¤ê
+83 ¥×¥í¥»¥¹°Ü¹Ô
+84 Secure ¥¢¥Æ¥ó¥·¥ç¥ó¥­¡¼
+85 ºÆ¥¹¥±¥¸¥å¡¼¥ë
+86 ¥·¥°¥Ê¥ë SS$_DEBUG
+87 Í¥ÀèÅÙÊѹ¹
+88 ¿¿¥Ç¥Ã¥É¥í¥Ã¥¯¸¡½Ð
+89 ¿·¤·¤¤Ê¸»úÆþÎÏ
+90 ¥¹¥¿¥Ã¥¯À©¸Â¥ª¡¼¥Ð¡¼
+91 ̤»ÈÍÑ¥·¥°¥Ê¥ë
diff --git a/contrib/tcsh/nls/ja/set21 b/contrib/tcsh/nls/ja/set21
new file mode 100644
index 0000000..29ae51c
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.1 1998/09/03 22:04:10 christos Exp $
+$ tc.disc.c
+$set 21
+1 ¥í¡¼¥«¥ë¥­¥ã¥é¤ò¼èÆÀ¤Ç¤­¤Þ¤»¤ó.\n
+2 ¥í¡¼¥«¥ë¥­¥ã¥é¤òÀßÄê¤Ç¤­¤Þ¤»¤ó.\n
diff --git a/contrib/tcsh/nls/ja/set24 b/contrib/tcsh/nls/ja/set24
new file mode 100644
index 0000000..debb53f
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.1 1998/09/03 22:04:11 christos Exp $
+$ tc.sched.c
+$set 24
+1 kludge
diff --git a/contrib/tcsh/nls/ja/set29 b/contrib/tcsh/nls/ja/set29
new file mode 100644
index 0000000..b67a7c7
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.2 1999/05/11 13:08:30 christos Exp $
+$ tw.help.c
+$set 29
+1 %S ÍѤΥإë¥×¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó\n
diff --git a/contrib/tcsh/nls/ja/set30 b/contrib/tcsh/nls/ja/set30
new file mode 100644
index 0000000..d7ad9b2
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.1 1998/09/03 22:04:13 christos Exp $
+$ tw.parse.c
+$set 30
+1 ¥³¥Þ¥ó¥É³«»Ï %d\n
+2 ´°Î» %d
+3 ´°Î» %d %S\n
+4 %s: ÆâÉô¥Þ¥Ã¥Á¥¨¥é¡¼.\n
+5 items
+6 rows
+7 %d %s¤¢¤ê¤Þ¤¹. ¥ê¥¹¥È½ÐÎϤò¹Ô¤¤¤Þ¤¹¤«? [n/y]
+8 ɽ¼¨ = %d\n
+9 \ntcsh ÆâÉô¥¨¥é¡¼: ²¿¤òõ¤·¤Æ¤¤¤ë¤«Ê¬¤«¤é¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤Ã¤¿!\n
+10 ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó
+11 ¸«¤Ä¤«¤ê¤Þ¤»¤ó
+12 Æɤ߹þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó
+13 yY
diff --git a/contrib/tcsh/nls/ja/set5 b/contrib/tcsh/nls/ja/set5
new file mode 100644
index 0000000..d6d5e80
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.1 1998/09/03 22:04:14 christos Exp $
+$ ed.chared.c
+$set 5
+1 ¥·¥¹¥Æ¥àÉé²Ùɽ¼¨¤Ï»ÈÍѤǤ­¤Þ¤»¤ó\n
diff --git a/contrib/tcsh/nls/ja/set6 b/contrib/tcsh/nls/ja/set6
new file mode 100644
index 0000000..66dcbf6
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.1 1998/09/03 22:04:14 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ¥¨¥é¡¼: ÉÔÀµ¤Ê¥­¡¼¤«¤é¤Î¥³¥Þ¥ó¥É 0%o\r\n
+2 ¤Ï¤¤\n
+3 ÊÔ½¸\n
+4 ̾ȧ\n
+5 ¤¤¤¤¤¨\n
+6 °ìÃפ·¤¿¥³¥Þ¥ó¥É¤¬¤¢¤ê¤Þ¤»¤ó\n
+7 Û£Ëæ¤Ê¥³¥Þ¥ó¥É¤Ç¤¹\n
+8 *** ¥¨¥Ç¥£¥¿¡¼¤ÎÃ×̿Ū¥¨¥é¡¼ ***\r\n\n
diff --git a/contrib/tcsh/nls/ja/set8 b/contrib/tcsh/nls/ja/set8
new file mode 100644
index 0000000..b23588f
--- /dev/null
+++ b/contrib/tcsh/nls/ja/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.1 1998/09/03 22:04:16 christos Exp $
+$ ed.term.c
+$set 8
+1 ÉÔÌÀ¤Êswitch
+2 ÉÔÀµ¤Ê¥¢¡¼¥®¥å¥á¥ó¥È¤Ç¤¹
diff --git a/contrib/tcsh/nls/spanish/set1 b/contrib/tcsh/nls/spanish/set1
new file mode 100644
index 0000000..8c1b663
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set1
@@ -0,0 +1,140 @@
+$ $Id: set1,v 1.2 1998/06/27 12:28:02 christos Exp $
+$ Mensajes de Error
+$set 1
+1 Error de sintaxis
+2 %s no está permitido
+3 Palabra demasiado larga
+4 $< línea demasiado larga
+5 No hay fichero para $0
+6 Modificador [] incompleto
+7 $ expansión debe terminar antes de ]
+8 Modificador erróneo : en $ (%c)
+9 Error de índice
+10 Número erróneamente formado
+11 No hay más palabras
+12 Falta nombre de fichero
+13 Error interno de glob
+14 Comando no encontrado
+15 Demasiado pocos argumentos
+16 Demasiados argumentos
+17 Es demasiado peligroso crear un alias para eso
+18 `If' vacío
+19 `Then' incorrecto
+20 Las palabras no están entre paréntesis
+21 No se encuentra %s
+22 Máscara incorrecta
+23 No existe límite de ese tipo
+24 Argumento demasiado grande
+25 Factor de escala incorrecto o desconocido
+26 Variable indefinida
+27 La pila de directorios no es tan profunda
+28 Mal número de señal
+29 Señal desconocida; `kill -l' lista las señales
+30 El nombre de la variable debe comenzar con una letra
+31 El nombre de la variable es demasiado grande
+32 El nombre de la variable debe contener caracteres alfanuméricos
+33 No hay control de trabajos en esta shell
+34 Sintaxis de la expresión
+35 No está el directorio personal
+36 No se puede cambiar al directorio personal
+37 Comando nulo inválido
+38 Expresion carece de asignación
+39 Operador desconocido
+40 Ambiguo
+41 %s: Archivo existente
+42 El argumento para `-c' debe terminar en una barra invertida
+43 Interumpido
+44 Índice fuera del rango válido
+45 Sobrepasada la capacidad de la línea
+46 No existe ese trabajo
+47 No se puede desde una terminal
+48 No se encuentra en bucle while/foreach
+49 No hay más procesos
+50 No existe correspondencia
+51 Falta %c
+52 No se ha hallado correspondencia con %c
+53 Memoria insuficiente
+54 No se puede crear la tubería
+55 %s: %s
+56 %s
+57 Uso: jobs [ -l ]
+58 Los argumentos deben ser trabajos o identificadores de proceso
+59 No hay trabajo en curso
+60 No hay trabajo previo
+61 No hay trabajo que corresponda con este patrón
+62 Llamadas a `fork' entrelazadas > %d; puede ser un bucle `...`
+63 No se puede gestionar trabajos en sub-shells
+64 Fallo de sincronización: No se encuentra el proceso %d
+65 %shay trabajos interrumpidos
+66 %shay trabajos parados
+67 No hay más directorios
+68 Pila de directorios vacía
+69 Directorio erróneo
+70 Uso: %s [-%s]%s
+71 `-h' necesita operandos
+72 No es un shell de ingreso
+73 División por 0
+74 Módulo por 0
+75 Error de escala: Seguro que era "%s"?
+76 No se puede suspender un shell de ingreso (aún)
+77 Usuario desconocido: %s
+78 La variable $home no está definida
+79 Uso: history [-%s] [# número de comandos]
+80 No esta permitido el uso de $, ! o < con $# o $?
+81 Nombre de variable incluye un retorno de carro
+82 No esta permitido el uso de * con $# o $?
+83 No esta permitido usar $?<dígito> o $#<dígito>
+84 Nombre de variable ilegal
+85 Retorno de carro en el índice de variables
+86 Desborde en el buffer de expansión
+87 Sintaxis de variable
+88 Forma ! incorrecta
+89 No existe sustituto previo
+90 Sustituto erróneo
+91 No existe `lado izquierdo' previo
+92 Valor de asignación demasiado largo
+93 Modificador de ! incorrecto: %c
+94 Error de modificador
+95 Desborde el el buffer de sustitución
+96 Selector de argumento de ! erróneo
+97 No existe búsqueda previa
+98 %s: No se encuentra el comando
+99 Demasiados `)'
+100 Demasiados `('
+101 Colocación de `(' incorrecta
+102 Falta el nombre de la redirección
+103 Redirección de salida ambigua
+104 No se puede usar << entre paréntesis
+105 Redirección de entrada ambigua
+106 Colocación de paréntesis errónea
+107 Lazo en los `alias'
+108 La variable $watch no ha sido definida
+109 No hay comandos programados
+110 Uso: sched -<item#>.\nUso: sched [+]hh:mm <comando>
+111 No hay tantos comandos programados
+112 No hay ningún comando a ejecutar
+113 Tiempo de ejecución del comando incorrecto
+114 Tiempo relativo inconsistente con am/pm
+115 Se ha agotado el espacio para cadenas termcap
+116 Uso: settc %s [yes|no]
+117 Característica `%s' desconocida
+118 Parámetro termcap `%%%c' desconocido
+119 Demasiados argumentos para `%s' (%d)
+120 `%s' requiere %d argumentos
+121 Uso: echotc [-v|-s] [<característica> [<args>]]
+122 %s: %s. Arquitectura errónea
+123 !# Lazo en el historial
+124 Consulta de archivo incorrecta
+125 Desborde en el selector
+126 Opción desconocida: `-%s'\nUso: %s [ -bcdefilmnqstvVxX -Dnombre[=valor] ] [ argumento ... ]
+127 Opción desconocida: `-%s'\nUso: %s [ -bcdefFilmnqstvVxX ] [ argumento ... ]
+128 Opción desconocida: `-%s'\nUso: %s [ -bcdefilmnqstvVxX ] [ argumento ... ]
+129 \nModo de terminación automática inválido: "%s"
+130 \nInválido %s: '%c'
+131 \nFalta el separador '%c' después %s "%s"
+132 \n%s incompleto: "%s"
+133 `-m' no necesita operandos
+134 Uso: unlimit [-fh] [límites]
+135 $%S es de sólo-lectura
+136 No existe ese trabajo
+137 Unknown colorls variable `%c%c'
diff --git a/contrib/tcsh/nls/spanish/set10 b/contrib/tcsh/nls/spanish/set10
new file mode 100644
index 0000000..867c794
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set10
@@ -0,0 +1,8 @@
+$ $Id: set10,v 1.1 1998/04/08 17:59:51 christos Exp $
+$ ma.setp.c
+$set 10
+1 setpath: comando '%s' incorrecto.\n
+2 setpath: insuficientes argumentos para el comando '%s'.\n
+3 setpath: falta el valor en la ruta '%s'\n
+4 setpath: no se encuentra %s en %s\n
+5 setpath: %d posición inválida en %s\n
diff --git a/contrib/tcsh/nls/spanish/set11 b/contrib/tcsh/nls/spanish/set11
new file mode 100644
index 0000000..d54fddc
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set11
@@ -0,0 +1,10 @@
+$ $Id: set11,v 1.1 1998/04/08 17:59:52 christos Exp $
+$ sh.c
+$set 11
+1 Aviso: no se puede acceder a la tty (%s).\n
+2 Por ello no hay control de trabajos en esta shell.\n
+3 Tiene %d mensajes de correo.\n
+4 Tiene %d mensajes de correo en %s.\n
+5 Tiene correo%s.\n
+6 nuevo
+7 Tiene correo%s en %s.\n
diff --git a/contrib/tcsh/nls/spanish/set12 b/contrib/tcsh/nls/spanish/set12
new file mode 100644
index 0000000..5e24d3b
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set12
@@ -0,0 +1,4 @@
+$ $Id: set12,v 1.1 1998/04/08 17:59:53 christos Exp $
+$ sh.dir.c
+$set 12
+1 %s: Tratando de empezar desde "%s"\n
diff --git a/contrib/tcsh/nls/spanish/set13 b/contrib/tcsh/nls/spanish/set13
new file mode 100644
index 0000000..5a49329
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set13
@@ -0,0 +1,13 @@
+$ $Id: set13,v 1.1 1998/04/08 17:59:54 christos Exp $
+$ sh.exec.c
+$set 13
+1 hash=%-4d dir=%-2d prog=%s\n
+2 %d grupos de hash de %d bits cada uno\n
+3 máscara de depurado = 0x%08x\n
+4 %d aciertos, %d fallos, %d%%\n
+5 %S: comando integrado en la shell.\n
+6 %S: Comando inexistente.\n
+7 donde: / en el comando carece de sentido\n
+8 %S es un alias para
+9 %S es un comando integrado en la shell\n
+10 fallo de hash:
diff --git a/contrib/tcsh/nls/spanish/set14 b/contrib/tcsh/nls/spanish/set14
new file mode 100644
index 0000000..62db4cd
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set14
@@ -0,0 +1,6 @@
+$ $Id: set14,v 1.1 1998/04/08 17:59:55 christos Exp $
+$ sh.file.c
+$set 14
+1 \n¡¡Qué asco!! ¡¡Hay demasiados %s!!\n
+2 nombres en el archivo de claves
+3 archivos
diff --git a/contrib/tcsh/nls/spanish/set15 b/contrib/tcsh/nls/spanish/set15
new file mode 100644
index 0000000..7408500
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set15
@@ -0,0 +1,7 @@
+$ $Id: set15,v 1.1 1998/04/08 17:59:56 christos Exp $
+$ sh.func.c
+$set 15
+1 %s: %s: No se puede %s el límite %s\n
+2 quitar
+3 poner
+4 \040(hard-limit)
diff --git a/contrib/tcsh/nls/spanish/set16 b/contrib/tcsh/nls/spanish/set16
new file mode 100644
index 0000000..58f8d5b
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set16
@@ -0,0 +1,13 @@
+$ $Id: set16,v 1.1 1998/04/08 17:59:56 christos Exp $
+$ sh.lex.c
+$set 16
+1 Se ha reinicializado el grupo de procesos de las terminales de %d a %d\n
+2 \nUtilice "logout" para desconectarse.\n
+3 \nUtilice "exit" para salir de %s.\n
+4 seek to eval %x %x\n
+5 seek to alias %x %x\n
+6 seek to file %x\n
+7 Tipo de seek erróneo %d\n
+8 tell eval %x %x\n
+9 tell alias %x %x\n
+10 tell file %x\n
diff --git a/contrib/tcsh/nls/spanish/set17 b/contrib/tcsh/nls/spanish/set17
new file mode 100644
index 0000000..e9e7427
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set17
@@ -0,0 +1,16 @@
+$ $Id: set17,v 1.1 1998/04/08 17:59:57 christos Exp $
+$ sh.proc.c
+$set 17
+1 BUG: ¡en espera de un trabajo en segundo plano!\n
+2 Finalizó %d\n
+3 BUG: Se ha aplicado "flush" al proceso por segunda vez
+4 Ejecutando
+5 Señal
+6 Finalizado %-25d
+7 Fin
+8 BUG: status=%-9o
+9 \040(se ha creado un `core')
+10 \040(dt:
+11 dt actual:
+12 %S: Ya ha sido suspendido\n
+13 %S: Ya ha sido parado\n
diff --git a/contrib/tcsh/nls/spanish/set18 b/contrib/tcsh/nls/spanish/set18
new file mode 100644
index 0000000..6db6343
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set18
@@ -0,0 +1,4 @@
+$ $Id: set18,v 1.1 1998/04/08 17:59:58 christos Exp $
+$ sh.set.c
+$set 18
+1 Aviso: PATH de tamaño ridículo ha sido truncado\n
diff --git a/contrib/tcsh/nls/spanish/set19 b/contrib/tcsh/nls/spanish/set19
new file mode 100644
index 0000000..8424412
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set19
@@ -0,0 +1,15 @@
+$ $Id: set19,v 1.1 1998/04/08 17:59:59 christos Exp $
+$ tc.alloc.c
+$set 19
+1 nbytes=%d: Se ha agotado la memoria\n
+2 Se ha llamado a free(%lx) antes de asignar nada.
+3 free(%lx) por encima del límite superior de la memoria.
+4 free(%lx) por debajo del límite inferior de la memoria.
+5 free(%lx) bloque erróneo.
+6 free(%lx) chequeo de rango erróneo.
+7 free(%lx) índice de bloque erróneo.
+8 %s asignación actual de memoria:\nfree:\t
+9 \nusada:\t
+10 \n\tTotal en uso: %d, total libre: %d\n
+11 \tSe ha asignado memoria de 0x%lx a 0x%lx. Límite superior real en 0x%lx\n
+12 Se ha asignado memoria de 0x%lx a 0x%lx (%ld).\n
diff --git a/contrib/tcsh/nls/spanish/set2 b/contrib/tcsh/nls/spanish/set2
new file mode 100644
index 0000000..a8761d0
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set2
@@ -0,0 +1,92 @@
+$ $Id: set2,v 1.1 1998/04/08 17:59:59 christos Exp $
+$ Nombres de señales
+$set 2
+1 Señal nula
+2 Colgar
+3 Interrumpir
+4 Salir
+5 Instrucción ilegal
+6 trap Trace/BPT
+7 Abortar
+8 trap IOT
+9 Caída del sistema inminente
+10 Salida con error
+11 trap EMT
+12 Excepción de punto flotante
+13 Terminado
+14 Señal de usuario 1
+15 Señal de usuario 2
+16 Error de segmentación
+17 Error de bus
+18 Error de rango de programa
+19 Error de rango de operando
+20 Llamada del sistema errónea
+21 Tubería rota
+22 Despertador
+23 Terminado
+24 Cambio de estado en el hijo
+25 Muerte del hijo
+26 Fallo específico de Apollo
+27 El hijo ha parado o terminado
+28 Hijo ha terminado
+29 Fallo de alimentación
+30 Recurso perdido
+31 Break (Ctrl-Break)
+32 Posible señal de entrada/salida
+33 E/S asíncrona (select)
+34 Condición urgente en el canal de E/S
+35 Despertar mutiltarea
+36 Finalización multitarea
+37 Final de E/S asíncrona Fortran
+38 Recuperación
+39 Error incorregible de memoria
+40 Excedido el tiempo de CPU
+41 Bajada del sistema inminente
+42 Grupo micro-tarea-no se ha activado la bandera de despertar
+43 Error de hilo de ejecución - (use cord -T para información detallada)
+44 Error de paridad de registro CRAY Y-MP
+45 Petición de información
+46 Suspendido (señal)
+47 Parado (señal)
+48 Suspendido
+49 Parado
+50 Continúa
+51 Suspendido (entrada tty)
+52 Parado (entrada tty)
+53 Suspendido (salida tty)
+54 Parado (salida tty)
+55 Modificado el estado de la ventana
+56 Modificado el tamaño de la ventana
+57 Modificado el estado del teléfono
+58 Excedido el tiempo de CPU
+59 Excedido el límite del tamaño de archivo
+60 Señal de temporizador virtual
+61 Perfilando la alarma de temporizador
+62 Señal DIL
+63 Ha tenido lugar un evento interrogable
+64 Los lwps del proceso están bloqueados
+65 Señal LWP especial
+66 Señal CPR especial
+67 Señal CPR especial
+68 Primera señal de tiempo real
+69 Segunda señal de tiempo real
+70 Tercera señal de tiempo real
+71 Cuarta señal de tiempo real
+72 Cuarta señal por la cola de tiempo real
+73 Antepenúltima señal de tiempo real
+74 Penúltima señal de tiempo real
+75 Última señal de tiempo real
+76 E/S asíncrona LAN
+77 Lectura/escritura PTY disponible
+78 Intervención E/S requerida
+79 Otorgado modo monitor HFT
+80 Se debería abandonar el modo monitor HFT
+81 Se ha completado el control de sonido HFT
+82 Hay datos en el buffer circular HFT
+83 Migrar proceso
+84 Tecla de atención asegurada
+85 Reprogramación
+86 Señalar SS$_DEBUG
+87 Prioridad cambiada
+88 Bloqueo real detectado
+89 Nuevo carácter de entrada
diff --git a/contrib/tcsh/nls/spanish/set20 b/contrib/tcsh/nls/spanish/set20
new file mode 100644
index 0000000..8359f1d
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set20
@@ -0,0 +1,42 @@
+$ $Id: set20,v 1.1 1998/04/08 18:00:01 christos Exp $
+$ tc.bind.c
+$set 20
+1 Nombre de tecla no válido `%S'\n
+2 Nombre de tecla incorrecto: %S\n
+3 Nombre de comando incorrecto: %S\n
+4 Especificador de tecla incorrecto %S\n
+5 Especificada la cadena nula\n
+6 Definiciones de teclas estándar\n
+7 Definiciones de teclas alternativas\n
+8 Definiciones Multi-carácter\n
+9 Definiciones de las teclas de flechas\n
+10 %-15s-> indefinida\n
+11 ¡¡¡BUG!!! %s no tiene definición asociada.\n
+12 Uso: bindkey [opciones] [--] [TECLA [COMANDO]]\n
+13 -a lista o define TECLA en un mapa de teclas alternativo\n
+14 -b acepta definiciones de teclas simbólicas\n
+15 -s asume que COMANDO es una cadena ha de imprimir literalmente\n
+16 -c interpreta COMANDO como comando interno o externo\n
+17 -v usa las definiciones del editor vi\n
+18 -e usa las definiciones del editor vi\n
+19 -d usa las definiciones del editor por defecto\n
+20 -l lista los comandos del editor y sus descripciones\n
+21 -r elimina la definición asociada a TECLA\n
+22 -k interpreta TECLA como nombre simbólico de tecla de flecha\n
+23 -- fuerza "break" en el procesamiento de opciones\n
+24 -u (o cualquier opción no válida) este mensaje\n
+25 Sin TECLA o COMANDO, imprime todas las asociaciones de teclas\n
+26 Sin COMANDO, imprime la asociación de TECLA.\n
+27 especificación de tecla inválida -- cadena nula\n
+28 especificación de tecla inválida -- cadena vacía\n
+29 Especificación de tecla de función inválida. No se permite una tecla nula\n
+30 especificación de tecla inválida -- número hexadecimal incorrecto\n
+31 especificación de tecla inválida -- número octal incorrecto\n
+32 especificación de tecla inválida -- número decimal incorrecto\n
+33 Especificación de tecla de función incorrecta.\n
+34 No se permite una tecla nula\n
+35 especificación de tecla inválida -- nombre desconocido "%S"\n
+36 uso: bind [TECLA | COMANDO TECLA | "emacs" | "vi" | "-a"]\n
+37 función no válida
+38 %s\t\tno está definida\n
+
diff --git a/contrib/tcsh/nls/spanish/set21 b/contrib/tcsh/nls/spanish/set21
new file mode 100644
index 0000000..5e4a734
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set21
@@ -0,0 +1,5 @@
+$ $Id: set21,v 1.1 1998/04/08 18:00:02 christos Exp $
+$ tc.disc.c
+$set 21
+1 No he podido leer los caracteres locales.\n
+2 No he podido establecer los caracteres locales.\n
diff --git a/contrib/tcsh/nls/spanish/set22 b/contrib/tcsh/nls/spanish/set22
new file mode 100644
index 0000000..268e307
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set22
@@ -0,0 +1,17 @@
+$ $Id: set22,v 1.1 1998/04/08 18:00:03 christos Exp $
+$ tc.func.c
+$set 22
+1 %S: \t es un alias de
+2 \nClave incorrecta para %s\n
+3 Alias erróneo de 'precmd' borrado.\n
+4 Alias erróneo de 'cwdcmd' borrado.\n
+5 Alias erróneo de 'beepcmd' borrado.\n
+6 Alias erróneo de 'periodic' borrado.\n
+7 analizando la línea de comandos\n
+8 ¿Realmente quiere borrar todos los archivos? [n/s]
+9 ¡Anulado el borrado de los archivos!\n
+10 ahora, la línea de comandos es:\n
+11 analizando la línea de comandos\n
+12 en una de las listas\n
+13 ahora, la línea de comandos es:\n
+14 sSyY
diff --git a/contrib/tcsh/nls/spanish/set23 b/contrib/tcsh/nls/spanish/set23
new file mode 100644
index 0000000..08eb8df
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set23
@@ -0,0 +1,34 @@
+$ $Id: set23,v 1.1 1998/04/08 18:00:03 christos Exp $
+$ tc.os.c
+$set 23
+1 Nombre de cpu/máquina incorrecto
+2 Ruta hasta máquina demasiado grande
+3 desconocida
+4 máquina: %s\n
+5 %d: No he encontrado esa máquina\n
+6 setlocal: %s: %s\n
+7 No he encontrado esa máquina
+8 Está atrapado en un universo que nunca creo
+9 Getwarp falló
+10 Warp inválido
+11 Setwarp falló
+12 Universo ilegal
+13 Error Desconocido: %d
+14 nombre_sis: %s\n
+15 nombre_nodo: %s\n
+16 release: %s\n
+17 versión: %s\n
+18 máquina: %s\n
+19 getwd: No puedo abrir ".." (%s)
+20 getwd: No puedo cambiar a ".." (%s)
+21 getwd: Error de lectura en ".." (%s)
+22 getwd: No puedo volver a "." (%s)
+23 getwd: No puedo ejecutar stat de "/" (%s)
+24 getwd: No puedo ejecutar stat de "." (%s)
+25 getwd: No puedo ejecutar stat de "%s" (%s)
+26 getwd: No puedo abrir el directorio "%s" (%s)
+27 getwd: No puedo encontrar "." en ".." (%s)
+28 Tipo de sistema inválido
+29 No se ha fijado el tipo de sistema
+30 Demasiados argumentos
+31 Argumento inválido
diff --git a/contrib/tcsh/nls/spanish/set24 b/contrib/tcsh/nls/spanish/set24
new file mode 100644
index 0000000..9da94ee
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set24
@@ -0,0 +1,4 @@
+$ $Id: set24,v 1.1 1998/04/08 18:00:04 christos Exp $
+$ tc.sched.c
+$set 24
+1 chapuza
diff --git a/contrib/tcsh/nls/spanish/set25 b/contrib/tcsh/nls/spanish/set25
new file mode 100644
index 0000000..2b96300
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set25
@@ -0,0 +1,6 @@
+$ $Id: set25,v 1.1 1998/04/08 18:00:05 christos Exp $
+$ tc.sig.c
+$set 25
+1 nuestro wait %d\n
+2 error: bsd_signal(%d) señal fuera de rango\n
+3 error: bsd_signal(%d) - sigaction ha fallado, errno %d\n
diff --git a/contrib/tcsh/nls/spanish/set26 b/contrib/tcsh/nls/spanish/set26
new file mode 100644
index 0000000..a4fed2c
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set26
@@ -0,0 +1,15 @@
+$ $Id: set26,v 1.1 1998/04/08 18:00:06 christos Exp $
+$ tc.who.c
+$set 26
+1 No se puede completar stat %s. Por favor, ejecute "unset watch".\n
+2 No se puede abrir %s. Por favor, ejecute "unset watch".\n
+3 ¡BUG! El último elemento no es whotail!\n
+4 hacia atrás:
+5 ¡BUG! El primer elemento no es whohead!\n
+6 nuevo: %s/%s\n
+7 %n tiene %a %l de %m.
+8 %n tiene %a %l.
+9 conectado
+10 desconectado
+11 sustituido %s en
+12 local
diff --git a/contrib/tcsh/nls/spanish/set27 b/contrib/tcsh/nls/spanish/set27
new file mode 100644
index 0000000..8cc991e
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set27
@@ -0,0 +1,8 @@
+$ $Id: set27,v 1.1 1998/04/08 18:00:07 christos Exp $
+$ tw.comp.c
+$set 27
+1 comando
+2 separador
+3 patrón
+4 rango
+5 modo de terminación automática
diff --git a/contrib/tcsh/nls/spanish/set29 b/contrib/tcsh/nls/spanish/set29
new file mode 100644
index 0000000..712d6b5
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set29
@@ -0,0 +1,4 @@
+$ $Id: set29,v 1.1 1998/04/08 18:00:07 christos Exp $
+$ tw.help.c
+$set 29
+1 No hay archivo de ayuda sobre %S\n
diff --git a/contrib/tcsh/nls/spanish/set3 b/contrib/tcsh/nls/spanish/set3
new file mode 100644
index 0000000..be8016a
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set3
@@ -0,0 +1,117 @@
+$ $Id: set3,v 1.1 1998/04/08 18:00:08 christos Exp $
+$ Descripción de las funciones de edición
+$set 3
+1 Retroceder un carácter
+2 Borrar el carácter detrás del cursor
+3 Cortar desde el comienzo de la palabra hasta el cursor - se guarda en el buffer
+4 Cortar desde el comienzo de la línea hasta el cursor - se guarda en el buffer
+5 Ir hasta el comienzo de la palabra
+6 Ir hasta el comienzo de la línea
+7 Convertir en mayúsculas los caracteres desde el cursor hasta el final de la palabra
+8 Vi: cambiar a mayúsculas o minúsculas el carácter bajo el cursor y avanza una posición
+9 Vi: cambia hasta el final de la línea
+10 Borra la pantalla y coloca la línea actual al comienzo
+11 Completa la palabra
+12 Avanza mediante `Tab' por los ficheros
+13 Retrocede mediante `Tab' por los ficheros
+14 Completa la palabra ignorando los modos programables
+15 Copia la palabra hasta el cursor
+16 Copia el área entre la marca y el cursor al buffer
+17 Expande a aquella palabra para la que esto es un prefijo
+18 Borra el carácter bajo el cursor
+19 Borra el carácter bajo el cursor o señala el fin de archivo en un archivo vacío
+20 Borra el carácter bajo el cursor o lista posibles finales si está al final de una línea
+21 Borra el carácter bajo el cursor, lista posibles finales o marca final de archivo
+22 Corta del cursor al final de la palabra - se guarda en el buffer
+23 Se suma al argumento si ha arrancado o introduce el dígito
+24 Dígito al comienzo del argumento
+25 Ir al final de la línea de historia
+26 Convierte en minúsculas los caracteres desde el cursor al final de la palabra
+27 Indica el fin de archivo
+28 Mover el cursor hasta el final de línea
+29 Intercambia el cursor y la marca
+30 Expande los comodines de nombre de archivo
+31 Expande los escapes del historial
+32 Expande los escapes del historial en una línea
+33 Expande variables
+34 Avanza un carácter
+35 Avanza hasta el final de la palabra
+36 Intercambia los dos caracteres delante del cursor
+37 Busca hacia atrás en el historial una línea que comience igual que la actual
+38 Busca hacia delante una línea que comience igual que la actual
+39 Inserta el último ítem del comando previo
+40 Búsqueda incremental hacia deleante
+41 Búsqueda incremental hacia atrás
+42 Borra la línea
+43 Corta hasta el final de la línea y guarda la información en el buffer
+44 Corta el área de la marca al cursor y guarda la información en el buffer
+45 Corta la línea completa y la guarda en el buffer
+46 Lista opciones para completar
+47 Lista opciones para completar ignorando los modos programables
+48 Lista los nombres de archivos que concuerdan con el comodín
+49 Lista opciones para completar o indica el final de línea si es una línea vacía
+50 Imprime la media de carga y es estado de este proceso
+51 Expande los escapes del historial e inserta un espacio
+52 Ejecuta el comando
+53 Expande rutas, eliminando cualquier `.' y `..' que encuentre al comienzo
+54 Expande comandos a la ruta o el alias resultante
+55 Cambia de modo de inserción a sobre escritura y vice versa
+56 Añade el octavo bit al siguiente carácter introducido
+57 Añade el siguiente carácter sin modificar a la línea
+58 Reimprime todo
+59 Reinicia un editor parado
+60 Busca ayuda sobre el comando actual
+61 Se añade este carácter a la línea
+62 Este carácter es el primero de una secuencia de caracteres
+63 Establece una marca bajo el cursor
+64 Corrige la ortografía de esta palabra
+65 Corrige la ortografía de la línea completa
+66 Envía el carácter a la terminal en modo `cooked'
+67 Cambia entre los modos literal y léxico en esta línea de historial
+68 Intercambia el carácter a la izquierda con el que está bajo el cursor
+69 Intercambia los dos caracteres que preceden al cursor
+70 Carácter tty para suspensión retrasada
+71 Carácter tty para `flush' de salida
+72 Carácter tty para interrupción
+73 Carácter tty para salida
+74 Carácter tty para suspensión
+75 Carácter tty para permitir salida
+76 Carácter tty para impedir salida
+77 Indica carácter no asignado
+78 Argumento Emacs universal (argumento por 4)
+79 Ir a la línea anterior
+80 Convierte en mayúsculas los caracteres desde el cursor al final de la palabra
+81 Vi: ir al comienzo de la siguiente palabra
+82 Vi: entrar en modo de inserción después el cursor
+83 Vi: entrar en modo de inserción al final de la línea
+84 Vi: cambia a mayúsculas o minúsculas el carácter bajo el cursor y avanza una posición
+85 Vi: cambiar el comando de prefijo
+86 Vi: cambiar hasta el final de la línea
+87 Entrar en modo vi (usa asignación de teclas alternativa)
+88 Vi: modo de comando completa la palabra
+89 Vi: ir al carácter previo (retroceso)
+90 Vi: borrar el comando de prefijo
+91 Vi: ir hasta el final de la palabra delimitado por espacios
+92 Vi: ir hasta el final de la palabra
+93 Vi: retroceder al carácter especificado
+94 Vi: avanzar al carácter especificado
+95 Vi: retrocede hasta el carácter especificado
+96 Vi: avanzar hasta el carácter especificado
+97 Entrar en modo de inserción `vi'
+98 Entrar en modo de inserción `vi' al comienzo de la línea
+99 Vi: repetir la búsqueda de carácter en la misma dirección
+100 Vi: repetir la búsqueda de carácter en la dirección contraria
+101 Vi: repetir la búsqueda en la misma dirección
+102 Vi: repetir la búsqueda en la dirección contraria
+103 Vi: reemplazar el carácter bajo el cursor por el que se introduzca
+104 Vi: modo de reemplazo
+105 Vi: buscar en el historial hacia atrás
+106 Vi: buscar en el historial hacia adelante
+107 Vi: reemplazar el carácter bajo el cursor cambiando a modo inserción
+108 Vi: reemplazar la línea completa
+109 Vi: ir a la palabra anterior
+110 Vi: ir a la palabra siguiente
+111 Vi: deshacer el cambio anterior
+112 Vi: ir al comienzo de la línea
+113 Ejecutar `which' para el comando actual
+114 Pegar el buffer donde el cursor
diff --git a/contrib/tcsh/nls/spanish/set30 b/contrib/tcsh/nls/spanish/set30
new file mode 100644
index 0000000..d89e708
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set30
@@ -0,0 +1,16 @@
+$ $Id: set30,v 1.1 1998/04/08 18:00:09 christos Exp $
+$ tw.parse.c
+$set 30
+1 comienzo_de_comando %d\n
+2 completar %d
+3 completar %d %S\n
+4 %s: Error interno de concordancia.\n
+5 ítems
+6 filas
+7 Existen %d %s, ¿listarlas de todos modos? [n/s]
+8 buscando = %d\n
+9 \nerror interno de tcsh: ¡No sé lo que busco!\n
+10 no es un directorio
+11 no he encontrado nada
+12 ilegible
+13 sSyY
diff --git a/contrib/tcsh/nls/spanish/set31 b/contrib/tcsh/nls/spanish/set31
new file mode 100644
index 0000000..00cb295
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set31
@@ -0,0 +1,7 @@
+$ $Id: set31,v 1.1 1998/04/08 18:00:10 christos Exp $
+$ vms.termcap.c
+$set 31
+1 No se puede abrir TERMCAP: [%s]\n
+2 No se puede abrir %s.\n
+3 He encontrado %s en %s.\n
+4 No he encontrado ninguna concordancia con %s en el archivo %s\n
diff --git a/contrib/tcsh/nls/spanish/set4 b/contrib/tcsh/nls/spanish/set4
new file mode 100644
index 0000000..04c1766
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set4
@@ -0,0 +1,45 @@
+$ $Id: set4,v 1.1 1998/04/08 18:00:11 christos Exp $
+$ cadenas de Termcap
+$set 4
+1 añade una línea vacía
+2 timbre audible
+3 borra hasta abajo
+4 borra hasta el final de la línea
+5 cursor hasta posición horizontal
+6 borra la pantalla
+7 borra un carácter
+8 borra una línea
+9 entra en modo de borrado
+10 termina modo de borrado
+11 termina modo de inserción
+12 cursor de línea de estado
+13 cursor en posición inicial
+14 insertar carácter
+15 entra en modo de inserción
+16 inserta carácter de relleno
+17 envía cursor hacia abajo
+18 envía cursor hacia la izquierda
+19 envía cursor hacia la derecha
+20 envía cursor hacia arriba
+21 comienza negrita
+22 fin de atributos
+23 espacio no destructivo
+24 fin de énfasis
+25 comienzo de énfasis
+26 cursor a la línea de estado
+27 mueve el cursor hacia arriba una línea
+28 comienza subrayado
+29 fin de subrayado
+30 timbre visible
+31 borra múltiples caracteres
+32 mueve el cursor varias líneas hacia abajo
+33 inserta múltiples caracteres
+34 mueve el cursor varias líneas hacia la izquierda
+35 mueve el cursor varias líneas hacia la derecha
+36 mueve el cursor varias líneas hacia arriba
+37 Tiene márgenes automáticos
+38 Puede usar tabuladores físicos
+39 Número de líneas
+40 Número de columnas
+41 Tiene teclas alternativa
+42 Ignorando retorno de carro en el margen derecho
diff --git a/contrib/tcsh/nls/spanish/set5 b/contrib/tcsh/nls/spanish/set5
new file mode 100644
index 0000000..ba7a18f
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set5
@@ -0,0 +1,4 @@
+$ $Id: set5,v 1.1 1998/04/08 18:00:11 christos Exp $
+$ ed.chared.c
+$set 5
+1 No está disponible la carga media\n
diff --git a/contrib/tcsh/nls/spanish/set6 b/contrib/tcsh/nls/spanish/set6
new file mode 100644
index 0000000..134eceb
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set6
@@ -0,0 +1,11 @@
+$ $Id: set6,v 1.1 1998/04/08 18:00:12 christos Exp $
+$ ed.inputl.c
+$set 6
+1 ERROR: comando ilegal asignado a la tecla 0%o\r\n
+2 sí\n
+3 editar\n
+4 abortar\n
+5 no\n
+6 No se ha encontrado comando que corresponda\n
+7 Comando ambiguo\n
+8 *** ERROR fatal del editor ***\r\n\n
diff --git a/contrib/tcsh/nls/spanish/set7 b/contrib/tcsh/nls/spanish/set7
new file mode 100644
index 0000000..7fe22f5
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set7
@@ -0,0 +1,30 @@
+$ $Id: set7,v 1.1 1998/04/08 18:00:13 christos Exp $
+$ ed.screen.c
+$set 7
+1 \n\tTcsh cree que su terminal tiene las\n
+2 \tsiguientes características:\n\n
+3 \tTiene %d columnas y %d líneas\n
+4 \t%s tecla `Alt'\n
+5 Tiene
+6 No tiene
+7 \t%spuede usar tabuladores\n
+8 No
+9 \t%s márgenes automáticos\n
+10 Tiene
+11 No tiene
+12 \t%s márgenes mágicos\n
+13 (vacío)
+14 sí
+15 no
+16 ERROR: no se puede suprimir\r\n
+17 DeleteChars: num es ridículo: %d\r\n
+18 ERROR: no se puede insertar\r\n
+19 StartInsert: num es ridículo: %d\r\n
+20 %s: No se puede abrir /etc/termcap.\n
+21 %s: No hay ninguna entrada correspondiente a la terminal tipo "%s"\n
+22 %s: usando los valores de una terminal tonta.\n
+23 %s: Aviso: Su terminal no puede moverse hacia arriba.\n
+24 La edición de líneas largas puede resultar extraña.\n
+25 no se puede borrar hasta el final de línea.\n
+26 no se puede borrar el siguiente carácter.\n
+27 no se puede insertar un carácter.\n
diff --git a/contrib/tcsh/nls/spanish/set8 b/contrib/tcsh/nls/spanish/set8
new file mode 100644
index 0000000..b997466
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set8
@@ -0,0 +1,5 @@
+$ $Id: set8,v 1.1 1998/04/08 18:00:14 christos Exp $
+$ ed.term.c
+$set 8
+1 Interruptor desconocido
+2 Argumento inválido
diff --git a/contrib/tcsh/nls/spanish/set9 b/contrib/tcsh/nls/spanish/set9
new file mode 100644
index 0000000..14e4629
--- /dev/null
+++ b/contrib/tcsh/nls/spanish/set9
@@ -0,0 +1,12 @@
+$ $Id: set9,v 1.1 1998/04/08 18:00:14 christos Exp $
+$ ed.xmap.c
+$set 9
+1 AddXkey: No se permite una tecla extendida nula.\n
+2 AddXkey: No se permite comando introducción de secuencia (sequence-lead-in)\n
+3 DeleteXkey: No se permite una tecla extendida nula.\n
+4 Tecla de extendida indefinida "%S"\n
+5 Algunas teclas extendidas son demasiado grandes para el buffer de impresión interno
+6 Enumerate: ¡¡BUG!! Se ha pasado un puntero nulo!\n
+7 no hay entrada
+8 Falta algo a continuación: %c\n
+9 Una constante octal no cabe en un carácter.\n
diff --git a/contrib/tcsh/patchlevel.h b/contrib/tcsh/patchlevel.h
new file mode 100644
index 0000000..a9874bc5
--- /dev/null
+++ b/contrib/tcsh/patchlevel.h
@@ -0,0 +1,14 @@
+/* $Header: /src/pub/tcsh/patchlevel.h,v 3.121 1999/08/16 20:06:57 christos Exp $ */
+/*
+ * patchlevel.h: Our life story.
+ */
+#ifndef _h_patchlevel
+#define _h_patchlevel
+
+#define ORIGIN "Astron"
+#define REV 6
+#define VERS 9
+#define PATCHLEVEL 0
+#define DATE "1999-08-16"
+
+#endif /* _h_patchlevel */
diff --git a/contrib/tcsh/pathnames.h b/contrib/tcsh/pathnames.h
new file mode 100644
index 0000000..3b29072
--- /dev/null
+++ b/contrib/tcsh/pathnames.h
@@ -0,0 +1,169 @@
+/* $Header: /src/pub/tcsh/pathnames.h,v 3.17 1998/09/13 13:51:03 christos Exp $ */
+/*
+ * pathnames.h: Location of things to find
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_pathnames
+#define _h_pathnames
+
+#ifdef BSD4_4
+# include <paths.h>
+#endif
+
+#if defined(CMUCS) && !defined(_PATH_LOCAL)
+# define _PATH_LOCAL "/usr/cs/bin"
+#endif /* CMUCS && !_PATH_LOCAL */
+
+#if defined(convex) || defined(stellar) || defined(INTEL)
+# ifndef _PATH_DOTLOGIN
+# define _PATH_DOTLOGIN "/etc/login"
+# endif /* !_PATH_DOTLOGIN */
+# ifndef _PATH_DOTLOGOUT
+# define _PATH_DOTLOGOUT "/etc/logout"
+# endif /* !_PATH_DOTLOGOUT */
+# ifndef _PATH_DOTCSHRC
+# define _PATH_DOTCSHRC "/etc/cshrc"
+# endif /* !_PATH_DOTCSHRC */
+#endif /* convex || stellar || INTEL */
+
+#ifdef NeXT
+# ifndef _PATH_DOTLOGIN
+# define _PATH_DOTLOGIN "/etc/login.std"
+# endif /* !_PATH_DOTLOGIN */
+# ifndef _PATH_DOTLOGOUT
+# define _PATH_DOTLOGOUT "/etc/logout.std"
+# endif /* !_PATH_DOTLOGOUT */
+# ifndef _PATH_DOTCSHRC
+# define _PATH_DOTCSHRC "/etc/cshrc.std"
+# endif /* !_PATH_DOTCSHRC */
+#endif /* NeXT */
+
+/* for sunos5. */
+#if ((defined(sun) || defined(__sun__)) && (SYSVREL == 4))
+# ifndef _PATH_DOTLOGIN
+# define _PATH_DOTLOGIN "/etc/.login"
+# endif /* !_PATH_DOTLOGIN */
+# ifndef _PATH_DOTLOGOUT
+# define _PATH_DOTLOGOUT "/etc/.logout"
+# endif /* !_PATH_DOTLOGOUT */
+# ifndef _PATH_DOTCSHRC
+# define _PATH_DOTCSHRC "/etc/.cshrc"
+# endif /* !_PATH_DOTCSHRC */
+#endif /* sun & SVR4 */
+
+#if defined(sgi) || defined(OREO) || defined(cray) || defined(AMIX) || defined(CDC)
+# ifndef _PATH_DOTLOGIN
+# define _PATH_DOTLOGIN "/etc/cshrc"
+# endif /* !_PATH_DOTLOGIN */
+#endif /* sgi || OREO || cray || AMIX || CDC */
+
+#if (defined(_CRAYCOM) || defined(Lynx)) && !defined(_PATH_TCSHELL)
+# define _PATH_TCSHELL "/bin/tcsh" /* 1st class shell */
+#endif /* _CRAYCOM && !_PATH_TCSHELL */
+
+#if defined(_MINIX) && !defined(_PATH_TCSHELL)
+# define _PATH_TCSHELL "/local/bin/tcsh" /* use ram disk */
+#endif /* _MINIX && !_PATH_TCSHELL */
+
+#if defined(__EMX__) && !defined(_PATH_DEVNULL)
+# define _PATH_DEVNULL "nul"
+#endif /* __EMX__ && !_PATH_DEVNULL */
+
+#ifndef _PATH_LOCAL
+# define _PATH_LOCAL "/usr/local/bin"
+#endif /* !_PATH_LOCAL */
+
+#ifndef _PATH_USRBIN
+# define _PATH_USRBIN "/usr/bin"
+#endif /* !_PATH_USRBIN */
+
+#ifndef _PATH_USRUCB
+# define _PATH_USRUCB "/usr/ucb"
+#endif /* !_PATH_USRUCB */
+
+#ifndef _PATH_USRBSD
+# define _PATH_USRBSD "/usr/bsd"
+#endif /* !_PATH_USRBSD */
+
+#ifndef _PATH_BIN
+# define _PATH_BIN "/bin"
+#endif /* !_PATH_BIN */
+
+#ifndef _PATH_DOTCSHRC
+# define _PATH_DOTCSHRC "/etc/csh.cshrc"
+#endif /* !_PATH_DOTCSHRC */
+
+#ifndef _PATH_DOTLOGIN
+# define _PATH_DOTLOGIN "/etc/csh.login"
+#endif /* !_PATH_DOTLOGIN */
+
+#ifndef _PATH_DOTLOGOUT
+# define _PATH_DOTLOGOUT "/etc/csh.logout"
+#endif /* !_PATH_DOTLOGOUT */
+
+#ifndef _PATH_DEVNULL
+# define _PATH_DEVNULL "/dev/null"
+#endif /* !_PATH_DEVNULL */
+
+#ifndef _PATH_BSHELL
+# define _PATH_BSHELL "/bin/sh"
+#endif /* !_PATH_BSHELL */
+
+#ifndef _PATH_CSHELL
+# define _PATH_CSHELL "/bin/csh"
+#endif /* !_PATH_CSHELL */
+
+#ifndef _PATH_TCSHELL
+# define _PATH_TCSHELL "/usr/local/bin/tcsh"
+#endif /* !_PATH_TCSHELL */
+
+#ifndef _PATH_BIN_LOGIN
+# define _PATH_BIN_LOGIN "/bin/login"
+#endif /* !_PATH_BIN_LOGIN */
+
+#ifndef _PATH_USRBIN_LOGIN
+# define _PATH_USRBIN_LOGIN "/usr/bin/login"
+#endif /* !_PATH_USRBIN_LOGIN */
+
+#ifndef _PATH_BIN_NEWGRP
+# define _PATH_BIN_NEWGRP "/bin/newgrp"
+#endif /* _PATH_BIN_NEWGRP */
+
+#ifndef _PATH_USRBIN_NEWGRP
+# define _PATH_USRBIN_NEWGRP "/usr/bin/newgrp"
+#endif /* _PATH_USRBIN_NEWGRP */
+
+
+
+#endif /* _h_pathnames */
diff --git a/contrib/tcsh/sh.c b/contrib/tcsh/sh.c
new file mode 100644
index 0000000..8703dc8
--- /dev/null
+++ b/contrib/tcsh/sh.c
@@ -0,0 +1,2441 @@
+/* $Header: /src/pub/tcsh/sh.c,v 3.89 1999/08/13 16:32:51 christos Exp $ */
+/*
+ * sh.c: Main shell routines
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define EXTERN /* Intern */
+#include "sh.h"
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+RCSID("$Id: sh.c,v 3.89 1999/08/13 16:32:51 christos Exp $")
+
+#include "tc.h"
+#include "ed.h"
+#include "tw.h"
+
+extern bool MapsAreInited;
+extern bool NLSMapsAreInited;
+extern bool NoNLSRebind;
+
+/*
+ * C Shell
+ *
+ * Bill Joy, UC Berkeley, California, USA
+ * October 1978, May 1980
+ *
+ * Jim Kulp, IIASA, Laxenburg, Austria
+ * April 1980
+ *
+ * Filename recognition added:
+ * Ken Greer, Ind. Consultant, Palo Alto CA
+ * October 1983.
+ *
+ * Karl Kleinpaste, Computer Consoles, Inc.
+ * Added precmd, periodic/tperiod, prompt changes,
+ * directory stack hack, and login watch.
+ * Sometime March 1983 - Feb 1984.
+ *
+ * Added scheduled commands, including the "sched" command,
+ * plus the call to sched_run near the precmd et al
+ * routines.
+ * Upgraded scheduled events for running events while
+ * sitting idle at command input.
+ *
+ * Paul Placeway, Ohio State
+ * added stuff for running with twenex/inputl 9 Oct 1984.
+ *
+ * ported to Apple Unix (TM) (OREO) 26 -- 29 Jun 1987
+ */
+
+jmp_buf_t reslab INIT_ZERO_STRUCT;
+
+static const char tcshstr[] = "tcsh";
+#ifdef WINNT
+static const char tcshstr_nt[] = "tcsh.exe";
+#endif /* WINNT */
+
+signalfun_t parintr = 0; /* Parents interrupt catch */
+signalfun_t parterm = 0; /* Parents terminate catch */
+
+#ifdef TESLA
+int do_logout = 0;
+#endif /* TESLA */
+
+
+bool use_fork = 0; /* use fork() instead of vfork()? */
+
+/*
+ * Magic pointer values. Used to specify other invalid conditions aside
+ * from null.
+ */
+static Char INVCHAR;
+Char *INVPTR = &INVCHAR;
+Char **INVPPTR = &INVPTR;
+
+static int nofile = 0;
+static bool reenter = 0;
+static bool nverbose = 0;
+static bool nexececho = 0;
+static bool quitit = 0;
+static bool rdirs = 0;
+bool fast = 0;
+static bool batch = 0;
+static bool mflag = 0;
+static bool prompt = 1;
+static int enterhist = 0;
+bool tellwhat = 0;
+time_t t_period;
+Char *ffile = NULL;
+bool dolzero = 0;
+int insource = 0;
+static time_t chktim; /* Time mail last checked */
+char *progname;
+int tcsh;
+extern char **environ;
+
+/*
+ * This preserves the input state of the shell. It is used by
+ * st_save and st_restore to manupulate shell state.
+ */
+struct saved_state {
+ int insource;
+ int SHIN;
+ int intty;
+ struct whyle *whyles;
+ Char *gointr;
+ Char *arginp;
+ Char *evalp;
+ Char **evalvec;
+ Char *alvecp;
+ Char **alvec;
+ int onelflg;
+ bool enterhist;
+ Char **argv;
+ Char HIST;
+ bool cantell;
+ struct Bin B;
+ /* These keep signal state and setjump state */
+#ifdef BSDSIGS
+ sigmask_t mask;
+#endif
+ jmp_buf_t oldexit;
+ int reenter;
+};
+
+static int srccat __P((Char *, Char *));
+static int srcfile __P((char *, bool, int, Char **));
+static sigret_t phup __P((int));
+static void srcunit __P((int, bool, int, Char **));
+static void mailchk __P((void));
+#ifndef _PATH_DEFPATH
+static Char **defaultpath __P((void));
+#endif
+static void record __P((void));
+static void st_save __P((struct saved_state *, int, int,
+ Char **, Char **));
+static void st_restore __P((struct saved_state *, Char **));
+
+ int main __P((int, char **));
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register Char *cp;
+#ifdef AUTOLOGOUT
+ register Char *cp2;
+#endif
+ register char *tcp, *ttyn;
+ register int f;
+ register char **tempv;
+
+#ifdef BSDSIGS
+ sigvec_t osv;
+#endif /* BSDSIGS */
+
+#ifdef WINNT
+ nt_init();
+#endif /* WINNT */
+#if defined(NLS_CATALOGS) && defined(LC_MESSAGES)
+ (void) setlocale(LC_MESSAGES, "");
+#endif /* NLS_CATALOGS && LC_MESSAGES */
+
+#ifdef NLS
+# ifdef LC_CTYPE
+ (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
+# endif /* LC_CTYPE */
+#endif /* NLS */
+
+ nlsinit();
+
+#ifdef MALLOC_TRACE
+ mal_setstatsfile(fdopen(dup2(open("/tmp/tcsh.trace",
+ O_WRONLY|O_CREAT, 0666), 25), "w"));
+ mal_trace(1);
+#endif /* MALLOC_TRACE */
+
+#if !(defined(BSDTIMES) || defined(_SEQUENT_)) && defined(POSIX)
+# ifdef _SC_CLK_TCK
+ clk_tck = (clock_t) sysconf(_SC_CLK_TCK);
+# else /* ! _SC_CLK_TCK */
+# ifdef CLK_TCK
+ clk_tck = CLK_TCK;
+# else /* !CLK_TCK */
+ clk_tck = HZ;
+# endif /* CLK_TCK */
+# endif /* _SC_CLK_TCK */
+#endif /* !BSDTIMES && POSIX */
+
+ settimes(); /* Immed. estab. timing base */
+#ifdef TESLA
+ do_logout = 0;
+#endif /* TESLA */
+
+ /*
+ * Make sure we have 0, 1, 2 open
+ * Otherwise `` jobs will not work... (From knaff@poly.polytechnique.fr)
+ */
+ {
+ do
+ if ((f = open(_PATH_DEVNULL, O_RDONLY)) == -1 &&
+ (f = open("/", O_RDONLY)) == -1)
+ exit(1);
+ while (f < 3);
+ (void) close(f);
+ }
+
+ osinit(); /* Os dependent initialization */
+
+
+ {
+ char *t;
+
+ t = strrchr(argv[0], '/');
+#ifdef WINNT
+ {
+ char *s = strrchr(argv[0], '\\');
+ if (s)
+ t = s;
+ }
+#endif /* WINNT */
+ t = t ? t + 1 : argv[0];
+ if (*t == '-') t++;
+ progname = strsave((t && *t) ? t : tcshstr); /* never want a null */
+ tcsh = strcmp(progname, tcshstr) == 0;
+ }
+
+ /*
+ * Initialize non constant strings
+ */
+#ifdef _PATH_BSHELL
+ STR_BSHELL = SAVE(_PATH_BSHELL);
+#endif
+#ifdef _PATH_TCSHELL
+ STR_SHELLPATH = SAVE(_PATH_TCSHELL);
+#else
+# ifdef _PATH_CSHELL
+ STR_SHELLPATH = SAVE(_PATH_CSHELL);
+# endif
+#endif
+ STR_environ = blk2short(environ);
+ environ = short2blk(STR_environ); /* So that we can free it */
+ STR_WORD_CHARS = SAVE(WORD_CHARS);
+
+ HIST = '!';
+ HISTSUB = '^';
+ PRCH = '>';
+ PRCHROOT = '#';
+ word_chars = STR_WORD_CHARS;
+ bslash_quote = 0; /* PWP: do tcsh-style backslash quoting? */
+
+ /* Default history size to 100 */
+ set(STRhistory, SAVE("100"), VAR_READWRITE);
+
+ tempv = argv;
+ ffile = SAVE(tempv[0]);
+ dolzero = 0;
+ if (eq(ffile, STRaout)) /* A.out's are quittable */
+ quitit = 1;
+ uid = getuid();
+ gid = getgid();
+ euid = geteuid();
+ egid = getegid();
+#if defined(OREO) || defined(DT_SUPPORT)
+ /*
+ * We are a login shell if: 1. we were invoked as -<something> with
+ * optional arguments 2. or we were invoked only with the -l flag
+ */
+ loginsh = (**tempv == '-') || (argc == 2 &&
+ tempv[1][0] == '-' && tempv[1][1] == 'l' &&
+ tempv[1][2] == '\0');
+#else
+ /*
+ * We are a login shell if: 1. we were invoked as -<something> and we had
+ * no arguments 2. or we were invoked only with the -l flag
+ */
+ loginsh = (**tempv == '-' && argc == 1) || (argc == 2 &&
+ tempv[1][0] == '-' && tempv[1][1] == 'l' &&
+ tempv[1][2] == '\0');
+#endif
+
+#ifdef _VMS_POSIX
+ /* No better way to find if we are a login shell */
+ if (!loginsh) {
+ loginsh = (argc == 1 && getppid() == 1);
+ **tempv = '-'; /* Avoid giving VMS an acidic stomach */
+ }
+#endif /* _VMS_POSIX */
+
+ if (loginsh && **tempv != '-') {
+ /*
+ * Mangle the argv space
+ */
+ tempv[1][0] = '\0';
+ tempv[1][1] = '\0';
+ tempv[1] = NULL;
+ for (tcp = *tempv; *tcp++;)
+ continue;
+ for (tcp--; tcp >= *tempv; tcp--)
+ tcp[1] = tcp[0];
+ *++tcp = '-';
+ argc--;
+ }
+ if (loginsh) {
+ (void) time(&chktim);
+ set(STRloginsh, Strsave(STRNULL), VAR_READWRITE);
+ }
+
+ AsciiOnly = 1;
+ NoNLSRebind = getenv("NOREBIND") != NULL;
+#ifdef NLS
+# ifdef SETLOCALEBUG
+ dont_free = 1;
+# endif /* SETLOCALEBUG */
+ (void) setlocale(LC_ALL, "");
+# ifdef LC_COLLATE
+ (void) setlocale(LC_COLLATE, "");
+# endif
+# ifdef SETLOCALEBUG
+ dont_free = 0;
+# endif /* SETLOCALEBUG */
+# ifdef STRCOLLBUG
+ fix_strcoll_bug();
+# endif /* STRCOLLBUG */
+
+ {
+ int k;
+
+ for (k = 0200; k <= 0377 && !Isprint(k); k++)
+ continue;
+ AsciiOnly = k > 0377;
+ }
+#else
+ AsciiOnly = getenv("LANG") == NULL && getenv("LC_CTYPE") == NULL;
+#endif /* NLS */
+ if (MapsAreInited && !NLSMapsAreInited)
+ ed_InitNLSMaps();
+ ResetArrowKeys();
+
+ /*
+ * Initialize for periodic command intervals. Also, initialize the dummy
+ * tty list for login-watch.
+ */
+ (void) time(&t_period);
+#ifndef HAVENOUTMP
+ initwatch();
+#endif /* !HAVENOUTMP */
+
+#if defined(alliant)
+ /*
+ * From: Jim Pace <jdp@research.att.com>
+ * tcsh does not work properly on the alliants through an rlogin session.
+ * The shell generally hangs. Also, reference to the controlling terminal
+ * does not work ( ie: echo foo > /dev/tty ).
+ *
+ * A security feature was added to rlogind affecting FX/80's Concentrix
+ * from revision 5.5.xx upwards (through 5.7 where this fix was implemented)
+ * This security change also affects the FX/2800 series.
+ * The security change to rlogind requires the process group of an rlogin
+ * session become disassociated with the tty in rlogind.
+ *
+ * The changes needed are:
+ * 1. set the process group
+ * 2. reenable the control terminal
+ */
+ if (loginsh && isatty(SHIN)) {
+ ttyn = (char *) ttyname(SHIN);
+ (void) close(SHIN);
+ SHIN = open(ttyn, O_RDWR);
+ shpgrp = getpid();
+ (void) ioctl (SHIN, TIOCSPGRP, (ioctl_t) &shpgrp);
+ (void) setpgid(0, shpgrp);
+ }
+#endif /* alliant */
+
+ /*
+ * Move the descriptors to safe places. The variable didfds is 0 while we
+ * have only FSH* to work with. When didfds is true, we have 0,1,2 and
+ * prefer to use these.
+ */
+ initdesc();
+
+ /*
+ * Get and set the tty now
+ */
+ if ((ttyn = ttyname(SHIN)) != NULL) {
+ /*
+ * Could use rindex to get rid of other possible path components, but
+ * hpux preserves the subdirectory /pty/ when storing the tty name in
+ * utmp, so we keep it too.
+ */
+ if (strncmp(ttyn, "/dev/", 5) == 0)
+ set(STRtty, cp = SAVE(ttyn + 5), VAR_READWRITE);
+ else
+ set(STRtty, cp = SAVE(ttyn), VAR_READWRITE);
+ }
+ else
+ set(STRtty, cp = SAVE(""), VAR_READWRITE);
+ /*
+ * Initialize the shell variables. ARGV and PROMPT are initialized later.
+ * STATUS is also munged in several places. CHILD is munged when
+ * forking/waiting
+ */
+
+ /*
+ * 7-10-87 Paul Placeway autologout should be set ONLY on login shells and
+ * on shells running as root. Out of these, autologout should NOT be set
+ * for any psudo-terminals (this catches most window systems) and not for
+ * any terminal running X windows.
+ *
+ * At Ohio State, we have had problems with a user having his X session
+ * drop out from under him (on a Sun) because the shell in his master
+ * xterm timed out and exited.
+ *
+ * Really, this should be done with a program external to the shell, that
+ * watches for no activity (and NO running programs, such as dump) on a
+ * terminal for a long peroid of time, and then SIGHUPS the shell on that
+ * terminal.
+ *
+ * bugfix by Rich Salz <rsalz@PINEAPPLE.BBN.COM>: For root rsh things
+ * allways first check to see if loginsh or really root, then do things
+ * with ttyname()
+ *
+ * Also by Jean-Francois Lamy <lamy%ai.toronto.edu@RELAY.CS.NET>: check the
+ * value of cp before using it! ("root can rsh too")
+ *
+ * PWP: keep the nested ifs; the order of the tests matters and a good
+ * (smart) C compiler might re-arange things wrong.
+ */
+#ifdef AUTOLOGOUT
+# ifdef convex
+ if (uid == 0) {
+ /* root always has a 15 minute autologout */
+ set(STRautologout, Strsave(STRrootdefautologout), VAR_READWRITE);
+ }
+ else
+ if (loginsh)
+ /* users get autologout set to 0 */
+ set(STRautologout, Strsave(STR0), VAR_READWRITE);
+# else /* convex */
+ if (loginsh || (uid == 0)) {
+ if (*cp) {
+ /* only for login shells or root and we must have a tty */
+ if ((cp2 = Strrchr(cp, (Char) '/')) != NULL) {
+ cp = cp2 + 1;
+ }
+ else
+ cp2 = cp;
+ if (!(((Strncmp(cp2, STRtty, 3) == 0) && Isalpha(cp2[3])) ||
+ ((Strncmp(cp, STRpts, 3) == 0) && cp[3] == '/'))) {
+ if (getenv("DISPLAY") == NULL) {
+ /* NOT on X window shells */
+ set(STRautologout, Strsave(STRdefautologout),
+ VAR_READWRITE);
+ }
+ }
+ }
+ }
+# endif /* convex */
+#endif /* AUTOLOGOUT */
+
+ (void) sigset(SIGALRM, alrmcatch);
+
+ set(STRstatus, Strsave(STR0), VAR_READWRITE);
+
+ /*
+ * get and set machine specific envirnment variables
+ */
+ getmachine();
+
+ fix_version(); /* publish the shell version */
+
+ /*
+ * Publish the selected echo style
+ */
+#if ECHO_STYLE == NONE_ECHO
+ set(STRecho_style, Strsave(STRnone), VAR_READWRITE);
+#endif /* ECHO_STYLE == NONE_ECHO */
+#if ECHO_STYLE == BSD_ECHO
+ set(STRecho_style, Strsave(STRbsd), VAR_READWRITE);
+#endif /* ECHO_STYLE == BSD_ECHO */
+#if ECHO_STYLE == SYSV_ECHO
+ set(STRecho_style, Strsave(STRsysv), VAR_READWRITE);
+#endif /* ECHO_STYLE == SYSV_ECHO */
+#if ECHO_STYLE == BOTH_ECHO
+ set(STRecho_style, Strsave(STRboth), VAR_READWRITE);
+#endif /* ECHO_STYLE == BOTH_ECHO */
+
+ /*
+ * increment the shell level.
+ */
+ shlvl(1);
+
+ if ((tcp = getenv("HOME")) != NULL)
+ cp = quote(SAVE(tcp));
+ else
+ cp = NULL;
+ if (cp == NULL)
+ fast = 1; /* No home -> can't read scripts */
+ else
+ set(STRhome, cp, VAR_READWRITE);
+ dinit(cp); /* dinit thinks that HOME == cwd in a login
+ * shell */
+ /*
+ * Grab other useful things from the environment. Should we grab
+ * everything??
+ */
+ {
+ char *cln, *cus, *cgr;
+ Char buff[BUFSIZE];
+ struct passwd *pw;
+ struct group *gr;
+
+
+#ifdef apollo
+ int oid = getoid();
+
+ (void) Itoa(oid, buff, 0, 0);
+ set(STRoid, Strsave(buff), VAR_READWRITE);
+#endif /* apollo */
+
+ (void) Itoa(uid, buff, 0, 0);
+ set(STRuid, Strsave(buff), VAR_READWRITE);
+
+ (void) Itoa(gid, buff, 0, 0);
+ set(STRgid, Strsave(buff), VAR_READWRITE);
+
+ cln = getenv("LOGNAME");
+ cus = getenv("USER");
+ if (cus != NULL)
+ set(STRuser, quote(SAVE(cus)), VAR_READWRITE);
+ else if (cln != NULL)
+ set(STRuser, quote(SAVE(cln)), VAR_READWRITE);
+ else if ((pw = getpwuid(uid)) == NULL)
+ set(STRuser, SAVE("unknown"), VAR_READWRITE);
+ else
+ set(STRuser, SAVE(pw->pw_name), VAR_READWRITE);
+ if (cln == NULL)
+ tsetenv(STRLOGNAME, varval(STRuser));
+ if (cus == NULL)
+ tsetenv(STRKUSER, varval(STRuser));
+
+ cgr = getenv("GROUP");
+ if (cgr != NULL)
+ set(STRgroup, quote(SAVE(cgr)), VAR_READWRITE);
+ else if ((gr = getgrgid(gid)) == NULL)
+ set(STRgroup, SAVE("unknown"), VAR_READWRITE);
+ else
+ set(STRgroup, SAVE(gr->gr_name), VAR_READWRITE);
+ if (cgr == NULL)
+ tsetenv(STRKGROUP, varval(STRgroup));
+ }
+
+ /*
+ * HOST may be wrong, since rexd transports the entire environment on sun
+ * 3.x Just set it again
+ */
+ {
+ char cbuff[MAXHOSTNAMELEN];
+
+ if (gethostname(cbuff, sizeof(cbuff)) >= 0) {
+ cbuff[sizeof(cbuff) - 1] = '\0'; /* just in case */
+ tsetenv(STRHOST, str2short(cbuff));
+ }
+ else
+ tsetenv(STRHOST, str2short("unknown"));
+ }
+
+
+#ifdef REMOTEHOST
+ /*
+ * Try to determine the remote host we were logged in from.
+ */
+ remotehost();
+#endif /* REMOTEHOST */
+
+#ifdef apollo
+ if ((tcp = getenv("SYSTYPE")) == NULL)
+ tcp = "bsd4.3";
+ tsetenv(STRSYSTYPE, quote(str2short(tcp)));
+#endif /* apollo */
+
+ /*
+ * set editing on by default, unless running under Emacs as an inferior
+ * shell.
+ * We try to do this intelligently. If $TERM is available, then it
+ * should determine if we should edit or not. $TERM is preserved
+ * across rlogin sessions, so we will not get confused if we rlogin
+ * under an emacs shell. Another advantage is that if we run an
+ * xterm under an emacs shell, then the $TERM will be set to
+ * xterm, so we are going to want to edit. Unfortunately emacs
+ * does not restore all the tty modes, so xterm is not very well
+ * set up. But this is not the shell's fault.
+ * Also don't edit if $TERM == wm, for when we're running under an ATK app.
+ * Finally, emacs compiled under terminfo, sets the terminal to dumb,
+ * so disable editing for that too.
+ *
+ * Unfortunately, in some cases the initial $TERM setting is "unknown",
+ * "dumb", or "network" which is then changed in the user's startup files.
+ * We fix this by setting noediting here if $TERM is unknown/dumb and
+ * if noediting is set, we switch on editing if $TERM is changed.
+ */
+ if ((tcp = getenv("TERM")) != NULL) {
+ set(STRterm, quote(SAVE(tcp)), VAR_READWRITE);
+ noediting = strcmp(tcp, "unknown") == 0 || strcmp(tcp, "dumb") == 0 ||
+ strcmp(tcp, "network") == 0;
+ editing = strcmp(tcp, "emacs") != 0 && strcmp(tcp, "wm") != 0 &&
+ !noediting;
+ }
+ else {
+ noediting = 0;
+ editing = ((tcp = getenv("EMACS")) == NULL || strcmp(tcp, "t") != 0);
+ }
+
+ /*
+ * The 'edit' variable is either set or unset. It doesn't
+ * need a value. Making it 'emacs' might be confusing.
+ */
+ if (editing)
+ set(STRedit, Strsave(STRNULL), VAR_READWRITE);
+
+
+ /*
+ * still more mutability: make the complete routine automatically add the
+ * suffix of file names...
+ */
+ set(STRaddsuffix, Strsave(STRNULL), VAR_READWRITE);
+
+ /*
+ * Re-initialize path if set in environment
+ */
+ if ((tcp = getenv("PATH")) == NULL)
+#ifdef _PATH_DEFPATH
+ importpath(str2short(_PATH_DEFPATH));
+#else /* !_PATH_DEFPATH */
+ setq(STRpath, defaultpath(), &shvhed, VAR_READWRITE);
+#endif /* _PATH_DEFPATH */
+ else
+ /* Importpath() allocates memory for the path, and the
+ * returned pointer from SAVE() was discarded, so
+ * this was a memory leak.. (sg)
+ *
+ * importpath(SAVE(tcp));
+ */
+ importpath(str2short(tcp));
+
+
+ {
+ /* If the SHELL environment variable ends with "tcsh", set
+ * STRshell to the same path. This is to facilitate using
+ * the executable in environments where the compiled-in
+ * default isn't appropriate (sg).
+ */
+
+ int sh_len = 0;
+
+ if ((tcp = getenv("SHELL")) != NULL) {
+ sh_len = strlen(tcp);
+ if ((sh_len >= 5 && strcmp(tcp + (sh_len - 5), "/tcsh") == 0) ||
+ (!tcsh && sh_len >= 4 && strcmp(tcp + (sh_len - 4), "/csh") == 0))
+ set(STRshell, quote(SAVE(tcp)), VAR_READWRITE);
+ else
+ sh_len = 0;
+ }
+ if (sh_len == 0)
+ set(STRshell, Strsave(STR_SHELLPATH), VAR_READWRITE);
+ }
+
+#ifdef COLOR_LS_F
+ if ((tcp = getenv("LS_COLORS")) != NULL)
+ parseLS_COLORS(str2short(tcp));
+#endif /* COLOR_LS_F */
+
+ doldol = putn((int) getpid()); /* For $$ */
+#ifdef WINNT
+ {
+ char *strtmp1, strtmp2[MAXPATHLEN];
+ if ((strtmp1 = getenv("TMP")) != NULL)
+ wsprintf(strtmp2, "%s/%s", strtmp1, "sh");
+ shtemp = Strspl(SAVE(strtmp2), doldol); /* For << */
+ }
+#else /* !WINNT */
+ shtemp = Strspl(STRtmpsh, doldol); /* For << */
+#endif /* WINNT */
+
+ /*
+ * Record the interrupt states from the parent process. If the parent is
+ * non-interruptible our hand must be forced or we (and our children) won't
+ * be either. Our children inherit termination from our parent. We catch it
+ * only if we are the login shell.
+ */
+#ifdef BSDSIGS
+ /*
+ * PURIFY-2 claims that osv does not get
+ * initialized after the sigvec call
+ */
+ setzero((char*) &osv, sizeof(osv));
+ /* parents interruptibility */
+ (void) mysigvec(SIGINT, NULL, &osv);
+ parintr = (signalfun_t) osv.sv_handler;
+ (void) mysigvec(SIGTERM, NULL, &osv);
+ parterm = (signalfun_t) osv.sv_handler;
+#else /* BSDSIGS */
+ parintr = signal(SIGINT, SIG_IGN); /* parents interruptibility */
+ (void) sigset(SIGINT, parintr); /* ... restore */
+
+# ifdef COHERENT
+ if (loginsh) /* it seems that SIGTERM is always set to SIG_IGN by */
+ /* init/getty so it should be set to SIG_DFL - there may be */
+ /* a better fix for this. */
+ parterm = SIG_DFL;
+ else
+# else /* !COHERENT */
+ parterm = signal(SIGTERM, SIG_IGN); /* parents terminability */
+# endif /* COHERENT */
+ (void) sigset(SIGTERM, parterm); /* ... restore */
+
+#endif /* BSDSIGS */
+
+
+#ifdef TCF
+ /* Enable process migration on ourselves and our progeny */
+ (void) signal(SIGMIGRATE, SIG_DFL);
+#endif /* TCF */
+
+ /*
+ * Process the arguments.
+ *
+ * Note that processing of -v/-x is actually delayed till after script
+ * processing.
+ *
+ * We set the first character of our name to be '-' if we are a shell
+ * running interruptible commands. Many programs which examine ps'es
+ * use this to filter such shells out.
+ */
+ argc--, tempv++;
+ while (argc > 0 && (tcp = tempv[0])[0] == '-' &&
+ *++tcp != '\0' && !batch) {
+ do
+ switch (*tcp++) {
+
+ case 0: /* - Interruptible, no prompt */
+ prompt = 0;
+ setintr = 1;
+ nofile = 1;
+ break;
+
+ case 'b': /* -b Next arg is input file */
+ batch = 1;
+ break;
+
+ case 'c': /* -c Command input from arg */
+ if (argc == 1)
+ xexit(0);
+ argc--, tempv++;
+#ifdef M_XENIX
+ /* Xenix Vi bug:
+ it relies on a 7 bit environment (/bin/sh), so it
+ pass ascii arguments with the 8th bit set */
+ if (!strcmp(argv[0], "sh"))
+ {
+ char *p;
+
+ for (p = tempv[0]; *p; ++p)
+ *p &= ASCII;
+ }
+#endif
+ arginp = SAVE(tempv[0]);
+
+ /*
+ * we put the command into a variable
+ */
+ if (arginp != NULL)
+ set(STRcommand, quote(Strsave(arginp)), VAR_READWRITE);
+
+ /*
+ * * Give an error on -c arguments that end in * backslash to
+ * ensure that you don't make * nonportable csh scripts.
+ */
+ {
+ register int count;
+
+ cp = arginp + Strlen(arginp);
+ count = 0;
+ while (cp > arginp && *--cp == '\\')
+ ++count;
+ if ((count & 1) != 0) {
+ exiterr = 1;
+ stderror(ERR_ARGC);
+ }
+ }
+ prompt = 0;
+ nofile = 1;
+ break;
+ case 'd': /* -d Load directory stack from file */
+ rdirs = 1;
+ break;
+
+#ifdef apollo
+ case 'D': /* -D Define environment variable */
+ {
+ register Char *dp;
+
+ cp = str2short(tcp);
+ if (dp = Strchr(cp, '=')) {
+ *dp++ = '\0';
+ tsetenv(cp, dp);
+ }
+ else
+ tsetenv(cp, STRNULL);
+ }
+ *tcp = '\0'; /* done with this argument */
+ break;
+#endif /* apollo */
+
+ case 'e': /* -e Exit on any error */
+ exiterr = 1;
+ break;
+
+ case 'f': /* -f Fast start */
+ fast = 1;
+ break;
+
+ case 'i': /* -i Interactive, even if !intty */
+ intact = 1;
+ nofile = 1;
+ break;
+
+ case 'm': /* -m read .cshrc (from su) */
+ mflag = 1;
+ break;
+
+ case 'n': /* -n Don't execute */
+ noexec = 1;
+ break;
+
+ case 'q': /* -q (Undoc'd) ... die on quit */
+ quitit = 1;
+ break;
+
+ case 's': /* -s Read from std input */
+ nofile = 1;
+ break;
+
+ case 't': /* -t Read one line from input */
+ onelflg = 2;
+ prompt = 0;
+ nofile = 1;
+ break;
+
+ case 'v': /* -v Echo hist expanded input */
+ nverbose = 1; /* ... later */
+ break;
+
+ case 'x': /* -x Echo just before execution */
+ nexececho = 1; /* ... later */
+ break;
+
+ case 'V': /* -V Echo hist expanded input */
+ setNS(STRverbose); /* NOW! */
+ break;
+
+ case 'X': /* -X Echo just before execution */
+ setNS(STRecho); /* NOW! */
+ break;
+
+ case 'F': /* Undocumented flag */
+ /*
+ * This will cause children to be created using fork instead of
+ * vfork.
+ */
+ use_fork = 1;
+ break;
+
+ case ' ':
+ case '\t':
+ /*
+ * for O/S's that don't do the argument parsing right in
+ * "#!/foo -f " scripts
+ */
+ break;
+
+ default: /* Unknown command option */
+ exiterr = 1;
+ stderror(ERR_TCSHUSAGE, tcp-1, progname);
+ break;
+
+ } while (*tcp);
+ tempv++, argc--;
+ }
+
+ if (quitit) /* With all due haste, for debugging */
+ (void) signal(SIGQUIT, SIG_DFL);
+
+ /*
+ * Unless prevented by -, -c, -i, -s, or -t, if there are remaining
+ * arguments the first of them is the name of a shell file from which to
+ * read commands.
+ */
+ if (nofile == 0 && argc > 0) {
+ nofile = open(tempv[0], O_RDONLY);
+ if (nofile < 0) {
+ child = 1; /* So this ... */
+ /* ... doesn't return */
+ stderror(ERR_SYSTEM, tempv[0], strerror(errno));
+ }
+ if (ffile != NULL)
+ xfree((ptr_t) ffile);
+ dolzero = 1;
+ ffile = SAVE(tempv[0]);
+ /*
+ * Replace FSHIN. Handle /dev/std{in,out,err} specially
+ * since once they are closed we cannot open them again.
+ * In that case we use our own saved descriptors
+ */
+ if ((SHIN = dmove(nofile, FSHIN)) < 0)
+ switch(nofile) {
+ case 0:
+ SHIN = FSHIN;
+ break;
+ case 1:
+ SHIN = FSHOUT;
+ break;
+ case 2:
+ SHIN = FSHDIAG;
+ break;
+ default:
+ stderror(ERR_SYSTEM, tempv[0], strerror(errno));
+ break;
+ }
+ (void) close_on_exec(SHIN, 1);
+ prompt = 0;
+ /* argc not used any more */ tempv++;
+ }
+
+
+ /*
+ * Consider input a tty if it really is or we are interactive. but not for
+ * editing (christos)
+ */
+ if (!(intty = isatty(SHIN))) {
+ if (adrof(STRedit))
+ unsetv(STRedit);
+ editing = 0;
+ }
+ intty |= intact;
+#ifndef convex
+ if (intty || (intact && isatty(SHOUT))) {
+ if (!batch && (uid != euid || gid != egid)) {
+ errno = EACCES;
+ child = 1; /* So this ... */
+ /* ... doesn't return */
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+ }
+ }
+#endif /* convex */
+ isoutatty = isatty(SHOUT);
+ isdiagatty = isatty(SHDIAG);
+ /*
+ * Decide whether we should play with signals or not. If we are explicitly
+ * told (via -i, or -) or we are a login shell (arg0 starts with -) or the
+ * input and output are both the ttys("csh", or "csh</dev/ttyx>/dev/ttyx")
+ * Note that in only the login shell is it likely that parent may have set
+ * signals to be ignored
+ */
+ if (loginsh || intact || (intty && isatty(SHOUT)))
+ setintr = 1;
+ settell();
+ /*
+ * Save the remaining arguments in argv.
+ */
+ setq(STRargv, blk2short(tempv), &shvhed, VAR_READWRITE);
+
+ /*
+ * Set up the prompt.
+ */
+ if (prompt) {
+ if (tcsh)
+ set(STRprompt, Strsave(STRdeftcshprompt), VAR_READWRITE);
+ else
+ set(STRprompt, Strsave(STRdefcshprompt), VAR_READWRITE);
+ /* that's a meta-questionmark */
+ set(STRprompt2, Strsave(STRmquestion), VAR_READWRITE);
+ set(STRprompt3, Strsave(STRKCORRECT), VAR_READWRITE);
+ }
+
+ /*
+ * If we are an interactive shell, then start fiddling with the signals;
+ * this is a tricky game.
+ */
+ shpgrp = mygetpgrp();
+ opgrp = tpgrp = -1;
+ if (setintr) {
+ signalfun_t osig;
+ **argv = '-';
+ if (!quitit) /* Wary! */
+ (void) signal(SIGQUIT, SIG_IGN);
+ (void) sigset(SIGINT, pintr);
+ (void) sighold(SIGINT);
+ (void) signal(SIGTERM, SIG_IGN);
+
+ /*
+ * No reason I can see not to save history on all these events..
+ * Most usual occurrence is in a window system, where we're not a login
+ * shell, but might as well be... (sg)
+ * But there might be races when lots of shells exit together...
+ * [this is also incompatible].
+ * We have to be mre careful here. If the parent wants to
+ * ignore the signals then we leave them untouched...
+ * We also only setup the handlers for shells that are trully
+ * interactive.
+ */
+ osig = signal(SIGHUP, phup); /* exit processing on HUP */
+ if (!loginsh && osig == SIG_IGN)
+ (void) signal(SIGHUP, osig);
+#ifdef SIGXCPU
+ osig = signal(SIGXCPU, phup); /* exit processing on XCPU */
+ if (!loginsh && osig == SIG_IGN)
+ (void) signal(SIGXCPU, osig);
+#endif
+#ifdef SIGXFSZ
+ osig = signal(SIGXFSZ, phup); /* exit processing on XFSZ */
+ if (!loginsh && osig == SIG_IGN)
+ (void) signal(SIGXFSZ, osig);
+#endif
+
+ if (quitit == 0 && arginp == 0) {
+#ifdef SIGTSTP
+ (void) signal(SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTIN
+ (void) signal(SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+ (void) signal(SIGTTOU, SIG_IGN);
+#endif
+ /*
+ * Wait till in foreground, in case someone stupidly runs csh &
+ * dont want to try to grab away the tty.
+ */
+ if (isatty(FSHDIAG))
+ f = FSHDIAG;
+ else if (isatty(FSHOUT))
+ f = FSHOUT;
+ else if (isatty(OLDSTD))
+ f = OLDSTD;
+ else
+ f = -1;
+
+#ifdef NeXT
+ /* NeXT 2.0 /usr/etc/rlogind, does not set our process group! */
+ if (shpgrp == 0) {
+ shpgrp = getpid();
+ (void) setpgid(0, shpgrp);
+ (void) tcsetpgrp(f, shpgrp);
+ }
+#endif /* NeXT */
+#ifdef BSDJOBS /* if we have tty job control */
+ retry:
+ if ((tpgrp = tcgetpgrp(f)) != -1) {
+ if (tpgrp != shpgrp) {
+ signalfun_t old = signal(SIGTTIN, SIG_DFL);
+ (void) kill(0, SIGTTIN);
+ (void) signal(SIGTTIN, old);
+ goto retry;
+ }
+ /*
+ * Thanks to Matt Day for the POSIX references, and to
+ * Paul Close for the SGI clarification.
+ */
+ if (setdisc(f) != -1) {
+ opgrp = shpgrp;
+ shpgrp = getpid();
+ tpgrp = shpgrp;
+ if (tcsetpgrp(f, shpgrp) == -1) {
+ /*
+ * On hpux 7.03 this fails with EPERM. This happens on
+ * the 800 when opgrp != shpgrp at this point. (we were
+ * forked from a non job control shell)
+ * POSIX 7.2.4, says we failed because the process
+ * group specified did not belong to a process
+ * in the same session with the tty. So we set our
+ * process group and try again.
+ */
+ if (setpgid(0, shpgrp) == -1) {
+ xprintf("setpgid:");
+ goto notty;
+ }
+ if (tcsetpgrp(f, shpgrp) == -1) {
+ xprintf("tcsetpgrp:");
+ goto notty;
+ }
+ }
+ /*
+ * We check the process group now. If it is the same, then
+ * we don't need to set it again. On hpux 7.0 on the 300's
+ * if we set it again it fails with EPERM. This is the
+ * correct behavior according to POSIX 4.3.3 if the process
+ * was a session leader .
+ */
+ else if (shpgrp != mygetpgrp()) {
+ if(setpgid(0, shpgrp) == -1) {
+ xprintf("setpgid:");
+ goto notty;
+ }
+ }
+#ifdef IRIS4D
+ /*
+ * But on irix 3.3 we need to set it again, even if it is
+ * the same. We do that to tell the system that we
+ * need BSD process group compatibility.
+ */
+ else
+ (void) setpgid(0, shpgrp);
+#endif
+ (void) close_on_exec(dcopy(f, FSHTTY), 1);
+ }
+ else
+ tpgrp = -1;
+ }
+ if (tpgrp == -1) {
+ notty:
+ xprintf(CGETS(11, 1, "Warning: no access to tty (%s).\n"),
+ strerror(errno));
+ xprintf(CGETS(11, 2, "Thus no job control in this shell.\n"));
+ /*
+ * Fix from:Sakari Jalovaara <sja@sirius.hut.fi> if we don't
+ * have access to tty, disable editing too
+ */
+ if (adrof(STRedit))
+ unsetv(STRedit);
+ editing = 0;
+ }
+#else /* BSDJOBS */ /* don't have job control, so frotz it */
+ tpgrp = -1;
+#endif /* BSDJOBS */
+ }
+ }
+ if ((setintr == 0) && (parintr == SIG_DFL))
+ setintr = 1;
+
+/*
+ * SVR4 doesn't send a SIGCHLD when a child is stopped or continued if the
+ * handler is installed with signal(2) or sigset(2). sigaction(2) must
+ * be used instead.
+ *
+ * David Dawes (dawes@physics.su.oz.au) Sept 1991
+ */
+
+#if SYSVREL > 3
+ {
+ struct sigaction act;
+ act.sa_handler=pchild;
+ (void) sigemptyset(&(act.sa_mask)); /* Don't block any extra sigs
+ * when the handler is called
+ */
+ act.sa_flags=0; /* want behaviour of sigset() without
+ * SA_NOCLDSTOP
+ */
+
+ if ((sigaction(SIGCHLD,&act,(struct sigaction *)NULL)) == -1)
+ stderror(ERR_SYSTEM, "sigaction", strerror(errno));
+ }
+#else /* SYSVREL <= 3 */
+ (void) sigset(SIGCHLD, pchild); /* while signals not ready */
+#endif /* SYSVREL <= 3 */
+
+
+ if (intty && !arginp)
+ (void) ed_Setup(editing);/* Get the tty state, and set defaults */
+ /* Only alter the tty state if editing */
+
+ /*
+ * Set an exit here in case of an interrupt or error reading the shell
+ * start-up scripts.
+ */
+ reenter = setexit(); /* PWP */
+ haderr = 0; /* In case second time through */
+ if (!fast && reenter == 0) {
+ /* Will have varval(STRhome) here because set fast if don't */
+ {
+ int osetintr = setintr;
+ signalfun_t oparintr = parintr;
+
+#ifdef BSDSIGS
+ sigmask_t omask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+ setintr = 0;
+ parintr = SIG_IGN; /* onintr in /etc/ files has no effect */
+#ifdef LOGINFIRST
+#ifdef _PATH_DOTLOGIN
+ if (loginsh)
+ (void) srcfile(_PATH_DOTLOGIN, 0, 0, NULL);
+#endif
+#endif
+
+#ifdef _PATH_DOTCSHRC
+ (void) srcfile(_PATH_DOTCSHRC, 0, 0, NULL);
+#endif
+ if (!arginp && !onelflg && !havhash)
+ dohash(NULL,NULL);
+#ifndef LOGINFIRST
+#ifdef _PATH_DOTLOGIN
+ if (loginsh)
+ (void) srcfile(_PATH_DOTLOGIN, 0, 0, NULL);
+#endif
+#endif
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ setintr = osetintr;
+ parintr = oparintr;
+ }
+#ifdef LOGINFIRST
+ if (loginsh)
+ (void) srccat(varval(STRhome), STRsldotlogin);
+#endif
+ /* upward compat. */
+ if (!srccat(varval(STRhome), STRsldottcshrc))
+ (void) srccat(varval(STRhome), STRsldotcshrc);
+
+ if (!fast && !arginp && !onelflg && !havhash)
+ dohash(NULL,NULL);
+
+ /*
+ * Source history before .login so that it is available in .login
+ */
+ loadhist(NULL, 0);
+#ifndef LOGINFIRST
+ if (loginsh)
+ (void) srccat(varval(STRhome), STRsldotlogin);
+#endif
+ if (!fast && (loginsh || rdirs))
+ loaddirs(NULL);
+ }
+ /* Initing AFTER .cshrc is the Right Way */
+ if (intty && !arginp) { /* PWP setup stuff */
+ ed_Init(); /* init the new line editor */
+#ifdef SIG_WINDOW
+ check_window_size(1); /* mung environment */
+#endif /* SIG_WINDOW */
+ }
+
+ /*
+ * dspkanji/dspmbyte autosetting
+ */
+ /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
+#if defined(DSPMBYTE)
+ if ((tcp = getenv("LANG")) != NULL && !adrof(CHECK_MBYTEVAR)) {
+ autoset_dspmbyte(str2short(tcp));
+ }
+#if defined(WINNT)
+ else if (!adrof(CHECK_MBYTEVAR))
+ nt_autoset_dspmbyte();
+#endif /* WINNT */
+#endif
+
+ /*
+ * Now are ready for the -v and -x flags
+ */
+ if (nverbose)
+ setNS(STRverbose);
+ if (nexececho)
+ setNS(STRecho);
+
+ /*
+ * All the rest of the world is inside this call. The argument to process
+ * indicates whether it should catch "error unwinds". Thus if we are a
+ * interactive shell our call here will never return by being blown past on
+ * an error.
+ */
+ process(setintr);
+
+ /*
+ * Mop-up.
+ */
+ if (intty) {
+ if (loginsh) {
+ xprintf("logout\n");
+ (void) close(SHIN);
+ child = 1;
+#ifdef TESLA
+ do_logout = 1;
+#endif /* TESLA */
+ goodbye(NULL, NULL);
+ }
+ else {
+ xprintf("exit\n");
+ }
+ }
+ record();
+ exitstat();
+ return (0);
+}
+
+void
+untty()
+{
+#ifdef BSDJOBS
+ if (tpgrp > 0 && opgrp != shpgrp) {
+ (void) setpgid(0, opgrp);
+ (void) tcsetpgrp(FSHTTY, opgrp);
+ (void) resetdisc(FSHTTY);
+ }
+#endif /* BSDJOBS */
+}
+
+void
+importpath(cp)
+ Char *cp;
+{
+ register int i = 0;
+ register Char *dp;
+ register Char **pv;
+ int c;
+
+ for (dp = cp; *dp; dp++)
+ if (*dp == PATHSEP)
+ i++;
+ /*
+ * i+2 where i is the number of colons in the path. There are i+1
+ * directories in the path plus we need room for a zero terminator.
+ */
+ pv = (Char **) xcalloc((size_t) (i + 2), sizeof(Char *));
+ dp = cp;
+ i = 0;
+ if (*dp)
+ for (;;) {
+ if ((c = *dp) == PATHSEP || c == 0) {
+ *dp = 0;
+ pv[i++] = Strsave(*cp ? cp : STRdot);
+ if (c) {
+ cp = dp + 1;
+ *dp = PATHSEP;
+ }
+ else
+ break;
+ }
+#ifdef WINNT
+ else if (*dp == '\\')
+ *dp = '/';
+#endif /* WINNT */
+ dp++;
+ }
+ pv[i] = 0;
+ setq(STRpath, pv, &shvhed, VAR_READWRITE);
+}
+
+/*
+ * Source to the file which is the catenation of the argument names.
+ */
+static int
+srccat(cp, dp)
+ Char *cp, *dp;
+{
+ if (cp[0] == '/' && cp[1] == '\0')
+ return srcfile(short2str(dp), (mflag ? 0 : 1), 0, NULL);
+ else {
+ register Char *ep;
+ char *ptr;
+ int rv;
+
+#ifdef WINNT
+ ep = cp;
+ while(*ep)
+ ep++;
+ if (ep[-1] == '/' && dp[0] == '/') /* silly win95 */
+ dp++;
+#endif /* WINNT */
+
+ ep = Strspl(cp, dp);
+ ptr = short2str(ep);
+
+ rv = srcfile(ptr, (mflag ? 0 : 1), 0, NULL);
+ xfree((ptr_t) ep);
+ return rv;
+ }
+}
+
+/*
+ * Source to a file putting the file descriptor in a safe place (> 2).
+ */
+static int
+srcfile(f, onlyown, flag, av)
+ char *f;
+ bool onlyown;
+ int flag;
+ Char **av;
+{
+ register int unit;
+
+ if ((unit = open(f, O_RDONLY)) == -1)
+ return 0;
+ unit = dmove(unit, -1);
+
+ (void) close_on_exec(unit, 1);
+ srcunit(unit, onlyown, flag, av);
+ return 1;
+}
+
+
+/*
+ * Save the shell state, and establish new argument vector, and new input
+ * fd.
+ */
+static void
+st_save(st, unit, hflg, al, av)
+ struct saved_state *st;
+ int unit, hflg;
+ Char **al, **av;
+{
+ st->insource = insource;
+ st->SHIN = SHIN;
+ st->intty = intty;
+ st->whyles = whyles;
+ st->gointr = gointr;
+ st->arginp = arginp;
+ st->evalp = evalp;
+ st->evalvec = evalvec;
+ st->alvecp = alvecp;
+ st->alvec = alvec;
+ st->onelflg = onelflg;
+ st->enterhist = enterhist;
+ if (hflg)
+ st->HIST = HIST;
+ else
+ st->HIST = '\0';
+ st->cantell = cantell;
+ cpybin(st->B, B);
+
+ /*
+ * we can now pass arguments to source.
+ * For compatibility we do that only if arguments were really
+ * passed, otherwise we keep the old, global $argv like before.
+ */
+ if (av != NULL && *av != NULL) {
+ struct varent *vp;
+ if ((vp = adrof(STRargv)) != NULL)
+ st->argv = saveblk(vp->vec);
+ else
+ st->argv = NULL;
+ setq(STRargv, saveblk(av), &shvhed, VAR_READWRITE);
+ }
+ else
+ st->argv = NULL;
+
+ SHIN = unit; /* Do this first */
+
+ /* Establish new input arena */
+ {
+ fbuf = NULL;
+ fseekp = feobp = fblocks = 0;
+ settell();
+ }
+
+ arginp = 0;
+ onelflg = 0;
+ intty = isatty(SHIN);
+ whyles = 0;
+ gointr = 0;
+ evalvec = 0;
+ evalp = 0;
+ alvec = al;
+ alvecp = 0;
+ enterhist = hflg;
+ if (enterhist)
+ HIST = '\0';
+ insource = 1;
+}
+
+
+/*
+ * Restore the shell to a saved state
+ */
+static void
+st_restore(st, av)
+ struct saved_state *st;
+ Char **av;
+{
+ if (st->SHIN == -1)
+ return;
+
+ /* Reset input arena */
+ {
+ register int i;
+ register Char** nfbuf = fbuf;
+ register int nfblocks = fblocks;
+
+ fblocks = 0;
+ fbuf = NULL;
+ for (i = 0; i < nfblocks; i++)
+ xfree((ptr_t) nfbuf[i]);
+ xfree((ptr_t) nfbuf);
+ }
+ cpybin(B, st->B);
+
+ (void) close(SHIN);
+
+ insource = st->insource;
+ SHIN = st->SHIN;
+ arginp = st->arginp;
+ onelflg = st->onelflg;
+ evalp = st->evalp;
+ evalvec = st->evalvec;
+ alvecp = st->alvecp;
+ alvec = st->alvec;
+ intty = st->intty;
+ whyles = st->whyles;
+ gointr = st->gointr;
+ if (st->HIST != '\0')
+ HIST = st->HIST;
+ enterhist = st->enterhist;
+ cantell = st->cantell;
+
+ if (st->argv != NULL)
+ setq(STRargv, st->argv, &shvhed, VAR_READWRITE);
+ else if (av != NULL && *av != NULL && adrof(STRargv) != NULL)
+ unsetv(STRargv);
+}
+
+/*
+ * Source to a unit. If onlyown it must be our file or our group or
+ * we don't chance it. This occurs on ".cshrc"s and the like.
+ */
+static void
+srcunit(unit, onlyown, hflg, av)
+ register int unit;
+ bool onlyown;
+ int hflg;
+ Char **av;
+{
+ struct saved_state st;
+ st.SHIN = -1; /* st_restore checks this */
+
+ if (unit < 0)
+ return;
+
+ if (didfds)
+ donefds();
+
+ if (onlyown) {
+ struct stat stb;
+
+ if (fstat(unit, &stb) < 0) {
+ (void) close(unit);
+ return;
+ }
+ }
+
+ getexit(st.oldexit);
+
+ if (setintr)
+#ifdef BSDSIGS
+ st.mask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+
+ /* Save the current state and move us to a new state */
+ st_save(&st, unit, hflg, NULL, av);
+
+ /*
+ * Now if we are allowing commands to be interrupted, we let ourselves be
+ * interrupted.
+ */
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(st.mask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+
+ /*
+ * Bugfix for running out of memory by: Jak Kirman
+ * <jak%cs.brown.edu@RELAY.CS.NET>. Solution: pay attention to what
+ * setexit() is returning because reenter _may_ be in a register, and
+ * thus restored to 0 on a longjump(). (PWP: insert flames about
+ * compiler-dependant code here) PWP: THANKS LOTS !!!
+ *
+ * PWP: think of this as like a LISP (unwind-protect ...)
+ * thanks to Diana Smetters for pointing out how this _should_ be written
+ */
+#ifdef cray
+ st.reenter = 1; /* assume non-zero return val */
+ if (setexit() == 0) {
+ st.reenter = 0; /* Oh well, we were wrong */
+#else
+ if ((st.reenter = setexit()) == 0) {
+#endif
+ process(0); /* 0 -> blow away on errors */
+ }
+
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(st.mask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+
+ /* Restore the old state */
+ st_restore(&st, av);
+ resexit(st.oldexit);
+ /*
+ * If process reset() (effectively an unwind) then we must also unwind.
+ */
+ if (st.reenter)
+ stderror(ERR_SILENT);
+}
+
+
+/*ARGSUSED*/
+void
+goodbye(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ record();
+
+ if (loginsh) {
+ (void) sigset(SIGQUIT, SIG_IGN);
+ (void) sigset(SIGINT, SIG_IGN);
+ (void) sigset(SIGTERM, SIG_IGN);
+ (void) sigset(SIGHUP, SIG_IGN);
+ setintr = 0; /* No interrupts after "logout" */
+ /* Trap errors inside .logout */
+ reenter = setexit();
+ if (reenter != 0)
+ exitstat();
+ if (!(adrof(STRlogout)))
+ set(STRlogout, Strsave(STRnormal), VAR_READWRITE);
+#ifdef _PATH_DOTLOGOUT
+ (void) srcfile(_PATH_DOTLOGOUT, 0, 0, NULL);
+#endif
+ if (adrof(STRhome))
+ (void) srccat(varval(STRhome), STRsldtlogout);
+#ifdef TESLA
+ do_logout = 1;
+#endif /* TESLA */
+ }
+ exitstat();
+}
+
+void
+exitstat()
+{
+#ifdef PROF
+ monitor(0);
+#endif
+ /*
+ * Note that if STATUS is corrupted (i.e. getn bombs) then error will exit
+ * directly because we poke child here. Otherwise we might continue
+ * unwarrantedly (sic).
+ */
+ child = 1;
+
+ xexit(getn(varval(STRstatus)));
+}
+
+/*
+ * in the event of a HUP we want to save the history
+ */
+static sigret_t
+phup(snum)
+int snum;
+{
+ /*
+ * There is no return from here,
+ * so we are not going to release SIGHUP
+ * anymore
+ */
+#ifdef UNRELSIGS
+ if (snum)
+ (void) sigset(snum, SIG_IGN);
+#else
+# ifdef BSDSIGS
+ (void) sigblock(sigmask(SIGHUP));
+# else
+ (void) sighold(SIGHUP);
+# endif /* BSDSIGS */
+#endif /* UNRELSIGS */
+
+ if (loginsh) {
+ set(STRlogout, Strsave(STRhangup), VAR_READWRITE);
+#ifdef _PATH_DOTLOGOUT
+ (void) srcfile(_PATH_DOTLOGOUT, 0, 0, NULL);
+#endif
+ if (adrof(STRhome))
+ (void) srccat(varval(STRhome), STRsldtlogout);
+ }
+
+ record();
+
+#ifdef POSIXJOBS
+ /*
+ * We kill the last foreground process group. It then becomes
+ * responsible to propagate the SIGHUP to its progeny.
+ */
+ {
+ struct process *pp, *np;
+
+ for (pp = proclist.p_next; pp; pp = pp->p_next) {
+ np = pp;
+ /*
+ * Find if this job is in the foreground. It could be that
+ * the process leader has exited and the foreground flag
+ * is cleared for it.
+ */
+ do
+ /*
+ * If a process is in the foreground we try to kill
+ * it's process group. If we succeed, then the
+ * whole job is gone. Otherwise we keep going...
+ * But avoid sending HUP to the shell again.
+ */
+ if (((np->p_flags & PFOREGND) != 0) && np->p_jobid != shpgrp) {
+ np->p_flags &= ~PHUP;
+ if (killpg(np->p_jobid, SIGHUP) != -1) {
+ /* In case the job was suspended... */
+#ifdef SIGCONT
+ (void) killpg(np->p_jobid, SIGCONT);
+#endif
+ break;
+ }
+ }
+ while ((np = np->p_friends) != pp);
+ }
+ }
+#endif /* POSIXJOBS */
+
+ xexit(snum);
+#ifndef SIGVOID
+ return (snum);
+#endif
+}
+
+static Char *jobargv[2] = {STRjobs, 0};
+
+/*
+ * Catch an interrupt, e.g. during lexical input.
+ * If we are an interactive shell, we reset the interrupt catch
+ * immediately. In any case we drain the shell output,
+ * and finally go through the normal error mechanism, which
+ * gets a chance to make the shell go away.
+ */
+int just_signaled; /* bugfix by Michael Bloom (mg@ttidca.TTI.COM) */
+
+#ifdef SIGVOID
+/*ARGSUSED*/
+#endif
+sigret_t
+pintr(snum)
+int snum;
+{
+#ifdef UNRELSIGS
+ if (snum)
+ (void) sigset(snum, pintr);
+#endif /* UNRELSIGS */
+ just_signaled = 1;
+ pintr1(1);
+#ifndef SIGVOID
+ return (snum);
+#endif
+}
+
+void
+pintr1(wantnl)
+ bool wantnl;
+{
+ register Char **v;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif
+
+#ifdef BSDSIGS
+ omask = sigblock((sigmask_t) 0);
+#endif
+ if (setintr) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask & ~sigmask(SIGINT));
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ if (pjobs) {
+ pjobs = 0;
+ xputchar('\n');
+ dojobs(jobargv, NULL);
+ stderror(ERR_NAME | ERR_INTR);
+ }
+ }
+ /* MH - handle interrupted completions specially */
+ {
+ extern int InsideCompletion;
+
+ if (InsideCompletion)
+ stderror(ERR_SILENT);
+ }
+ /* JV - Make sure we shut off inputl */
+ {
+ extern Char GettingInput;
+
+ (void) Cookedmode();
+ GettingInput = 0;
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask & ~sigmask(SIGCHLD));
+#else
+ if (setintr)
+ (void) sighold(SIGINT);
+ (void) sigrelse(SIGCHLD);
+#endif
+ drainoline();
+#if !defined(_VMS_POSIX) && !defined(WINNT)
+ (void) endpwent();
+#endif /* !_VMS_POSIX && !WINNT */
+
+ /*
+ * If we have an active "onintr" then we search for the label. Note that if
+ * one does "onintr -" then we shan't be interruptible so we needn't worry
+ * about that here.
+ */
+ if (gointr) {
+ gotolab(gointr);
+ timflg = 0;
+ if ((v = pargv) != 0)
+ pargv = 0, blkfree(v);
+ if ((v = gargv) != 0)
+ gargv = 0, blkfree(v);
+ reset();
+ }
+ else if (intty && wantnl) {
+ if (editing) {
+ /*
+ * If we are editing a multi-line input command, and move to
+ * the beginning of the line, we don't want to trash it when
+ * we hit ^C
+ */
+ PastBottom();
+ ClearLines();
+ ClearDisp();
+ }
+ else {
+ /* xputchar('\n'); *//* Some like this, others don't */
+ (void) putraw('\r');
+ (void) putraw('\n');
+ }
+ }
+ stderror(ERR_SILENT);
+}
+
+/*
+ * Process is the main driving routine for the shell.
+ * It runs all command processing, except for those within { ... }
+ * in expressions (which is run by a routine evalav in sh.exp.c which
+ * is a stripped down process), and `...` evaluation which is run
+ * also by a subset of this code in sh.glob.c in the routine backeval.
+ *
+ * The code here is a little strange because part of it is interruptible
+ * and hence freeing of structures appears to occur when none is necessary
+ * if this is ignored.
+ *
+ * Note that if catch is not set then we will unwind on any error.
+ * If an end-of-file occurs, we return.
+ */
+static struct command *savet = NULL;
+void
+process(catch)
+ bool catch;
+{
+ extern char Expand;
+ jmp_buf_t osetexit;
+ /* PWP: This might get nuked my longjmp so don't make it a register var */
+ struct command *t = savet;
+
+ savet = NULL;
+ getexit(osetexit);
+ for (;;) {
+
+ pendjob();
+
+ /* This was leaking memory badly, particularly when sourcing
+ * files, etc.. For whatever reason we were arriving here with
+ * allocated pointers still active, and the code was simply
+ * overwriting them. I can't say I fully understand the
+ * control flow here, but according to Purify this particular
+ * leak has been plugged, and I haven't noticed any ill
+ * effects.. (sg)
+ */
+ if (paraml.next && paraml.next != &paraml)
+ freelex(&paraml);
+
+ paraml.next = paraml.prev = &paraml;
+ paraml.word = STRNULL;
+ (void) setexit();
+ justpr = enterhist; /* execute if not entering history */
+
+ /*
+ * Interruptible during interactive reads
+ */
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else
+ (void) sigrelse(SIGINT);
+#endif
+
+
+ /*
+ * For the sake of reset()
+ */
+ freelex(&paraml);
+ if (savet)
+ freesyn(savet), savet = NULL;
+
+ if (haderr) {
+ if (!catch) {
+ /* unwind */
+ doneinp = 0;
+ savet = t;
+ resexit(osetexit);
+ reset();
+ }
+ haderr = 0;
+ /*
+ * Every error is eventually caught here or the shell dies. It is
+ * at this point that we clean up any left-over open files, by
+ * closing all but a fixed number of pre-defined files. Thus
+ * routines don't have to worry about leaving files open due to
+ * deeper errors... they will get closed here.
+ */
+ closem();
+ continue;
+ }
+ if (doneinp) {
+ doneinp = 0;
+ break;
+ }
+ if (chkstop)
+ chkstop--;
+ if (neednote)
+ pnote();
+ if (intty && prompt && evalvec == 0) {
+ just_signaled = 0;
+ mailchk();
+ /*
+ * Watch for logins/logouts. Next is scheduled commands stored
+ * previously using "sched." Then execute periodic commands.
+ * Following that, the prompt precmd is run.
+ */
+#ifndef HAVENOUTMP
+ watch_login(0);
+#endif /* !HAVENOUTMP */
+ sched_run(0);
+ period_cmd();
+ precmd();
+ /*
+ * If we are at the end of the input buffer then we are going to
+ * read fresh stuff. Otherwise, we are rereading input and don't
+ * need or want to prompt.
+ */
+ if (fseekp == feobp && aret == F_SEEK)
+ printprompt(0, NULL);
+ flush();
+ setalarm(1);
+ }
+ if (seterr) {
+ xfree((ptr_t) seterr);
+ seterr = NULL;
+ }
+
+ /*
+ * Echo not only on VERBOSE, but also with history expansion. If there
+ * is a lexical error then we forego history echo.
+ */
+ if ((lex(&paraml) && !seterr && intty && !tellwhat && !Expand &&
+ !whyles) || adrof(STRverbose)) {
+ haderr = 1;
+ prlex(&paraml);
+ haderr = 0;
+ }
+ (void) alarm(0); /* Autologout OFF */
+
+ /*
+ * The parser may lose space if interrupted.
+ */
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+
+ /*
+ * Save input text on the history list if reading in old history, or it
+ * is from the terminal at the top level and not in a loop.
+ *
+ * PWP: entry of items in the history list while in a while loop is done
+ * elsewhere...
+ */
+ if (enterhist || (catch && intty && !whyles && !tellwhat && !arun))
+ savehist(&paraml, enterhist > 1);
+
+ if (Expand && seterr)
+ Expand = 0;
+
+ /*
+ * Print lexical error messages, except when sourcing history lists.
+ */
+ if (!enterhist && seterr)
+ stderror(ERR_OLD);
+
+ /*
+ * If had a history command :p modifier then this is as far as we
+ * should go
+ */
+ if (justpr)
+ reset();
+
+ /*
+ * If had a tellwhat from twenex() then do
+ */
+ if (tellwhat) {
+ (void) tellmewhat(&paraml, NULL);
+ reset();
+ }
+
+ alias(&paraml);
+
+#ifdef BSDJOBS
+ /*
+ * If we are interactive, try to continue jobs that we have stopped
+ */
+ if (prompt)
+ continue_jobs(&paraml);
+#endif /* BSDJOBS */
+
+ /*
+ * Check to see if the user typed "rm * .o" or something
+ */
+ if (prompt)
+ rmstar(&paraml);
+ /*
+ * Parse the words of the input into a parse tree.
+ */
+ savet = syntax(paraml.next, &paraml, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+
+ postcmd();
+ /*
+ * Execute the parse tree From: Michael Schroeder
+ * <mlschroe@immd4.informatik.uni-erlangen.de> was execute(t, tpgrp);
+ */
+ execute(savet, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
+
+ /*
+ * Made it!
+ */
+ freelex(&paraml);
+ freesyn(savet), savet = NULL;
+#ifdef SIG_WINDOW
+ if (catch && intty && !whyles && !tellwhat)
+ (void) window_change(0); /* for window systems */
+#endif /* SIG_WINDOW */
+ set(STR_, Strsave(InputBuf), VAR_READWRITE | VAR_NOGLOB);
+ }
+ savet = t;
+ resexit(osetexit);
+}
+
+/*ARGSUSED*/
+void
+dosource(t, c)
+ register Char **t;
+ struct command *c;
+{
+ register Char *f;
+ bool hflg = 0;
+ extern int bequiet;
+ char buf[BUFSIZE];
+
+ USE(c);
+ t++;
+ if (*t && eq(*t, STRmh)) {
+ if (*++t == NULL)
+ stderror(ERR_NAME | ERR_HFLAG);
+ hflg++;
+ }
+ else if (*t && eq(*t, STRmm)) {
+ if (*++t == NULL)
+ stderror(ERR_NAME | ERR_MFLAG);
+ hflg = 2;
+ }
+
+ f = globone(*t++, G_ERROR);
+ (void) strcpy(buf, short2str(f));
+ xfree((ptr_t) f);
+ if ((!srcfile(buf, 0, hflg, t)) && (!hflg) && (!bequiet))
+ stderror(ERR_SYSTEM, buf, strerror(errno));
+}
+
+/*
+ * Check for mail.
+ * If we are a login shell, then we don't want to tell
+ * about any mail file unless its been modified
+ * after the time we started.
+ * This prevents us from telling the user things he already
+ * knows, since the login program insists on saying
+ * "You have mail."
+ */
+
+/*
+ * The AMS version.
+ * This version checks if the file is a directory, and if so,
+ * tells you the number of files in it, otherwise do the old thang.
+ * The magic "+1" in the time calculation is to compensate for
+ * an AFS bug where directory mtimes are set to 1 second in
+ * the future.
+ */
+
+static void
+mailchk()
+{
+ register struct varent *v;
+ register Char **vp;
+ time_t t;
+ int intvl, cnt;
+ struct stat stb;
+ bool new;
+
+ v = adrof(STRmail);
+ if (v == 0)
+ return;
+ (void) time(&t);
+ vp = v->vec;
+ cnt = blklen(vp);
+ intvl = (cnt && number(*vp)) ? (--cnt, getn(*vp++)) : MAILINTVL;
+ if (intvl < 1)
+ intvl = 1;
+ if (chktim + intvl > t)
+ return;
+ for (; *vp; vp++) {
+ char *filename = short2str(*vp);
+ char *mboxdir = filename;
+
+ if (stat(filename, &stb) < 0)
+ continue;
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+ new = stb.st_mtime > time0.tv_sec;
+#else
+ new = stb.st_mtime > time0;
+#endif
+ if (S_ISDIR(stb.st_mode)) {
+ DIR *mailbox;
+ int mailcount = 0;
+ char tempfilename[MAXPATHLEN];
+ struct stat stc;
+
+ xsnprintf(tempfilename, MAXPATHLEN, "%s/new", filename);
+
+ if (stat(tempfilename, &stc) != -1 && S_ISDIR(stc.st_mode)) {
+ /*
+ * "filename/new" exists and is a directory; you are
+ * using Qmail.
+ */
+ stb = stc;
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+ new = stb.st_mtime > time0.tv_sec;
+#else
+ new = stb.st_mtime > time0;
+#endif
+ mboxdir = tempfilename;
+ }
+
+ if (stb.st_mtime <= chktim + 1 || (loginsh && !new))
+ continue;
+
+ if ((mailbox = opendir(mboxdir)) == NULL)
+ continue;
+
+ /* skip . and .. */
+ if (!readdir(mailbox) || !readdir(mailbox))
+ continue;
+
+ while (readdir(mailbox))
+ mailcount++;
+
+ if (mailcount == 0)
+ continue;
+
+ if (cnt == 1)
+ xprintf(CGETS(11, 3, "You have %d mail messages.\n"),
+ mailcount);
+ else
+ xprintf(CGETS(11, 4, "You have %d mail messages in %s.\n"),
+ mailcount, filename);
+ }
+ else {
+ if (stb.st_size == 0 || stb.st_atime > stb.st_mtime ||
+ (stb.st_atime <= chktim && stb.st_mtime <= chktim) ||
+ (loginsh && !new))
+ continue;
+ if (cnt == 1)
+ xprintf(CGETS(11, 5, "You have %smail.\n"),
+ new ? CGETS(11, 6, "new ") : "");
+ else
+ xprintf(CGETS(11, 7, "You have %smail in %s.\n"),
+ new ? CGETS(11, 6, "new ") : "", filename);
+ }
+ }
+ chktim = t;
+}
+
+/*
+ * Extract a home directory from the password file
+ * The argument points to a buffer where the name of the
+ * user whose home directory is sought is currently.
+ * We write the home directory of the user back there.
+ */
+int
+gethdir(home)
+ Char *home;
+{
+ Char *h;
+
+ /*
+ * Is it us?
+ */
+ if (*home == '\0') {
+ if ((h = varval(STRhome)) != STRNULL) {
+ (void) Strcpy(home, h);
+ return 0;
+ }
+ else
+ return 1;
+ }
+
+ /*
+ * Look in the cache
+ */
+ if ((h = gettilde(home)) == NULL)
+ return 1;
+ else {
+ (void) Strcpy(home, h);
+ return 0;
+ }
+}
+
+/*
+ * Move the initial descriptors to their eventual
+ * resting places, closing all other units.
+ */
+void
+initdesc()
+{
+#ifdef NLS_BUGS
+#ifdef NLS_CATALOGS
+ (void)catclose(catd);
+#endif /* NLS_CATALOGS */
+#endif /* NLS_BUGS */
+
+
+ didfds = 0; /* 0, 1, 2 aren't set up */
+ (void) close_on_exec(SHIN = dcopy(0, FSHIN), 1);
+ (void) close_on_exec(SHOUT = dcopy(1, FSHOUT), 1);
+ (void) close_on_exec(SHDIAG = dcopy(2, FSHDIAG), 1);
+ (void) close_on_exec(OLDSTD = dcopy(SHIN, FOLDSTD), 1);
+#ifndef CLOSE_ON_EXEC
+ didcch = 0; /* Havent closed for child */
+#endif /* CLOSE_ON_EXEC */
+ isdiagatty = isatty(SHDIAG);
+ isoutatty = isatty(SHOUT);
+ closem();
+#ifdef NLS_BUGS
+#ifdef NLS_CATALOGS
+ nlsinit();
+#endif /* NLS_CATALOGS */
+#endif /* NLS_BUGS */
+}
+
+
+void
+#ifdef PROF
+done(i)
+#else
+xexit(i)
+#endif
+ int i;
+{
+#ifdef TESLA
+ if (loginsh && do_logout) {
+ /* this is to send hangup signal to the develcon */
+ /* we toggle DTR. clear dtr - sleep 1 - set dtr */
+ /* ioctl will return ENOTTY for pty's but we ignore it */
+ /* exitstat will run after disconnect */
+ /* we sleep for 2 seconds to let things happen in */
+ /* .logout and rechist() */
+#ifdef TIOCCDTR
+ (void) sleep(2);
+ (void) ioctl(FSHTTY, TIOCCDTR, NULL);
+ (void) sleep(1);
+ (void) ioctl(FSHTTY, TIOCSDTR, NULL);
+#endif /* TIOCCDTR */
+ }
+#endif /* TESLA */
+
+ {
+ struct process *pp, *np;
+
+ /* Kill all processes marked for hup'ing */
+ for (pp = proclist.p_next; pp; pp = pp->p_next) {
+ np = pp;
+ do
+ if ((np->p_flags & PHUP) && np->p_jobid != shpgrp) {
+ if (killpg(np->p_jobid, SIGHUP) != -1) {
+ /* In case the job was suspended... */
+#ifdef SIGCONT
+ (void) killpg(np->p_jobid, SIGCONT);
+#endif
+ break;
+ }
+ }
+ while ((np = np->p_friends) != pp);
+ }
+ }
+ untty();
+#ifdef NLS_CATALOGS
+ /*
+ * We need to call catclose, because SVR4 leaves symlinks behind otherwise
+ * in the catalog directories. We cannot close on a vforked() child,
+ * because messages will stop working on the parent too.
+ */
+ if (child == 0)
+ (void) catclose(catd);
+#endif /* NLS_CATALOGS */
+#ifdef WINNT
+ nt_cleanup();
+#endif /* WINNT */
+ _exit(i);
+}
+
+#ifndef _PATH_DEFPATH
+static Char **
+defaultpath()
+{
+ char *ptr;
+ Char **blk, **blkp;
+ struct stat stb;
+
+ blkp = blk = (Char **) xmalloc((size_t) sizeof(Char *) * 10);
+
+#ifndef NODOT
+# ifndef DOTLAST
+ *blkp++ = Strsave(STRdot);
+# endif
+#endif
+
+#define DIRAPPEND(a) \
+ if (stat(ptr = a, &stb) == 0 && S_ISDIR(stb.st_mode)) \
+ *blkp++ = SAVE(ptr)
+
+#ifdef _PATH_LOCAL
+ DIRAPPEND(_PATH_LOCAL);
+#endif
+
+#ifdef _PATH_USRUCB
+ DIRAPPEND(_PATH_USRUCB);
+#endif
+
+#ifdef _PATH_USRBSD
+ DIRAPPEND(_PATH_USRBSD);
+#endif
+
+#ifdef _PATH_BIN
+ DIRAPPEND(_PATH_BIN);
+#endif
+
+#ifdef _PATH_USRBIN
+ DIRAPPEND(_PATH_USRBIN);
+#endif
+
+#undef DIRAPPEND
+
+#ifndef NODOT
+# ifdef DOTLAST
+ *blkp++ = Strsave(STRdot);
+# endif
+#endif
+ *blkp = NULL;
+ return (blk);
+}
+#endif
+
+static void
+record()
+{
+ if (!fast) {
+ recdirs(NULL, adrof(STRsavedirs) != NULL);
+ rechist(NULL, adrof(STRsavehist) != NULL);
+ }
+}
diff --git a/contrib/tcsh/sh.char.c b/contrib/tcsh/sh.char.c
new file mode 100644
index 0000000..b3cfaf1
--- /dev/null
+++ b/contrib/tcsh/sh.char.c
@@ -0,0 +1,1206 @@
+/* $Header: /src/pub/tcsh/sh.char.c,v 3.12 1998/09/18 16:09:06 christos Exp $ */
+/*
+ * sh.char.c: Character classification tables
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.char.c,v 3.12 1998/09/18 16:09:06 christos Exp $")
+
+#include "sh.char.h"
+
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+/* on default same as original map */
+unsigned short _cmap[256] = {
+/* 0 nul 1 soh 2 stx 3 etx */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 4 eot 5 enq 6 ack 7 bel */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 8 bs 9 ht 10 nl 11 vt */
+ _CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
+
+/* 12 np 13 cr 14 so 15 si */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 16 dle 17 dc1 18 dc2 19 dc3 */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 20 dc4 21 nak 22 syn 23 etb */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 24 can 25 em 26 sub 27 esc */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 28 fs 29 gs 30 rs 31 us */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 32 sp 33 ! 34 " 35 # */
+ _SP|_META, _PUN, _QF|_PUN, _META|_PUN,
+
+/* 36 $ 37 % 38 & 39 ' */
+ _DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN,
+
+/* 40 ( 41 ) 42 * 43 + */
+ _META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN,
+
+/* 44 , 45 - 46 . 47 / */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 48 0 49 1 50 2 51 3 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 52 4 53 5 54 6 55 7 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 56 8 57 9 58 : 59 ; */
+ _DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN,
+
+/* 60 < 61 = 62 > 63 ? */
+ _META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN,
+
+/* 64 @ 65 A 66 B 67 C */
+ _PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
+
+/* 68 D 69 E 70 F 71 G */
+ _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
+
+/* 72 H 73 I 74 J 75 K */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 76 L 77 M 78 N 79 O */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 80 P 81 Q 82 R 83 S */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 84 T 85 U 86 V 87 W */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 88 X 89 Y 90 Z 91 [ */
+ _LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN,
+
+/* 92 \ 93 ] 94 ^ 95 _ */
+ _ESC|_PUN, _PUN, _PUN, _PUN,
+
+/* 96 ` 97 a 98 b 99 c */
+ _QB|_GLOB|_META|_PUN, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD,
+
+/* 100 d 101 e 102 f 103 g */
+ _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW,
+
+/* 104 h 105 i 106 j 107 k */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 108 l 109 m 110 n 111 o */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 112 p 113 q 114 r 115 s */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 116 t 117 u 118 v 119 w */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 120 x 121 y 122 z 123 { */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _GLOB|_PUN,
+
+/* 124 | 125 } 126 ~ 127 del */
+ _META|_CMD|_PUN,_PUN, _PUN, _CTR,
+
+/****************************************************************/
+/* 128 - 255 The below is supposedly ISO 8859/1 */
+/****************************************************************/
+/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */
+ _PUN, /* XXX */ _PUN, _PUN, _PUN,
+
+/* 164 currency 165 yen 166 brokenbar 167 section */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 172 notsign 173 hyphen 174 registered 175 macron */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 180 acute 181 mu 182 paragraph 183 periodcentered*/
+ _PUN, _PUN, /*XXX*/ _PUN, _PUN,
+
+/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */
+ _LET|_UP, _LET|_UP, _LET|_UP, _PUN,
+
+/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_DOW,
+
+/* 224 agrave 225 aacute 226 acircumflex 227 atilde */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 240 eth 241 ntilde 242 ograve 243 oacute */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _PUN,
+
+/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+};
+/* original table */
+unsigned short _cmap_c[256] = {
+/* 0 nul 1 soh 2 stx 3 etx */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 4 eot 5 enq 6 ack 7 bel */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 8 bs 9 ht 10 nl 11 vt */
+ _CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
+
+/* 12 np 13 cr 14 so 15 si */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 16 dle 17 dc1 18 dc2 19 dc3 */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 20 dc4 21 nak 22 syn 23 etb */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 24 can 25 em 26 sub 27 esc */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 28 fs 29 gs 30 rs 31 us */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 32 sp 33 ! 34 " 35 # */
+ _SP|_META, _PUN, _QF|_PUN, _META|_PUN,
+
+/* 36 $ 37 % 38 & 39 ' */
+ _DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN,
+
+/* 40 ( 41 ) 42 * 43 + */
+ _META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN,
+
+/* 44 , 45 - 46 . 47 / */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 48 0 49 1 50 2 51 3 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 52 4 53 5 54 6 55 7 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 56 8 57 9 58 : 59 ; */
+ _DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN,
+
+/* 60 < 61 = 62 > 63 ? */
+ _META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN,
+
+/* 64 @ 65 A 66 B 67 C */
+ _PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
+
+/* 68 D 69 E 70 F 71 G */
+ _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
+
+/* 72 H 73 I 74 J 75 K */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 76 L 77 M 78 N 79 O */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 80 P 81 Q 82 R 83 S */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 84 T 85 U 86 V 87 W */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 88 X 89 Y 90 Z 91 [ */
+ _LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN,
+
+/* 92 \ 93 ] 94 ^ 95 _ */
+ _ESC|_PUN, _PUN, _PUN, _PUN,
+
+/* 96 ` 97 a 98 b 99 c */
+ _QB|_GLOB|_META|_PUN, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD,
+
+/* 100 d 101 e 102 f 103 g */
+ _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW,
+
+/* 104 h 105 i 106 j 107 k */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 108 l 109 m 110 n 111 o */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 112 p 113 q 114 r 115 s */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 116 t 117 u 118 v 119 w */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 120 x 121 y 122 z 123 { */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _GLOB|_PUN,
+
+/* 124 | 125 } 126 ~ 127 del */
+ _META|_CMD|_PUN,_PUN, _PUN, _CTR,
+
+/****************************************************************/
+/* 128 - 255 The below is supposedly ISO 8859/1 */
+/****************************************************************/
+/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */
+ _PUN, /* XXX */ _PUN, _PUN, _PUN,
+
+/* 164 currency 165 yen 166 brokenbar 167 section */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 172 notsign 173 hyphen 174 registered 175 macron */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 180 acute 181 mu 182 paragraph 183 periodcentered*/
+ _PUN, _PUN, /*XXX*/ _PUN, _PUN,
+
+/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */
+ _LET|_UP, _LET|_UP, _LET|_UP, _PUN,
+
+/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_DOW,
+
+/* 224 agrave 225 aacute 226 acircumflex 227 atilde */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 240 eth 241 ntilde 242 ograve 243 oacute */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _PUN,
+
+/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+};
+
+/* multi-byte table */
+/* BY Masaaki Koyanagi VERY THANKS */
+unsigned short _cmap_mbyte[256] = {
+/* 0 nul 1 soh 2 stx 3 etx */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 4 eot 5 enq 6 ack 7 bel */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 8 bs 9 ht 10 nl 11 vt */
+ _CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
+
+/* 12 np 13 cr 14 so 15 si */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 16 dle 17 dc1 18 dc2 19 dc3 */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 20 dc4 21 nak 22 syn 23 etb */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 24 can 25 em 26 sub 27 esc */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 28 fs 29 gs 30 rs 31 us */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 32 sp 33 ! 34 " 35 # */
+ _SP|_META, _PUN, _QF|_PUN, _META|_PUN,
+
+/* 36 $ 37 % 38 & 39 ' */
+ _DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN,
+
+/* 40 ( 41 ) 42 * 43 + */
+ _META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN,
+
+/* 44 , 45 - 46 . 47 / */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 48 0 49 1 50 2 51 3 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 52 4 53 5 54 6 55 7 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 56 8 57 9 58 : 59 ; */
+ _DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN,
+
+/* 60 < 61 = 62 > 63 ? */
+ _META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN,
+
+/* 64 @ 65 A 66 B 67 C */
+ _PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
+
+/* 68 D 69 E 70 F 71 G */
+ _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
+
+/* 72 H 73 I 74 J 75 K */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 76 L 77 M 78 N 79 O */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 80 P 81 Q 82 R 83 S */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 84 T 85 U 86 V 87 W */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 88 X 89 Y 90 Z 91 [ */
+ _LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN,
+
+/* 92 \ 93 ] 94 ^ 95 _ */
+ _ESC|_PUN, _PUN, _PUN, _PUN,
+
+/* 96 ` 97 a 98 b 99 c */
+ _QB|_GLOB|_META|_PUN, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD,
+
+/* 100 d 101 e 102 f 103 g */
+ _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW,
+
+/* 104 h 105 i 106 j 107 k */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 108 l 109 m 110 n 111 o */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 112 p 113 q 114 r 115 s */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 116 t 117 u 118 v 119 w */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 120 x 121 y 122 z 123 { */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _GLOB|_PUN,
+
+/* 124 | 125 } 126 ~ 127 del */
+ _META|_CMD|_PUN,_PUN, _PUN, _CTR,
+
+/****************************************************************/
+/* 128 - 255 The below is supposedly ISO 8859/1 */
+/****************************************************************/
+/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */
+ _PUN, /* XXX */ _PUN, _PUN, _PUN,
+
+/* 164 currency 165 yen 166 brokenbar 167 section */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 172 notsign 173 hyphen 174 registered 175 macron */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 180 acute 181 mu 182 paragraph 183 periodcentered*/
+ _PUN, _PUN, /*XXX*/ _PUN, _PUN,
+
+/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */
+ _LET|_UP, _LET|_UP, _LET|_UP, _PUN,
+
+/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_DOW,
+
+/* 224 agrave 225 aacute 226 acircumflex 227 atilde */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 240 eth 241 ntilde 242 ograve 243 oacute */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _PUN,
+
+/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+};
+
+short _enable_mbdisp = 0; /* control multi-byte 0...disable 1...enable */
+
+/* multi-byte check table */
+/* default = all 0 (clear process in update_vars()/unset()) */
+unsigned short _mbmap[256];
+
+unsigned short _mbmap_euc[256] = {
+/* first byte 0x8e,0xa0 - 0xf4 */
+/* second byte 0xa0 - 0xfe */
+/* 0 - 7f all 0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/* 80 81 82 83 */
+ 0, 0, 0, 0,
+/* 84 85 86 87 */
+ 0, 0, 0, 0,
+/* 88 89 8a 8b */
+ 0, 0, 0, 0,
+/* 8c 8d 8e 8f */
+ 0, 0, _MB1, 0,
+/* 90 - 9f all 0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/* a0 a1 a2 a3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* a4 a5 a6 a7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* a8 a9 aa ab */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* ac ad ae af */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* b0 b1 b2 b3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* b4 b5 b6 b7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* b8 b9 ba bb */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* bc bd be bf */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* c0 c1 c2 c3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* c4 c5 c6 c7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* c8 c9 ca cb */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* cc cd ce cf */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* d0 d1 d2 d3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* d4 d5 d6 d7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* d8 d9 da db */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* dc dd de df */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* e0 e1 e2 e3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* e4 e5 e6 e7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* e8 e9 ea eb */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* ec ed ee ef */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* f0 f1 f2 f3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* f4 f5 f6 f7 */
+ _MB1|_MB2, _MB2, _MB2, _MB2,
+/* f8 f9 fa fb */
+ _MB2, _MB2, _MB2, _MB2,
+/* fc fd fe ff */
+ _MB2, _MB2, _MB2, 0,
+};
+
+unsigned short _mbmap_sjis[256] = {
+/* first byte 0x81-0x9f,0xe0 - 0xfc */
+/* second byte 0x40-0x7e,0x80 - 0xfc */
+/* 0 - 3f all 0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/* 40 41 42 43 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 44 45 46 47 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 48 49 4a 4b */
+ _MB2, _MB2, _MB2, _MB2,
+/* 4c 4d 4e 4f */
+ _MB2, _MB2, _MB2, _MB2,
+/* 50 51 52 53 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 54 55 56 57 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 58 59 5a 5b */
+ _MB2, _MB2, _MB2, _MB2,
+/* 5c 5d 5e 5f */
+ _MB2, _MB2, _MB2, _MB2,
+/* 60 61 62 63 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 64 65 66 67 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 68 69 6a 6b */
+ _MB2, _MB2, _MB2, _MB2,
+/* 6c 6d 6e 6f */
+ _MB2, _MB2, _MB2, _MB2,
+/* 70 71 72 73 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 74 75 76 77 */
+ _MB2, _MB2, _MB2, _MB2,
+/* 78 79 7a 7b */
+ _MB2, _MB2, _MB2, _MB2,
+/* 7c 7d 7e 7f */
+ _MB2, _MB2, _MB2, 0,
+/* 80 81 82 83 */
+ _MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 84 85 86 87 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 88 89 8a 8b */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 8c 8d 8e 8f */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 90 91 92 93 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 94 95 96 97 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 98 99 9a 9b */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* 9c 9d 9e 9f */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* a0 a1 a2 a3 */
+ _MB2, _MB2, _MB2, _MB2,
+/* a4 a5 a6 a7 */
+ _MB2, _MB2, _MB2, _MB2,
+/* a8 a9 aa ab */
+ _MB2, _MB2, _MB2, _MB2,
+/* ac ad ae af */
+ _MB2, _MB2, _MB2, _MB2,
+/* b0 b1 b2 b3 */
+ _MB2, _MB2, _MB2, _MB2,
+/* b4 b5 b6 b7 */
+ _MB2, _MB2, _MB2, _MB2,
+/* b8 b9 ba bb */
+ _MB2, _MB2, _MB2, _MB2,
+/* bc bd be bf */
+ _MB2, _MB2, _MB2, _MB2,
+/* c0 c1 c2 c3 */
+ _MB2, _MB2, _MB2, _MB2,
+/* c4 c5 c6 c7 */
+ _MB2, _MB2, _MB2, _MB2,
+/* c8 c9 ca cb */
+ _MB2, _MB2, _MB2, _MB2,
+/* cc cd ce cf */
+ _MB2, _MB2, _MB2, _MB2,
+/* d0 d1 d2 d3 */
+ _MB2, _MB2, _MB2, _MB2,
+/* d4 d5 d6 d7 */
+ _MB2, _MB2, _MB2, _MB2,
+/* d8 d9 da db */
+ _MB2, _MB2, _MB2, _MB2,
+/* dc dd de df */
+ _MB2, _MB2, _MB2, _MB2,
+/* e0 e1 e2 e3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* e4 e5 e6 e7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* e8 e9 ea eb */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* ec ed ee ef */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* f0 f1 f2 f3 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* f4 f5 f6 f7 */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* f8 f9 fa fb */
+ _MB1|_MB2, _MB1|_MB2, _MB1|_MB2, _MB1|_MB2,
+/* fc fd fe ff */
+ _MB1|_MB2, 0, 0, 0,
+};
+
+#else /* !(defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)) */
+unsigned short _cmap[256] = {
+/* 0 nul 1 soh 2 stx 3 etx */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 4 eot 5 enq 6 ack 7 bel */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 8 bs 9 ht 10 nl 11 vt */
+ _CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
+
+/* 12 np 13 cr 14 so 15 si */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 16 dle 17 dc1 18 dc2 19 dc3 */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 20 dc4 21 nak 22 syn 23 etb */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 24 can 25 em 26 sub 27 esc */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 28 fs 29 gs 30 rs 31 us */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 32 sp 33 ! 34 " 35 # */
+ _SP|_META, _PUN, _QF|_PUN, _META|_PUN,
+
+/* 36 $ 37 % 38 & 39 ' */
+ _DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN,
+
+/* 40 ( 41 ) 42 * 43 + */
+ _META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN,
+
+/* 44 , 45 - 46 . 47 / */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 48 0 49 1 50 2 51 3 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 52 4 53 5 54 6 55 7 */
+ _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
+
+/* 56 8 57 9 58 : 59 ; */
+ _DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN,
+
+/* 60 < 61 = 62 > 63 ? */
+ _META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN,
+
+/* 64 @ 65 A 66 B 67 C */
+ _PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
+
+/* 68 D 69 E 70 F 71 G */
+ _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
+
+/* 72 H 73 I 74 J 75 K */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 76 L 77 M 78 N 79 O */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 80 P 81 Q 82 R 83 S */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 84 T 85 U 86 V 87 W */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 88 X 89 Y 90 Z 91 [ */
+ _LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN,
+
+/* 92 \ 93 ] 94 ^ 95 _ */
+ _ESC|_PUN, _PUN, _PUN, _PUN,
+
+/* 96 ` 97 a 98 b 99 c */
+ _QB|_GLOB|_META|_PUN, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD,
+
+/* 100 d 101 e 102 f 103 g */
+ _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW|_XD, _LET|_DOW,
+
+/* 104 h 105 i 106 j 107 k */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 108 l 109 m 110 n 111 o */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 112 p 113 q 114 r 115 s */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 116 t 117 u 118 v 119 w */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 120 x 121 y 122 z 123 { */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _GLOB|_PUN,
+
+/* 124 | 125 } 126 ~ 127 del */
+ _META|_CMD|_PUN,_PUN, _PUN, _CTR,
+
+#ifdef SHORT_STRINGS
+/****************************************************************/
+/* 128 - 255 The below is supposedly ISO 8859/1 */
+/****************************************************************/
+/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */
+ _CTR, _CTR, _CTR, _CTR,
+
+/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */
+ _PUN, /* XXX */ _PUN, _PUN, _PUN,
+
+/* 164 currency 165 yen 166 brokenbar 167 section */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 172 notsign 173 hyphen 174 registered 175 macron */
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 180 acute 181 mu 182 paragraph 183 periodcentered*/
+ _PUN, _PUN, /*XXX*/ _PUN, _PUN,
+
+/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/
+ _PUN, _PUN, _PUN, _PUN,
+
+/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */
+ _LET|_UP, _LET|_UP, _LET|_UP, _PUN,
+
+/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
+
+/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */
+ _LET|_UP, _LET|_UP, _LET|_UP, _LET|_DOW,
+
+/* 224 agrave 225 aacute 226 acircumflex 227 atilde */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 240 eth 241 ntilde 242 ograve 243 oacute */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _PUN,
+
+/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+
+/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */
+ _LET|_DOW, _LET|_DOW, _LET|_DOW, _LET|_DOW,
+#endif /* SHORT_STRINGS */
+};
+#endif /* defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) */
+
+#ifndef NLS
+/* _cmap_lower, _cmap_upper for ISO 8859/1 */
+
+unsigned char _cmap_lower[256] = {
+ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
+ 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
+ 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
+ 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
+ 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
+ 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
+ 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
+ 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
+ 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
+ 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
+ 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0327,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
+};
+
+unsigned char _cmap_upper[256] = {
+ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
+ 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
+ 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
+ 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
+ 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
+ 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0367,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0377,
+};
+#endif /* NLS */
+
+#ifdef _OSD_POSIX
+/*
+ Initial Port for tcsh-6.07.04 by <Martin.Kraemer@Mch.SNI.De>
+
+"BS2000 OSD" is a POSIX on a main frame.
+It is made by Siemens Nixdorf AG, Germany.
+Within the POSIX subsystem, the same character set was chosen as in
+"native BS2000", namely EBCDIC. Yes, tcsh now runs on EBCDIC platforms, too.
+
+EBCDIC Table. (Yes, in EBCDIC, the letters 'a'..'z' are not contiguous!)
+This table is bijective, i.e. there are no ambigous or duplicate characters
+00 00 01 02 03 85 09 86 7f 87 8d 8e 0b 0c 0d 0e 0f * ................ *
+10 10 11 12 13 8f 0a 08 97 18 19 9c 9d 1c 1d 1e 1f * ................ *
+20 80 81 82 83 84 92 17 1b 88 89 8a 8b 8c 05 06 07 * ................ *
+30 90 91 16 93 94 95 96 04 98 99 9a 9b 14 15 9e 1a * ................ *
+40 20 a0 e2 e4 e0 e1 e3 e5 e7 f1 60 2e 3c 28 2b 7c * .........`.<(+| *
+50 26 e9 ea eb e8 ed ee ef ec df 21 24 2a 29 3b 9f * &.........!$*);. *
+60 2d 2f c2 c4 c0 c1 c3 c5 c7 d1 5e 2c 25 5f 3e 3f * -/........^,%_>? *
+70 f8 c9 ca cb c8 cd ce cf cc a8 3a 23 40 27 3d 22 * ..........:#@'=" *
+80 d8 61 62 63 64 65 66 67 68 69 ab bb f0 fd fe b1 * .abcdefghi...... *
+90 b0 6a 6b 6c 6d 6e 6f 70 71 72 aa ba e6 b8 c6 a4 * .jklmnopqr...... *
+a0 b5 af 73 74 75 76 77 78 79 7a a1 bf d0 dd de ae * ..stuvwxyz...... *
+b0 a2 a3 a5 b7 a9 a7 b6 bc bd be ac 5b 5c 5d b4 d7 * ...........[\].. *
+c0 f9 41 42 43 44 45 46 47 48 49 ad f4 f6 f2 f3 f5 * .ABCDEFGHI...... *
+d0 a6 4a 4b 4c 4d 4e 4f 50 51 52 b9 fb fc db fa ff * .JKLMNOPQR...... *
+e0 d9 f7 53 54 55 56 57 58 59 5a b2 d4 d6 d2 d3 d5 * ..STUVWXYZ...... *
+f0 30 31 32 33 34 35 36 37 38 39 b3 7b dc 7d da 7e * 0123456789.{.}.~ *
+*/
+unsigned short _toascii[256] = {
+/*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
+ 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */
+/*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
+ 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */
+/*20*/ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */
+/*30*/ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */
+/*40*/ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+| */
+/*50*/ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /* &.........!$*);. */
+/*60*/ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /* -/........^,%_>? */
+/*70*/ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* ..........:#@'=" */
+/*80*/ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */
+/*90*/ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */
+/*a0*/ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /* ..stuvwxyz...... */
+/*b0*/ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /* ...........[\].. */
+/*c0*/ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* .ABCDEFGHI...... */
+/*d0*/ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /* .JKLMNOPQR...... */
+/*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* ..STUVWXYZ...... */
+/*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /* 0123456789.{.}.~ */
+};
+/* The same, for ascii-in-ebcdic
+00 00 01 02 03 37 2d 2e 2f 16 05 15 0b 0c 0d 0e 0f * ................ *
+10 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f * ................ *
+20 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 * !"#$%&'()*+,-./ *
+30 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f * 0123456789:;<=>? *
+40 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 * @ABCDEFGHIJKLMNO *
+50 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 bb bc bd 6a 6d * PQRSTUVWXYZ[\]^_ *
+60 4a 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 * `abcdefghijklmno *
+70 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 fb 4f fd ff 07 * pqrstuvwxyz{|}~. *
+80 20 21 22 23 24 04 06 08 28 29 2a 2b 2c 09 0a 14 * ................ *
+90 30 31 25 33 34 35 36 17 38 39 3a 3b 1a 1b 3e 5f * ................ *
+a0 41 aa b0 b1 9f b2 d0 b5 79 b4 9a 8a ba ca af a1 * ................ *
+b0 90 8f ea fa be a0 b6 b3 9d da 9b 8b b7 b8 b9 ab * ................ *
+c0 64 65 62 66 63 67 9e 68 74 71 72 73 78 75 76 77 * ................ *
+d0 ac 69 ed ee eb ef ec bf 80 e0 fe dd fc ad ae 59 * ................ *
+e0 44 45 42 46 43 47 9c 48 54 51 52 53 58 55 56 57 * ................ *
+f0 8c 49 cd ce cb cf cc e1 70 c0 de db dc 8d 8e df * ................ *
+*/
+unsigned short _toebcdic[256] = {
+/*00*/ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */
+/*10*/ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */
+/*20*/ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */
+/*30*/ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /* 0123456789:;<=>? */
+/*40*/ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /* @ABCDEFGHIJKLMNO */
+/*50*/ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xbb, 0xbc, 0xbd, 0x6a, 0x6d, /* PQRSTUVWXYZ[\]^_ */
+/*60*/ 0x4a, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* `abcdefghijklmno */
+/*70*/ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xfb, 0x4f, 0xfd, 0xff, 0x07, /* pqrstuvwxyz{|}~. */
+/*80*/ 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /* ................ */
+/*90*/ 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17,
+ 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0x5f, /* ................ */
+/*a0*/ 0x41, 0xaa, 0xb0, 0xb1, 0x9f, 0xb2, 0xd0, 0xb5,
+ 0x79, 0xb4, 0x9a, 0x8a, 0xba, 0xca, 0xaf, 0xa1, /* ................ */
+/*b0*/ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /* ................ */
+/*c0*/ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* ................ */
+/*d0*/ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xe0, 0xfe, 0xdd, 0xfc, 0xad, 0xae, 0x59, /* ................ */
+/*e0*/ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* ................ */
+/*f0*/ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xc0, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /* ................ */
+};
+
+#endif /*_OSD_POSIX*/
diff --git a/contrib/tcsh/sh.char.h b/contrib/tcsh/sh.char.h
new file mode 100644
index 0000000..63c127c
--- /dev/null
+++ b/contrib/tcsh/sh.char.h
@@ -0,0 +1,250 @@
+/* $Header: /src/pub/tcsh/sh.char.h,v 3.15 1998/09/18 16:09:07 christos Exp $ */
+/*
+ * sh.char.h: Table for spotting special characters quickly
+ * Makes for very obscure but efficient coding.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh_char
+#define _h_sh_char
+#if defined(NeXT) && defined(NLS)
+# include <appkit/NXCType.h>
+#else
+# include <ctype.h>
+#endif
+
+typedef unsigned char tcshuc;
+#ifdef _MINIX
+# undef _SP
+#endif /* _MINIX */
+extern unsigned short _cmap[];
+#if defined(DSPMBYTE)
+extern unsigned short _mbmap[];
+# define CHECK_MBYTEVAR STRdspmbyte
+#endif
+extern unsigned short _cmap_c[];
+extern unsigned short _cmap_mbyte[];
+extern short _enable_mbdisp;
+extern unsigned short _mbmap[];
+extern unsigned short _mbmap_euc[];
+extern unsigned short _mbmap_sjis[];
+/* VARIABLE Check str */
+/* same compiler require #define even not define DSPMBYTE */
+#define _MB1 0x0001
+#define _MB2 0x0002
+
+#ifndef NLS
+extern tcshuc _cmap_lower[], _cmap_upper[];
+
+#endif
+
+#define _QF 0x0001 /* '" (Forward quotes) */
+#define _QB 0x0002 /* ` (Backquote) */
+#define _SP 0x0004 /* space and tab */
+#define _NL 0x0008 /* \n */
+#define _META 0x0010 /* lex meta characters, sp #'`";&<>()|\t\n */
+#define _GLOB 0x0020 /* glob characters, *?{[` */
+#define _ESC 0x0040 /* \ */
+#define _DOL 0x0080 /* $ */
+#define _DIG 0x0100 /* 0-9 */
+#define _LET 0x0200 /* a-z, A-Z, _ */
+#define _UP 0x0400 /* A-Z */
+#define _DOW 0x0800 /* a-z */
+#define _XD 0x1000 /* 0-9, a-f, A-F */
+#define _CMD 0x2000 /* lex end of command chars, ;&(|` */
+#define _CTR 0x4000 /* control */
+#define _PUN 0x8000 /* punctuation */
+
+#if defined(SHORT_STRINGS) && defined(KANJI)
+#define ASC(ch) ch
+#define CTL_ESC(ch) ch
+#define cmap(c, bits) \
+ ((((c) & QUOTE) || ((c & 0x80) && adrof(STRnokanji))) ? \
+ 0 : (_cmap[(tcshuc)(c)] & (bits)))
+#else
+#ifndef _OSD_POSIX
+#define ASC(ch) ch
+#define CTL_ESC(ch) ch
+#define cmap(c, bits) \
+ (((c) & QUOTE) ? 0 : (_cmap[(tcshuc)(c)] & (bits)))
+#else /*_OSD_POSIX*/
+/* "BS2000 OSD" is a POSIX on a main frame using a EBCDIC char set */
+extern unsigned short _toascii[256];
+extern unsigned short _toebcdic[256];
+
+/* mainly for comparisons if (ASC(ch)=='\177')... */
+#define ASC(ch) _toascii[(tcshuc)ch]
+
+/* Literal escapes ('\010') must be mapped to EBCDIC,
+ * for C-Escapes ('\b'), the compiler already does it.
+ */
+#define CTL_ESC(ch) _toebcdic[(tcshuc)ch]
+
+#define cmap(c, bits) \
+ (((c) & QUOTE) ? 0 : (_cmap[_toascii[(tcshuc)(c)]] & (bits)))
+#endif /*_OSD_POSIX*/
+#endif
+
+#define isglob(c) cmap(c, _GLOB)
+#define isspc(c) cmap(c, _SP)
+#define ismeta(c) cmap(c, _META)
+#define iscmdmeta(c) cmap(c, _CMD)
+#define letter(c) (((Char)(c) & QUOTE) ? 0 : \
+ (isalpha((tcshuc) (c)) || (c) == '_'))
+#define alnum(c) (((Char)(c) & QUOTE) ? 0 : \
+ (isalnum((tcshuc) (c)) || (c) == '_'))
+
+#if defined(DSPMBYTE)
+# define IsmbyteU(c) (Ismbyte1((Char)(c))||(Ismbyte2((Char)(c))&&((c)&0200)))
+#endif
+
+#ifdef NLS
+# ifdef NeXT
+# define Isspace(c) (((Char)(c) & QUOTE) ? 0 : NXIsSpace((unsigned) (c)))
+# define Isdigit(c) (((Char)(c) & QUOTE) ? 0 : NXIsDigit((unsigned) (c)))
+# define Isalpha(c) (((Char)(c) & QUOTE) ? 0 : NXIsAlpha((unsigned) (c)))
+# define Islower(c) (((Char)(c) & QUOTE) ? 0 : NXIsLower((unsigned) (c)))
+# define Isupper(c) (((Char)(c) & QUOTE) ? 0 : NXIsUpper((unsigned) (c)))
+# define Tolower(c) (((Char)(c) & QUOTE) ? 0 : NXToLower((unsigned) (c)))
+# define Toupper(c) (((Char)(c) & QUOTE) ? 0 : NXToUpper((unsigned) (c)))
+# define Isxdigit(c) (((Char)(c) & QUOTE) ? 0 : NXIsXDigit((unsigned) (c)))
+#if defined(DSPMBYTE)
+# define IscntrlM(c) (((Char)(c) & QUOTE) ? 0 : NXIsCntrl((unsigned) (c)))
+# define Iscntrl(c) ( (IscntrlM(c)) && !(_enable_mbdisp&&(IsmbyteU((c)))) )
+# define IsprintM(c) (((Char)(c) & QUOTE) ? 0 : NXIsPrint((unsigned) (c)))
+# define Isprint(c) ( (IsprintM(c)) || (_enable_mbdisp&&(IsmbyteU((c)))) )
+#else
+# define Isalnum(c) (((Char)(c) & QUOTE) ? 0 : NXIsAlNum((unsigned) (c)))
+# define Iscntrl(c) (((Char)(c) & QUOTE) ? 0 : NXIsCntrl((unsigned) (c)))
+# define Isprint(c) (((Char)(c) & QUOTE) ? 0 : NXIsPrint((unsigned) (c)))
+#endif /* !defined(DSPMBYTE) */
+# define Ispunct(c) (((Char)(c) & QUOTE) ? 0 : NXIsPunct((unsigned) (c)))
+# else /* !NeXT */
+# ifndef WINNT
+# define Isspace(c) (((Char)(c) & QUOTE) ? 0 : isspace((tcshuc) (c)))
+# define Isdigit(c) (((Char)(c) & QUOTE) ? 0 : isdigit((tcshuc) (c)))
+# define Isalpha(c) (((Char)(c) & QUOTE) ? 0 : isalpha((tcshuc) (c)))
+# define Islower(c) (((Char)(c) & QUOTE) ? 0 : islower((tcshuc) (c)))
+# define Isupper(c) (((Char)(c) & QUOTE) ? 0 : isupper((tcshuc) (c)))
+# define Tolower(c) (((Char)(c) & QUOTE) ? 0 : tolower((tcshuc) (c)))
+# define Toupper(c) (((Char)(c) & QUOTE) ? 0 : toupper((tcshuc) (c)))
+# define Isxdigit(c) (((Char)(c) & QUOTE) ? 0 : isxdigit((tcshuc) (c)))
+# define Isalnum(c) (((Char)(c) & QUOTE) ? 0 : isalnum((tcshuc) (c)))
+#if defined(DSPMBYTE)
+# define IscntrlM(c) (((Char)(c) & QUOTE) ? 0 : iscntrl((tcshuc) (c)))
+# define Iscntrl(c) ( (IscntrlM(c)) && !(_enable_mbdisp&&(IsmbyteU((c)))) )
+#else
+# define Iscntrl(c) (((Char)(c) & QUOTE) ? 0 : iscntrl((tcshuc) (c)))
+#endif /* !defined(DSPMBYTE) */
+# if SOLARIS2 == 24
+ /*
+ * From <casper@fwi.uva.nl> Casper Dik:
+ * In Solaris 2.4, isprint('\t') returns true after setlocal(LC_ALL,"").
+ * This breaks commandline editing when you include tabs.
+ * (This is in the en_US locale).
+ */
+#if defined(DSPMBYTE)
+# define IsprintM(c) (((Char)(c) & QUOTE) ? 0 : \
+ (isprint((tcshuc) (c)) && (c) != '\t'))
+#else
+# define Isprint(c) (((Char)(c) & QUOTE) ? 0 : \
+ (isprint((tcshuc) (c)) && (c) != '\t'))
+#endif /* !defined(DSPMBYTE) */
+# else
+#if defined(DSPMBYTE)
+# define IsprintM(c) (((Char)(c) & QUOTE) ? 0 : isprint((tcshuc) (c)))
+#else
+# define Isprint(c) (((Char)(c) & QUOTE) ? 0 : isprint((tcshuc) (c)))
+#endif /* !defined(DSPMBYTE) */
+# endif /* SOLARIS2 == 24 */
+#if defined(DSPMBYTE)
+# define Isprint(c) ( (IsprintM(c)) || (_enable_mbdisp&&(IsmbyteU((c)))) )
+#endif /* !defined(DSPMBYTE) */
+# define Ispunct(c) (((Char)(c) & QUOTE) ? 0 : ispunct((tcshuc) (c)))
+# else /* WINNT */
+# define Isspace(c) (((Char)(c) & QUOTE) ? 0 : isspace( oem_it((tcshuc)(c))))
+# define Isdigit(c) (((Char)(c) & QUOTE) ? 0 : isdigit( oem_it((tcshuc)(c))))
+# define Isalpha(c) (((Char)(c) & QUOTE) ? 0 : isalpha( oem_it((tcshuc)(c))))
+# define Islower(c) (((Char)(c) & QUOTE) ? 0 : islower( oem_it((tcshuc)(c))))
+# define Isupper(c) (((Char)(c) & QUOTE) ? 0 : isupper( oem_it((tcshuc)(c))))
+# define Tolower(c) (((Char)(c) & QUOTE) ? 0 : tolower( oem_it((tcshuc)(c))))
+# define Toupper(c) (((Char)(c) & QUOTE) ? 0 : toupper( oem_it((tcshuc)(c))))
+# define Isxdigit(c)(((Char)(c) & QUOTE) ? 0 : isxdigit(oem_it((tcshuc)(c))))
+# define Isalnum(c) (((Char)(c) & QUOTE) ? 0 : isalnum( oem_it((tcshuc)(c))))
+# define Ispunct(c) (((Char)(c) & QUOTE) ? 0 : ispunct( oem_it((tcshuc)(c))))
+#if defined(DSPMBYTE)
+# define IscntrlM(c) (((Char)(c) & QUOTE) ? 0 : iscntrl( oem_it((tcshuc)(c))))
+# define Iscntrl(c) ( (IscntrlM(c)) && !(_enable_mbdisp&&(IsmbyteU((c)))) )
+# define IsprintM(c) (((Char)(c) & QUOTE) ? 0 : isprint( oem_it((tcshuc)(c))))
+# define Isprint(c) ( (IsprintM(c)) || (_enable_mbdisp&&(IsmbyteU((c)))) )
+#else
+# define Iscntrl(c) (((Char)(c) & QUOTE) ? 0 : iscntrl( oem_it((tcshuc)(c))))
+# define Isprint(c) (((Char)(c) & QUOTE) ? 0 : isprint( oem_it((tcshuc)(c))))
+#endif /* !defined(DSPMBYTE) */
+# endif /* WINNT */
+# endif /* !NeXT */
+#else /* !NLS */
+# define Isspace(c) cmap(c, _SP|_NL)
+# define Isdigit(c) cmap(c, _DIG)
+# define Isalpha(c) (cmap(c,_LET) && !(((c) & META) && AsciiOnly))
+# define Islower(c) (cmap(c,_DOW) && !(((c) & META) && AsciiOnly))
+# define Isupper(c) (cmap(c, _UP) && !(((c) & META) && AsciiOnly))
+#ifndef _OSD_POSIX
+# define Tolower(c) (_cmap_lower[(tcshuc)(c)])
+# define Toupper(c) (_cmap_upper[(tcshuc)(c)])
+#else /*_OSD_POSIX*/
+/* "BS2000 OSD" is a POSIX on a main frame using a EBCDIC char set */
+# define Tolower(c) (_cmap_lower[_toascii[(tcshuc)(c)]])
+# define Toupper(c) (_cmap_upper[_toascii[(tcshuc)(c)]])
+#endif /*_OSD_POSIX*/
+# define Isxdigit(c) cmap(c, _XD)
+# define Isalnum(c) (cmap(c, _DIG|_LET) && !(((Char)(c) & META) && AsciiOnly))
+#if defined(DSPMBYTE)
+# define IscntrlM(c) (cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
+# define Iscntrl(c) ( (IscntrlM(c)) && !(_enable_mbdisp&&(IsmbyteU((c)))) )
+# define IsprintM(c) (!cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
+# define Isprint(c) ( (IsprintM(c)) || (_enable_mbdisp&&(IsmbyteU((c)))) )
+#else
+# define Iscntrl(c) (cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
+# define Isprint(c) (!cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
+#endif /* !defined(DSPMBYTE) */
+# define Ispunct(c) (cmap(c,_PUN) && !(((c) & META) && AsciiOnly))
+
+#endif /* !NLS */
+
+#if defined(DSPMBYTE)
+# define Ismbyte1(c) ((_mbmap[(c) & 0377] & _MB1) ? 1 : 0)
+# define Ismbyte2(c) ((_mbmap[(c) & 0377] & _MB2) ? 1 : 0)
+#endif
+
+#endif /* _h_sh_char */
diff --git a/contrib/tcsh/sh.decls.h b/contrib/tcsh/sh.decls.h
new file mode 100644
index 0000000..4fd433d
--- /dev/null
+++ b/contrib/tcsh/sh.decls.h
@@ -0,0 +1,380 @@
+/* $Header: /src/pub/tcsh/sh.decls.h,v 3.34 1999/02/06 15:01:21 christos Exp $ */
+/*
+ * sh.decls.h External declarations from sh*.c
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh_decls
+#define _h_sh_decls
+
+/*
+ * sh.c
+ */
+extern int gethdir __P((Char *));
+extern void dosource __P((Char **, struct command *));
+extern void exitstat __P((void));
+extern void goodbye __P((Char **, struct command *));
+extern void importpath __P((Char *));
+extern void initdesc __P((void));
+extern sigret_t pintr __P((int));
+extern void pintr1 __P((bool));
+extern void process __P((bool));
+extern void untty __P((void));
+#ifdef PROF
+extern void done __P((int));
+#else
+extern void xexit __P((int));
+#endif
+
+/*
+ * sh.dir.c
+ */
+extern void dinit __P((Char *));
+extern void dodirs __P((Char **, struct command *));
+extern Char *dcanon __P((Char *, Char *));
+extern void dtildepr __P((Char *));
+extern void dtilde __P((void));
+extern void dochngd __P((Char **, struct command *));
+extern Char *dnormalize __P((Char *, int));
+extern void dopushd __P((Char **, struct command *));
+extern void dopopd __P((Char **, struct command *));
+extern void dfree __P((struct directory *));
+extern void dsetstack __P((void));
+extern int getstakd __P((Char *, int));
+extern void recdirs __P((Char *, int));
+extern void loaddirs __P((Char *));
+
+/*
+ * sh.dol.c
+ */
+extern void Dfix __P((struct command *));
+extern Char *Dfix1 __P((Char *));
+extern void heredoc __P((Char *));
+
+/*
+ * sh.err.c
+ */
+extern void errinit __P((void));
+extern void seterror __P((unsigned int, ...));
+extern void stderror __P((unsigned int, ...));
+
+/*
+ * sh.exec.c
+ */
+extern void doexec __P((struct command *));
+extern void dohash __P((Char **, struct command *));
+extern void dounhash __P((Char **, struct command *));
+extern void execash __P((Char **, struct command *));
+extern void hashstat __P((Char **, struct command *));
+extern void xechoit __P((Char **));
+extern int executable __P((Char *, Char *, bool));
+extern int tellmewhat __P((struct wordent *, Char *));
+extern void dowhere __P((Char **, struct command *));
+extern int find_cmd __P((Char *, int));
+
+/*
+ * sh.exp.c
+ */
+extern Char *filetest __P((Char *, Char ***, bool));
+extern int expr __P((Char ***));
+extern int exp0 __P((Char ***, bool));
+
+/*
+ * sh.file.c
+ */
+#ifdef FILEC
+extern int tenex __P((Char *, int));
+#endif
+
+/*
+ * sh.func.c
+ */
+extern void tsetenv __P((Char *, Char *));
+extern void Unsetenv __P((Char *));
+extern void doalias __P((Char **, struct command *));
+extern void dobreak __P((Char **, struct command *));
+extern void docontin __P((Char **, struct command *));
+extern void doecho __P((Char **, struct command *));
+extern void doelse __P((Char **, struct command *));
+extern void doend __P((Char **, struct command *));
+extern void doeval __P((Char **, struct command *));
+extern void doexit __P((Char **, struct command *));
+extern void doforeach __P((Char **, struct command *));
+extern void doglob __P((Char **, struct command *));
+extern void dogoto __P((Char **, struct command *));
+extern void doif __P((Char **, struct command *));
+extern void dolimit __P((Char **, struct command *));
+extern void dologin __P((Char **, struct command *));
+extern void dologout __P((Char **, struct command *));
+#ifdef NEWGRP
+extern void donewgrp __P((Char **, struct command *));
+#endif
+extern void donohup __P((Char **, struct command *));
+extern void dohup __P((Char **, struct command *));
+extern void doonintr __P((Char **, struct command *));
+extern void doprintenv __P((Char **, struct command *));
+extern void dorepeat __P((Char **, struct command *));
+extern void dofiletest __P((Char **, struct command *));
+extern void dosetenv __P((Char **, struct command *));
+extern void dosuspend __P((Char **, struct command *));
+extern void doswbrk __P((Char **, struct command *));
+extern void doswitch __P((Char **, struct command *));
+extern void doumask __P((Char **, struct command *));
+extern void dounlimit __P((Char **, struct command *));
+extern void dounsetenv __P((Char **, struct command *));
+extern void dowhile __P((Char **, struct command *));
+extern void dozip __P((Char **, struct command *));
+extern void func __P((struct command *,
+ struct biltins *));
+extern void gotolab __P((Char *));
+extern struct biltins *isbfunc __P((struct command *));
+extern void prvars __P((void));
+extern int srchx __P((Char *));
+extern void unalias __P((Char **, struct command *));
+extern void wfree __P((void));
+extern void dobuiltins __P((Char **, struct command *));
+extern void reexecute __P((struct command *));
+
+/*
+ * sh.glob.c
+ */
+extern Char *globequal __P((Char *, Char *));
+extern Char **dobackp __P((Char *, bool));
+extern void Gcat __P((Char *, Char *));
+extern Char *globone __P((Char *, int));
+extern int Gmatch __P((Char *, Char *));
+extern int Gnmatch __P((Char *, Char *, Char **));
+extern void ginit __P((void));
+extern Char **globall __P((Char **));
+extern void rscan __P((Char **, void (*)(int)));
+extern void tglob __P((Char **));
+extern void trim __P((Char **));
+#ifdef FILEC
+extern int sortscmp __P((Char **, Char **));
+#endif
+extern void nlsinit __P((void));
+
+/*
+ * sh.hist.c
+ */
+extern void dohist __P((Char **, struct command *));
+extern struct Hist *enthist __P((int, struct wordent *, bool, bool));
+extern void savehist __P((struct wordent *, bool));
+extern void fmthist __P((int, ptr_t, char *, size_t));
+extern void rechist __P((Char *, int));
+extern void loadhist __P((Char *, bool));
+
+/*
+ * sh.init.c
+ */
+extern void mesginit __P((void));
+
+/*
+ * sh.lex.c
+ */
+extern void addla __P((Char *));
+extern void bseek __P((struct Ain *));
+extern void btell __P((struct Ain *));
+extern void btoeof __P((void));
+extern void copylex __P((struct wordent *,
+ struct wordent *));
+extern Char *domod __P((Char *, int));
+extern void freelex __P((struct wordent *));
+extern int lex __P((struct wordent *));
+extern void prlex __P((struct wordent *));
+extern int readc __P((bool));
+extern void settell __P((void));
+extern void unreadc __P((int));
+
+
+/*
+ * sh.misc.c
+ */
+extern int any __P((char *, int));
+extern Char **blkcpy __P((Char **, Char **));
+extern void blkfree __P((Char **));
+extern int blklen __P((Char **));
+extern void blkpr __P((Char **));
+extern void blkexpand __P((Char **, Char *));
+extern Char **blkspl __P((Char **, Char **));
+extern void closem __P((void));
+#ifndef CLOSE_ON_EXEC
+extern void closech __P((void));
+#endif /* !CLOSE_ON_EXEC */
+extern Char **copyblk __P((Char **));
+extern int dcopy __P((int, int));
+extern int dmove __P((int, int));
+extern void donefds __P((void));
+extern Char lastchr __P((Char *));
+extern void lshift __P((Char **, int));
+extern int number __P((Char *));
+extern int prefix __P((Char *, Char *));
+extern Char **saveblk __P((Char **));
+extern void setzero __P((char *, int));
+extern Char *strip __P((Char *));
+extern Char *quote __P((Char *));
+extern Char *quote_meta __P((Char *, const Char *));
+extern char *strsave __P((const char *));
+extern void udvar __P((Char *));
+#ifndef POSIX
+extern char *strstr __P((const char *, const char *));
+#endif /* !POSIX */
+#ifndef SHORT_STRINGS
+extern char *strspl __P((char *, char *));
+extern char *strend __P((char *));
+#endif /* SHORT_STRINGS */
+
+/*
+ * sh.parse.c
+ */
+extern void alias __P((struct wordent *));
+extern void freesyn __P((struct command *));
+extern struct command *syntax __P((struct wordent *,
+ struct wordent *, int));
+
+/*
+ * sh.print.c
+ */
+extern void drainoline __P((void));
+extern void flush __P((void));
+#ifdef BSDTIMES
+extern void pcsecs __P((long));
+#else /* !BSDTIMES */
+# ifdef POSIX
+extern void pcsecs __P((clock_t));
+# else /* !POSIX */
+extern void pcsecs __P((time_t));
+# endif /* !POSIX */
+#endif /* BSDTIMES */
+#ifdef BSDLIMIT
+extern void psecs __P((long));
+#endif /* BSDLIMIT */
+extern int putpure __P((int));
+extern int putraw __P((int));
+extern void xputchar __P((int));
+
+
+/*
+ * sh.proc.c
+ */
+extern void dobg __P((Char **, struct command *));
+extern void dobg1 __P((Char **, struct command *));
+extern void dofg __P((Char **, struct command *));
+extern void dofg1 __P((Char **, struct command *));
+extern void dojobs __P((Char **, struct command *));
+extern void dokill __P((Char **, struct command *));
+extern void donotify __P((Char **, struct command *));
+extern void dostop __P((Char **, struct command *));
+extern void dowait __P((Char **, struct command *));
+extern void palloc __P((int, struct command *));
+extern void panystop __P((bool));
+extern sigret_t pchild __P((int));
+extern void pendjob __P((void));
+extern int pfork __P((struct command *, int));
+extern void pgetty __P((int, int));
+extern void pjwait __P((struct process *));
+extern void pnote __P((void));
+extern void prestjob __P((void));
+extern void psavejob __P((void));
+extern int pstart __P((struct process *, int));
+extern void pwait __P((void));
+extern struct process *pfind __P((Char *));
+
+/*
+ * sh.sem.c
+ */
+extern void execute __P((struct command *, int, int *,
+ int *));
+extern void mypipe __P((int *));
+
+/*
+ * sh.set.c
+ */
+extern struct varent *adrof1 __P((Char *, struct varent *));
+extern void doset __P((Char **, struct command *));
+extern void dolet __P((Char **, struct command *));
+extern Char *putn __P((int));
+extern int getn __P((Char *));
+extern Char *value1 __P((Char *, struct varent *));
+extern void set __P((Char *, Char *, int));
+extern void set1 __P((Char *, Char **, struct varent *,
+ int));
+extern void setq __P((Char *, Char **, struct varent *,
+ int));
+extern void unset __P((Char **, struct command *));
+extern void unset1 __P((Char *[], struct varent *));
+extern void unsetv __P((Char *));
+extern void setNS __P((Char *));
+extern void shift __P((Char **, struct command *));
+extern void plist __P((struct varent *, int));
+#if defined(DSPMBYTE)
+extern void update_dspmbyte_vars __P((void));
+extern void autoset_dspmbyte __P((Char *));
+#endif
+
+/*
+ * sh.time.c
+ */
+extern void donice __P((Char **, struct command *));
+extern void dotime __P((Char **, struct command *));
+#ifdef BSDTIMES
+extern void prusage __P((struct sysrusage *,
+ struct sysrusage *,
+ timeval_t *, timeval_t *));
+extern void ruadd __P((struct sysrusage *,
+ struct sysrusage *));
+#else /* BSDTIMES */
+# ifdef _SEQUENT_
+extern void prusage __P((struct process_stats *,
+ struct process_stats *,
+ timeval_t *, timeval_t *));
+extern void ruadd __P((struct process_stats *,
+ struct process_stats *));
+# else /* !_SEQUENT_ */
+# ifdef POSIX
+extern void prusage __P((struct tms *, struct tms *,
+ clock_t, clock_t));
+# else /* !POSIX */
+extern void prusage __P((struct tms *, struct tms *,
+ time_t, time_t));
+# endif /* !POSIX */
+# endif /* !_SEQUENT_ */
+#endif /* BSDTIMES */
+extern void settimes __P((void));
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+extern void tvsub __P((struct timeval *,
+ struct timeval *,
+ struct timeval *));
+#endif /* BSDTIMES || _SEQUENT_ */
+
+#endif /* _h_sh_decls */
diff --git a/contrib/tcsh/sh.dir.c b/contrib/tcsh/sh.dir.c
new file mode 100644
index 0000000..d6e90ed
--- /dev/null
+++ b/contrib/tcsh/sh.dir.c
@@ -0,0 +1,1381 @@
+/* $Header: /src/pub/tcsh/sh.dir.c,v 3.52 1998/10/25 15:10:03 christos Exp $ */
+/*
+ * sh.dir.c: Directory manipulation functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.dir.c,v 3.52 1998/10/25 15:10:03 christos Exp $")
+
+/*
+ * C Shell - directory management
+ */
+
+static void dstart __P((const char *));
+static struct directory *dfind __P((Char *));
+static Char *dfollow __P((Char *));
+static void printdirs __P((int));
+static Char *dgoto __P((Char *));
+static void dnewcwd __P((struct directory *, int));
+static void dset __P((Char *));
+static void dextract __P((struct directory *));
+static int skipargs __P((Char ***, char *, char *));
+static void dgetstack __P((void));
+
+static struct directory dhead INIT_ZERO_STRUCT; /* "head" of loop */
+static int printd; /* force name to be printed */
+
+int bequiet = 0; /* do not print dir stack -strike */
+
+static void
+dstart(from)
+ const char *from;
+{
+ xprintf(CGETS(12, 1, "%s: Trying to start from \"%s\"\n"), progname, from);
+}
+
+/*
+ * dinit - initialize current working directory
+ */
+void
+dinit(hp)
+ Char *hp;
+{
+ register char *tcp;
+ register Char *cp;
+ register struct directory *dp;
+ char path[MAXPATHLEN];
+
+ /* Don't believe the login shell home, because it may be a symlink */
+ tcp = (char *) getcwd(path, sizeof(path));
+ if (tcp == NULL || *tcp == '\0') {
+ xprintf("%s: %s\n", progname, strerror(errno));
+ if (hp && *hp) {
+ tcp = short2str(hp);
+ dstart(tcp);
+ if (chdir(tcp) == -1)
+ cp = NULL;
+ else
+ cp = Strsave(hp);
+ }
+ else
+ cp = NULL;
+ if (cp == NULL) {
+ dstart("/");
+ if (chdir("/") == -1)
+ /* I am not even try to print an error message! */
+ xexit(1);
+ cp = SAVE("/");
+ }
+ }
+ else {
+#ifdef S_IFLNK
+ struct stat swd, shp;
+
+ /*
+ * See if $HOME is the working directory we got and use that
+ */
+ if (hp && *hp &&
+ stat(tcp, &swd) != -1 && stat(short2str(hp), &shp) != -1 &&
+ DEV_DEV_COMPARE(swd.st_dev, shp.st_dev) &&
+ swd.st_ino == shp.st_ino)
+ cp = Strsave(hp);
+ else {
+ char *cwd;
+
+ /*
+ * use PWD if we have it (for subshells)
+ */
+ if ((cwd = getenv("PWD")) != NULL) {
+ if (stat(cwd, &shp) != -1 &&
+ DEV_DEV_COMPARE(swd.st_dev, shp.st_dev) &&
+ swd.st_ino == shp.st_ino)
+ tcp = cwd;
+ }
+ cp = dcanon(SAVE(tcp), STRNULL);
+ }
+#else /* S_IFLNK */
+ cp = dcanon(SAVE(tcp), STRNULL);
+#endif /* S_IFLNK */
+ }
+
+ dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
+ dp->di_name = cp;
+ dp->di_count = 0;
+ dhead.di_next = dhead.di_prev = dp;
+ dp->di_next = dp->di_prev = &dhead;
+ printd = 0;
+ dnewcwd(dp, 0);
+ set(STRdirstack, Strsave(dp->di_name), VAR_READWRITE|VAR_NOGLOB);
+}
+
+static void
+dset(dp)
+Char *dp;
+{
+ /*
+ * Don't call set() directly cause if the directory contains ` or
+ * other junk characters glob will fail.
+ */
+ set(STRowd, Strsave(varval(STRcwd)), VAR_READWRITE|VAR_NOGLOB);
+ set(STRcwd, Strsave(dp), VAR_READWRITE|VAR_NOGLOB);
+
+ tsetenv(STRPWD, dp);
+}
+
+#define DIR_PRINT 0x01 /* -p */
+#define DIR_LONG 0x02 /* -l */
+#define DIR_VERT 0x04 /* -v */
+#define DIR_LINE 0x08 /* -n */
+#define DIR_SAVE 0x10 /* -S */
+#define DIR_LOAD 0x20 /* -L */
+#define DIR_CLEAR 0x40 /* -c */
+#define DIR_OLD 0x80 /* - */
+
+static int
+skipargs(v, dstr, str)
+ Char ***v;
+ char *dstr;
+ char *str;
+{
+ Char **n = *v, *s;
+
+ int dflag = 0, loop = 1;
+ for (n++; loop && *n != NULL && (*n)[0] == '-'; n++)
+ if (*(s = &((*n)[1])) == '\0') /* test for bare "-" argument */
+ dflag |= DIR_OLD;
+ else {
+ char *p;
+ while (loop && *s != '\0') /* examine flags */
+ {
+ if ((p = strchr(dstr, *s++)) != NULL)
+ dflag |= (1 << (p - dstr));
+ else {
+ stderror(ERR_DIRUS, short2str(**v), dstr, str);
+ loop = 0; /* break from both loops */
+ break;
+ }
+ }
+ }
+ if (*n && (dflag & DIR_OLD))
+ stderror(ERR_DIRUS, short2str(**v), dstr, str);
+ *v = n;
+ /* make -l, -v, and -n imply -p */
+ if (dflag & (DIR_LONG|DIR_VERT|DIR_LINE))
+ dflag |= DIR_PRINT;
+ return dflag;
+}
+
+/*
+ * dodirs - list all directories in directory loop
+ */
+/*ARGSUSED*/
+void
+dodirs(v, c)
+ Char **v;
+ struct command *c;
+{
+ static char flags[] = "plvnSLc";
+ int dflag = skipargs(&v, flags, "");
+
+ USE(c);
+ if ((dflag & DIR_CLEAR) != 0) {
+ struct directory *dp, *fdp;
+ for (dp = dcwd->di_next; dp != dcwd; ) {
+ fdp = dp;
+ dp = dp->di_next;
+ if (fdp != &dhead)
+ dfree(fdp);
+ }
+ dhead.di_next = dhead.di_prev = dp;
+ dp->di_next = dp->di_prev = &dhead;
+ }
+ if ((dflag & DIR_LOAD) != 0)
+ loaddirs(*v);
+ else if ((dflag & DIR_SAVE) != 0)
+ recdirs(*v, 1);
+
+ if (*v && (dflag & (DIR_SAVE|DIR_LOAD)))
+ v++;
+
+ if (*v != NULL || (dflag & DIR_OLD))
+ stderror(ERR_DIRUS, "dirs", flags, "");
+ if ((dflag & (DIR_CLEAR|DIR_LOAD|DIR_SAVE)) == 0 || (dflag & DIR_PRINT))
+ printdirs(dflag);
+}
+
+static void
+printdirs(dflag)
+ int dflag;
+{
+ register struct directory *dp;
+ Char *s, *user;
+ int idx, len, cur;
+ extern int T_Cols;
+
+ dp = dcwd;
+ idx = 0;
+ cur = 0;
+ do {
+ if (dp == &dhead)
+ continue;
+ if (dflag & DIR_VERT) {
+ xprintf("%d\t", idx++);
+ cur = 0;
+ }
+ s = dp->di_name;
+ user = NULL;
+ if (!(dflag & DIR_LONG) && (user = getusername(&s)) != NULL)
+ len = (int) (Strlen(user) + Strlen(s) + 2);
+ else
+ len = (int) (Strlen(s) + 1);
+
+ cur += len;
+ if ((dflag & DIR_LINE) && cur >= T_Cols - 1 && len < T_Cols) {
+ xputchar('\n');
+ cur = len;
+ }
+ if (user)
+ xprintf("~%S", user);
+ xprintf("%S%c", s, (dflag & DIR_VERT) ? '\n' : ' ');
+ } while ((dp = dp->di_prev) != dcwd);
+ if (!(dflag & DIR_VERT))
+ xputchar('\n');
+}
+
+void
+dtildepr(dir)
+ Char *dir;
+{
+ Char* user;
+ if ((user = getusername(&dir)) != NULL)
+ xprintf("~%S%S", user, dir);
+ else
+ xprintf("%S", dir);
+}
+
+void
+dtilde()
+{
+ struct directory *d = dcwd;
+
+ do {
+ if (d == &dhead)
+ continue;
+ d->di_name = dcanon(d->di_name, STRNULL);
+ } while ((d = d->di_prev) != dcwd);
+
+ dset(dcwd->di_name);
+}
+
+
+/* dnormalize():
+ * The path will be normalized if it
+ * 1) is "..",
+ * 2) or starts with "../",
+ * 3) or ends with "/..",
+ * 4) or contains the string "/../",
+ * then it will be normalized, unless those strings are quoted.
+ * Otherwise, a copy is made and sent back.
+ */
+Char *
+dnormalize(cp, exp)
+ Char *cp;
+ int exp;
+{
+
+/* return true if dp is of the form "../xxx" or "/../xxx" */
+#define IS_DOTDOT(sp, p) (ISDOTDOT(p) && ((p) == (sp) || *((p) - 1) == '/'))
+#define IS_DOT(sp, p) (ISDOT(p) && ((p) == (sp) || *((p) - 1) == '/'))
+
+#ifdef S_IFLNK
+ if (exp) {
+ int dotdot = 0;
+ Char *dp, *cwd, *start = cp, buf[MAXPATHLEN];
+# ifdef apollo
+ bool slashslash;
+# endif /* apollo */
+
+ /*
+ * count the number of "../xxx" or "xxx/../xxx" in the path
+ */
+ for (dp=start; *dp && *(dp+1); dp++)
+ if (IS_DOTDOT(start, dp))
+ dotdot++;
+ /*
+ * if none, we are done.
+ */
+ if (dotdot == 0)
+ return (Strsave(cp));
+
+ cwd = (Char *) xmalloc((size_t) (((int) Strlen(dcwd->di_name) + 3) *
+ sizeof(Char)));
+ (void) Strcpy(cwd, dcwd->di_name);
+
+ /*
+ * If the path starts with a slash, we are not relative to
+ * the current working directory.
+ */
+ if (ABSOLUTEP(start))
+ *cwd = '\0';
+# ifdef apollo
+ slashslash = cwd[0] == '/' && cwd[1] == '/';
+# endif /* apollo */
+
+ /*
+ * Ignore . and count ..'s
+ */
+ for (;;) {
+ dotdot = 0;
+ buf[0] = '\0';
+ dp = buf;
+ while (*cp)
+ if (IS_DOT(start, cp)) {
+ if (*++cp)
+ cp++;
+ }
+ else if (IS_DOTDOT(start, cp)) {
+ if (buf[0])
+ break; /* finish analyzing .././../xxx/[..] */
+ dotdot++;
+ cp += 2;
+ if (*cp)
+ cp++;
+ }
+ else
+ *dp++ = *cp++;
+
+ *dp = '\0';
+ while (dotdot > 0)
+ if ((dp = Strrchr(cwd, '/')) != NULL) {
+# ifdef apollo
+ if (dp == &cwd[1])
+ slashslash = 1;
+# endif /* apollo */
+ *dp = '\0';
+ dotdot--;
+ }
+ else
+ break;
+
+ if (!*cwd) { /* too many ..'s, starts with "/" */
+ cwd[0] = '/';
+# ifdef apollo
+ cwd[1] = '/';
+ cwd[2] = '\0';
+# else /* !apollo */
+ cwd[1] = '\0';
+# endif /* apollo */
+ }
+# ifdef apollo
+ else if (slashslash && cwd[1] == '\0') {
+ cwd[1] = '/';
+ cwd[2] = '\0';
+ }
+# endif /* apollo */
+
+ if (buf[0]) {
+ if ((TRM(cwd[(dotdot = (int) Strlen(cwd)) - 1])) != '/')
+ cwd[dotdot++] = '/';
+ cwd[dotdot] = '\0';
+ dp = Strspl(cwd, TRM(buf[0]) == '/' ? &buf[1] : buf);
+ xfree((ptr_t) cwd);
+ cwd = dp;
+ if ((TRM(cwd[(dotdot = (int) Strlen(cwd)) - 1])) == '/')
+ cwd[--dotdot] = '\0';
+ }
+ if (!*cp)
+ break;
+ }
+ return cwd;
+ }
+#endif /* S_IFLNK */
+ return Strsave(cp);
+}
+
+
+/*
+ * dochngd - implement chdir command.
+ */
+/*ARGSUSED*/
+void
+dochngd(v, c)
+ Char **v;
+ struct command *c;
+{
+ register Char *cp;
+ register struct directory *dp;
+ int dflag = skipargs(&v, "plvn", "[-|<dir>]");
+
+ USE(c);
+ printd = 0;
+ cp = (dflag & DIR_OLD) ? varval(STRowd) : *v;
+
+ if (cp == NULL) {
+ if ((cp = varval(STRhome)) == STRNULL || *cp == 0)
+ stderror(ERR_NAME | ERR_NOHOMEDIR);
+ if (chdir(short2str(cp)) < 0)
+ stderror(ERR_NAME | ERR_CANTCHANGE);
+ cp = Strsave(cp);
+ }
+ else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) {
+ stderror(ERR_NAME | ERR_TOOMANY);
+ /* NOTREACHED */
+ return;
+ }
+ else if ((dp = dfind(cp)) != 0) {
+ char *tmp;
+
+ printd = 1;
+ if (chdir(tmp = short2str(dp->di_name)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ dcwd->di_prev->di_next = dcwd->di_next;
+ dcwd->di_next->di_prev = dcwd->di_prev;
+ dfree(dcwd);
+ dnewcwd(dp, dflag);
+ return;
+ }
+ else
+ if ((cp = dfollow(cp)) == NULL)
+ return;
+ dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
+ dp->di_name = cp;
+ dp->di_count = 0;
+ dp->di_next = dcwd->di_next;
+ dp->di_prev = dcwd->di_prev;
+ dp->di_prev->di_next = dp;
+ dp->di_next->di_prev = dp;
+ dfree(dcwd);
+ dnewcwd(dp, dflag);
+}
+
+static Char *
+dgoto(cp)
+ Char *cp;
+{
+ Char *dp;
+
+ if (!ABSOLUTEP(cp))
+ {
+ register Char *p, *q;
+ int cwdlen;
+
+ for (p = dcwd->di_name; *p++;)
+ continue;
+ if ((cwdlen = (int) (p - dcwd->di_name - 1)) == 1) /* root */
+ cwdlen = 0;
+ for (p = cp; *p++;)
+ continue;
+ dp = (Char *) xmalloc((size_t)((cwdlen + (p - cp) + 1) * sizeof(Char)));
+ for (p = dp, q = dcwd->di_name; (*p++ = *q++) != '\0';)
+ continue;
+ if (cwdlen)
+ p[-1] = '/';
+ else
+ p--; /* don't add a / after root */
+ for (q = cp; (*p++ = *q++) != '\0';)
+ continue;
+ xfree((ptr_t) cp);
+ cp = dp;
+ dp += cwdlen;
+ }
+ else
+ dp = cp;
+
+#ifdef WINNT
+ cp = SAVE(getcwd(NULL, 0));
+#else /* !WINNT */
+ cp = dcanon(cp, dp);
+#endif /* WINNT */
+ return cp;
+}
+
+/*
+ * dfollow - change to arg directory; fall back on cdpath if not valid
+ */
+static Char *
+dfollow(cp)
+ register Char *cp;
+{
+ register Char *dp;
+ struct varent *c;
+ char ebuf[MAXPATHLEN];
+ int serrno;
+
+ cp = globone(cp, G_ERROR);
+#ifdef apollo
+ if (Strchr(cp, '`')) {
+ char *dptr, *ptr;
+ if (chdir(dptr = short2str(cp)) < 0)
+ stderror(ERR_SYSTEM, dptr, strerror(errno));
+ else if ((ptr = getcwd(ebuf, sizeof(ebuf))) && *ptr != '\0') {
+ xfree((ptr_t) cp);
+ cp = Strsave(str2short(ptr));
+ return dgoto(cp);
+ }
+ else
+ stderror(ERR_SYSTEM, dptr, ebuf);
+ }
+#endif /* apollo */
+
+ (void) strncpy(ebuf, short2str(cp), MAXPATHLEN);
+ ebuf[MAXPATHLEN-1] = '\0';
+ /*
+ * if we are ignoring symlinks, try to fix relatives now.
+ * if we are expading symlinks, it should be done by now.
+ */
+ dp = dnormalize(cp, symlinks == SYM_IGNORE);
+ if (chdir(short2str(dp)) >= 0) {
+ xfree((ptr_t) cp);
+ return dgoto(dp);
+ }
+ else {
+ xfree((ptr_t) dp);
+ if (chdir(short2str(cp)) >= 0)
+ return dgoto(cp);
+ else if (errno != ENOENT && errno != ENOTDIR)
+ stderror(ERR_SYSTEM, ebuf, strerror(errno));
+ serrno = errno;
+ }
+
+ if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp)
+ && (c = adrof(STRcdpath))) {
+ Char **cdp;
+ register Char *p;
+ Char buf[MAXPATHLEN];
+
+ for (cdp = c->vec; *cdp; cdp++) {
+ for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';)
+ continue;
+ dp[-1] = '/';
+ for (p = cp; (*dp++ = *p++) != '\0';)
+ continue;
+ /*
+ * We always want to fix the directory here
+ * If we are normalizing symlinks
+ */
+ dp = dnormalize(buf, symlinks == SYM_IGNORE ||
+ symlinks == SYM_EXPAND);
+ if (chdir(short2str(dp)) >= 0) {
+ printd = 1;
+ xfree((ptr_t) cp);
+ return dgoto(dp);
+ }
+ else if (chdir(short2str(cp)) >= 0) {
+ printd = 1;
+ xfree((ptr_t) dp);
+ return dgoto(cp);
+ }
+ }
+ }
+ dp = varval(cp);
+ if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) {
+ xfree((ptr_t) cp);
+ cp = Strsave(dp);
+ printd = 1;
+ return dgoto(cp);
+ }
+ xfree((ptr_t) cp);
+ /*
+ * on login source of ~/.cshdirs, errors are eaten. the dir stack is all
+ * directories we could get to.
+ */
+ if (!bequiet) {
+ stderror(ERR_SYSTEM, ebuf, strerror(serrno));
+ return (NULL);
+ }
+ else
+ return (NULL);
+}
+
+
+/*
+ * dopushd - push new directory onto directory stack.
+ * with no arguments exchange top and second.
+ * with numeric argument (+n) bring it to top.
+ */
+/*ARGSUSED*/
+void
+dopushd(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct directory *dp;
+ register Char *cp;
+ int dflag = skipargs(&v, "plvn", " [-|<dir>|+<n>]");
+
+ USE(c);
+ printd = 1;
+ cp = (dflag & DIR_OLD) ? varval(STRowd) : *v;
+
+ if (cp == NULL) {
+ if (adrof(STRpushdtohome)) {
+ if ((cp = varval(STRhome)) == STRNULL || *cp == 0)
+ stderror(ERR_NAME | ERR_NOHOMEDIR);
+ if (chdir(short2str(cp)) < 0)
+ stderror(ERR_NAME | ERR_CANTCHANGE);
+ cp = Strsave(cp); /* hmmm... PWP */
+ if ((cp = dfollow(cp)) == NULL)
+ return;
+ dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
+ dp->di_name = cp;
+ dp->di_count = 0;
+ dp->di_prev = dcwd;
+ dp->di_next = dcwd->di_next;
+ dcwd->di_next = dp;
+ dp->di_next->di_prev = dp;
+ }
+ else {
+ char *tmp;
+
+ if ((dp = dcwd->di_prev) == &dhead)
+ dp = dhead.di_prev;
+ if (dp == dcwd)
+ stderror(ERR_NAME | ERR_NODIR);
+ if (chdir(tmp = short2str(dp->di_name)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ dp->di_prev->di_next = dp->di_next;
+ dp->di_next->di_prev = dp->di_prev;
+ dp->di_next = dcwd->di_next;
+ dp->di_prev = dcwd;
+ dcwd->di_next->di_prev = dp;
+ dcwd->di_next = dp;
+ }
+ }
+ else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) {
+ stderror(ERR_NAME | ERR_TOOMANY);
+ /* NOTREACHED */
+ return;
+ }
+ else if ((dp = dfind(cp)) != NULL) {
+ char *tmp;
+
+ if (chdir(tmp = short2str(dp->di_name)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ /*
+ * kfk - 10 Feb 1984 - added new "extraction style" pushd +n
+ */
+ if (adrof(STRdextract))
+ dextract(dp);
+ }
+ else {
+ register Char *ccp;
+
+ if ((ccp = dfollow(cp)) == NULL)
+ return;
+ dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
+ dp->di_name = ccp;
+ dp->di_count = 0;
+ dp->di_prev = dcwd;
+ dp->di_next = dcwd->di_next;
+ dcwd->di_next = dp;
+ dp->di_next->di_prev = dp;
+ }
+ dnewcwd(dp, dflag);
+}
+
+/*
+ * dfind - find a directory if specified by numeric (+n) argument
+ */
+static struct directory *
+dfind(cp)
+ register Char *cp;
+{
+ register struct directory *dp;
+ register int i;
+ register Char *ep;
+
+ if (*cp++ != '+')
+ return (0);
+ for (ep = cp; Isdigit(*ep); ep++)
+ continue;
+ if (*ep)
+ return (0);
+ i = getn(cp);
+ if (i <= 0)
+ return (0);
+ for (dp = dcwd; i != 0; i--) {
+ if ((dp = dp->di_prev) == &dhead)
+ dp = dp->di_prev;
+ if (dp == dcwd)
+ stderror(ERR_NAME | ERR_DEEP);
+ }
+ return (dp);
+}
+
+/*
+ * dopopd - pop a directory out of the directory stack
+ * with a numeric argument just discard it.
+ */
+/*ARGSUSED*/
+void
+dopopd(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char *cp;
+ register struct directory *dp, *p = NULL;
+ int dflag = skipargs(&v, "plvn", " [-|+<n>]");
+
+ USE(c);
+ printd = 1;
+ cp = (dflag & DIR_OLD) ? varval(STRowd) : *v;
+
+ if (cp == NULL)
+ dp = dcwd;
+ else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) {
+ stderror(ERR_NAME | ERR_TOOMANY);
+ /* NOTREACHED */
+ return;
+ }
+ else if ((dp = dfind(cp)) == 0)
+ stderror(ERR_NAME | ERR_BADDIR);
+ if (dp->di_prev == &dhead && dp->di_next == &dhead)
+ stderror(ERR_NAME | ERR_EMPTY);
+ if (dp == dcwd) {
+ char *tmp;
+
+ if ((p = dp->di_prev) == &dhead)
+ p = dhead.di_prev;
+ if (chdir(tmp = short2str(p->di_name)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ }
+ dp->di_prev->di_next = dp->di_next;
+ dp->di_next->di_prev = dp->di_prev;
+ if (dp == dcwd) {
+ dnewcwd(p, dflag);
+ }
+ else {
+ printdirs(dflag);
+ }
+ dfree(dp);
+}
+
+/*
+ * dfree - free the directory (or keep it if it still has ref count)
+ */
+void
+dfree(dp)
+ register struct directory *dp;
+{
+
+ if (dp->di_count != 0) {
+ dp->di_next = dp->di_prev = 0;
+ }
+ else {
+ xfree((ptr_t) dp->di_name);
+ xfree((ptr_t) dp);
+ }
+}
+
+/*
+ * dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
+ * we are of course assuming that the file system is standardly
+ * constructed (always have ..'s, directories have links)
+ */
+Char *
+dcanon(cp, p)
+ register Char *cp, *p;
+{
+ register Char *sp;
+ register Char *p1, *p2; /* general purpose */
+ bool slash;
+#ifdef apollo
+ bool slashslash;
+#endif /* apollo */
+
+#ifdef S_IFLNK /* if we have symlinks */
+ Char link[MAXPATHLEN];
+ char tlink[MAXPATHLEN];
+ int cc;
+ Char *newcp;
+#endif /* S_IFLNK */
+
+ /*
+ * kim: if the path given is too long abort().
+ */
+ if (Strlen(cp) >= MAXPATHLEN)
+ abort();
+
+ /*
+ * christos: if the path given does not start with a slash prepend cwd. If
+ * cwd does not start with a slash or the result would be too long abort().
+ */
+ if (!ABSOLUTEP(cp)) {
+ Char tmpdir[MAXPATHLEN];
+
+ p1 = varval(STRcwd);
+ if (p1 == STRNULL || !ABSOLUTEP(p1))
+ abort();
+ if (Strlen(p1) + Strlen(cp) + 1 >= MAXPATHLEN)
+ abort();
+ (void) Strcpy(tmpdir, p1);
+ (void) Strcat(tmpdir, STRslash);
+ (void) Strcat(tmpdir, cp);
+ xfree((ptr_t) cp);
+ cp = p = Strsave(tmpdir);
+ }
+
+#ifdef COMMENT
+ if (*cp != '/')
+ abort();
+#endif /* COMMENT */
+
+#ifdef apollo
+ slashslash = (cp[0] == '/' && cp[1] == '/');
+#endif /* apollo */
+
+ while (*p) { /* for each component */
+ sp = p; /* save slash address */
+ while (*++p == '/') /* flush extra slashes */
+ continue;
+ if (p != ++sp)
+ for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';)
+ continue;
+ p = sp; /* save start of component */
+ slash = 0;
+ if (*p)
+ while (*++p) /* find next slash or end of path */
+ if (*p == '/') {
+ slash = 1;
+ *p = 0;
+ break;
+ }
+
+#ifdef apollo
+ if (&cp[1] == sp && sp[0] == '.' && sp[1] == '.' && sp[2] == '\0')
+ slashslash = 1;
+#endif /* apollo */
+ if (*sp == '\0') { /* if component is null */
+ if (--sp == cp) /* if path is one char (i.e. /) */
+ break;
+ else
+ *sp = '\0';
+ }
+ else if (sp[0] == '.' && sp[1] == 0) {
+ if (slash) {
+ for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';)
+ continue;
+ p = --sp;
+ }
+ else if (--sp != cp)
+ *sp = '\0';
+ else
+ sp[1] = '\0';
+ }
+ else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) {
+ /*
+ * We have something like "yyy/xxx/..", where "yyy" can be null or
+ * a path starting at /, and "xxx" is a single component. Before
+ * compressing "xxx/..", we want to expand "yyy/xxx", if it is a
+ * symbolic link.
+ */
+ *--sp = 0; /* form the pathname for readlink */
+#ifdef S_IFLNK /* if we have symlinks */
+ if (sp != cp && /* symlinks != SYM_IGNORE && */
+ (cc = readlink(short2str(cp), tlink,
+ sizeof tlink)) >= 0) {
+ tlink[cc] = '\0';
+ (void) Strncpy(link, str2short(tlink),
+ sizeof(link) / sizeof(Char));
+ link[sizeof(link) / sizeof(Char) - 1] = '\0';
+
+ if (slash)
+ *p = '/';
+ /*
+ * Point p to the '/' in "/..", and restore the '/'.
+ */
+ *(p = sp) = '/';
+ /*
+ * find length of p
+ */
+ for (p1 = p; *p1++;)
+ continue;
+ if (*link != '/') {
+ /*
+ * Relative path, expand it between the "yyy/" and the
+ * "/..". First, back sp up to the character past "yyy/".
+ */
+ while (*--sp != '/')
+ continue;
+ sp++;
+ *sp = 0;
+ /*
+ * New length is "yyy/" + link + "/.." and rest
+ */
+ p1 = newcp = (Char *) xmalloc((size_t)
+ (((sp - cp) + cc + (p1 - p)) *
+ sizeof(Char)));
+ /*
+ * Copy new path into newcp
+ */
+ for (p2 = cp; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
+ continue;
+ /*
+ * Restart canonicalization at expanded "/xxx".
+ */
+ p = sp - cp - 1 + newcp;
+ }
+ else {
+ /*
+ * New length is link + "/.." and rest
+ */
+ p1 = newcp = (Char *) xmalloc((size_t)
+ ((cc + (p1 - p)) * sizeof(Char)));
+ /*
+ * Copy new path into newcp
+ */
+ for (p2 = link; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
+ continue;
+ /*
+ * Restart canonicalization at beginning
+ */
+ p = newcp;
+ }
+ xfree((ptr_t) cp);
+ cp = newcp;
+#ifdef apollo
+ slashslash = (cp[0] == '/' && cp[1] == '/');
+#endif /* apollo */
+ continue; /* canonicalize the link */
+ }
+#endif /* S_IFLNK */
+ *sp = '/';
+ if (sp != cp)
+ while (*--sp != '/')
+ continue;
+ if (slash) {
+ for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';)
+ continue;
+ p = sp;
+ }
+ else if (cp == sp)
+ *++sp = '\0';
+ else
+ *sp = '\0';
+ }
+ else { /* normal dir name (not . or .. or nothing) */
+
+#ifdef S_IFLNK /* if we have symlinks */
+ if (sp != cp && symlinks == SYM_CHASE &&
+ (cc = readlink(short2str(cp), tlink,
+ sizeof tlink)) >= 0) {
+ tlink[cc] = '\0';
+ (void) Strncpy(link, str2short(tlink),
+ sizeof(link) / sizeof(Char));
+ link[sizeof(link) / sizeof(Char) - 1] = '\0';
+
+ /*
+ * restore the '/'.
+ */
+ if (slash)
+ *p = '/';
+
+ /*
+ * point sp to p (rather than backing up).
+ */
+ sp = p;
+
+ /*
+ * find length of p
+ */
+ for (p1 = p; *p1++;)
+ continue;
+ if (*link != '/') {
+ /*
+ * Relative path, expand it between the "yyy/" and the
+ * remainder. First, back sp up to the character past
+ * "yyy/".
+ */
+ while (*--sp != '/')
+ continue;
+ sp++;
+ *sp = 0;
+ /*
+ * New length is "yyy/" + link + "/.." and rest
+ */
+ p1 = newcp = (Char *) xmalloc((size_t)
+ (((sp - cp) + cc + (p1 - p))
+ * sizeof(Char)));
+ /*
+ * Copy new path into newcp
+ */
+ for (p2 = cp; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
+ continue;
+ /*
+ * Restart canonicalization at expanded "/xxx".
+ */
+ p = sp - cp - 1 + newcp;
+ }
+ else {
+ /*
+ * New length is link + the rest
+ */
+ p1 = newcp = (Char *) xmalloc((size_t)
+ ((cc + (p1 - p)) * sizeof(Char)));
+ /*
+ * Copy new path into newcp
+ */
+ for (p2 = link; (*p1++ = *p2++) != '\0';)
+ continue;
+ for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
+ continue;
+ /*
+ * Restart canonicalization at beginning
+ */
+ p = newcp;
+ }
+ xfree((ptr_t) cp);
+ cp = newcp;
+#ifdef apollo
+ slashslash = (cp[0] == '/' && cp[1] == '/');
+#endif /* apollo */
+ continue; /* canonicalize the link */
+ }
+#endif /* S_IFLNK */
+ if (slash)
+ *p = '/';
+ }
+ }
+
+ /*
+ * fix home...
+ */
+#ifdef S_IFLNK
+ p1 = varval(STRhome);
+ cc = (int) Strlen(p1);
+ /*
+ * See if we're not in a subdir of STRhome
+ */
+ if (p1 && *p1 == '/' && (Strncmp(p1, cp, (size_t) cc) != 0 ||
+ (cp[cc] != '/' && cp[cc] != '\0'))) {
+ static ino_t home_ino = (ino_t) -1;
+ static dev_t home_dev = (dev_t) -1;
+ static Char *home_ptr = NULL;
+ struct stat statbuf;
+ int found;
+
+ /*
+ * Get dev and ino of STRhome
+ */
+ if (home_ptr != p1 &&
+ stat(short2str(p1), &statbuf) != -1) {
+ home_dev = statbuf.st_dev;
+ home_ino = statbuf.st_ino;
+ home_ptr = p1;
+ }
+ /*
+ * Start comparing dev & ino backwards
+ */
+ p2 = Strncpy(link, cp, sizeof(link) / sizeof(Char));
+ link[sizeof(link) / sizeof(Char) - 1] = '\0';
+ found = 0;
+ while (*p2 && stat(short2str(p2), &statbuf) != -1) {
+ if (DEV_DEV_COMPARE(statbuf.st_dev, home_dev) &&
+ statbuf.st_ino == home_ino) {
+ found = 1;
+ break;
+ }
+ if ((sp = Strrchr(p2, '/')) != NULL)
+ *sp = '\0';
+ }
+ /*
+ * See if we found it
+ */
+ if (*p2 && found) {
+ /*
+ * Use STRhome to make '~' work
+ */
+ newcp = Strspl(p1, cp + Strlen(p2));
+ xfree((ptr_t) cp);
+ cp = newcp;
+ }
+ }
+#endif /* S_IFLNK */
+
+#ifdef apollo
+ if (slashslash) {
+ if (cp[1] != '/') {
+ p = (Char *) xmalloc((size_t) (Strlen(cp) + 2) * sizeof(Char));
+ *p = '/';
+ (void) Strcpy(&p[1], cp);
+ xfree((ptr_t) cp);
+ cp = p;
+ }
+ }
+ if (cp[1] == '/' && cp[2] == '/')
+ (void) Strcpy(&cp[1], &cp[2]);
+#endif /* apollo */
+ return cp;
+}
+
+
+/*
+ * dnewcwd - make a new directory in the loop the current one
+ */
+static void
+dnewcwd(dp, dflag)
+ register struct directory *dp;
+ int dflag;
+{
+ int print;
+
+ if (adrof(STRdunique)) {
+ struct directory *dn;
+
+ for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev)
+ if (dn != dp && Strcmp(dn->di_name, dp->di_name) == 0) {
+ dn->di_next->di_prev = dn->di_prev;
+ dn->di_prev->di_next = dn->di_next;
+ dfree(dn);
+ break;
+ }
+ }
+ dcwd = dp;
+ dset(dcwd->di_name);
+ dgetstack();
+ print = printd; /* if printd is set, print dirstack... */
+ if (adrof(STRpushdsilent)) /* but pushdsilent overrides printd... */
+ print = 0;
+ if (dflag & DIR_PRINT) /* but DIR_PRINT overrides pushdsilent... */
+ print = 1;
+ if (bequiet) /* and bequiet overrides everything */
+ print = 0;
+ if (print)
+ printdirs(dflag);
+ cwd_cmd(); /* PWP: run the defined cwd command */
+}
+
+void
+dsetstack()
+{
+ Char **cp;
+ struct varent *vp;
+ struct directory *dn, *dp;
+
+ if ((vp = adrof(STRdirstack)) == NULL)
+ return;
+
+ /* Free the whole stack */
+ while ((dn = dhead.di_prev) != &dhead) {
+ dn->di_next->di_prev = dn->di_prev;
+ dn->di_prev->di_next = dn->di_next;
+ if (dn != dcwd)
+ dfree(dn);
+ }
+
+ /* thread the current working directory */
+ dhead.di_prev = dhead.di_next = dcwd;
+ dcwd->di_next = dcwd->di_prev = &dhead;
+
+ /* put back the stack */
+ for (cp = vp->vec; cp && *cp && **cp; cp++) {
+ dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
+ dp->di_name = Strsave(*cp);
+ dp->di_count = 0;
+ dp->di_prev = dcwd;
+ dp->di_next = dcwd->di_next;
+ dcwd->di_next = dp;
+ dp->di_next->di_prev = dp;
+ }
+ dgetstack(); /* Make $dirstack reflect the current state */
+}
+
+static void
+dgetstack()
+{
+ int i = 0;
+ Char **dblk, **dbp;
+ struct directory *dn;
+
+ if (adrof(STRdirstack) == NULL)
+ return;
+
+ for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, i++)
+ continue;
+ dbp = dblk = (Char**) xmalloc((size_t) (i + 1) * sizeof(Char *));
+ for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, dbp++)
+ *dbp = Strsave(dn->di_name);
+ *dbp = NULL;
+ setq(STRdirstack, dblk, &shvhed, VAR_READWRITE);
+}
+
+/*
+ * getstakd - added by kfk 17 Jan 1984
+ * Support routine for the stack hack. Finds nth directory in
+ * the directory stack, or finds last directory in stack.
+ */
+int
+getstakd(s, cnt)
+ Char *s;
+ int cnt;
+{
+ struct directory *dp;
+
+ dp = dcwd;
+ if (cnt < 0) { /* < 0 ==> last dir requested. */
+ dp = dp->di_next;
+ if (dp == &dhead)
+ dp = dp->di_next;
+ }
+ else {
+ while (cnt-- > 0) {
+ dp = dp->di_prev;
+ if (dp == &dhead)
+ dp = dp->di_prev;
+ if (dp == dcwd)
+ return (0);
+ }
+ }
+ (void) Strcpy(s, dp->di_name);
+ return (1);
+}
+
+/*
+ * Karl Kleinpaste - 10 Feb 1984
+ * Added dextract(), which is used in pushd +n.
+ * Instead of just rotating the entire stack around, dextract()
+ * lets the user have the nth dir extracted from its current
+ * position, and pushes it onto the top.
+ */
+static void
+dextract(dp)
+ struct directory *dp;
+{
+ if (dp == dcwd)
+ return;
+ dp->di_next->di_prev = dp->di_prev;
+ dp->di_prev->di_next = dp->di_next;
+ dp->di_next = dcwd->di_next;
+ dp->di_prev = dcwd;
+ dp->di_next->di_prev = dp;
+ dcwd->di_next = dp;
+}
+
+void
+loaddirs(fname)
+ Char *fname;
+{
+ static Char *loaddirs_cmd[] = { STRsource, NULL, NULL };
+
+ bequiet = 1;
+ if (fname)
+ loaddirs_cmd[1] = fname;
+ else if ((fname = varval(STRdirsfile)) != STRNULL)
+ loaddirs_cmd[1] = fname;
+ else
+ loaddirs_cmd[1] = STRtildotdirs;
+ dosource(loaddirs_cmd, (struct command *)0);
+ bequiet = 0;
+}
+
+/*
+ * create a file called ~/.cshdirs which has a sequence
+ * of pushd commands which will restore the dir stack to
+ * its state before exit/logout. remember that the order
+ * is reversed in the file because we are pushing.
+ * -strike
+ */
+void
+recdirs(fname, def)
+ Char *fname;
+ int def;
+{
+ int fp, ftmp, oldidfds;
+ int cdflag = 0;
+ extern struct directory *dcwd;
+ struct directory *dp;
+ unsigned int num;
+ Char *snum;
+ Char qname[MAXPATHLEN*2];
+
+ if (fname == NULL && !def)
+ return;
+
+ if (fname == NULL) {
+ if ((fname = varval(STRdirsfile)) == STRNULL)
+ fname = Strspl(varval(STRhome), &STRtildotdirs[1]);
+ else
+ fname = Strsave(fname);
+ }
+ else
+ fname = globone(fname, G_ERROR);
+
+ if ((fp = creat(short2str(fname), 0600)) == -1) {
+ xfree((ptr_t) fname);
+ return;
+ }
+
+ if ((snum = varval(STRsavedirs)) == STRNULL)
+ num = (unsigned int) ~0;
+ else
+ num = (unsigned int) atoi(short2str(snum));
+
+ oldidfds = didfds;
+ didfds = 0;
+ ftmp = SHOUT;
+ SHOUT = fp;
+
+ dp = dcwd->di_next;
+ do {
+ if (dp == &dhead)
+ continue;
+
+ if (cdflag == 0) {
+ cdflag = 1;
+ xprintf("cd %S\n", quote_meta(qname, dp->di_name));
+ }
+ else
+ xprintf("pushd %S\n", quote_meta(qname, dp->di_name));
+
+ if (num-- == 0)
+ break;
+
+ } while ((dp = dp->di_next) != dcwd->di_next);
+
+ (void) close(fp);
+ SHOUT = ftmp;
+ didfds = oldidfds;
+ xfree((ptr_t) fname);
+}
diff --git a/contrib/tcsh/sh.dir.h b/contrib/tcsh/sh.dir.h
new file mode 100644
index 0000000..9cb0af8
--- /dev/null
+++ b/contrib/tcsh/sh.dir.h
@@ -0,0 +1,61 @@
+/* $Header: /src/pub/tcsh/sh.dir.h,v 3.5 1997/10/27 22:44:26 christos Exp $ */
+/*
+ * sh.dir.h: Directory data structures and globals
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh_dir
+#define _h_sh_dir
+/*
+ * Structure for entries in directory stack.
+ */
+struct directory {
+ struct directory *di_next; /* next in loop */
+ struct directory *di_prev; /* prev in loop */
+ unsigned short *di_count; /* refcount of processes */
+ Char *di_name; /* actual name */
+};
+EXTERN struct directory *dcwd IZERO_STRUCT; /* the one we are in now */
+EXTERN int symlinks;
+
+#define SYM_CHASE 1
+#define SYM_IGNORE 2
+#define SYM_EXPAND 3
+
+#define TRM(a) ((a) & TRIM)
+#define NTRM(a) (a)
+#define ISDOT(c) (NTRM((c)[0]) == '.' && ((NTRM((c)[1]) == '\0') || \
+ (NTRM((c)[1]) == '/')))
+#define ISDOTDOT(c) (NTRM((c)[0]) == '.' && ISDOT(&((c)[1])))
+
+#endif /* _h_sh_dir */
diff --git a/contrib/tcsh/sh.dol.c b/contrib/tcsh/sh.dol.c
new file mode 100644
index 0000000..9b14b6f
--- /dev/null
+++ b/contrib/tcsh/sh.dol.c
@@ -0,0 +1,1150 @@
+/* $Header: /src/pub/tcsh/sh.dol.c,v 3.38 1998/10/25 15:10:05 christos Exp $ */
+/*
+ * sh.dol.c: Variable substitutions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.dol.c,v 3.38 1998/10/25 15:10:05 christos Exp $")
+
+/*
+ * C shell
+ */
+
+/*
+ * These routines perform variable substitution and quoting via ' and ".
+ * To this point these constructs have been preserved in the divided
+ * input words. Here we expand variables and turn quoting via ' and " into
+ * QUOTE bits on characters (which prevent further interpretation).
+ * If the `:q' modifier was applied during history expansion, then
+ * some QUOTEing may have occurred already, so we dont "trim()" here.
+ */
+
+static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
+static Char *Dcp, **Dvp; /* Input vector for Dreadc */
+
+#define DEOF -1
+
+#define unDgetC(c) Dpeekc = c
+
+#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
+
+/*
+ * The following variables give the information about the current
+ * $ expansion, recording the current word position, the remaining
+ * words within this expansion, the count of remaining words, and the
+ * information about any : modifier which is being applied.
+ */
+#define MAXWLEN (BUFSIZE - 4)
+#ifndef COMPAT
+#define MAXMOD MAXWLEN /* This cannot overflow */
+#endif /* COMPAT */
+static Char *dolp; /* Remaining chars from this word */
+static Char **dolnxt; /* Further words */
+static int dolcnt; /* Count of further words */
+#ifdef COMPAT
+static Char dolmod; /* : modifier character */
+#else
+static Char dolmod[MAXMOD]; /* : modifier character */
+static int dolnmod; /* Number of modifiers */
+#endif /* COMPAT */
+static int dolmcnt; /* :gx -> 10000, else 1 */
+static int dolwcnt; /* :ax -> 10000, else 1 */
+
+static void Dfix2 __P((Char **));
+static Char *Dpack __P((Char *, Char *));
+static int Dword __P((void));
+static void dolerror __P((Char *));
+static int DgetC __P((int));
+static void Dgetdol __P((void));
+static void fixDolMod __P((void));
+static void setDolp __P((Char *));
+static void unDredc __P((int));
+static int Dredc __P((void));
+static void Dtestq __P((int));
+
+/*
+ * Fix up the $ expansions and quotations in the
+ * argument list to command t.
+ */
+void
+Dfix(t)
+ register struct command *t;
+{
+ register Char **pp;
+ register Char *p;
+
+ if (noexec)
+ return;
+ /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
+ for (pp = t->t_dcom; (p = *pp++) != NULL;) {
+ for (; *p; p++) {
+ if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
+ Dfix2(t->t_dcom); /* found one */
+ blkfree(t->t_dcom);
+ t->t_dcom = gargv;
+ gargv = 0;
+ return;
+ }
+ }
+ }
+}
+
+/*
+ * $ substitute one word, for i/o redirection
+ */
+Char *
+Dfix1(cp)
+ register Char *cp;
+{
+ Char *Dv[2];
+
+ if (noexec)
+ return (0);
+ Dv[0] = cp;
+ Dv[1] = NULL;
+ Dfix2(Dv);
+ if (gargc != 1) {
+ setname(short2str(cp));
+ stderror(ERR_NAME | ERR_AMBIG);
+ }
+ cp = Strsave(gargv[0]);
+ blkfree(gargv), gargv = 0;
+ return (cp);
+}
+
+/*
+ * Subroutine to do actual fixing after state initialization.
+ */
+static void
+Dfix2(v)
+ Char **v;
+{
+ ginit(); /* Initialize glob's area pointers */
+ Dvp = v;
+ Dcp = STRNULL; /* Setup input vector for Dreadc */
+ unDgetC(0);
+ unDredc(0); /* Clear out any old peeks (at error) */
+ dolp = 0;
+ dolcnt = 0; /* Clear out residual $ expands (...) */
+ while (Dword())
+ continue;
+}
+
+/*
+ * Pack up more characters in this word
+ */
+static Char *
+Dpack(wbuf, wp)
+ Char *wbuf, *wp;
+{
+ register int c;
+ register int i = MAXWLEN - (int) (wp - wbuf);
+
+ for (;;) {
+ c = DgetC(DODOL);
+ if (c == '\\') {
+ c = DgetC(0);
+ if (c == DEOF) {
+ unDredc(c);
+ *wp = 0;
+ Gcat(STRNULL, wbuf);
+ return (NULL);
+ }
+ if (c == '\n')
+ c = ' ';
+ else
+ c |= QUOTE;
+ }
+ if (c == DEOF) {
+ unDredc(c);
+ *wp = 0;
+ Gcat(STRNULL, wbuf);
+ return (NULL);
+ }
+ if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
+ unDgetC(c);
+ if (cmap(c, QUOTES))
+ return (wp);
+ *wp++ = 0;
+ Gcat(STRNULL, wbuf);
+ return (NULL);
+ }
+ if (--i <= 0)
+ stderror(ERR_WTOOLONG);
+ *wp++ = (Char) c;
+ }
+}
+
+/*
+ * Get a word. This routine is analogous to the routine
+ * word() in sh.lex.c for the main lexical input. One difference
+ * here is that we don't get a newline to terminate our expansion.
+ * Rather, DgetC will return a DEOF when we hit the end-of-input.
+ */
+static int
+Dword()
+{
+ register int c, c1;
+ Char wbuf[BUFSIZE];
+ register Char *wp = wbuf;
+ register int i = MAXWLEN;
+ register bool dolflg;
+ bool sofar = 0, done = 0;
+
+ while (!done) {
+ done = 1;
+ c = DgetC(DODOL);
+ switch (c) {
+
+ case DEOF:
+ if (sofar == 0)
+ return (0);
+ /* finish this word and catch the code above the next time */
+ unDredc(c);
+ /*FALLTHROUGH*/
+
+ case '\n':
+ *wp = 0;
+ Gcat(STRNULL, wbuf);
+ return (1);
+
+ case ' ':
+ case '\t':
+ done = 0;
+ break;
+
+ case '`':
+ /* We preserve ` quotations which are done yet later */
+ *wp++ = (Char) c, --i;
+ /*FALLTHROUGH*/
+ case '\'':
+ case '"':
+ /*
+ * Note that DgetC never returns a QUOTES character from an
+ * expansion, so only true input quotes will get us here or out.
+ */
+ c1 = c;
+ dolflg = c1 == '"' ? DODOL : 0;
+ for (;;) {
+ c = DgetC(dolflg);
+ if (c == c1)
+ break;
+ if (c == '\n' || c == DEOF)
+ stderror(ERR_UNMATCHED, c1);
+ if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) {
+ if ((wp[-1] & TRIM) == '\\')
+ --wp;
+ ++i;
+ }
+ if (--i <= 0)
+ stderror(ERR_WTOOLONG);
+ switch (c1) {
+
+ case '"':
+ /*
+ * Leave any `s alone for later. Other chars are all
+ * quoted, thus `...` can tell it was within "...".
+ */
+ *wp++ = c == '`' ? '`' : c | QUOTE;
+ break;
+
+ case '\'':
+ /* Prevent all further interpretation */
+ *wp++ = c | QUOTE;
+ break;
+
+ case '`':
+ /* Leave all text alone for later */
+ *wp++ = (Char) c;
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (c1 == '`')
+ *wp++ = '`' /* i--; eliminated */;
+ sofar = 1;
+ if ((wp = Dpack(wbuf, wp)) == NULL)
+ return (1);
+ else {
+#ifdef masscomp
+ /*
+ * Avoid a nasty message from the RTU 4.1A & RTU 5.0 compiler concerning
+ * the "overuse of registers". According to the compiler release notes,
+ * incorrect code may be produced unless the offending expression is
+ * rewritten. Therefore, we can't just ignore it, DAS DEC-90.
+ */
+ i = MAXWLEN;
+ i -= (int) (wp - wbuf);
+#else /* !masscomp */
+ i = MAXWLEN - (int) (wp - wbuf);
+#endif /* masscomp */
+ done = 0;
+ }
+ break;
+
+ case '\\':
+ c = DgetC(0); /* No $ subst! */
+ if (c == '\n' || c == DEOF) {
+ done = 0;
+ break;
+ }
+ c |= QUOTE;
+ break;
+
+ default:
+ break;
+ }
+ if (done) {
+ unDgetC(c);
+ sofar = 1;
+ if ((wp = Dpack(wbuf, wp)) == NULL)
+ return (1);
+ else {
+#ifdef masscomp
+ /*
+ * Avoid a nasty message from the RTU 4.1A & RTU 5.0 compiler concerning
+ * the "overuse of registers". According to the compiler release notes,
+ * incorrect code may be produced unless the offending expression is
+ * rewritten. Therefore, we can't just ignore it, DAS DEC-90.
+ */
+ i = MAXWLEN;
+ i -= (int) (wp - wbuf);
+#else /* !masscomp */
+ i = MAXWLEN - (int) (wp - wbuf);
+#endif /* masscomp */
+ done = 0;
+ }
+ }
+ }
+ /* Really NOTREACHED */
+ return (0);
+}
+
+
+/*
+ * Get a character, performing $ substitution unless flag is 0.
+ * Any QUOTES character which is returned from a $ expansion is
+ * QUOTEd so that it will not be recognized above.
+ */
+static int
+DgetC(flag)
+ register int flag;
+{
+ register int c;
+
+top:
+ if ((c = Dpeekc) != 0) {
+ Dpeekc = 0;
+ return (c);
+ }
+ if (lap) {
+ c = *lap++ & (QUOTE | TRIM);
+ if (c == 0) {
+ lap = 0;
+ goto top;
+ }
+quotspec:
+ if (cmap(c, QUOTES))
+ return (c | QUOTE);
+ return (c);
+ }
+ if (dolp) {
+ if ((c = *dolp++ & (QUOTE | TRIM)) != 0)
+ goto quotspec;
+ if (dolcnt > 0) {
+ setDolp(*dolnxt++);
+ --dolcnt;
+ return (' ');
+ }
+ dolp = 0;
+ }
+ if (dolcnt > 0) {
+ setDolp(*dolnxt++);
+ --dolcnt;
+ goto top;
+ }
+ c = Dredc();
+ if (c == '$' && flag) {
+ Dgetdol();
+ goto top;
+ }
+ return (c);
+}
+
+static Char *nulvec[] = { NULL };
+static struct varent nulargv = {nulvec, STRargv, VAR_READWRITE,
+ { NULL, NULL, NULL }, 0 };
+
+static void
+dolerror(s)
+ Char *s;
+{
+ setname(short2str(s));
+ stderror(ERR_NAME | ERR_RANGE);
+}
+
+/*
+ * Handle the multitudinous $ expansion forms.
+ * Ugh.
+ */
+static void
+Dgetdol()
+{
+ register Char *np;
+ register struct varent *vp = NULL;
+ Char name[4 * MAXVARLEN + 1];
+ int c, sc;
+ int subscr = 0, lwb = 1, upb = 0;
+ bool dimen = 0, bitset = 0, length = 0;
+ char tnp;
+ Char wbuf[BUFSIZE];
+ static Char *dolbang = NULL;
+
+#ifdef COMPAT
+ dolmod = dolmcnt = dolwcnt = 0;
+#else
+ dolnmod = dolmcnt = dolwcnt = 0;
+#endif /* COMPAT */
+ c = sc = DgetC(0);
+ if (c == '{')
+ c = DgetC(0); /* sc is { to take } later */
+ if ((c & TRIM) == '#')
+ dimen++, c = DgetC(0); /* $# takes dimension */
+ else if (c == '?')
+ bitset++, c = DgetC(0); /* $? tests existence */
+ else if (c == '%')
+ length++, c = DgetC(0); /* $% returns length in chars */
+ switch (c) {
+
+ case '!':
+ if (dimen || bitset || length)
+ stderror(ERR_SYNTAX);
+ if (backpid != 0) {
+ if (dolbang)
+ xfree((ptr_t) dolbang);
+ setDolp(dolbang = putn(backpid));
+ }
+ goto eatbrac;
+
+ case '$':
+ if (dimen || bitset || length)
+ stderror(ERR_SYNTAX);
+ setDolp(doldol);
+ goto eatbrac;
+
+#ifdef COHERENT
+ /* Coherent compiler doesn't allow case-labels that are not
+ constant-expressions */
+#ifdef SHORT_STRINGS
+ case 0100074:
+#else /* !SHORT_STRINGS */
+ case 0274:
+#endif
+#else /* !COHERENT */
+ case '<'|QUOTE:
+#endif
+ if (bitset)
+ stderror(ERR_NOTALLOWED, "$?<");
+ if (dimen)
+ stderror(ERR_NOTALLOWED, "$#<");
+ if (length)
+ stderror(ERR_NOTALLOWED, "$%<");
+ {
+#ifdef BSDSIGS
+ sigmask_t omask = sigsetmask(sigblock(0) & ~sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+ for (np = wbuf; force_read(OLDSTD, &tnp, 1) == 1; np++) {
+ *np = (unsigned char) tnp;
+ if (np >= &wbuf[BUFSIZE - 1])
+ stderror(ERR_LTOOLONG);
+ if (tnp == '\n')
+ break;
+ }
+ *np = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ }
+
+#ifdef COMPAT
+ /*
+ * KLUDGE: dolmod is set here because it will cause setDolp to call
+ * domod and thus to copy wbuf. Otherwise setDolp would use it
+ * directly. If we saved it ourselves, no one would know when to free
+ * it. The actual function of the 'q' causes filename expansion not to
+ * be done on the interpolated value.
+ */
+ /*
+ * If we do that, then other modifiers don't work.
+ * in addition, let the user specify :q if wanted
+ * [christos]
+ */
+/*old*/ dolmod = 'q';
+/*new*/ dolmod[dolnmod++] = 'q';
+ dolmcnt = 10000;
+#endif /* COMPAT */
+
+ fixDolMod();
+ setDolp(wbuf);
+ goto eatbrac;
+
+ case '*':
+ (void) Strcpy(name, STRargv);
+ vp = adrof(STRargv);
+ subscr = -1; /* Prevent eating [...] */
+ break;
+
+ case DEOF:
+ case '\n':
+ np = dimen ? STRargv : (bitset ? STRstatus : NULL);
+ if (np) {
+ bitset = 0;
+ (void) Strcpy(name, np);
+ vp = adrof(np);
+ subscr = -1; /* Prevent eating [...] */
+ unDredc(c);
+ break;
+ }
+ else
+ stderror(ERR_SYNTAX);
+ /*NOTREACHED*/
+
+ default:
+ np = name;
+ if (Isdigit(c)) {
+ if (dimen)
+ stderror(ERR_NOTALLOWED, "$#<num>");
+ subscr = 0;
+ do {
+ subscr = subscr * 10 + c - '0';
+ c = DgetC(0);
+ } while (Isdigit(c));
+ unDredc(c);
+ if (subscr < 0) {
+ dolerror(vp->v_name);
+ return;
+ }
+ if (subscr == 0) {
+ if (bitset) {
+ dolp = dolzero ? STR1 : STR0;
+ goto eatbrac;
+ }
+ if (ffile == 0)
+ stderror(ERR_DOLZERO);
+ if (length) {
+ Char *cp;
+ length = Strlen(ffile);
+ cp = putn(length);
+ addla(cp);
+ xfree((ptr_t) cp);
+ }
+ else {
+ fixDolMod();
+ setDolp(ffile);
+ }
+ goto eatbrac;
+ }
+#if 0
+ if (bitset)
+ stderror(ERR_NOTALLOWED, "$?<num>");
+ if (length)
+ stderror(ERR_NOTALLOWED, "$%<num>");
+#endif
+ vp = adrof(STRargv);
+ if (vp == 0) {
+ vp = &nulargv;
+ goto eatmod;
+ }
+ break;
+ }
+ if (!alnum(c)) {
+ np = dimen ? STRargv : (bitset ? STRstatus : NULL);
+ if (np) {
+ bitset = 0;
+ (void) Strcpy(name, np);
+ vp = adrof(np);
+ subscr = -1; /* Prevent eating [...] */
+ unDredc(c);
+ break;
+ }
+ else
+ stderror(ERR_VARALNUM);
+ }
+ for (;;) {
+ *np++ = (Char) c;
+ c = DgetC(0);
+ if (!alnum(c))
+ break;
+ if (np >= &name[MAXVARLEN])
+ stderror(ERR_VARTOOLONG);
+ }
+ *np++ = 0;
+ unDredc(c);
+ vp = adrof(name);
+ }
+ if (bitset) {
+ dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
+ goto eatbrac;
+ }
+ if (vp == 0) {
+ np = str2short(getenv(short2str(name)));
+ if (np) {
+ fixDolMod();
+ setDolp(np);
+ goto eatbrac;
+ }
+ udvar(name);
+ /* NOTREACHED */
+ }
+ c = DgetC(0);
+ upb = blklen(vp->vec);
+ if (dimen == 0 && subscr == 0 && c == '[') {
+ np = name;
+ for (;;) {
+ c = DgetC(DODOL); /* Allow $ expand within [ ] */
+ if (c == ']')
+ break;
+ if (c == '\n' || c == DEOF)
+ stderror(ERR_INCBR);
+ if (np >= &name[sizeof(name) / sizeof(Char) - 2])
+ stderror(ERR_VARTOOLONG);
+ *np++ = (Char) c;
+ }
+ *np = 0, np = name;
+ if (dolp || dolcnt) /* $ exp must end before ] */
+ stderror(ERR_EXPORD);
+ if (!*np)
+ stderror(ERR_SYNTAX);
+ if (Isdigit(*np)) {
+ int i;
+
+ for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
+ continue;
+ if ((i < 0 || i > upb) && !any("-*", *np)) {
+ dolerror(vp->v_name);
+ return;
+ }
+ lwb = i;
+ if (!*np)
+ upb = lwb, np = STRstar;
+ }
+ if (*np == '*')
+ np++;
+ else if (*np != '-')
+ stderror(ERR_MISSING, '-');
+ else {
+ register int i = upb;
+
+ np++;
+ if (Isdigit(*np)) {
+ i = 0;
+ while (Isdigit(*np))
+ i = i * 10 + *np++ - '0';
+ if (i < 0 || i > upb) {
+ dolerror(vp->v_name);
+ return;
+ }
+ }
+ if (i < lwb)
+ upb = lwb - 1;
+ else
+ upb = i;
+ }
+ if (lwb == 0) {
+ if (upb != 0) {
+ dolerror(vp->v_name);
+ return;
+ }
+ upb = -1;
+ }
+ if (*np)
+ stderror(ERR_SYNTAX);
+ }
+ else {
+ if (subscr > 0) {
+ if (subscr > upb)
+ lwb = 1, upb = 0;
+ else
+ lwb = upb = subscr;
+ }
+ unDredc(c);
+ }
+ if (dimen) {
+ Char *cp = putn(upb - lwb + 1);
+
+ /* this is a kludge. It prevents Dgetdol() from */
+ /* pushing erroneous ${#<error> values into the labuf. */
+ if (sc == '{') {
+ c = Dredc();
+ if (c != '}')
+ {
+ xfree((ptr_t) cp);
+ stderror(ERR_MISSING, '}');
+ return;
+ }
+ unDredc(c);
+ }
+ addla(cp);
+ xfree((ptr_t) cp);
+ }
+ else if (length) {
+ int i;
+ Char *cp;
+ for (i = lwb - 1, length = 0; i < upb; i++)
+ length += Strlen(vp->vec[i]);
+#ifdef notdef
+ /* We don't want that, since we can always compute it by adding $#xxx */
+ length += i - 1; /* Add the number of spaces in */
+#endif
+ cp = putn(length);
+ addla(cp);
+ xfree((ptr_t) cp);
+ }
+ else {
+eatmod:
+ fixDolMod();
+ dolnxt = &vp->vec[lwb - 1];
+ dolcnt = upb - lwb + 1;
+ }
+eatbrac:
+ if (sc == '{') {
+ c = Dredc();
+ if (c != '}')
+ stderror(ERR_MISSING, '}');
+ }
+}
+
+static void
+fixDolMod()
+{
+ register int c;
+
+ c = DgetC(0);
+ if (c == ':') {
+#ifndef COMPAT
+ do {
+#endif /* COMPAT */
+ c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
+ if (c == 'g' || c == 'a') {
+ if (c == 'g')
+ dolmcnt = 10000;
+ else
+ dolwcnt = 10000;
+ c = DgetC(0);
+ }
+ if ((c == 'g' && dolmcnt != 10000) ||
+ (c == 'a' && dolwcnt != 10000)) {
+ if (c == 'g')
+ dolmcnt = 10000;
+ else
+ dolwcnt = 10000;
+ c = DgetC(0);
+ }
+
+ if (c == 's') { /* [eichin:19910926.0755EST] */
+ int delimcnt = 2;
+ int delim = DgetC(0);
+ dolmod[dolnmod++] = (Char) c;
+ dolmod[dolnmod++] = (Char) delim;
+
+ if (!delim || letter(delim)
+ || Isdigit(delim) || any(" \t\n", delim)) {
+ seterror(ERR_BADSUBST);
+ break;
+ }
+ while ((c = DgetC(0)) != (-1)) {
+ dolmod[dolnmod++] = (Char) c;
+ if(c == delim) delimcnt--;
+ if(!delimcnt) break;
+ }
+ if(delimcnt) {
+ seterror(ERR_BADSUBST);
+ break;
+ }
+ continue;
+ }
+ if (!any("luhtrqxes", c))
+ stderror(ERR_BADMOD, c);
+#ifndef COMPAT
+ dolmod[dolnmod++] = (Char) c;
+#else
+ dolmod = (Char) c;
+#endif /* COMPAT */
+ if (c == 'q')
+ dolmcnt = 10000;
+#ifndef COMPAT
+ }
+ while ((c = DgetC(0)) == ':');
+ unDredc(c);
+#endif /* COMPAT */
+ }
+ else
+ unDredc(c);
+}
+
+static void
+setDolp(cp)
+ register Char *cp;
+{
+ register Char *dp;
+#ifndef COMPAT
+ int i;
+#endif /* COMPAT */
+
+#ifdef COMPAT
+ if (dolmod == 0 || dolmcnt == 0) {
+#else
+ if (dolnmod == 0 || dolmcnt == 0) {
+#endif /* COMPAT */
+ dolp = cp;
+ return;
+ }
+#ifdef COMPAT
+ dp = domod(cp, dolmod);
+#else
+ dp = cp = Strsave(cp);
+ for (i = 0; i < dolnmod; i++) {
+ /* handle s// [eichin:19910926.0510EST] */
+ if(dolmod[i] == 's') {
+ int delim;
+ Char *lhsub, *rhsub, *np;
+ size_t lhlen = 0, rhlen = 0;
+ int didmod = 0;
+
+ delim = dolmod[++i];
+ if (!delim || letter(delim)
+ || Isdigit(delim) || any(" \t\n", delim)) {
+ seterror(ERR_BADSUBST);
+ break;
+ }
+ lhsub = &dolmod[++i];
+ while(dolmod[i] != delim && dolmod[++i]) {
+ lhlen++;
+ }
+ dolmod[i] = 0;
+ rhsub = &dolmod[++i];
+ while(dolmod[i] != delim && dolmod[++i]) {
+ rhlen++;
+ }
+ dolmod[i] = 0;
+
+ do {
+ strip(lhsub);
+ strip(cp);
+ dp = Strstr(cp, lhsub);
+ if (dp) {
+ np = (Char *) xmalloc((size_t)
+ ((Strlen(cp) + 1 - lhlen + rhlen) *
+ sizeof(Char)));
+ (void) Strncpy(np, cp, (size_t) (dp - cp));
+ (void) Strcpy(np + (dp - cp), rhsub);
+ (void) Strcpy(np + (dp - cp) + rhlen, dp + lhlen);
+
+ xfree((ptr_t) cp);
+ dp = cp = np;
+ didmod = 1;
+ } else {
+ /* should this do a seterror? */
+ break;
+ }
+ }
+ while (dolwcnt == 10000);
+ /*
+ * restore dolmod for additional words
+ */
+ dolmod[i] = rhsub[-1] = (Char) delim;
+ if (didmod)
+ dolmcnt--;
+#ifdef notdef
+ else
+ break;
+#endif
+ } else {
+ int didmod = 0;
+
+ do {
+ if ((dp = domod(cp, dolmod[i])) != NULL) {
+ didmod = 1;
+ if (Strcmp(cp, dp) == 0) {
+ xfree((ptr_t) cp);
+ cp = dp;
+ break;
+ }
+ else {
+ xfree((ptr_t) cp);
+ cp = dp;
+ }
+ }
+ else
+ break;
+ }
+ while (dolwcnt == 10000);
+ dp = cp;
+ if (didmod)
+ dolmcnt--;
+#ifdef notdef
+ else
+ break;
+#endif
+ }
+ }
+#endif /* COMPAT */
+
+ if (dp) {
+#ifdef COMPAT
+ dolmcnt--;
+#endif /* COMPAT */
+ addla(dp);
+ xfree((ptr_t) dp);
+ }
+#ifndef COMPAT
+ else
+ addla(cp);
+#endif /* COMPAT */
+
+ dolp = STRNULL;
+ if (seterr)
+ stderror(ERR_OLD);
+}
+
+static void
+unDredc(c)
+ int c;
+{
+
+ Dpeekrd = c;
+}
+
+static int
+Dredc()
+{
+ register int c;
+
+ if ((c = Dpeekrd) != 0) {
+ Dpeekrd = 0;
+ return (c);
+ }
+ if (Dcp && (c = *Dcp++))
+ return (c & (QUOTE | TRIM));
+ if (*Dvp == 0) {
+ Dcp = 0;
+ return (DEOF);
+ }
+ Dcp = *Dvp++;
+ return (' ');
+}
+
+static void
+Dtestq(c)
+ register int c;
+{
+
+ if (cmap(c, QUOTES))
+ gflag = 1;
+}
+
+/*
+ * Form a shell temporary file (in unit 0) from the words
+ * of the shell input up to EOF or a line the same as "term".
+ * Unit 0 should have been closed before this call.
+ */
+void
+heredoc(term)
+ Char *term;
+{
+ register int c;
+ Char *Dv[2];
+ Char obuf[BUFSIZE], lbuf[BUFSIZE], mbuf[BUFSIZE];
+ int ocnt, lcnt, mcnt;
+ register Char *lbp, *obp, *mbp;
+ Char **vp;
+ bool quoted;
+ char *tmp;
+
+ tmp = short2str(shtemp);
+#ifndef O_CREAT
+# define O_CREAT 0
+ if (creat(tmp, 0600) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+#endif
+ (void) close(0);
+#ifndef O_TEMPORARY
+# define O_TEMPORARY 0
+#endif
+ if (open(tmp, O_RDWR|O_CREAT|O_TEMPORARY) < 0) {
+ int oerrno = errno;
+
+ (void) unlink(tmp);
+ errno = oerrno;
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ }
+ (void) unlink(tmp); /* 0 0 inode! */
+ Dv[0] = term;
+ Dv[1] = NULL;
+ gflag = 0;
+ trim(Dv);
+ rscan(Dv, Dtestq);
+ quoted = gflag;
+ ocnt = BUFSIZE;
+ obp = obuf;
+ inheredoc = 1;
+#ifdef WINNT
+ __dup_stdin = 1;
+#endif /* WINNT */
+ for (;;) {
+ /*
+ * Read up a line
+ */
+ lbp = lbuf;
+ lcnt = BUFSIZE - 4;
+ for (;;) {
+ c = readc(1); /* 1 -> Want EOF returns */
+ if (c < 0 || c == '\n')
+ break;
+ if ((c &= TRIM) != 0) {
+ *lbp++ = (Char) c;
+ if (--lcnt < 0) {
+ setname("<<");
+ stderror(ERR_NAME | ERR_OVERFLOW);
+ }
+ }
+ }
+ *lbp = 0;
+
+ /*
+ * Check for EOF or compare to terminator -- before expansion
+ */
+ if (c < 0 || eq(lbuf, term)) {
+ (void) write(0, short2str(obuf), (size_t) (BUFSIZE - ocnt));
+ (void) lseek(0, (off_t) 0, L_SET);
+ inheredoc = 0;
+ return;
+ }
+
+ /*
+ * If term was quoted or -n just pass it on
+ */
+ if (quoted || noexec) {
+ *lbp++ = '\n';
+ *lbp = 0;
+ for (lbp = lbuf; (c = *lbp++) != 0;) {
+ *obp++ = (Char) c;
+ if (--ocnt == 0) {
+ (void) write(0, short2str(obuf), BUFSIZE);
+ obp = obuf;
+ ocnt = BUFSIZE;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * Term wasn't quoted so variable and then command expand the input
+ * line
+ */
+ Dcp = lbuf;
+ Dvp = Dv + 1;
+ mbp = mbuf;
+ mcnt = BUFSIZE - 4;
+ for (;;) {
+ c = DgetC(DODOL);
+ if (c == DEOF)
+ break;
+ if ((c &= TRIM) == 0)
+ continue;
+ /* \ quotes \ $ ` here */
+ if (c == '\\') {
+ c = DgetC(0);
+ if (!any("$\\`", c))
+ unDgetC(c | QUOTE), c = '\\';
+ else
+ c |= QUOTE;
+ }
+ *mbp++ = (Char) c;
+ if (--mcnt == 0) {
+ setname("<<");
+ stderror(ERR_NAME | ERR_OVERFLOW);
+ }
+ }
+ *mbp++ = 0;
+
+ /*
+ * If any ` in line do command substitution
+ */
+ mbp = mbuf;
+ if (Strchr(mbp, '`') != NULL) {
+ /*
+ * 1 arg to dobackp causes substitution to be literal. Words are
+ * broken only at newlines so that all blanks and tabs are
+ * preserved. Blank lines (null words) are not discarded.
+ */
+ vp = dobackp(mbuf, 1);
+ }
+ else
+ /* Setup trivial vector similar to return of dobackp */
+ Dv[0] = mbp, Dv[1] = NULL, vp = Dv;
+
+ /*
+ * Resurrect the words from the command substitution each separated by
+ * a newline. Note that the last newline of a command substitution
+ * will have been discarded, but we put a newline after the last word
+ * because this represents the newline after the last input line!
+ */
+ for (; *vp; vp++) {
+ for (mbp = *vp; *mbp; mbp++) {
+ *obp++ = *mbp & TRIM;
+ if (--ocnt == 0) {
+ (void) write(0, short2str(obuf), BUFSIZE);
+ obp = obuf;
+ ocnt = BUFSIZE;
+ }
+ }
+ *obp++ = '\n';
+ if (--ocnt == 0) {
+ (void) write(0, short2str(obuf), BUFSIZE);
+ obp = obuf;
+ ocnt = BUFSIZE;
+ }
+ }
+ if (pargv)
+ blkfree(pargv), pargv = 0;
+ }
+}
diff --git a/contrib/tcsh/sh.err.c b/contrib/tcsh/sh.err.c
new file mode 100644
index 0000000..b53fe7e
--- /dev/null
+++ b/contrib/tcsh/sh.err.c
@@ -0,0 +1,522 @@
+/* $Header: /src/pub/tcsh/sh.err.c,v 3.34 1999/05/11 13:07:45 christos Exp $ */
+/*
+ * sh.err.c: Error printing routines.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _h_sh_err /* Don't redefine the errors */
+#include "sh.h"
+
+RCSID("$Id: sh.err.c,v 3.34 1999/05/11 13:07:45 christos Exp $")
+
+/*
+ * C Shell
+ */
+
+#ifdef lint
+#undef va_arg
+#define va_arg(a, b) (a ? (b) 0 : (b) 0)
+#endif
+
+char *seterr = NULL; /* Holds last error if there was one */
+
+#define ERR_FLAGS 0xf0000000
+#define ERR_NAME 0x10000000
+#define ERR_SILENT 0x20000000
+#define ERR_OLD 0x40000000
+
+#define ERR_SYNTAX 0
+#define ERR_NOTALLOWED 1
+#define ERR_WTOOLONG 2
+#define ERR_LTOOLONG 3
+#define ERR_DOLZERO 4
+#define ERR_INCBR 5
+#define ERR_EXPORD 6
+#define ERR_BADMOD 7
+#define ERR_SUBSCRIPT 8
+#define ERR_BADNUM 9
+#define ERR_NOMORE 10
+#define ERR_FILENAME 11
+#define ERR_GLOB 12
+#define ERR_COMMAND 13
+#define ERR_TOOFEW 14
+#define ERR_TOOMANY 15
+#define ERR_DANGER 16
+#define ERR_EMPTYIF 17
+#define ERR_IMPRTHEN 18
+#define ERR_NOPAREN 19
+#define ERR_NOTFOUND 20
+#define ERR_MASK 21
+#define ERR_LIMIT 22
+#define ERR_TOOLARGE 23
+#define ERR_SCALEF 24
+#define ERR_UNDVAR 25
+#define ERR_DEEP 26
+#define ERR_BADSIG 27
+#define ERR_UNKSIG 28
+#define ERR_VARBEGIN 29
+#define ERR_VARTOOLONG 30
+#define ERR_VARALNUM 31
+#define ERR_JOBCONTROL 32
+#define ERR_EXPRESSION 33
+#define ERR_NOHOMEDIR 34
+#define ERR_CANTCHANGE 35
+#define ERR_NULLCOM 36
+#define ERR_ASSIGN 37
+#define ERR_UNKNOWNOP 38
+#define ERR_AMBIG 39
+#define ERR_EXISTS 40
+#define ERR_ARGC 41
+#define ERR_INTR 42
+#define ERR_RANGE 43
+#define ERR_OVERFLOW 44
+#define ERR_NOSUCHJOB 45
+#define ERR_TERMINAL 46
+#define ERR_NOTWHILE 47
+#define ERR_NOPROC 48
+#define ERR_NOMATCH 49
+#define ERR_MISSING 50
+#define ERR_UNMATCHED 51
+#define ERR_NOMEM 52
+#define ERR_PIPE 53
+#define ERR_SYSTEM 54
+#define ERR_STRING 55
+#define ERR_JOBS 56
+#define ERR_JOBARGS 57
+#define ERR_JOBCUR 58
+#define ERR_JOBPREV 59
+#define ERR_JOBPAT 60
+#define ERR_NESTING 61
+#define ERR_JOBCTRLSUB 62
+#define ERR_SYNC 63
+#define ERR_STOPPED 64
+#define ERR_NODIR 65
+#define ERR_EMPTY 66
+#define ERR_BADDIR 67
+#define ERR_DIRUS 68
+#define ERR_HFLAG 69
+#define ERR_NOTLOGIN 70
+#define ERR_DIV0 71
+#define ERR_MOD0 72
+#define ERR_BADSCALE 73
+#define ERR_SUSPLOG 74
+#define ERR_UNKUSER 75
+#define ERR_NOHOME 76
+#define ERR_HISTUS 77
+#define ERR_SPDOLLT 78
+#define ERR_NEWLINE 79
+#define ERR_SPSTAR 80
+#define ERR_DIGIT 81
+#define ERR_VARILL 82
+#define ERR_NLINDEX 83
+#define ERR_EXPOVFL 84
+#define ERR_VARSYN 85
+#define ERR_BADBANG 86
+#define ERR_NOSUBST 87
+#define ERR_BADSUBST 88
+#define ERR_LHS 89
+#define ERR_RHSLONG 90
+#define ERR_BADBANGMOD 91
+#define ERR_MODFAIL 92
+#define ERR_SUBOVFL 93
+#define ERR_BADBANGARG 94
+#define ERR_NOSEARCH 95
+#define ERR_NOEVENT 96
+#define ERR_TOOMANYRP 97
+#define ERR_TOOMANYLP 98
+#define ERR_BADPLP 99
+#define ERR_MISRED 100
+#define ERR_OUTRED 101
+#define ERR_REDPAR 102
+#define ERR_INRED 103
+#define ERR_BADPLPS 104
+#define ERR_ALIASLOOP 105
+#define ERR_NOWATCH 106
+#define ERR_NOSCHED 107
+#define ERR_SCHEDUSAGE 108
+#define ERR_SCHEDEV 109
+#define ERR_SCHEDCOM 110
+#define ERR_SCHEDTIME 111
+#define ERR_SCHEDREL 112
+#define ERR_TCNOSTR 113
+#define ERR_SETTCUS 114
+#define ERR_TCCAP 115
+#define ERR_TCPARM 116
+#define ERR_TCARGS 117
+#define ERR_TCNARGS 118
+#define ERR_TCUSAGE 119
+#define ERR_ARCH 120
+#define ERR_HISTLOOP 121
+#define ERR_FILEINQ 122
+#define ERR_SELOVFL 123
+#define ERR_TCSHUSAGE 124
+#define ERR_COMPCOM 125
+#define ERR_COMPINV 126
+#define ERR_COMPMIS 127
+#define ERR_COMPINC 128
+#define ERR_MFLAG 129
+#define ERR_ULIMUS 130
+#define ERR_READONLY 131
+#define ERR_BADJOB 132
+#define ERR_INVALID 133
+#define ERR_BADCOLORVAR 134
+#define NO_ERRORS 135
+
+static char *elst[NO_ERRORS] INIT_ZERO_STRUCT;
+
+/*
+ * Init the elst depending on the locale
+ */
+void
+errinit()
+{
+#ifdef NLS_CATALOGS
+ int i;
+
+ for (i = 0; i < NO_ERRORS; i++)
+ xfree((ptr_t) elst[i]);
+# if defined(__FreeBSD__) || defined(hpux)
+# define NLS_MAXSET 30
+ for (i = 1; i <= NLS_MAXSET; i++)
+ CGETS(i, 1, "" );
+# endif
+#endif
+
+ elst[ERR_SYNTAX] = CSAVS(1, 1, "Syntax Error");
+ elst[ERR_NOTALLOWED] = CSAVS(1, 2, "%s is not allowed");
+ elst[ERR_WTOOLONG] = CSAVS(1, 3, "Word too long");
+ elst[ERR_LTOOLONG] = CSAVS(1, 4, "$< line too long");
+ elst[ERR_DOLZERO] = CSAVS(1, 5, "No file for $0");
+ elst[ERR_INCBR] = CSAVS(1, 6, "Incomplete [] modifier");
+ elst[ERR_EXPORD] = CSAVS(1, 7, "$ expansion must end before ]");
+ elst[ERR_BADMOD] = CSAVS(1, 8, "Bad : modifier in $ (%c)");
+ elst[ERR_SUBSCRIPT] = CSAVS(1, 9, "Subscript error");
+ elst[ERR_BADNUM] = CSAVS(1, 10, "Badly formed number");
+ elst[ERR_NOMORE] = CSAVS(1, 11, "No more words");
+ elst[ERR_FILENAME] = CSAVS(1, 12, "Missing file name");
+ elst[ERR_GLOB] = CSAVS(1, 13, "Internal glob error");
+ elst[ERR_COMMAND] = CSAVS(1, 14, "Command not found");
+ elst[ERR_TOOFEW] = CSAVS(1, 15, "Too few arguments");
+ elst[ERR_TOOMANY] = CSAVS(1, 16, "Too many arguments");
+ elst[ERR_DANGER] = CSAVS(1, 17, "Too dangerous to alias that");
+ elst[ERR_EMPTYIF] = CSAVS(1, 18, "Empty if");
+ elst[ERR_IMPRTHEN] = CSAVS(1, 19, "Improper then");
+ elst[ERR_NOPAREN] = CSAVS(1, 20, "Words not parenthesized");
+ elst[ERR_NOTFOUND] = CSAVS(1, 21, "%s not found");
+ elst[ERR_MASK] = CSAVS(1, 22, "Improper mask");
+ elst[ERR_LIMIT] = CSAVS(1, 23, "No such limit");
+ elst[ERR_TOOLARGE] = CSAVS(1, 24, "Argument too large");
+ elst[ERR_SCALEF] = CSAVS(1, 25, "Improper or unknown scale factor");
+ elst[ERR_UNDVAR] = CSAVS(1, 26, "Undefined variable");
+ elst[ERR_DEEP] = CSAVS(1, 27, "Directory stack not that deep");
+ elst[ERR_BADSIG] = CSAVS(1, 28, "Bad signal number");
+ elst[ERR_UNKSIG] = CSAVS(1, 29, "Unknown signal; kill -l lists signals");
+ elst[ERR_VARBEGIN] = CSAVS(1, 30, "Variable name must begin with a letter");
+ elst[ERR_VARTOOLONG] = CSAVS(1, 31, "Variable name too long");
+ elst[ERR_VARALNUM] = CSAVS(1, 32,
+ "Variable name must contain alphanumeric characters");
+ elst[ERR_JOBCONTROL] = CSAVS(1, 33, "No job control in this shell");
+ elst[ERR_EXPRESSION] = CSAVS(1, 34, "Expression Syntax");
+ elst[ERR_NOHOMEDIR] = CSAVS(1, 35, "No home directory");
+ elst[ERR_CANTCHANGE] = CSAVS(1, 36, "Can't change to home directory");
+ elst[ERR_NULLCOM] = CSAVS(1, 37, "Invalid null command");
+ elst[ERR_ASSIGN] = CSAVS(1, 38, "Assignment missing expression");
+ elst[ERR_UNKNOWNOP] = CSAVS(1, 39, "Unknown operator");
+ elst[ERR_AMBIG] = CSAVS(1, 40, "Ambiguous");
+ elst[ERR_EXISTS] = CSAVS(1, 41, "%s: File exists");
+ elst[ERR_ARGC] = CSAVS(1, 42, "Argument for -c ends in backslash");
+ elst[ERR_INTR] = CSAVS(1, 43, "Interrupted");
+ elst[ERR_RANGE] = CSAVS(1, 44, "Subscript out of range");
+ elst[ERR_OVERFLOW] = CSAVS(1, 45, "Line overflow");
+ elst[ERR_NOSUCHJOB] = CSAVS(1, 46, "No such job");
+ elst[ERR_TERMINAL] = CSAVS(1, 47, "Can't from terminal");
+ elst[ERR_NOTWHILE] = CSAVS(1, 48, "Not in while/foreach");
+ elst[ERR_NOPROC] = CSAVS(1, 49, "No more processes");
+ elst[ERR_NOMATCH] = CSAVS(1, 50, "No match");
+ elst[ERR_MISSING] = CSAVS(1, 51, "Missing %c");
+ elst[ERR_UNMATCHED] = CSAVS(1, 52, "Unmatched %c");
+ elst[ERR_NOMEM] = CSAVS(1, 53, "Out of memory");
+ elst[ERR_PIPE] = CSAVS(1, 54, "Can't make pipe");
+ elst[ERR_SYSTEM] = CSAVS(1, 55, "%s: %s");
+ elst[ERR_STRING] = CSAVS(1, 56, "%s");
+ elst[ERR_JOBS] = CSAVS(1, 57, "Usage: jobs [ -l ]");
+ elst[ERR_JOBARGS] = CSAVS(1, 58, "Arguments should be jobs or process id's");
+ elst[ERR_JOBCUR] = CSAVS(1, 59, "No current job");
+ elst[ERR_JOBPREV] = CSAVS(1, 60, "No previous job");
+ elst[ERR_JOBPAT] = CSAVS(1, 61, "No job matches pattern");
+ elst[ERR_NESTING] = CSAVS(1, 62, "Fork nesting > %d; maybe `...` loop");
+ elst[ERR_JOBCTRLSUB] = CSAVS(1, 63, "No job control in subshells");
+ elst[ERR_SYNC] = CSAVS(1, 64, "Sync fault: Process %d not found");
+ elst[ERR_STOPPED] =
+#ifdef SUSPENDED
+ CSAVS(1, 65, "%sThere are suspended jobs");
+#else
+ CSAVS(1, 66, "%sThere are stopped jobs");
+#endif /* SUSPENDED */
+ elst[ERR_NODIR] = CSAVS(1, 67, "No other directory");
+ elst[ERR_EMPTY] = CSAVS(1, 68, "Directory stack empty");
+ elst[ERR_BADDIR] = CSAVS(1, 69, "Bad directory");
+ elst[ERR_DIRUS] = CSAVS(1, 70, "Usage: %s [-%s]%s");
+ elst[ERR_HFLAG] = CSAVS(1, 71, "No operand for -h flag");
+ elst[ERR_NOTLOGIN] = CSAVS(1, 72, "Not a login shell");
+ elst[ERR_DIV0] = CSAVS(1, 73, "Division by 0");
+ elst[ERR_MOD0] = CSAVS(1, 74, "Mod by 0");
+ elst[ERR_BADSCALE] = CSAVS(1, 75, "Bad scaling; did you mean \"%s\"?");
+ elst[ERR_SUSPLOG] = CSAVS(1, 76, "Can't suspend a login shell (yet)");
+ elst[ERR_UNKUSER] = CSAVS(1, 77, "Unknown user: %s");
+ elst[ERR_NOHOME] = CSAVS(1, 78, "No $home variable set");
+ elst[ERR_HISTUS] = CSAVS(1, 79,
+ "Usage: history [-%s] [# number of events]");
+ elst[ERR_SPDOLLT] = CSAVS(1, 80, "$, ! or < not allowed with $# or $?");
+ elst[ERR_NEWLINE] = CSAVS(1, 81, "Newline in variable name");
+ elst[ERR_SPSTAR] = CSAVS(1, 82, "* not allowed with $# or $?");
+ elst[ERR_DIGIT] = CSAVS(1, 83, "$?<digit> or $#<digit> not allowed");
+ elst[ERR_VARILL] = CSAVS(1, 84, "Illegal variable name");
+ elst[ERR_NLINDEX] = CSAVS(1, 85, "Newline in variable index");
+ elst[ERR_EXPOVFL] = CSAVS(1, 86, "Expansion buffer overflow");
+ elst[ERR_VARSYN] = CSAVS(1, 87, "Variable syntax");
+ elst[ERR_BADBANG] = CSAVS(1, 88, "Bad ! form");
+ elst[ERR_NOSUBST] = CSAVS(1, 89, "No previous substitute");
+ elst[ERR_BADSUBST] = CSAVS(1, 90, "Bad substitute");
+ elst[ERR_LHS] = CSAVS(1, 91, "No previous left hand side");
+ elst[ERR_RHSLONG] = CSAVS(1, 92, "Right hand side too long");
+ elst[ERR_BADBANGMOD] = CSAVS(1, 93, "Bad ! modifier: %c");
+ elst[ERR_MODFAIL] = CSAVS(1, 94, "Modifier failed");
+ elst[ERR_SUBOVFL] = CSAVS(1, 95, "Substitution buffer overflow");
+ elst[ERR_BADBANGARG] = CSAVS(1, 96, "Bad ! arg selector");
+ elst[ERR_NOSEARCH] = CSAVS(1, 97, "No prev search");
+ elst[ERR_NOEVENT] = CSAVS(1, 98, "%s: Event not found");
+ elst[ERR_TOOMANYRP] = CSAVS(1, 99, "Too many )'s");
+ elst[ERR_TOOMANYLP] = CSAVS(1, 100, "Too many ('s");
+ elst[ERR_BADPLP] = CSAVS(1, 101, "Badly placed (");
+ elst[ERR_MISRED] = CSAVS(1, 102, "Missing name for redirect");
+ elst[ERR_OUTRED] = CSAVS(1, 103, "Ambiguous output redirect");
+ elst[ERR_REDPAR] = CSAVS(1, 104, "Can't << within ()'s");
+ elst[ERR_INRED] = CSAVS(1, 105, "Ambiguous input redirect");
+ elst[ERR_BADPLPS] = CSAVS(1, 106, "Badly placed ()'s");
+ elst[ERR_ALIASLOOP] = CSAVS(1, 107, "Alias loop");
+ elst[ERR_NOWATCH] = CSAVS(1, 108, "No $watch variable set");
+ elst[ERR_NOSCHED] = CSAVS(1, 109, "No scheduled events");
+ elst[ERR_SCHEDUSAGE] = CSAVS(1, 110,
+ "Usage: sched -<item#>.\nUsage: sched [+]hh:mm <command>");
+ elst[ERR_SCHEDEV] = CSAVS(1, 111, "Not that many scheduled events");
+ elst[ERR_SCHEDCOM] = CSAVS(1, 112, "No command to run");
+ elst[ERR_SCHEDTIME] = CSAVS(1, 113, "Invalid time for event");
+ elst[ERR_SCHEDREL] = CSAVS(1, 114, "Relative time inconsistent with am/pm");
+ elst[ERR_TCNOSTR] = CSAVS(1, 115, "Out of termcap string space");
+ elst[ERR_SETTCUS] = CSAVS(1, 116, "Usage: settc %s [yes|no]");
+ elst[ERR_TCCAP] = CSAVS(1, 117, "Unknown capability `%s'");
+ elst[ERR_TCPARM] = CSAVS(1, 118, "Unknown termcap parameter `%%%c'");
+ elst[ERR_TCARGS] = CSAVS(1, 119, "Too many arguments for `%s' (%d)");
+ elst[ERR_TCNARGS] = CSAVS(1, 120, "`%s' requires %d arguments");
+ elst[ERR_TCUSAGE] = CSAVS(1, 121,
+ "Usage: echotc [-v|-s] [<capability> [<args>]]");
+ elst[ERR_ARCH] = CSAVS(1, 122, "%s: %s. Binary file not executable");
+ elst[ERR_HISTLOOP] = CSAVS(1, 123, "!# History loop");
+ elst[ERR_FILEINQ] = CSAVS(1, 124, "Malformed file inquiry");
+ elst[ERR_SELOVFL] = CSAVS(1, 125, "Selector overflow");
+#ifdef apollo
+ elst[ERR_TCSHUSAGE] = CSAVS(1, 126,
+"Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX -Dname[=value] ] [ argument ... ]");
+#else /* !apollo */
+# ifdef convex
+ elst[ERR_TCSHUSAGE] = CSAVS(1, 127,
+"Unknown option: `-%s'\nUsage: %s [ -bcdefFilmnqstvVxX ] [ argument ... ]");
+# else /* rest */
+ elst[ERR_TCSHUSAGE] = CSAVS(1, 128,
+"Unknown option: `-%s'\nUsage: %s [ -bcdefilmnqstvVxX ] [ argument ... ]");
+# endif /* convex */
+#endif /* apollo */
+ elst[ERR_COMPCOM] = CSAVS(1, 129, "\nInvalid completion: \"%s\"");
+ elst[ERR_COMPINV] = CSAVS(1, 130, "\nInvalid %s: '%c'");
+ elst[ERR_COMPMIS] = CSAVS(1, 131,
+ "\nMissing separator '%c' after %s \"%s\"");
+ elst[ERR_COMPINC] = CSAVS(1, 132, "\nIncomplete %s: \"%s\"");
+ elst[ERR_MFLAG] = CSAVS(1, 133, "No operand for -m flag");
+ elst[ERR_ULIMUS] = CSAVS(1, 134, "Usage: unlimit [-fh] [limits]");
+ elst[ERR_READONLY] = CSAVS(1, 135, "$%S is read-only");
+ elst[ERR_BADJOB] = CSAVS(1, 136, "No such job (badjob)");
+ elst[ERR_BADCOLORVAR] = CSAVS(1, 137, "Unknown colorls variable `%c%c'");
+}
+/*
+ * The parser and scanner set up errors for later by calling seterr,
+ * which sets the variable err as a side effect; later to be tested,
+ * e.g. in process.
+ */
+void
+/*VARARGS1*/
+#ifdef FUNCPROTO
+seterror(unsigned int id, ...)
+#else
+seterror(va_alist)
+ va_dcl
+#endif
+{
+
+ if (seterr == 0) {
+ va_list va;
+ char berr[BUFSIZE];
+#ifdef FUNCPROTO
+ va_start(va, id);
+#else
+ unsigned int id;
+ va_start(va);
+ id = va_arg(va, unsigned int);
+#endif
+
+ if (id >= sizeof(elst) / sizeof(elst[0]))
+ id = ERR_INVALID;
+ xvsnprintf(berr, sizeof(berr), elst[id], va);
+ va_end(va);
+
+ seterr = strsave(berr);
+ }
+}
+
+/*
+ * Print the error with the given id.
+ *
+ * Special ids:
+ * ERR_SILENT: Print nothing.
+ * ERR_OLD: Print the previously set error if one was there.
+ * otherwise return.
+ * ERR_NAME: If this bit is set, print the name of the function
+ * in bname
+ *
+ * This routine always resets or exits. The flag haderr
+ * is set so the routine who catches the unwind can propogate
+ * it if they want.
+ *
+ * Note that any open files at the point of error will eventually
+ * be closed in the routine process in sh.c which is the only
+ * place error unwinds are ever caught.
+ */
+void
+/*VARARGS*/
+#ifdef FUNCPROTO
+stderror(unsigned int id, ...)
+#else
+stderror(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+ register Char **v;
+ int flags;
+ int vareturn;
+
+#ifdef FUNCPROTO
+ va_start(va, id);
+#else
+ unsigned int id;
+
+ va_start(va);
+ id = va_arg(va, unsigned int);
+#endif
+
+ /*
+ * Reset don't free flag for buggy os's
+ */
+ dont_free = 0;
+
+ flags = (int) id & ERR_FLAGS;
+ id &= ~ERR_FLAGS;
+
+ /* Pyramid's OS/x has a subtle bug in <varargs.h> which prevents calling
+ * va_end more than once in the same function. -- sterling@netcom.com
+ */
+ if (!((flags & ERR_OLD) && seterr == NULL)) {
+ vareturn = 0; /* Don't return immediately after va_end */
+ if (id >= sizeof(elst) / sizeof(elst[0]))
+ id = ERR_INVALID;
+
+ /*
+ * Must flush before we print as we wish output before the error to go
+ * on (some form of) standard output, while output after goes on (some
+ * form of) diagnostic output. If didfds then output will go to 1/2
+ * else to FSHOUT/FSHDIAG. See flush in sh.print.c.
+ */
+ flush();
+ haderr = 1; /* Now to diagnostic output */
+ timflg = 0; /* This isn't otherwise reset */
+
+
+ if (!(flags & ERR_SILENT)) {
+ if (flags & ERR_NAME)
+ xprintf("%s: ", bname);
+ if ((flags & ERR_OLD)) {
+ /* Old error. */
+ xprintf("%s.\n", seterr);
+ } else {
+ xvprintf(elst[id], va);
+ xprintf(".\n");
+ }
+ }
+ } else {
+ vareturn = 1; /* Return immediately after va_end */
+ }
+ va_end(va);
+ if (vareturn)
+ return;
+
+ if (seterr) {
+ xfree((ptr_t) seterr);
+ seterr = NULL;
+ }
+
+ if ((v = pargv) != 0)
+ pargv = 0, blkfree(v);
+ if ((v = gargv) != 0)
+ gargv = 0, blkfree(v);
+
+ inheredoc = 0; /* Not anymore in a heredoc */
+ didfds = 0; /* Forget about 0,1,2 */
+ /*
+ * Go away if -e or we are a child shell
+ */
+ if (exiterr || child)
+ xexit(1);
+
+ /*
+ * Reset the state of the input. This buffered seek to end of file will
+ * also clear the while/foreach stack.
+ */
+ btoeof();
+
+ set(STRstatus, Strsave(STR1), VAR_READWRITE);
+#ifdef BSDJOBS
+ if (tpgrp > 0)
+ (void) tcsetpgrp(FSHTTY, tpgrp);
+#endif
+ reset(); /* Unwind */
+}
diff --git a/contrib/tcsh/sh.exec.c b/contrib/tcsh/sh.exec.c
new file mode 100644
index 0000000..68c24b6
--- /dev/null
+++ b/contrib/tcsh/sh.exec.c
@@ -0,0 +1,1262 @@
+/* $Header: /src/pub/tcsh/sh.exec.c,v 3.47 1999/04/20 07:48:44 christos Exp $ */
+/*
+ * sh.exec.c: Search, find, and execute a command!
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.exec.c,v 3.47 1999/04/20 07:48:44 christos Exp $")
+
+#include "tc.h"
+#include "tw.h"
+#ifdef WINNT
+#include <nt.const.h>
+#endif /*WINNT*/
+
+/*
+ * C shell
+ */
+
+#ifndef OLDHASH
+# define FASTHASH /* Fast hashing is the default */
+#endif /* OLDHASH */
+
+/*
+ * System level search and execute of a command.
+ * We look in each directory for the specified command name.
+ * If the name contains a '/' then we execute only the full path name.
+ * If there is no search path then we execute only full path names.
+ */
+
+/*
+ * As we search for the command we note the first non-trivial error
+ * message for presentation to the user. This allows us often
+ * to show that a file has the wrong mode/no access when the file
+ * is not in the last component of the search path, so we must
+ * go on after first detecting the error.
+ */
+static char *exerr; /* Execution error message */
+static Char *expath; /* Path for exerr */
+
+/*
+ * The two part hash function is designed to let texec() call the
+ * more expensive hashname() only once and the simple hash() several
+ * times (once for each path component checked).
+ * Byte size is assumed to be 8.
+ */
+#define BITS_PER_BYTE 8
+
+#ifdef FASTHASH
+/*
+ * xhash is an array of hash buckets which are used to hash execs. If
+ * it is allocated (havhash true), then to tell if ``name'' is
+ * (possibly) presend in the i'th component of the variable path, look
+ * at the [hashname(name)] bucket of size [hashwidth] bytes, in the [i
+ * mod size*8]'th bit. The cache size is defaults to a length of 1024
+ * buckets, each 1 byte wide. This implementation guarantees that
+ * objects n bytes wide will be aligned on n byte boundaries.
+ */
+# define HSHMUL 241
+
+static unsigned long *xhash = NULL;
+static unsigned int hashlength = 0, uhashlength = 0;
+static unsigned int hashwidth = 0, uhashwidth = 0;
+static int hashdebug = 0;
+
+# define hash(a, b) (((a) * HSHMUL + (b)) % (hashlength))
+# define widthof(t) (sizeof(t) * BITS_PER_BYTE)
+# define tbit(f, i, t) (((t *) xhash)[(f)] & \
+ (1L << (i & (widthof(t) - 1))))
+# define tbis(f, i, t) (((t *) xhash)[(f)] |= \
+ (1L << (i & (widthof(t) - 1))))
+# define cbit(f, i) tbit(f, i, unsigned char)
+# define cbis(f, i) tbis(f, i, unsigned char)
+# define sbit(f, i) tbit(f, i, unsigned short)
+# define sbis(f, i) tbis(f, i, unsigned short)
+# define ibit(f, i) tbit(f, i, unsigned int)
+# define ibis(f, i) tbis(f, i, unsigned int)
+# define lbit(f, i) tbit(f, i, unsigned long)
+# define lbis(f, i) tbis(f, i, unsigned long)
+
+# define bit(f, i) (hashwidth==sizeof(unsigned char) ? cbit(f,i) : \
+ ((hashwidth==sizeof(unsigned short) ? sbit(f,i) : \
+ ((hashwidth==sizeof(unsigned int) ? ibit(f,i) : \
+ lbit(f,i))))))
+# define bis(f, i) (hashwidth==sizeof(unsigned char) ? cbis(f,i) : \
+ ((hashwidth==sizeof(unsigned short) ? sbis(f,i) : \
+ ((hashwidth==sizeof(unsigned int) ? ibis(f,i) : \
+ lbis(f,i))))))
+#else /* OLDHASH */
+/*
+ * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
+ * to hash execs. If it is allocated (havhash true), then to tell
+ * whether ``name'' is (possibly) present in the i'th component
+ * of the variable path, you look at the bit in xhash indexed by
+ * hash(hashname("name"), i). This is setup automatically
+ * after .login is executed, and recomputed whenever ``path'' is
+ * changed.
+ */
+# define HSHSIZ 8192 /* 1k bytes */
+# define HSHMASK (HSHSIZ - 1)
+# define HSHMUL 243
+static char xhash[HSHSIZ / BITS_PER_BYTE];
+
+# define hash(a, b) (((a) * HSHMUL + (b)) & HSHMASK)
+# define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
+# define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */
+
+#endif /* FASTHASH */
+
+#ifdef VFORK
+static int hits, misses;
+#endif /* VFORK */
+
+/* Dummy search path for just absolute search when no path */
+static Char *justabs[] = {STRNULL, 0};
+
+static void pexerr __P((void));
+static void texec __P((Char *, Char **));
+static int hashname __P((Char *));
+static int iscommand __P((Char *));
+
+void
+doexec(t)
+ register struct command *t;
+{
+ register Char *dp, **pv, **av, *sav;
+ register struct varent *v;
+ register bool slash;
+ register int hashval, i;
+ Char *blk[2];
+
+ /*
+ * Glob the command name. We will search $path even if this does something,
+ * as in sh but not in csh. One special case: if there is no PATH, then we
+ * execute only commands which start with '/'.
+ */
+ blk[0] = t->t_dcom[0];
+ blk[1] = 0;
+ gflag = 0, tglob(blk);
+ if (gflag) {
+ pv = globall(blk);
+ if (pv == 0) {
+ setname(short2str(blk[0]));
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ gargv = 0;
+ }
+ else
+ pv = saveblk(blk);
+
+ trim(pv);
+
+ exerr = 0;
+ expath = Strsave(pv[0]);
+#ifdef VFORK
+ Vexpath = expath;
+#endif /* VFORK */
+
+ v = adrof(STRpath);
+ if (v == 0 && expath[0] != '/' && expath[0] != '.') {
+ blkfree(pv);
+ pexerr();
+ }
+ slash = any(short2str(expath), '/');
+
+ /*
+ * Glob the argument list, if necessary. Otherwise trim off the quote bits.
+ */
+ gflag = 0;
+ av = &t->t_dcom[1];
+ tglob(av);
+ if (gflag) {
+ av = globall(av);
+ if (av == 0) {
+ blkfree(pv);
+ setname(short2str(expath));
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ gargv = 0;
+ }
+ else
+ av = saveblk(av);
+
+ blkfree(t->t_dcom);
+ t->t_dcom = blkspl(pv, av);
+ xfree((ptr_t) pv);
+ xfree((ptr_t) av);
+ av = t->t_dcom;
+ trim(av);
+
+ if (*av == NULL || **av == '\0')
+ pexerr();
+
+ xechoit(av); /* Echo command if -x */
+#ifdef CLOSE_ON_EXEC
+ /*
+ * Since all internal file descriptors are set to close on exec, we don't
+ * need to close them explicitly here. Just reorient ourselves for error
+ * messages.
+ */
+ SHIN = 0;
+ SHOUT = 1;
+ SHDIAG = 2;
+ OLDSTD = 0;
+ isoutatty = isatty(SHOUT);
+ isdiagatty = isatty(SHDIAG);
+#else
+ closech(); /* Close random fd's */
+#endif
+ /*
+ * We must do this AFTER any possible forking (like `foo` in glob) so that
+ * this shell can still do subprocesses.
+ */
+#ifdef BSDSIGS
+ (void) sigsetmask((sigmask_t) 0);
+#else /* BSDSIGS */
+ (void) sigrelse(SIGINT);
+ (void) sigrelse(SIGCHLD);
+#endif /* BSDSIGS */
+
+ /*
+ * If no path, no words in path, or a / in the filename then restrict the
+ * command search.
+ */
+ if (v == 0 || v->vec[0] == 0 || slash)
+ pv = justabs;
+ else
+ pv = v->vec;
+ sav = Strspl(STRslash, *av);/* / command name for postpending */
+#ifdef VFORK
+ Vsav = sav;
+#endif /* VFORK */
+ hashval = havhash ? hashname(*av) : 0;
+
+ i = 0;
+#ifdef VFORK
+ hits++;
+#endif /* VFORK */
+ do {
+ /*
+ * Try to save time by looking at the hash table for where this command
+ * could be. If we are doing delayed hashing, then we put the names in
+ * one at a time, as the user enters them. This is kinda like Korn
+ * Shell's "tracked aliases".
+ */
+ if (!slash && ABSOLUTEP(pv[0]) && havhash) {
+#ifdef FASTHASH
+ if (!bit(hashval, i))
+ goto cont;
+#else /* OLDHASH */
+ int hashval1 = hash(hashval, i);
+ if (!bit(xhash, hashval1))
+ goto cont;
+#endif /* FASTHASH */
+ }
+ if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
+ {
+
+#ifdef COHERENT
+ if (t->t_dflg & F_AMPERSAND) {
+# ifdef JOBDEBUG
+ xprintf("set SIGINT to SIG_IGN\n");
+ xprintf("set SIGQUIT to SIG_DFL\n");
+# endif /* JOBDEBUG */
+ (void) signal(SIGINT,SIG_IGN); /* may not be necessary */
+ (void) signal(SIGQUIT,SIG_DFL);
+ }
+
+ if (gointr && eq(gointr, STRminus)) {
+# ifdef JOBDEBUG
+ xprintf("set SIGINT to SIG_IGN\n");
+ xprintf("set SIGQUIT to SIG_IGN\n");
+# endif /* JOBDEBUG */
+ (void) signal(SIGINT,SIG_IGN); /* may not be necessary */
+ (void) signal(SIGQUIT,SIG_IGN);
+ }
+#endif /* COHERENT */
+
+ texec(*av, av);
+}
+ else {
+ dp = Strspl(*pv, sav);
+#ifdef VFORK
+ Vdp = dp;
+#endif /* VFORK */
+
+#ifdef COHERENT
+ if ((t->t_dflg & F_AMPERSAND)) {
+# ifdef JOBDEBUG
+ xprintf("set SIGINT to SIG_IGN\n");
+# endif /* JOBDEBUG */
+ /*
+ * this is necessary on Coherent or all background
+ * jobs are killed by CTRL-C
+ * (there must be a better fix for this)
+ */
+ (void) signal(SIGINT,SIG_IGN);
+ }
+ if (gointr && eq(gointr,STRminus)) {
+# ifdef JOBDEBUG
+ xprintf("set SIGINT to SIG_IGN\n");
+ xprintf("set SIGQUIT to SIG_IGN\n");
+# endif /* JOBDEBUG */
+ (void) signal(SIGINT,SIG_IGN); /* may not be necessary */
+ (void) signal(SIGQUIT,SIG_IGN);
+ }
+#endif /* COHERENT */
+
+ texec(dp, av);
+#ifdef VFORK
+ Vdp = 0;
+#endif /* VFORK */
+ xfree((ptr_t) dp);
+ }
+#ifdef VFORK
+ misses++;
+#endif /* VFORK */
+cont:
+ pv++;
+ i++;
+ } while (*pv);
+#ifdef VFORK
+ hits--;
+ Vsav = 0;
+#endif /* VFORK */
+ xfree((ptr_t) sav);
+ pexerr();
+}
+
+static void
+pexerr()
+{
+ /* Couldn't find the damn thing */
+ if (expath) {
+ setname(short2str(expath));
+#ifdef VFORK
+ Vexpath = 0;
+#endif /* VFORK */
+ xfree((ptr_t) expath);
+ expath = 0;
+ }
+ else
+ setname("");
+ if (exerr)
+ stderror(ERR_NAME | ERR_STRING, exerr);
+ stderror(ERR_NAME | ERR_COMMAND);
+}
+
+/*
+ * Execute command f, arg list t.
+ * Record error message if not found.
+ * Also do shell scripts here.
+ */
+static void
+texec(sf, st)
+ Char *sf;
+ register Char **st;
+{
+ register char **t;
+ register char *f;
+ register struct varent *v;
+ Char **vp;
+ Char *lastsh[2];
+ char pref[2];
+ int fd;
+ Char *st0, **ost;
+
+ /* The order for the conversions is significant */
+ t = short2blk(st);
+ f = short2str(sf);
+#ifdef VFORK
+ Vt = t;
+#endif /* VFORK */
+ errno = 0; /* don't use a previous error */
+#ifdef apollo
+ /*
+ * If we try to execute an nfs mounted directory on the apollo, we
+ * hang forever. So until apollo fixes that..
+ */
+ {
+ struct stat stb;
+ if (stat(f, &stb) == 0 && S_ISDIR(stb.st_mode))
+ errno = EISDIR;
+ }
+ if (errno == 0)
+#endif /* apollo */
+ {
+#ifdef ISC_POSIX_EXEC_BUG
+ __setostype(0); /* "0" is "__OS_SYSV" in <sys/user.h> */
+#endif /* ISC_POSIX_EXEC_BUG */
+ (void) execv(f, t);
+#ifdef ISC_POSIX_EXEC_BUG
+ __setostype(1); /* "1" is "__OS_POSIX" in <sys/user.h> */
+#endif /* ISC_POSIX_EXEC_BUG */
+ }
+#ifdef VFORK
+ Vt = 0;
+#endif /* VFORK */
+ blkfree((Char **) t);
+ switch (errno) {
+
+ case ENOEXEC:
+#ifdef WINNT
+ nt_feed_to_cmd(f,t);
+#endif /* WINNT */
+ /*
+ * From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute
+ * it, don't feed it to the shell if it looks like a binary!
+ */
+ if ((fd = open(f, O_RDONLY)) != -1) {
+ int nread;
+ if ((nread = read(fd, (char *) pref, 2)) == 2) {
+ if (!Isprint(pref[0]) && (pref[0] != '\n' && pref[0] != '\t')) {
+ (void) close(fd);
+ /*
+ * We *know* what ENOEXEC means.
+ */
+ stderror(ERR_ARCH, f, strerror(errno));
+ }
+ }
+ else if (nread < 0 && errno != EINTR) {
+#ifdef convex
+ /* need to print error incase the file is migrated */
+ stderror(ERR_SYSTEM, f, strerror(errno));
+#endif
+ }
+#ifdef _PATH_BSHELL
+ else {
+ pref[0] = '#';
+ pref[1] = '\0';
+ }
+#endif
+ }
+#ifdef HASHBANG
+ if (fd == -1 ||
+ pref[0] != '#' || pref[1] != '!' || hashbang(fd, &vp) == -1) {
+#endif /* HASHBANG */
+ /*
+ * If there is an alias for shell, then put the words of the alias in
+ * front of the argument list replacing the command name. Note no
+ * interpretation of the words at this point.
+ */
+ v = adrof1(STRshell, &aliases);
+ if (v == 0) {
+ vp = lastsh;
+ vp[0] = adrof(STRshell) ? varval(STRshell) : STR_SHELLPATH;
+ vp[1] = NULL;
+#ifdef _PATH_BSHELL
+ if (fd != -1
+# ifndef ISC /* Compatible with ISC's /bin/csh */
+ && pref[0] != '#'
+# endif /* ISC */
+ )
+ vp[0] = STR_BSHELL;
+#endif
+ vp = saveblk(vp);
+ }
+ else
+ vp = saveblk(v->vec);
+#ifdef HASHBANG
+ }
+#endif /* HASHBANG */
+ if (fd != -1)
+ (void) close(fd);
+
+ st0 = st[0];
+ st[0] = sf;
+ ost = st;
+ st = blkspl(vp, st); /* Splice up the new arglst */
+ ost[0] = st0;
+ sf = *st;
+ /* The order for the conversions is significant */
+ t = short2blk(st);
+ f = short2str(sf);
+ xfree((ptr_t) st);
+ blkfree((Char **) vp);
+#ifdef VFORK
+ Vt = t;
+#endif /* VFORK */
+#ifdef ISC_POSIX_EXEC_BUG
+ __setostype(0); /* "0" is "__OS_SYSV" in <sys/user.h> */
+#endif /* ISC_POSIX_EXEC_BUG */
+ (void) execv(f, t);
+#ifdef ISC_POSIX_EXEC_BUG
+ __setostype(1); /* "1" is "__OS_POSIX" in <sys/user.h> */
+#endif /* ISC_POSIX_EXEC_BUG */
+#ifdef VFORK
+ Vt = 0;
+#endif /* VFORK */
+ blkfree((Char **) t);
+ /* The sky is falling, the sky is falling! */
+ stderror(ERR_SYSTEM, f, strerror(errno));
+ break;
+
+ case ENOMEM:
+ stderror(ERR_SYSTEM, f, strerror(errno));
+ break;
+
+#ifdef _IBMR2
+ case 0: /* execv fails and returns 0! */
+#endif /* _IBMR2 */
+ case ENOENT:
+ break;
+
+ default:
+ if (exerr == 0) {
+ exerr = strerror(errno);
+ if (expath)
+ xfree((ptr_t) expath);
+ expath = Strsave(sf);
+#ifdef VFORK
+ Vexpath = expath;
+#endif /* VFORK */
+ }
+ break;
+ }
+}
+
+/*ARGSUSED*/
+void
+execash(t, kp)
+ Char **t;
+ register struct command *kp;
+{
+ int saveIN, saveOUT, saveDIAG, saveSTD;
+ int oSHIN;
+ int oSHOUT;
+ int oSHDIAG;
+ int oOLDSTD;
+ jmp_buf_t osetexit;
+ int my_reenter;
+ int odidfds;
+#ifndef CLOSE_ON_EXEC
+ int odidcch;
+#endif /* CLOSE_ON_EXEC */
+ signalfun_t osigint, osigquit, osigterm;
+
+ USE(t);
+ if (chkstop == 0 && setintr)
+ panystop(0);
+ /*
+ * Hmm, we don't really want to do that now because we might
+ * fail, but what is the choice
+ */
+ rechist(NULL, adrof(STRsavehist) != NULL);
+
+
+ osigint = signal(SIGINT, parintr);
+ osigquit = signal(SIGQUIT, parintr);
+ osigterm = signal(SIGTERM, parterm);
+
+ odidfds = didfds;
+#ifndef CLOSE_ON_EXEC
+ odidcch = didcch;
+#endif /* CLOSE_ON_EXEC */
+ oSHIN = SHIN;
+ oSHOUT = SHOUT;
+ oSHDIAG = SHDIAG;
+ oOLDSTD = OLDSTD;
+
+ saveIN = dcopy(SHIN, -1);
+ saveOUT = dcopy(SHOUT, -1);
+ saveDIAG = dcopy(SHDIAG, -1);
+ saveSTD = dcopy(OLDSTD, -1);
+
+ lshift(kp->t_dcom, 1);
+
+ getexit(osetexit);
+
+ /* PWP: setjmp/longjmp bugfix for optimizing compilers */
+#ifdef cray
+ my_reenter = 1; /* assume non-zero return val */
+ if (setexit() == 0) {
+ my_reenter = 0; /* Oh well, we were wrong */
+#else /* !cray */
+ if ((my_reenter = setexit()) == 0) {
+#endif /* cray */
+ SHIN = dcopy(0, -1);
+ SHOUT = dcopy(1, -1);
+ SHDIAG = dcopy(2, -1);
+#ifndef CLOSE_ON_EXEC
+ didcch = 0;
+#endif /* CLOSE_ON_EXEC */
+ didfds = 0;
+ /*
+ * Decrement the shell level
+ */
+ shlvl(-1);
+#ifdef WINNT
+ __nt_really_exec=1;
+#endif /* WINNT */
+ doexec(kp);
+ }
+
+ (void) sigset(SIGINT, osigint);
+ (void) sigset(SIGQUIT, osigquit);
+ (void) sigset(SIGTERM, osigterm);
+
+ doneinp = 0;
+#ifndef CLOSE_ON_EXEC
+ didcch = odidcch;
+#endif /* CLOSE_ON_EXEC */
+ didfds = odidfds;
+ (void) close(SHIN);
+ (void) close(SHOUT);
+ (void) close(SHDIAG);
+ (void) close(OLDSTD);
+ SHIN = dmove(saveIN, oSHIN);
+ SHOUT = dmove(saveOUT, oSHOUT);
+ SHDIAG = dmove(saveDIAG, oSHDIAG);
+ OLDSTD = dmove(saveSTD, oOLDSTD);
+
+ resexit(osetexit);
+ if (my_reenter)
+ stderror(ERR_SILENT);
+}
+
+void
+xechoit(t)
+ Char **t;
+{
+ if (adrof(STRecho)) {
+ flush();
+ haderr = 1;
+ blkpr(t), xputchar('\n');
+ haderr = 0;
+ }
+}
+
+/*ARGSUSED*/
+void
+dohash(vv, c)
+ Char **vv;
+ struct command *c;
+{
+#ifdef COMMENT
+ struct stat stb;
+#endif
+ DIR *dirp;
+ register struct dirent *dp;
+ int i = 0;
+ struct varent *v = adrof(STRpath);
+ Char **pv;
+ int hashval;
+#ifdef WINNT
+ int is_windir; /* check if it is the windows directory */
+ USE(hashval);
+#endif /* WINNT */
+
+ USE(c);
+#ifdef FASTHASH
+ if (vv && vv[1]) {
+ uhashlength = atoi(short2str(vv[1]));
+ if (vv[2]) {
+ uhashwidth = atoi(short2str(vv[2]));
+ if ((uhashwidth != sizeof(unsigned char)) &&
+ (uhashwidth != sizeof(unsigned short)) &&
+ (uhashwidth != sizeof(unsigned long)))
+ uhashwidth = 0;
+ if (vv[3])
+ hashdebug = atoi(short2str(vv[3]));
+ }
+ }
+
+ if (uhashwidth)
+ hashwidth = uhashwidth;
+ else {
+ hashwidth = 0;
+ for (pv = v->vec; *pv; pv++, hashwidth++)
+ continue;
+ if (hashwidth <= widthof(unsigned char))
+ hashwidth = sizeof(unsigned char);
+ else if (hashwidth <= widthof(unsigned short))
+ hashwidth = sizeof(unsigned short);
+ else if (hashwidth <= widthof(unsigned int))
+ hashwidth = sizeof(unsigned int);
+ else
+ hashwidth = sizeof(unsigned long);
+ }
+
+ if (uhashlength)
+ hashlength = uhashlength;
+ else
+ hashlength = hashwidth * (8*64);/* "average" files per dir in path */
+
+ if (xhash)
+ xfree((ptr_t) xhash);
+ xhash = (unsigned long *) xcalloc((size_t) (hashlength * hashwidth),
+ (size_t) 1);
+#endif /* FASTHASH */
+
+ (void) getusername(NULL); /* flush the tilde cashe */
+ tw_cmd_free();
+ havhash = 1;
+ if (v == NULL)
+ return;
+ for (pv = v->vec; *pv; pv++, i++) {
+ if (!ABSOLUTEP(pv[0]))
+ continue;
+ dirp = opendir(short2str(*pv));
+ if (dirp == NULL)
+ continue;
+#ifdef COMMENT /* this isn't needed. opendir won't open
+ * non-dirs */
+ if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
+ (void) closedir(dirp);
+ continue;
+ }
+#endif
+#ifdef WINNT
+ is_windir = nt_check_if_windir(short2str(*pv));
+#endif /* WINNT */
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0)
+ continue;
+ if (dp->d_name[0] == '.' &&
+ (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+#ifdef WINNT
+ nt_check_name_and_hash(is_windir, dp->d_name, i);
+#else /* !WINNT */
+#if defined(_UWIN) /* XXX: Add cygwin too */
+ /* Turn foo.{exe,com,bat} into foo since UWIN's readdir returns
+ * the file with the .exe, .com, .bat extension
+ */
+ {
+ size_t ext = strlen(dp->d_name) - 4;
+ if ((ext > 0) && (strcmp(&dp->d_name[ext], ".exe") == 0 ||
+ strcmp(&dp->d_name[ext], ".bat") == 0 ||
+ strcmp(&dp->d_name[ext], ".com") == 0))
+ dp->d_name[ext] = '\0';
+ }
+#endif /* _UWIN */
+# ifdef FASTHASH
+ hashval = hashname(str2short(dp->d_name));
+ bis(hashval, i);
+ if (hashdebug & 1)
+ xprintf(CGETS(13, 1, "hash=%-4d dir=%-2d prog=%s\n"),
+ hashname(str2short(dp->d_name)), i, dp->d_name);
+# else /* OLD HASH */
+ hashval = hash(hashname(str2short(dp->d_name)), i);
+ bis(xhash, hashval);
+# endif /* FASTHASH */
+ /* tw_add_comm_name (dp->d_name); */
+#endif /* WINNT */
+ }
+ (void) closedir(dirp);
+ }
+}
+
+/*ARGSUSED*/
+void
+dounhash(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+ havhash = 0;
+#ifdef FASTHASH
+ if (xhash) {
+ xfree((ptr_t) xhash);
+ xhash = NULL;
+ }
+#endif /* FASTHASH */
+}
+
+/*ARGSUSED*/
+void
+hashstat(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+#ifdef FASTHASH
+ if (havhash && hashlength && hashwidth)
+ xprintf(CGETS(13, 2, "%d hash buckets of %d bits each\n"),
+ hashlength, hashwidth*8);
+ if (hashdebug)
+ xprintf(CGETS(13, 3, "debug mask = 0x%08x\n"), hashdebug);
+#endif /* FASTHASH */
+#ifdef VFORK
+ if (hits + misses)
+ xprintf(CGETS(13, 4, "%d hits, %d misses, %d%%\n"),
+ hits, misses, 100 * hits / (hits + misses));
+#endif
+}
+
+
+/*
+ * Hash a command name.
+ */
+static int
+hashname(cp)
+ register Char *cp;
+{
+ register long h;
+
+ for (h = 0; *cp; cp++)
+ h = hash(h, *cp);
+ return ((int) h);
+}
+
+static int
+iscommand(name)
+ Char *name;
+{
+ register Char **pv;
+ register Char *sav;
+ register struct varent *v;
+ register bool slash = any(short2str(name), '/');
+ register int hashval, i;
+
+ v = adrof(STRpath);
+ if (v == 0 || v->vec[0] == 0 || slash)
+ pv = justabs;
+ else
+ pv = v->vec;
+ sav = Strspl(STRslash, name); /* / command name for postpending */
+ hashval = havhash ? hashname(name) : 0;
+ i = 0;
+ do {
+ if (!slash && ABSOLUTEP(pv[0]) && havhash) {
+#ifdef FASTHASH
+ if (!bit(hashval, i))
+ goto cont;
+#else /* OLDHASH */
+ int hashval1 = hash(hashval, i);
+ if (!bit(xhash, hashval1))
+ goto cont;
+#endif /* FASTHASH */
+ }
+ if (pv[0][0] == 0 || eq(pv[0], STRdot)) { /* don't make ./xxx */
+ if (executable(NULL, name, 0)) {
+ xfree((ptr_t) sav);
+ return i + 1;
+ }
+ }
+ else {
+ if (executable(*pv, sav, 0)) {
+ xfree((ptr_t) sav);
+ return i + 1;
+ }
+ }
+cont:
+ pv++;
+ i++;
+ } while (*pv);
+ xfree((ptr_t) sav);
+ return 0;
+}
+
+/* Also by:
+ * Andreas Luik <luik@isaak.isa.de>
+ * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
+ * Azenberstr. 35
+ * D-7000 Stuttgart 1
+ * West-Germany
+ * is the executable() routine below and changes to iscommand().
+ * Thanks again!!
+ */
+
+/*
+ * executable() examines the pathname obtained by concatenating dir and name
+ * (dir may be NULL), and returns 1 either if it is executable by us, or
+ * if dir_ok is set and the pathname refers to a directory.
+ * This is a bit kludgy, but in the name of optimization...
+ */
+int
+executable(dir, name, dir_ok)
+ Char *dir, *name;
+ bool dir_ok;
+{
+ struct stat stbuf;
+ Char path[MAXPATHLEN + 1];
+ char *strname;
+#ifdef WINNT
+ int nt_exetype;
+#endif /* WINNT */
+ (void) memset(path, 0, sizeof(path));
+
+ if (dir && *dir) {
+ copyn(path, dir, MAXPATHLEN);
+ catn(path, name, MAXPATHLEN);
+#ifdef WINNT
+ {
+ char *ptr = short2str(path);
+ char *p2 = ptr;
+ int has_ext = 0;
+
+ while (*ptr++)
+ continue;
+ --ptr;
+
+ while(ptr > p2) {
+ if (*ptr == '/')
+ break;
+ if (*ptr == '.') {
+ has_ext = 1;
+ break;
+ }
+ ptr--;
+ }
+ if (!has_ext && (stat(p2, &stbuf) == -1))
+ catn(path, STRdotEXE, MAXPATHLEN);
+ }
+#endif /* WINNT */
+ strname = short2str(path);
+ }
+ else
+ strname = short2str(name);
+
+ return (stat(strname, &stbuf) != -1 &&
+ ((dir_ok && S_ISDIR(stbuf.st_mode)) ||
+ (S_ISREG(stbuf.st_mode) &&
+ /* save time by not calling access() in the hopeless case */
+#ifdef WINNT
+ (GetBinaryType(strname,&nt_exetype) ||
+ (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)))
+#else /* !WINNT */
+ (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
+ access(strname, X_OK) == 0
+#endif /* WINNT */
+ )));
+}
+
+int
+tellmewhat(lexp, str)
+ struct wordent *lexp;
+ Char *str;
+{
+ register int i;
+ register struct biltins *bptr;
+ register struct wordent *sp = lexp->next;
+ bool aliased = 0, found;
+ Char *s0, *s1, *s2, *cmd;
+ Char qc;
+
+ if (adrof1(sp->word, &aliases)) {
+ alias(lexp);
+ sp = lexp->next;
+ aliased = 1;
+ }
+
+ s0 = sp->word; /* to get the memory freeing right... */
+
+ /* handle quoted alias hack */
+ if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
+ (sp->word)++;
+
+ /* do quoting, if it hasn't been done */
+ s1 = s2 = sp->word;
+ while (*s2)
+ switch (*s2) {
+ case '\'':
+ case '"':
+ qc = *s2++;
+ while (*s2 && *s2 != qc)
+ *s1++ = *s2++ | QUOTE;
+ if (*s2)
+ s2++;
+ break;
+ case '\\':
+ if (*++s2)
+ *s1++ = *s2++ | QUOTE;
+ break;
+ default:
+ *s1++ = *s2++;
+ }
+ *s1 = '\0';
+
+ for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
+ if (eq(sp->word, str2short(bptr->bname))) {
+ if (str == NULL) {
+ if (aliased)
+ prlex(lexp);
+ xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
+ sp->word);
+ flush();
+ }
+ else
+ (void) Strcpy(str, sp->word);
+ sp->word = s0; /* we save and then restore this */
+ return TRUE;
+ }
+ }
+#ifdef WINNT
+ for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
+ if (eq(sp->word, str2short(bptr->bname))) {
+ if (str == NULL) {
+ if (aliased)
+ prlex(lexp);
+ xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
+ sp->word);
+ flush();
+ }
+ else
+ (void) Strcpy(str, sp->word);
+ sp->word = s0; /* we save and then restore this */
+ return TRUE;
+ }
+ }
+#endif /* WINNT*/
+
+ sp->word = cmd = globone(sp->word, G_IGNORE);
+
+ if ((i = iscommand(sp->word)) != 0) {
+ register Char **pv;
+ register struct varent *v;
+ bool slash = any(short2str(sp->word), '/');
+
+ v = adrof(STRpath);
+ if (v == 0 || v->vec[0] == 0 || slash)
+ pv = justabs;
+ else
+ pv = v->vec;
+
+ while (--i)
+ pv++;
+ if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
+ if (!slash) {
+ sp->word = Strspl(STRdotsl, sp->word);
+ prlex(lexp);
+ xfree((ptr_t) sp->word);
+ }
+ else
+ prlex(lexp);
+ }
+ else {
+ s1 = Strspl(*pv, STRslash);
+ sp->word = Strspl(s1, sp->word);
+ xfree((ptr_t) s1);
+ if (str == NULL)
+ prlex(lexp);
+ else
+ (void) Strcpy(str, sp->word);
+ xfree((ptr_t) sp->word);
+ }
+ found = 1;
+ }
+ else {
+ if (str == NULL) {
+ if (aliased)
+ prlex(lexp);
+ xprintf(CGETS(13, 6, "%S: Command not found.\n"), sp->word);
+ flush();
+ }
+ else
+ (void) Strcpy(str, sp->word);
+ found = 0;
+ }
+ sp->word = s0; /* we save and then restore this */
+ xfree((ptr_t) cmd);
+ return found;
+}
+
+/*
+ * Builtin to look at and list all places a command may be defined:
+ * aliases, shell builtins, and the path.
+ *
+ * Marc Horowitz <marc@mit.edu>
+ * MIT Student Information Processing Board
+ */
+
+/*ARGSUSED*/
+void
+dowhere(v, c)
+ register Char **v;
+ struct command *c;
+{
+ int found = 1;
+ USE(c);
+ for (v++; *v; v++)
+ found &= find_cmd(*v, 1);
+ /* Make status nonzero if any command is not found. */
+ if (!found)
+ set(STRstatus, Strsave(STR1), VAR_READWRITE);
+}
+
+int
+find_cmd(cmd, prt)
+ Char *cmd;
+ int prt;
+{
+ struct varent *var;
+ struct biltins *bptr;
+ Char **pv;
+ Char *sv;
+ int hashval, i, ex, rval = 0;
+
+ if (prt && any(short2str(cmd), '/')) {
+ xprintf(CGETS(13, 7, "where: / in command makes no sense\n"));
+ return rval;
+ }
+
+ /* first, look for an alias */
+
+ if (prt && adrof1(cmd, &aliases)) {
+ if ((var = adrof1(cmd, &aliases)) != NULL) {
+ xprintf(CGETS(13, 8, "%S is aliased to "), cmd);
+ blkpr(var->vec);
+ xputchar('\n');
+ rval = 1;
+ }
+ }
+
+ /* next, look for a shell builtin */
+
+ for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
+ if (eq(cmd, str2short(bptr->bname))) {
+ rval = 1;
+ if (prt)
+ xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
+ else
+ return rval;
+ }
+ }
+#ifdef WINNT
+ for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
+ if (eq(cmd, str2short(bptr->bname))) {
+ rval = 1;
+ if (prt)
+ xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
+ else
+ return rval;
+ }
+ }
+#endif /* WINNT*/
+
+ /* last, look through the path for the command */
+
+ if ((var = adrof(STRpath)) == NULL)
+ return rval;
+
+ hashval = havhash ? hashname(cmd) : 0;
+
+ sv = Strspl(STRslash, cmd);
+
+ for (pv = var->vec, i = 0; *pv; pv++, i++) {
+ if (havhash && !eq(*pv, STRdot)) {
+#ifdef FASTHASH
+ if (!bit(hashval, i))
+ continue;
+#else /* OLDHASH */
+ int hashval1 = hash(hashval, i);
+ if (!bit(xhash, hashval1))
+ continue;
+#endif /* FASTHASH */
+ }
+ ex = executable(*pv, sv, 0);
+#ifdef FASTHASH
+ if (!ex && (hashdebug & 2)) {
+ xprintf(CGETS(13, 10, "hash miss: "));
+ ex = 1; /* Force printing */
+ }
+#endif /* FASTHASH */
+ if (ex) {
+ rval = 1;
+ if (prt) {
+ xprintf("%S/", *pv);
+ xprintf("%S\n", cmd);
+ }
+ else
+ return rval;
+ }
+ }
+ xfree((ptr_t) sv);
+ return rval;
+}
+
+#ifdef WINNT
+int
+nt_check_if_windir(path)
+ char *path;
+{
+ char windir[MAX_PATH];
+
+ (void)GetWindowsDirectory(windir, sizeof(windir));
+ windir[2] = '/';
+
+ return (strstr(path, windir) != NULL);
+}
+
+void
+nt_check_name_and_hash(is_windir, file, i)
+ int is_windir;
+ char *file;
+ int i;
+{
+ char name_only[MAX_PATH];
+ char *tmp = (char *)strrchr(file, '.');
+ char uptmp[5], *nameptr, *np2;
+ int icount, hashval;
+
+ if(!tmp || tmp[4])
+ goto nodot;
+
+ for (icount = 0; icount < 4; icount++)
+ uptmp[icount] = toupper(tmp[icount]);
+ uptmp[4]=0;
+
+ if (is_windir)
+ if((uptmp[1] != 'E') || (uptmp[2] != 'X') || (uptmp[3] != 'E'))
+ return;
+ (void) memset(name_only, 0, MAX_PATH);
+ nameptr = file;
+ np2 = name_only;
+ while(nameptr != tmp) {
+ *np2++= tolower(*nameptr);
+ nameptr++;
+ }
+ hashval = hashname(str2short(name_only));
+ bis(hashval, i);
+nodot:
+ hashval = hashname(str2short(file));
+ bis(hashval, i);
+}
+int hashval_extern(cp)
+ Char *cp;
+{
+ return havhash?hashname(cp):0;
+}
+int bit_extern(val,i)
+ int val;
+ int i;
+{
+ return bit(val,i);
+}
+#endif /* WINNT */
diff --git a/contrib/tcsh/sh.exp.c b/contrib/tcsh/sh.exp.c
new file mode 100644
index 0000000..6a26775
--- /dev/null
+++ b/contrib/tcsh/sh.exp.c
@@ -0,0 +1,1107 @@
+/* $Header: /src/pub/tcsh/sh.exp.c,v 3.38 1998/11/24 18:17:32 christos Exp $ */
+/*
+ * sh.exp.c: Expression evaluations
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.exp.c,v 3.38 1998/11/24 18:17:32 christos Exp $")
+
+/*
+ * C shell
+ */
+
+#define TEXP_IGNORE 1 /* in ignore, it means to ignore value, just parse */
+#define TEXP_NOGLOB 2 /* in ignore, it means not to globone */
+
+#define ADDOP 1
+#define MULOP 2
+#define EQOP 4
+#define RELOP 8
+#define RESTOP 16
+#define ANYOP 31
+
+#define EQEQ 1
+#define GTR 2
+#define LSS 4
+#define NOTEQ 6
+#define EQMATCH 7
+#define NOTEQMATCH 8
+
+static int sh_access __P((Char *, int));
+static int exp1 __P((Char ***, bool));
+static int exp2 __P((Char ***, bool));
+static int exp2a __P((Char ***, bool));
+static int exp2b __P((Char ***, bool));
+static int exp2c __P((Char ***, bool));
+static Char *exp3 __P((Char ***, bool));
+static Char *exp3a __P((Char ***, bool));
+static Char *exp4 __P((Char ***, bool));
+static Char *exp5 __P((Char ***, bool));
+static Char *exp6 __P((Char ***, bool));
+static void evalav __P((Char **));
+static int isa __P((Char *, int));
+static int egetn __P((Char *));
+
+
+#ifdef EDEBUG
+static void etracc __P((char *, Char *, Char ***));
+static void etraci __P((char *, int, Char ***));
+#endif /* EDEBUG */
+
+
+/*
+ * shell access function according to POSIX and non POSIX
+ * From Beto Appleton (beto@aixwiz.aix.ibm.com)
+ */
+static int
+sh_access(fname, mode)
+ Char *fname;
+ int mode;
+{
+#if defined(POSIX) && !defined(USE_ACCESS)
+ struct stat statb;
+#endif /* POSIX */
+ char *name = short2str(fname);
+
+ if (*name == '\0')
+ return 1;
+
+#if !defined(POSIX) || defined(USE_ACCESS)
+ return access(name, mode);
+#else /* POSIX */
+
+ /*
+ * POSIX 1003.2-d11.2
+ * -r file True if file exists and is readable.
+ * -w file True if file exists and is writable.
+ * True shall indicate only that the write flag is on.
+ * The file shall not be writable on a read-only file
+ * system even if this test indicates true.
+ * -x file True if file exists and is executable.
+ * True shall indicate only that the execute flag is on.
+ * If file is a directory, true indicates that the file
+ * can be searched.
+ */
+ if (mode != W_OK && mode != X_OK)
+ return access(name, mode);
+
+ if (stat(name, &statb) == -1)
+ return 1;
+
+ if (access(name, mode) == 0) {
+#ifdef S_ISDIR
+ if (S_ISDIR(statb.st_mode) && mode == X_OK)
+ return 0;
+#endif /* S_ISDIR */
+
+ /* root needs permission for someone */
+ switch (mode) {
+ case W_OK:
+ mode = S_IWUSR | S_IWGRP | S_IWOTH;
+ break;
+ case X_OK:
+ mode = S_IXUSR | S_IXGRP | S_IXOTH;
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ }
+
+ else if (euid == statb.st_uid)
+ mode <<= 6;
+
+ else if (egid == statb.st_gid)
+ mode <<= 3;
+
+# ifdef NGROUPS_MAX
+ else {
+# if defined(__386BSD__) || defined(BSD4_4)
+ /*
+ * These two decided that setgroup() should take an array of int's
+ * and they define _SC_NGROUPS_MAX without having sysconf
+ */
+# undef _SC_NGROUPS_MAX
+# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__)
+# define GID_T gid_t
+# else
+# define GID_T int
+# endif
+# else
+# define GID_T gid_t
+# endif /* __386BSD__ || BSD4_4 */
+ /* you can be in several groups */
+ long n;
+ GID_T *groups;
+
+ /*
+ * Try these things to find a positive maximum groups value:
+ * 1) sysconf(_SC_NGROUPS_MAX)
+ * 2) NGROUPS_MAX
+ * 3) getgroups(0, unused)
+ * Then allocate and scan the groups array if one of these worked.
+ */
+# ifdef _SC_NGROUPS_MAX
+ if ((n = sysconf(_SC_NGROUPS_MAX)) == -1)
+# endif /* _SC_NGROUPS_MAX */
+ n = NGROUPS_MAX;
+ if (n <= 0)
+ n = getgroups(0, (GID_T *) NULL);
+
+ if (n > 0) {
+ groups = (GID_T *) xmalloc((size_t) (n * sizeof(GID_T)));
+ n = getgroups((int) n, groups);
+ while (--n >= 0)
+ if (groups[n] == statb.st_gid) {
+ mode <<= 3;
+ break;
+ }
+ }
+ }
+# endif /* NGROUPS_MAX */
+
+ if (statb.st_mode & mode)
+ return 0;
+ else
+ return 1;
+#endif /* !POSIX */
+}
+
+int
+expr(vp)
+ register Char ***vp;
+{
+ return (exp0(vp, 0));
+}
+
+int
+exp0(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register int p1 = exp1(vp, ignore);
+
+#ifdef EDEBUG
+ etraci("exp0 p1", p1, vp);
+#endif /* EDEBUG */
+ if (**vp && eq(**vp, STRor2)) {
+ register int p2;
+
+ (*vp)++;
+ p2 = exp0(vp, (ignore & TEXP_IGNORE) || p1);
+#ifdef EDEBUG
+ etraci("exp0 p2", p2, vp);
+#endif /* EDEBUG */
+ return (p1 || p2);
+ }
+ return (p1);
+}
+
+static int
+exp1(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register int p1 = exp2(vp, ignore);
+
+#ifdef EDEBUG
+ etraci("exp1 p1", p1, vp);
+#endif /* EDEBUG */
+ if (**vp && eq(**vp, STRand2)) {
+ register int p2;
+
+ (*vp)++;
+ p2 = exp1(vp, (ignore & TEXP_IGNORE) || !p1);
+#ifdef EDEBUG
+ etraci("exp1 p2", p2, vp);
+#endif /* EDEBUG */
+ return (p1 && p2);
+ }
+ return (p1);
+}
+
+static int
+exp2(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register int p1 = exp2a(vp, ignore);
+
+#ifdef EDEBUG
+ etraci("exp3 p1", p1, vp);
+#endif /* EDEBUG */
+ if (**vp && eq(**vp, STRor)) {
+ register int p2;
+
+ (*vp)++;
+ p2 = exp2(vp, ignore);
+#ifdef EDEBUG
+ etraci("exp3 p2", p2, vp);
+#endif /* EDEBUG */
+ return (p1 | p2);
+ }
+ return (p1);
+}
+
+static int
+exp2a(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register int p1 = exp2b(vp, ignore);
+
+#ifdef EDEBUG
+ etraci("exp2a p1", p1, vp);
+#endif /* EDEBUG */
+ if (**vp && eq(**vp, STRcaret)) {
+ register int p2;
+
+ (*vp)++;
+ p2 = exp2a(vp, ignore);
+#ifdef EDEBUG
+ etraci("exp2a p2", p2, vp);
+#endif /* EDEBUG */
+ return (p1 ^ p2);
+ }
+ return (p1);
+}
+
+static int
+exp2b(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register int p1 = exp2c(vp, ignore);
+
+#ifdef EDEBUG
+ etraci("exp2b p1", p1, vp);
+#endif /* EDEBUG */
+ if (**vp && eq(**vp, STRand)) {
+ register int p2;
+
+ (*vp)++;
+ p2 = exp2b(vp, ignore);
+#ifdef EDEBUG
+ etraci("exp2b p2", p2, vp);
+#endif /* EDEBUG */
+ return (p1 & p2);
+ }
+ return (p1);
+}
+
+static int
+exp2c(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register Char *p1 = exp3(vp, ignore);
+ register Char *p2;
+ register int i;
+
+#ifdef EDEBUG
+ etracc("exp2c p1", p1, vp);
+#endif /* EDEBUG */
+ if ((i = isa(**vp, EQOP)) != 0) {
+ (*vp)++;
+ if (i == EQMATCH || i == NOTEQMATCH)
+ ignore |= TEXP_NOGLOB;
+ p2 = exp3(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp2c p2", p2, vp);
+#endif /* EDEBUG */
+ if (!(ignore & TEXP_IGNORE))
+ switch (i) {
+
+ case EQEQ:
+ i = eq(p1, p2);
+ break;
+
+ case NOTEQ:
+ i = !eq(p1, p2);
+ break;
+
+ case EQMATCH:
+ i = Gmatch(p1, p2);
+ break;
+
+ case NOTEQMATCH:
+ i = !Gmatch(p1, p2);
+ break;
+ }
+ xfree((ptr_t) p1);
+ xfree((ptr_t) p2);
+ return (i);
+ }
+ i = egetn(p1);
+ xfree((ptr_t) p1);
+ return (i);
+}
+
+static Char *
+exp3(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register Char *p1, *p2;
+ register int i;
+
+ p1 = exp3a(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp3 p1", p1, vp);
+#endif /* EDEBUG */
+ if ((i = isa(**vp, RELOP)) != 0) {
+ (*vp)++;
+ if (**vp && eq(**vp, STRequal))
+ i |= 1, (*vp)++;
+ p2 = exp3(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp3 p2", p2, vp);
+#endif /* EDEBUG */
+ if (!(ignore & TEXP_IGNORE))
+ switch (i) {
+
+ case GTR:
+ i = egetn(p1) > egetn(p2);
+ break;
+
+ case GTR | 1:
+ i = egetn(p1) >= egetn(p2);
+ break;
+
+ case LSS:
+ i = egetn(p1) < egetn(p2);
+ break;
+
+ case LSS | 1:
+ i = egetn(p1) <= egetn(p2);
+ break;
+ }
+ xfree((ptr_t) p1);
+ xfree((ptr_t) p2);
+ return (putn(i));
+ }
+ return (p1);
+}
+
+static Char *
+exp3a(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register Char *p1, *p2, *op;
+ register int i;
+
+ p1 = exp4(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp3a p1", p1, vp);
+#endif /* EDEBUG */
+ op = **vp;
+ if (op && any("<>", op[0]) && op[0] == op[1]) {
+ (*vp)++;
+ p2 = exp3a(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp3a p2", p2, vp);
+#endif /* EDEBUG */
+ if (op[0] == '<')
+ i = egetn(p1) << egetn(p2);
+ else
+ i = egetn(p1) >> egetn(p2);
+ xfree((ptr_t) p1);
+ xfree((ptr_t) p2);
+ return (putn(i));
+ }
+ return (p1);
+}
+
+static Char *
+exp4(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register Char *p1, *p2;
+ register int i = 0;
+
+ p1 = exp5(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp4 p1", p1, vp);
+#endif /* EDEBUG */
+ if (isa(**vp, ADDOP)) {
+ register Char *op = *(*vp)++;
+
+ p2 = exp4(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp4 p2", p2, vp);
+#endif /* EDEBUG */
+ if (!(ignore & TEXP_IGNORE))
+ switch (op[0]) {
+
+ case '+':
+ i = egetn(p1) + egetn(p2);
+ break;
+
+ case '-':
+ i = egetn(p1) - egetn(p2);
+ break;
+ }
+ xfree((ptr_t) p1);
+ xfree((ptr_t) p2);
+ return (putn(i));
+ }
+ return (p1);
+}
+
+static Char *
+exp5(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ register Char *p1, *p2;
+ register int i = 0;
+
+ p1 = exp6(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp5 p1", p1, vp);
+#endif /* EDEBUG */
+
+ if (isa(**vp, MULOP)) {
+ register Char *op = *(*vp)++;
+ if ((ignore & TEXP_NOGLOB) != 0)
+ /*
+ * We are just trying to get the right side of
+ * a =~ or !~ operator
+ */
+ return Strsave(op);
+
+ p2 = exp5(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp5 p2", p2, vp);
+#endif /* EDEBUG */
+ if (!(ignore & TEXP_IGNORE))
+ switch (op[0]) {
+
+ case '*':
+ i = egetn(p1) * egetn(p2);
+ break;
+
+ case '/':
+ i = egetn(p2);
+ if (i == 0)
+ stderror(ERR_DIV0);
+ i = egetn(p1) / i;
+ break;
+
+ case '%':
+ i = egetn(p2);
+ if (i == 0)
+ stderror(ERR_MOD0);
+ i = egetn(p1) % i;
+ break;
+ }
+ xfree((ptr_t) p1);
+ xfree((ptr_t) p2);
+ return (putn(i));
+ }
+ return (p1);
+}
+
+static Char *
+exp6(vp, ignore)
+ register Char ***vp;
+ bool ignore;
+{
+ int ccode, i = 0;
+ register Char *cp;
+
+ if (**vp == 0)
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ if (eq(**vp, STRbang)) {
+ (*vp)++;
+ cp = exp6(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp6 ! cp", cp, vp);
+#endif /* EDEBUG */
+ i = egetn(cp);
+ xfree((ptr_t) cp);
+ return (putn(!i));
+ }
+ if (eq(**vp, STRtilde)) {
+ (*vp)++;
+ cp = exp6(vp, ignore);
+#ifdef EDEBUG
+ etracc("exp6 ~ cp", cp, vp);
+#endif /* EDEBUG */
+ i = egetn(cp);
+ xfree((ptr_t) cp);
+ return (putn(~i));
+ }
+ if (eq(**vp, STRLparen)) {
+ (*vp)++;
+ ccode = exp0(vp, ignore);
+#ifdef EDEBUG
+ etraci("exp6 () ccode", ccode, vp);
+#endif /* EDEBUG */
+ if (*vp == 0 || **vp == 0 || ***vp != ')')
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ (*vp)++;
+ return (putn(ccode));
+ }
+ if (eq(**vp, STRLbrace)) {
+ register Char **v;
+ struct command faket;
+ Char *fakecom[2];
+
+ faket.t_dtyp = NODE_COMMAND;
+ faket.t_dflg = F_BACKQ;
+ faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
+ faket.t_dcom = fakecom;
+ fakecom[0] = STRfakecom;
+ fakecom[1] = NULL;
+ (*vp)++;
+ v = *vp;
+ for (;;) {
+ if (!**vp)
+ stderror(ERR_NAME | ERR_MISSING, '}');
+ if (eq(*(*vp)++, STRRbrace))
+ break;
+ }
+ if (ignore & TEXP_IGNORE)
+ return (Strsave(STRNULL));
+ psavejob();
+ if (pfork(&faket, -1) == 0) {
+ *--(*vp) = 0;
+ evalav(v);
+ exitstat();
+ }
+ pwait();
+ prestjob();
+#ifdef EDEBUG
+ etraci("exp6 {} status", egetn(varval(STRstatus)), vp);
+#endif /* EDEBUG */
+ return (putn(egetn(varval(STRstatus)) == 0));
+ }
+ if (isa(**vp, ANYOP))
+ return (Strsave(STRNULL));
+ cp = *(*vp)++;
+#ifdef convex
+# define FILETESTS "erwxfdzoplstSXLbcugkmKR"
+#else
+# define FILETESTS "erwxfdzoplstSXLbcugkmK"
+#endif /* convex */
+#define FILEVALS "ZAMCDIUGNFPL"
+ if (*cp == '-' && (any(FILETESTS, cp[1]) || any(FILEVALS, cp[1])))
+ return(filetest(cp, vp, ignore));
+#ifdef EDEBUG
+ etracc("exp6 default", cp, vp);
+#endif /* EDEBUG */
+ return (ignore & TEXP_NOGLOB ? Strsave(cp) : globone(cp, G_APPEND));
+}
+
+
+/*
+ * Extended file tests
+ * From: John Rowe <rowe@excc.exeter.ac.uk>
+ */
+Char *
+filetest(cp, vp, ignore)
+ Char *cp, ***vp;
+ bool ignore;
+{
+#ifdef convex
+ struct cvxstat stb, *st = NULL;
+# define TCSH_STAT stat64
+#else
+# define TCSH_STAT stat
+ struct stat stb, *st = NULL;
+#endif /* convex */
+
+#ifdef S_IFLNK
+# ifdef convex
+ struct cvxstat lstb, *lst = NULL;
+# define TCSH_LSTAT lstat64
+# else
+# define TCSH_LSTAT lstat
+ struct stat lstb, *lst = NULL;
+# endif /* convex */
+ char *filnam;
+#endif /* S_IFLNK */
+
+ int i = 0;
+ unsigned pmask = 0xffff;
+ bool altout = 0;
+ Char *ft = cp, *dp, *ep, *strdev, *strino, *strF, *str, valtest = '\0',
+ *errval = STR0;
+ char *string, string0[8];
+ time_t footime;
+ struct passwd *pw;
+ struct group *gr;
+
+ while(any(FILETESTS, *++ft))
+ continue;
+
+ if (!*ft && *(ft - 1) == 'L')
+ --ft;
+
+ if (any(FILEVALS, *ft)) {
+ valtest = *ft++;
+ /*
+ * Value tests return '-1' on failure as 0 is
+ * a legitimate value for many of them.
+ * 'F' returns ':' for compatibility.
+ */
+ errval = valtest == 'F' ? STRcolon : STRminus1;
+
+ if (valtest == 'P' && *ft >= '0' && *ft <= '7') {
+ pmask = (char) *ft - '0';
+ while ( *++ft >= '0' && *ft <= '7' )
+ pmask = 8 * pmask + ((char) *ft - '0');
+ }
+ if (Strcmp(ft, STRcolon) == 0 && any("AMCUGP", valtest)) {
+ altout = 1;
+ ++ft;
+ }
+ }
+
+ if (*ft || ft == cp + 1)
+ stderror(ERR_NAME | ERR_FILEINQ);
+
+ /*
+ * Detect missing file names by checking for operator in the file name
+ * position. However, if an operator name appears there, we must make
+ * sure that there's no file by that name (e.g., "/") before announcing
+ * an error. Even this check isn't quite right, since it doesn't take
+ * globbing into account.
+ */
+
+ if (isa(**vp, ANYOP) && TCSH_STAT(short2str(**vp), &stb))
+ stderror(ERR_NAME | ERR_FILENAME);
+
+ dp = *(*vp)++;
+ if (ignore & TEXP_IGNORE)
+ return (Strsave(STRNULL));
+ ep = globone(dp, G_APPEND);
+ ft = &cp[1];
+ do
+ switch (*ft) {
+
+ case 'r':
+ i = !sh_access(ep, R_OK);
+ break;
+
+ case 'w':
+ i = !sh_access(ep, W_OK);
+ break;
+
+ case 'x':
+ i = !sh_access(ep, X_OK);
+ break;
+
+ case 'X': /* tcsh extension, name is an executable in the path
+ * or a tcsh builtin command
+ */
+ i = find_cmd(ep, 0);
+ break;
+
+ case 't': /* SGI extension, true when file is a tty */
+ i = isatty(atoi(short2str(ep)));
+ break;
+
+ default:
+
+#ifdef S_IFLNK
+ if (tolower(*ft) == 'l') {
+ /*
+ * avoid convex compiler bug.
+ */
+ if (!lst) {
+ lst = &lstb;
+ if (TCSH_LSTAT(short2str(ep), lst) == -1) {
+ xfree((ptr_t) ep);
+ return (Strsave(errval));
+ }
+ }
+ if (*ft == 'L')
+ st = lst;
+ }
+ else
+#endif /* S_IFLNK */
+ /*
+ * avoid convex compiler bug.
+ */
+ if (!st) {
+ st = &stb;
+ if (TCSH_STAT(short2str(ep), st) == -1) {
+ xfree((ptr_t) ep);
+ return (Strsave(errval));
+ }
+ }
+
+ switch (*ft) {
+
+ case 'f':
+#ifdef S_ISREG
+ i = S_ISREG(st->st_mode);
+#else /* !S_ISREG */
+ i = 0;
+#endif /* S_ISREG */
+ break;
+
+ case 'd':
+#ifdef S_ISDIR
+ i = S_ISDIR(st->st_mode);
+#else /* !S_ISDIR */
+ i = 0;
+#endif /* S_ISDIR */
+ break;
+
+ case 'p':
+#ifdef S_ISFIFO
+ i = S_ISFIFO(st->st_mode);
+#else /* !S_ISFIFO */
+ i = 0;
+#endif /* S_ISFIFO */
+ break;
+
+ case 'm' :
+#ifdef S_ISOFL
+ i = S_ISOFL(st->st_dm_mode);
+#else /* !S_ISOFL */
+ i = 0;
+#endif /* S_ISOFL */
+ break ;
+
+ case 'K' :
+#ifdef S_ISOFL
+ i = stb.st_dm_key;
+#else /* !S_ISOFL */
+ i = 0;
+#endif /* S_ISOFL */
+ break ;
+
+
+ case 'l':
+#ifdef S_ISLNK
+ i = S_ISLNK(lst->st_mode);
+#else /* !S_ISLNK */
+ i = 0;
+#endif /* S_ISLNK */
+ break;
+
+ case 'S':
+# ifdef S_ISSOCK
+ i = S_ISSOCK(st->st_mode);
+# else /* !S_ISSOCK */
+ i = 0;
+# endif /* S_ISSOCK */
+ break;
+
+ case 'b':
+#ifdef S_ISBLK
+ i = S_ISBLK(st->st_mode);
+#else /* !S_ISBLK */
+ i = 0;
+#endif /* S_ISBLK */
+ break;
+
+ case 'c':
+#ifdef S_ISCHR
+ i = S_ISCHR(st->st_mode);
+#else /* !S_ISCHR */
+ i = 0;
+#endif /* S_ISCHR */
+ break;
+
+ case 'u':
+ i = (S_ISUID & st->st_mode) != 0;
+ break;
+
+ case 'g':
+ i = (S_ISGID & st->st_mode) != 0;
+ break;
+
+ case 'k':
+ i = (S_ISVTX & st->st_mode) != 0;
+ break;
+
+ case 'z':
+ i = st->st_size == 0;
+ break;
+
+#ifdef convex
+ case 'R':
+ i = (stb.st_dmonflags & IMIGRATED) == IMIGRATED;
+ break;
+#endif /* convex */
+
+ case 's':
+ i = stb.st_size != 0;
+ break;
+
+ case 'e':
+ i = 1;
+ break;
+
+ case 'o':
+ i = st->st_uid == uid;
+ break;
+
+ /*
+ * Value operators are a tcsh extension.
+ */
+
+ case 'D':
+ i = (int) st->st_dev;
+ break;
+
+ case 'I':
+ i = (int) st->st_ino;
+ break;
+
+ case 'F':
+ strdev = putn( (int) st->st_dev);
+ strino = putn( (int) st->st_ino);
+ strF = (Char *) xmalloc((size_t) (2 + Strlen(strdev) +
+ Strlen(strino)) * sizeof(Char));
+ (void) Strcat(Strcat(Strcpy(strF, strdev), STRcolon), strino);
+ xfree((ptr_t) strdev);
+ xfree((ptr_t) strino);
+ xfree((ptr_t) ep);
+ return(strF);
+
+ case 'L':
+ if ( *(ft + 1) ) {
+ i = 1;
+ break;
+ }
+#ifdef S_ISLNK
+ filnam = short2str(ep);
+#ifdef PATH_MAX
+# define MY_PATH_MAX PATH_MAX
+#else /* !PATH_MAX */
+/*
+ * I can't think of any more sensible alterative; readlink doesn't give
+ * us an errno if the buffer isn't large enough :-(
+ */
+# define MY_PATH_MAX 2048
+#endif /* PATH_MAX */
+ i = readlink(filnam, string = (char *)
+ xmalloc((size_t) (1 + MY_PATH_MAX) * sizeof(char)),
+ MY_PATH_MAX);
+ if (i >= 0 && i <= MY_PATH_MAX)
+ string[i] = '\0'; /* readlink does not null terminate */
+ strF = (i < 0) ? errval : str2short(string);
+ xfree((ptr_t) string);
+ xfree((ptr_t) ep);
+ return(Strsave(strF));
+
+#else /* !S_ISLNK */
+ i = 0;
+ break;
+#endif /* S_ISLNK */
+
+
+ case 'N':
+ i = (int) st->st_nlink;
+ break;
+
+ case 'P':
+ string = string0 + 1;
+ (void) xsnprintf(string, sizeof(string0) - 1, "%o",
+ pmask & (unsigned int)
+ ((S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID) & st->st_mode));
+ if (altout && *string != '0')
+ *--string = '0';
+ xfree((ptr_t) ep);
+ return(Strsave(str2short(string)));
+
+ case 'U':
+ if (altout && (pw = getpwuid(st->st_uid))) {
+ xfree((ptr_t) ep);
+ return(Strsave(str2short(pw->pw_name)));
+ }
+ i = (int) st->st_uid;
+ break;
+
+ case 'G':
+ if ( altout && (gr = getgrgid(st->st_gid))) {
+ xfree((ptr_t) ep);
+ return(Strsave(str2short(gr->gr_name)));
+ }
+ i = (int) st->st_gid;
+ break;
+
+ case 'Z':
+ i = (int) st->st_size;
+ break;
+
+ case 'A': case 'M': case 'C':
+ footime = *ft == 'A' ? st->st_atime :
+ *ft == 'M' ? st->st_mtime : st->st_ctime;
+ if (altout) {
+ strF = str2short(ctime(&footime));
+ if ((str = Strchr(strF, '\n')) != NULL)
+ *str = (Char) '\0';
+ xfree((ptr_t) ep);
+ return(Strsave(strF));
+ }
+ i = (int) footime;
+ break;
+
+ }
+ }
+ while (*++ft && i);
+#ifdef EDEBUG
+ etraci("exp6 -? i", i, vp);
+#endif /* EDEBUG */
+ xfree((ptr_t) ep);
+ return (putn(i));
+}
+
+
+static void
+evalav(v)
+ register Char **v;
+{
+ struct wordent paraml1;
+ register struct wordent *hp = &paraml1;
+ struct command *t;
+ register struct wordent *wdp = hp;
+
+ set(STRstatus, Strsave(STR0), VAR_READWRITE);
+ hp->prev = hp->next = hp;
+ hp->word = STRNULL;
+ while (*v) {
+ register struct wordent *new =
+ (struct wordent *) xcalloc(1, sizeof *wdp);
+
+ new->prev = wdp;
+ new->next = hp;
+ wdp->next = new;
+ wdp = new;
+ wdp->word = Strsave(*v++);
+ }
+ hp->prev = wdp;
+ alias(&paraml1);
+ t = syntax(paraml1.next, &paraml1, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+ execute(t, -1, NULL, NULL);
+ freelex(&paraml1), freesyn(t);
+}
+
+static int
+isa(cp, what)
+ register Char *cp;
+ register int what;
+{
+ if (cp == 0)
+ return ((what & RESTOP) != 0);
+ if (*cp == '\0')
+ return 0;
+ if (cp[1] == 0) {
+ if (what & ADDOP && (*cp == '+' || *cp == '-'))
+ return (1);
+ if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
+ return (1);
+ if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
+ *cp == '~' || *cp == '^' || *cp == '"'))
+ return (1);
+ }
+ else if (cp[2] == 0) {
+ if (what & RESTOP) {
+ if (cp[0] == '|' && cp[1] == '&')
+ return (1);
+ if (cp[0] == '<' && cp[1] == '<')
+ return (1);
+ if (cp[0] == '>' && cp[1] == '>')
+ return (1);
+ }
+ if (what & EQOP) {
+ if (cp[0] == '=') {
+ if (cp[1] == '=')
+ return (EQEQ);
+ if (cp[1] == '~')
+ return (EQMATCH);
+ }
+ else if (cp[0] == '!') {
+ if (cp[1] == '=')
+ return (NOTEQ);
+ if (cp[1] == '~')
+ return (NOTEQMATCH);
+ }
+ }
+ }
+ if (what & RELOP) {
+ if (*cp == '<')
+ return (LSS);
+ if (*cp == '>')
+ return (GTR);
+ }
+ return (0);
+}
+
+static int
+egetn(cp)
+ register Char *cp;
+{
+ if (*cp && *cp != '-' && !Isdigit(*cp))
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ return (getn(cp));
+}
+
+/* Phew! */
+
+#ifdef EDEBUG
+static void
+etraci(str, i, vp)
+ char *str;
+ int i;
+ Char ***vp;
+{
+ xprintf("%s=%d\t", str, i);
+ blkpr(*vp);
+ xputchar('\n');
+}
+static void
+etracc(str, cp, vp)
+ char *str;
+ Char *cp;
+ Char ***vp;
+{
+ xprintf("%s=%s\t", str, cp);
+ blkpr(*vp);
+ xputchar('\n');
+}
+#endif /* EDEBUG */
diff --git a/contrib/tcsh/sh.file.c b/contrib/tcsh/sh.file.c
new file mode 100644
index 0000000..28646f1
--- /dev/null
+++ b/contrib/tcsh/sh.file.c
@@ -0,0 +1,848 @@
+/* $Header: /src/pub/tcsh/sh.file.c,v 3.15 1997/10/02 16:36:29 christos Exp $ */
+/*
+ * sh.file.c: File completion for csh. This file is not used in tcsh.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.file.c,v 3.15 1997/10/02 16:36:29 christos Exp $")
+
+#ifdef FILEC
+
+/*
+ * Tenex style file name recognition, .. and more.
+ * History:
+ * Author: Ken Greer, Sept. 1975, CMU.
+ * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
+ */
+
+#define ON 1
+#define OFF 0
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define ESC CTL_ESC('\033')
+
+typedef enum {
+ LIST, RECOGNIZE
+} COMMAND;
+
+static void setup_tty __P((int));
+static void back_to_col_1 __P((void));
+static void pushback __P((Char *));
+static void catn __P((Char *, Char *, int));
+static void copyn __P((Char *, Char *, int));
+static Char filetype __P((Char *, Char *));
+static void print_by_column __P((Char *, Char *[], int));
+static Char *tilde __P((Char *, Char *));
+static void retype __P((void));
+static void beep __P((void));
+static void print_recognized_stuff __P((Char *));
+static void extract_dir_and_name __P((Char *, Char *, Char *));
+static Char *getitem __P((DIR *, int));
+static void free_items __P((Char **));
+static int tsearch __P((Char *, COMMAND, int));
+static int recognize __P((Char *, Char *, int, int));
+static int is_prefix __P((Char *, Char *));
+static int is_suffix __P((Char *, Char *));
+static int ignored __P((Char *));
+
+
+/*
+ * Put this here so the binary can be patched with adb to enable file
+ * completion by default. Filec controls completion, nobeep controls
+ * ringing the terminal bell on incomplete expansions.
+ */
+bool filec = 0;
+
+static void
+setup_tty(on)
+ int on;
+{
+#ifdef TERMIO
+# ifdef POSIX
+ struct termios tchars;
+# else
+ struct termio tchars;
+# endif /* POSIX */
+
+# ifdef POSIX
+ (void) tcgetattr(SHIN, &tchars);
+# else
+ (void) ioctl(SHIN, TCGETA, (ioctl_t) &tchars);
+# endif /* POSIX */
+ if (on) {
+ tchars.c_cc[VEOL] = ESC;
+ if (tchars.c_lflag & ICANON)
+# ifdef POSIX
+ on = TCSADRAIN;
+# else
+ on = TCSETA;
+# endif /* POSIX */
+ else {
+# ifdef POSIX
+ on = TCSAFLUSH;
+# else
+ on = TCSETAF;
+# endif /* POSIX */
+ tchars.c_lflag |= ICANON;
+
+ }
+ }
+ else {
+ tchars.c_cc[VEOL] = _POSIX_VDISABLE;
+# ifdef POSIX
+ on = TCSADRAIN;
+# else
+ on = TCSETA;
+# endif /* POSIX */
+ }
+# ifdef POSIX
+ (void) tcsetattr(SHIN, on, &tchars);
+# else
+ (void) ioctl(SHIN, on, (ioctl_t) &tchars);
+# endif /* POSIX */
+#else
+ struct sgttyb sgtty;
+ static struct tchars tchars;/* INT, QUIT, XON, XOFF, EOF, BRK */
+
+ if (on) {
+ (void) ioctl(SHIN, TIOCGETC, (ioctl_t) & tchars);
+ tchars.t_brkc = ESC;
+ (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars);
+ /*
+ * This must be done after every command: if the tty gets into raw or
+ * cbreak mode the user can't even type 'reset'.
+ */
+ (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & sgtty);
+ if (sgtty.sg_flags & (RAW | CBREAK)) {
+ sgtty.sg_flags &= ~(RAW | CBREAK);
+ (void) ioctl(SHIN, TIOCSETP, (ioctl_t) & sgtty);
+ }
+ }
+ else {
+ tchars.t_brkc = -1;
+ (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars);
+ }
+#endif /* TERMIO */
+}
+
+/*
+ * Move back to beginning of current line
+ */
+static void
+back_to_col_1()
+{
+#ifdef TERMIO
+# ifdef POSIX
+ struct termios tty, tty_normal;
+# else
+ struct termio tty, tty_normal;
+# endif /* POSIX */
+#else
+ struct sgttyb tty, tty_normal;
+#endif /* TERMIO */
+
+# ifdef BSDSIGS
+ sigmask_t omask = sigblock(sigmask(SIGINT));
+# else
+ (void) sighold(SIGINT);
+# endif /* BSDSIGS */
+
+#ifdef TERMIO
+# ifdef POSIX
+ (void) tcgetattr(SHOUT, &tty);
+# else
+ (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty_normal);
+# endif /* POSIX */
+ tty_normal = tty;
+ tty.c_iflag &= ~INLCR;
+ tty.c_oflag &= ~ONLCR;
+# ifdef POSIX
+ (void) tcsetattr(SHOUT, TCSANOW, &tty);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty);
+# endif /* POSIX */
+ (void) write(SHOUT, "\r", 1);
+# ifdef POSIX
+ (void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal);
+# endif /* POSIX */
+#else
+ (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & tty);
+ tty_normal = tty;
+ tty.sg_flags &= ~CRMOD;
+ (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty);
+ (void) write(SHOUT, "\r", 1);
+ (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty_normal);
+#endif /* TERMIO */
+
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif /* BSDISGS */
+}
+
+/*
+ * Push string contents back into tty queue
+ */
+static void
+pushback(string)
+ Char *string;
+{
+ register Char *p;
+ char c;
+#ifdef TERMIO
+# ifdef POSIX
+ struct termios tty, tty_normal;
+# else
+ struct termio tty, tty_normal;
+# endif /* POSIX */
+#else
+ struct sgttyb tty, tty_normal;
+#endif /* TERMIO */
+
+#ifdef BSDSIGS
+ sigmask_t omask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+
+#ifdef TERMIO
+# ifdef POSIX
+ (void) tcgetattr(SHOUT, &tty);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty);
+# endif /* POSIX */
+ tty_normal = tty;
+ tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL);
+# ifdef POSIX
+ (void) tcsetattr(SHOUT, TCSANOW, &tty);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty);
+# endif /* POSIX */
+
+ for (p = string; c = *p; p++)
+ (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c);
+# ifdef POSIX
+ (void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty_normal);
+# endif /* POSIX */
+ (void) sigsetmask(omask);
+#else
+ (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty);
+ tty_normal = tty;
+ tty.sg_flags &= ~ECHO;
+ (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty);
+
+ for (p = string; c = *p; p++)
+ (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c);
+ (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty_normal);
+#endif /* TERMIO */
+
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif /* BSDISGS */
+}
+
+/*
+ * Concatenate src onto tail of des.
+ * Des is a string whose maximum length is count.
+ * Always null terminate.
+ */
+static void
+catn(des, src, count)
+ register Char *des, *src;
+ register count;
+{
+ while (--count >= 0 && *des)
+ des++;
+ while (--count >= 0)
+ if ((*des++ = *src++) == 0)
+ return;
+ *des = '\0';
+}
+
+/*
+ * Like strncpy but always leave room for trailing \0
+ * and always null terminate.
+ */
+static void
+copyn(des, src, count)
+ register Char *des, *src;
+ register count;
+{
+ while (--count >= 0)
+ if ((*des++ = *src++) == 0)
+ return;
+ *des = '\0';
+}
+
+static Char
+filetype(dir, file)
+ Char *dir, *file;
+{
+ Char path[MAXPATHLEN];
+ struct stat statb;
+
+ catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char));
+ if (lstat(short2str(path), &statb) == 0) {
+ switch (statb.st_mode & S_IFMT) {
+ case S_IFDIR:
+ return ('/');
+
+ case S_IFLNK:
+ if (stat(short2str(path), &statb) == 0 && /* follow it out */
+ S_ISDIR(statb.st_mode))
+ return ('>');
+ else
+ return ('@');
+
+ case S_IFSOCK:
+ return ('=');
+
+ default:
+ if (statb.st_mode & 0111)
+ return ('*');
+ }
+ }
+ return (' ');
+}
+
+static struct winsize win;
+
+/*
+ * Print sorted down columns
+ */
+static void
+print_by_column(dir, items, count)
+ Char *dir, *items[];
+ int count;
+{
+ register int i, rows, r, c, maxwidth = 0, columns;
+
+ if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0)
+ win.ws_col = 80;
+ for (i = 0; i < count; i++)
+ maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r;
+ maxwidth += 2; /* for the file tag and space */
+ columns = win.ws_col / maxwidth;
+ if (columns == 0)
+ columns = 1;
+ rows = (count + (columns - 1)) / columns;
+ for (r = 0; r < rows; r++) {
+ for (c = 0; c < columns; c++) {
+ i = c * rows + r;
+ if (i < count) {
+ register int w;
+
+ xprintf("%S", items[i]);
+ xputchar(dir ? filetype(dir, items[i]) : ' ');
+ if (c < columns - 1) { /* last column? */
+ w = Strlen(items[i]) + 1;
+ for (; w < maxwidth; w++)
+ xputchar(' ');
+ }
+ }
+ }
+ xputchar('\r');
+ xputchar('\n');
+ }
+}
+
+/*
+ * Expand file name with possible tilde usage
+ * ~person/mumble
+ * expands to
+ * home_directory_of_person/mumble
+ */
+static Char *
+tilde(new, old)
+ Char *new, *old;
+{
+ register Char *o, *p;
+ register struct passwd *pw;
+ static Char person[40];
+
+ if (old[0] != '~')
+ return (Strcpy(new, old));
+
+ for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++);
+ *p = '\0';
+ if (person[0] == '\0')
+ (void) Strcpy(new, varval(STRhome));
+ else {
+ pw = getpwnam(short2str(person));
+ if (pw == NULL)
+ return (NULL);
+ (void) Strcpy(new, str2short(pw->pw_dir));
+ }
+ (void) Strcat(new, o);
+ return (new);
+}
+
+/*
+ * Cause pending line to be printed
+ */
+static void
+retype()
+{
+#ifdef TERMIO
+# ifdef POSIX
+ struct termios tty;
+
+ (void) tcgetattr(SHOUT, &tty);
+# else
+ struct termio tty;
+
+ (void) ioctl(SHOUT, TCGETA, (ioctl_t) &tty);
+# endif /* POSIX */
+
+ tty.c_lflag |= PENDIN;
+
+# ifdef POSIX
+ (void) tcsetattr(SHOUT, TCSANOW, &tty);
+# else
+ (void) ioctl(SHOUT, TCSETAW, (ioctl_t) &tty);
+# endif /* POSIX */
+#else
+ int pending_input = LPENDIN;
+
+ (void) ioctl(SHOUT, TIOCLBIS, (ioctl_t) & pending_input);
+#endif /* TERMIO */
+}
+
+static void
+beep()
+{
+ if (adrof(STRnobeep) == 0)
+#ifndef _OSD_POSIX
+ (void) write(SHOUT, "\007", 1);
+#else /*_OSD_POSIX*/
+ {
+ unsigned char beep_ch = CTL_ESC('\007');
+ (void) write(SHOUT, &beep_ch, 1);
+ }
+#endif /*_OSD_POSIX*/
+}
+
+/*
+ * Erase that silly ^[ and
+ * print the recognized part of the string
+ */
+static void
+print_recognized_stuff(recognized_part)
+ Char *recognized_part;
+{
+ /* An optimized erasing of that silly ^[ */
+ (void) putraw('\b');
+ (void) putraw('\b');
+ switch (Strlen(recognized_part)) {
+
+ case 0: /* erase two Characters: ^[ */
+ (void) putraw(' ');
+ (void) putraw(' ');
+ (void) putraw('\b');
+ (void) putraw('\b');
+ break;
+
+ case 1: /* overstrike the ^, erase the [ */
+ xprintf("%S", recognized_part);
+ (void) putraw(' ');
+ (void) putraw('\b');
+ break;
+
+ default: /* overstrike both Characters ^[ */
+ xprintf("%S", recognized_part);
+ break;
+ }
+ flush();
+}
+
+/*
+ * Parse full path in file into 2 parts: directory and file names
+ * Should leave final slash (/) at end of dir.
+ */
+static void
+extract_dir_and_name(path, dir, name)
+ Char *path, *dir, *name;
+{
+ register Char *p;
+
+ p = Strrchr(path, '/');
+ if (p == NULL) {
+ copyn(name, path, MAXNAMLEN);
+ dir[0] = '\0';
+ }
+ else {
+ copyn(name, ++p, MAXNAMLEN);
+ copyn(dir, path, p - path);
+ }
+}
+/* atp vmsposix - I need to remove all the setpwent
+ * getpwent endpwent stuff. VMS_POSIX has getpwnam getpwuid
+ * and getlogin. This needs fixing. (There is no access to
+ * pw->passwd in VMS - a secure system benefit :-| )
+ */
+static Char *
+getitem(dir_fd, looking_for_lognames)
+ DIR *dir_fd;
+ int looking_for_lognames;
+{
+ register struct passwd *pw;
+ register struct dirent *dirp;
+
+ if (looking_for_lognames) {
+#ifdef _VMS_POSIX
+ return (NULL);
+#else
+ if ((pw = getpwent()) == NULL)
+ return (NULL);
+ return (str2short(pw->pw_name));
+#endif /* atp vmsposix */
+ }
+ if (dirp = readdir(dir_fd))
+ return (str2short(dirp->d_name));
+ return (NULL);
+}
+
+static void
+free_items(items)
+ register Char **items;
+{
+ register int i;
+
+ for (i = 0; items[i]; i++)
+ xfree((ptr_t) items[i]);
+ xfree((ptr_t) items);
+}
+
+#ifdef BSDSIGS
+# define FREE_ITEMS(items) { \
+ sigmask_t omask;\
+\
+ omask = sigblock(sigmask(SIGINT));\
+ free_items(items);\
+ items = NULL;\
+ (void) sigsetmask(omask);\
+}
+#else
+# define FREE_ITEMS(items) { \
+ (void) sighold(SIGINT);\
+ free_items(items);\
+ items = NULL;\
+ (void) sigrelse(SIGINT);\
+}
+#endif /* BSDSIGS */
+
+/*
+ * Perform a RECOGNIZE or LIST command on string "word".
+ */
+static int
+tsearch(word, command, max_word_length)
+ Char *word;
+ int max_word_length;
+ COMMAND command;
+{
+ static Char **items = NULL;
+ register DIR *dir_fd;
+ register numitems = 0, ignoring = TRUE, nignored = 0;
+ register name_length, looking_for_lognames;
+ Char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1];
+ Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1];
+ Char *item;
+
+#define MAXITEMS 1024
+
+ if (items != NULL)
+ FREE_ITEMS(items);
+
+ looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL);
+ if (looking_for_lognames) {
+#ifndef _VMS_POSIX
+ (void) setpwent();
+#endif /*atp vmsposix */
+ copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
+ dir_fd = NULL;
+ }
+ else {
+ extract_dir_and_name(word, dir, name);
+ if (tilde(tilded_dir, dir) == 0)
+ return (0);
+ dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : ".");
+ if (dir_fd == NULL)
+ return (0);
+ }
+
+again: /* search for matches */
+ name_length = Strlen(name);
+ for (numitems = 0; item = getitem(dir_fd, looking_for_lognames);) {
+ if (!is_prefix(name, item))
+ continue;
+ /* Don't match . files on null prefix match */
+ if (name_length == 0 && item[0] == '.' &&
+ !looking_for_lognames)
+ continue;
+ if (command == LIST) {
+ if (numitems >= MAXITEMS) {
+ xprintf(CGETS(14, 1, "\nYikes!! Too many %s!!\n"),
+ looking_for_lognames ?
+ CGETS(14, 2, "names in password file") :
+ CGETS(14, 3, "files");
+ break;
+ }
+ /*
+ * From Beto Appleton (beto@aixwiz.austin.ibm.com)
+ * typing "./control-d" will cause the csh to core-dump.
+ * the problem can be reproduce as following:
+ * 1. set ignoreeof
+ * 2. set filec
+ * 3. create a directory with 1050 files
+ * 4. typing "./control-d" will cause the csh to core-dump
+ * Solution: Add + 1 to MAXITEMS
+ */
+ if (items == NULL)
+ items = (Char **) xcalloc(sizeof(items[0]), MAXITEMS + 1);
+ items[numitems] = (Char *) xmalloc((size_t) (Strlen(item) + 1) *
+ sizeof(Char));
+ copyn(items[numitems], item, MAXNAMLEN);
+ numitems++;
+ }
+ else { /* RECOGNIZE command */
+ if (ignoring && ignored(item))
+ nignored++;
+ else if (recognize(extended_name,
+ item, name_length, ++numitems))
+ break;
+ }
+ }
+ if (ignoring && numitems == 0 && nignored > 0) {
+ ignoring = FALSE;
+ nignored = 0;
+ if (looking_for_lognames)
+#ifndef _VMS_POSIX
+ (void) setpwent();
+#endif /* atp vmsposix */
+ else
+ rewinddir(dir_fd);
+ goto again;
+ }
+
+ if (looking_for_lognames)
+#ifndef _VMS_POSIX
+ (void) endpwent();
+#endif /*atp vmsposix */
+ else
+ (void) closedir(dir_fd);
+ if (numitems == 0)
+ return (0);
+ if (command == RECOGNIZE) {
+ if (looking_for_lognames)
+ copyn(word, STRtilde, 1);
+ else
+ /* put back dir part */
+ copyn(word, dir, max_word_length);
+ /* add extended name */
+ catn(word, extended_name, max_word_length);
+ return (numitems);
+ }
+ else { /* LIST */
+ qsort((ptr_t) items, (size_t) numitems, sizeof(items[0]), sortscmp);
+ print_by_column(looking_for_lognames ? NULL : tilded_dir,
+ items, numitems);
+ if (items != NULL)
+ FREE_ITEMS(items);
+ }
+ return (0);
+}
+
+/*
+ * Object: extend what user typed up to an ambiguity.
+ * Algorithm:
+ * On first match, copy full item (assume it'll be the only match)
+ * On subsequent matches, shorten extended_name to the first
+ * Character mismatch between extended_name and item.
+ * If we shorten it back to the prefix length, stop searching.
+ */
+static int
+recognize(extended_name, item, name_length, numitems)
+ Char *extended_name, *item;
+ int name_length, numitems;
+{
+ if (numitems == 1) /* 1st match */
+ copyn(extended_name, item, MAXNAMLEN);
+ else { /* 2nd & subsequent matches */
+ register Char *x, *ent;
+ register int len = 0;
+
+ x = extended_name;
+ for (ent = item; *x && *x == *ent++; x++, len++);
+ *x = '\0'; /* Shorten at 1st Char diff */
+ if (len == name_length) /* Ambiguous to prefix? */
+ return (-1); /* So stop now and save time */
+ }
+ return (0);
+}
+
+/*
+ * Return true if check matches initial Chars in template.
+ * This differs from PWB imatch in that if check is null
+ * it matches anything.
+ */
+static int
+is_prefix(check, template)
+ register Char *check, *template;
+{
+ do
+ if (*check == 0)
+ return (TRUE);
+ while (*check++ == *template++);
+ return (FALSE);
+}
+
+/*
+ * Return true if the Chars in template appear at the
+ * end of check, I.e., are it's suffix.
+ */
+static int
+is_suffix(check, template)
+ Char *check, *template;
+{
+ register Char *c, *t;
+
+ for (c = check; *c++;);
+ for (t = template; *t++;);
+ for (;;) {
+ if (t == template)
+ return 1;
+ if (c == check || *--t != *--c)
+ return 0;
+ }
+}
+
+int
+tenex(inputline, inputline_size)
+ Char *inputline;
+ int inputline_size;
+{
+ register int numitems, num_read;
+ char tinputline[BUFSIZE];
+
+
+ setup_tty(ON);
+
+ while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) {
+ int i;
+ static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<',
+ '>', '(', ')', '|', '^', '%', '\0'};
+ register Char *str_end, *word_start, last_Char, should_retype;
+ register int space_left;
+ COMMAND command;
+
+ for (i = 0; i < num_read; i++)
+ inputline[i] = (unsigned char) tinputline[i];
+ last_Char = inputline[num_read - 1] & ASCII;
+
+ if (last_Char == '\n' || num_read == inputline_size)
+ break;
+ command = (last_Char == ESC) ? RECOGNIZE : LIST;
+ if (command == LIST)
+ xputchar('\n');
+ str_end = &inputline[num_read];
+ if (last_Char == ESC)
+ --str_end; /* wipeout trailing cmd Char */
+ *str_end = '\0';
+ /*
+ * Find LAST occurence of a delimiter in the inputline. The word start
+ * is one Character past it.
+ */
+ for (word_start = str_end; word_start > inputline; --word_start)
+ if (Strchr(delims, word_start[-1]))
+ break;
+ space_left = inputline_size - (word_start - inputline) - 1;
+ numitems = tsearch(word_start, command, space_left);
+
+ if (command == RECOGNIZE) {
+ /* print from str_end on */
+ print_recognized_stuff(str_end);
+ if (numitems != 1) /* Beep = No match/ambiguous */
+ beep();
+ }
+
+ /*
+ * Tabs in the input line cause trouble after a pushback. tty driver
+ * won't backspace over them because column positions are now
+ * incorrect. This is solved by retyping over current line.
+ */
+ should_retype = FALSE;
+ if (Strchr(inputline, '\t')) { /* tab Char in input line? */
+ back_to_col_1();
+ should_retype = TRUE;
+ }
+ if (command == LIST) /* Always retype after a LIST */
+ should_retype = TRUE;
+ if (should_retype)
+ printprompt(0, NULL);
+ pushback(inputline);
+ if (should_retype)
+ retype();
+ }
+ setup_tty(OFF);
+ return (num_read);
+}
+
+static int
+ignored(item)
+ register Char *item;
+{
+ struct varent *vp;
+ register Char **cp;
+
+ if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
+ return (FALSE);
+ for (; *cp != NULL; cp++)
+ if (is_suffix(item, *cp))
+ return (TRUE);
+ return (FALSE);
+}
+#endif /* FILEC */
diff --git a/contrib/tcsh/sh.func.c b/contrib/tcsh/sh.func.c
new file mode 100644
index 0000000..d0667f5
--- /dev/null
+++ b/contrib/tcsh/sh.func.c
@@ -0,0 +1,2401 @@
+/* $Header: /src/pub/tcsh/sh.func.c,v 3.85 1999/08/16 20:05:49 christos Exp $ */
+/*
+ * sh.func.c: csh builtin functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.func.c,v 3.85 1999/08/16 20:05:49 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+#include "tc.h"
+#ifdef WINNT
+#include "nt.const.h"
+#endif /* WINNT */
+
+/*
+ * C shell
+ */
+extern int just_signaled;
+extern char **environ;
+
+extern bool MapsAreInited;
+extern bool NLSMapsAreInited;
+extern bool NoNLSRebind;
+extern bool GotTermCaps;
+
+static int zlast = -1;
+
+static void islogin __P((void));
+static void preread __P((void));
+static void doagain __P((void));
+static char *isrchx __P((int));
+static void search __P((int, int, Char *));
+static int getword __P((Char *));
+static void toend __P((void));
+static void xecho __P((int, Char **));
+static bool islocale_var __P((Char *));
+
+struct biltins *
+isbfunc(t)
+ struct command *t;
+{
+ register Char *cp = t->t_dcom[0];
+ register struct biltins *bp, *bp1, *bp2;
+ static struct biltins label = {"", dozip, 0, 0};
+ static struct biltins foregnd = {"%job", dofg1, 0, 0};
+ static struct biltins backgnd = {"%job &", dobg1, 0, 0};
+
+ /*
+ * We never match a builtin that has quoted the first
+ * character; this has been the traditional way to escape
+ * builtin commands.
+ */
+ if (*cp & QUOTE)
+ return NULL;
+
+ if (*cp != ':' && lastchr(cp) == ':') {
+ label.bname = short2str(cp);
+ return (&label);
+ }
+ if (*cp == '%') {
+ if (t->t_dflg & F_AMPERSAND) {
+ t->t_dflg &= ~F_AMPERSAND;
+ backgnd.bname = short2str(cp);
+ return (&backgnd);
+ }
+ foregnd.bname = short2str(cp);
+ return (&foregnd);
+ }
+#ifdef WARP
+ /*
+ * This is a perhaps kludgy way to determine if the warp builtin is to be
+ * acknowledged or not. If checkwarp() fails, then we are to assume that
+ * the warp command is invalid, and carry on as we would handle any other
+ * non-builtin command. -- JDK 2/4/88
+ */
+ if (eq(STRwarp, cp) && !checkwarp()) {
+ return (0); /* this builtin disabled */
+ }
+#endif /* WARP */
+ /*
+ * Binary search Bp1 is the beginning of the current search range. Bp2 is
+ * one past the end.
+ */
+ for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
+ int i;
+
+ bp = bp1 + ((bp2 - bp1) >> 1);
+ if ((i = ((char) *cp) - *bp->bname) == 0 &&
+ (i = StrQcmp(cp, str2short(bp->bname))) == 0)
+ return bp;
+ if (i < 0)
+ bp2 = bp;
+ else
+ bp1 = bp + 1;
+ }
+#ifdef WINNT
+ return nt_check_additional_builtins(cp);
+#endif /*WINNT*/
+ return (0);
+}
+
+void
+func(t, bp)
+ register struct command *t;
+ register struct biltins *bp;
+{
+ int i;
+
+ xechoit(t->t_dcom);
+ setname(bp->bname);
+ i = blklen(t->t_dcom) - 1;
+ if (i < bp->minargs)
+ stderror(ERR_NAME | ERR_TOOFEW);
+ if (i > bp->maxargs)
+ stderror(ERR_NAME | ERR_TOOMANY);
+ (*bp->bfunct) (t->t_dcom, t);
+}
+
+/*ARGSUSED*/
+void
+doonintr(v, c)
+ Char **v;
+ struct command *c;
+{
+ register Char *cp;
+ register Char *vv = v[1];
+
+ USE(c);
+ if (parintr == SIG_IGN)
+ return;
+ if (setintr && intty)
+ stderror(ERR_NAME | ERR_TERMINAL);
+ cp = gointr;
+ gointr = 0;
+ xfree((ptr_t) cp);
+ if (vv == 0) {
+#ifdef BSDSIGS
+ if (setintr) {
+ (void) sigblock(sigmask(SIGINT));
+ (void) signal(SIGINT, pintr);
+ }
+ else
+ (void) signal(SIGINT, SIG_DFL);
+#else /* !BSDSIGS */
+ if (setintr) {
+ (void) sighold(SIGINT);
+ (void) sigset(SIGINT, pintr);
+ }
+ else
+ (void) sigset(SIGINT, SIG_DFL);
+#endif /* BSDSIGS */
+ gointr = 0;
+ }
+ else if (eq((vv = strip(vv)), STRminus)) {
+#ifdef BSDSIGS
+ (void) signal(SIGINT, SIG_IGN);
+#else /* !BSDSIGS */
+ (void) sigset(SIGINT, SIG_IGN);
+#endif /* BSDSIGS */
+ gointr = Strsave(STRminus);
+ }
+ else {
+ gointr = Strsave(vv);
+#ifdef BSDSIGS
+ (void) signal(SIGINT, pintr);
+#else /* !BSDSIGS */
+ (void) sigset(SIGINT, pintr);
+#endif /* BSDSIGS */
+ }
+}
+
+/*ARGSUSED*/
+void
+donohup(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+ if (intty)
+ stderror(ERR_NAME | ERR_TERMINAL);
+ if (setintr == 0) {
+ (void) signal(SIGHUP, SIG_IGN);
+#ifdef CC
+ submit(getpid());
+#endif /* CC */
+ }
+}
+
+/*ARGSUSED*/
+void
+dohup(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+ if (intty)
+ stderror(ERR_NAME | ERR_TERMINAL);
+ if (setintr == 0)
+ (void) signal(SIGHUP, SIG_DFL);
+}
+
+
+/*ARGSUSED*/
+void
+dozip(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+}
+
+/*ARGSUSED*/
+void
+dofiletest(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char **fileptr, *ftest, *res;
+
+ if (*(ftest = *++v) != '-')
+ stderror(ERR_NAME | ERR_FILEINQ);
+ ++v;
+
+ gflag = 0;
+ tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else
+ v = gargv = saveblk(v);
+ trim(v);
+
+ while (*(fileptr = v++) != '\0') {
+ xprintf("%S", res = filetest(ftest, &fileptr, 0));
+ xfree((ptr_t) res);
+ if (*v)
+ xprintf(" ");
+ }
+ xprintf("\n");
+
+ if (gargv) {
+ blkfree(gargv);
+ gargv = 0;
+ }
+}
+
+void
+prvars()
+{
+ plist(&shvhed, VAR_ALL);
+}
+
+/*ARGSUSED*/
+void
+doalias(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register struct varent *vp;
+ register Char *p;
+
+ USE(c);
+ v++;
+ p = *v++;
+ if (p == 0)
+ plist(&aliases, VAR_ALL);
+ else if (*v == 0) {
+ vp = adrof1(strip(p), &aliases);
+ if (vp)
+ blkpr(vp->vec), xputchar('\n');
+ }
+ else {
+ if (eq(p, STRalias) || eq(p, STRunalias)) {
+ setname(short2str(p));
+ stderror(ERR_NAME | ERR_DANGER);
+ }
+ set1(strip(p), saveblk(v), &aliases, VAR_READWRITE);
+ tw_cmd_free();
+ }
+}
+
+/*ARGSUSED*/
+void
+unalias(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ unset1(v, &aliases);
+ tw_cmd_free();
+}
+
+/*ARGSUSED*/
+void
+dologout(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+ islogin();
+ goodbye(NULL, NULL);
+}
+
+/*ARGSUSED*/
+void
+dologin(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+#ifdef WINNT
+ USE(v);
+#else /* !WINNT */
+ islogin();
+ rechist(NULL, adrof(STRsavehist) != NULL);
+ (void) signal(SIGTERM, parterm);
+ (void) execl(_PATH_BIN_LOGIN, "login", short2str(v[1]), NULL);
+ (void) execl(_PATH_USRBIN_LOGIN, "login", short2str(v[1]), NULL);
+ untty();
+ xexit(1);
+#endif /* !WINNT */
+}
+
+
+#ifdef NEWGRP
+/*ARGSUSED*/
+void
+donewgrp(v, c)
+ Char **v;
+ struct command *c;
+{
+ char **p;
+ if (chkstop == 0 && setintr)
+ panystop(0);
+ (void) signal(SIGTERM, parterm);
+ p = short2blk(v);
+ /*
+ * From Beto Appleton (beto@aixwiz.austin.ibm.com)
+ * Newgrp can take 2 arguments...
+ */
+ (void) execv(_PATH_BIN_NEWGRP, p);
+ (void) execv(_PATH_USRBIN_NEWGRP, p);
+ blkfree((Char **) p);
+ untty();
+ xexit(1);
+}
+#endif /* NEWGRP */
+
+static void
+islogin()
+{
+ if (chkstop == 0 && setintr)
+ panystop(0);
+ if (loginsh)
+ return;
+ stderror(ERR_NOTLOGIN);
+}
+
+void
+doif(v, kp)
+ Char **v;
+ struct command *kp;
+{
+ register int i;
+ register Char **vv;
+
+ v++;
+ i = expr(&v);
+ vv = v;
+ if (*vv == NULL)
+ stderror(ERR_NAME | ERR_EMPTYIF);
+ if (eq(*vv, STRthen)) {
+ if (*++vv)
+ stderror(ERR_NAME | ERR_IMPRTHEN);
+ setname(short2str(STRthen));
+ /*
+ * If expression was zero, then scan to else , otherwise just fall into
+ * following code.
+ */
+ if (!i)
+ search(TC_IF, 0, NULL);
+ return;
+ }
+ /*
+ * Simple command attached to this if. Left shift the node in this tree,
+ * munging it so we can reexecute it.
+ */
+ if (i) {
+ lshift(kp->t_dcom, vv - kp->t_dcom);
+ reexecute(kp);
+ donefds();
+ }
+}
+
+/*
+ * Reexecute a command, being careful not
+ * to redo i/o redirection, which is already set up.
+ */
+void
+reexecute(kp)
+ register struct command *kp;
+{
+ kp->t_dflg &= F_SAVE;
+ kp->t_dflg |= F_REPEAT;
+ /*
+ * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
+ * pgrp's as the jobs would then have no way to get the tty (we can't give
+ * it to them, and our parent wouldn't know their pgrp, etc.
+ */
+ execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
+}
+
+/*ARGSUSED*/
+void
+doelse (v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ USE(v);
+ search(TC_ELSE, 0, NULL);
+}
+
+/*ARGSUSED*/
+void
+dogoto(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char *lp;
+
+ USE(c);
+ gotolab(lp = globone(v[1], G_ERROR));
+ xfree((ptr_t) lp);
+}
+
+void
+gotolab(lab)
+ Char *lab;
+{
+ register struct whyle *wp;
+ /*
+ * While we still can, locate any unknown ends of existing loops. This
+ * obscure code is the WORST result of the fact that we don't really parse.
+ */
+ zlast = TC_GOTO;
+ for (wp = whyles; wp; wp = wp->w_next)
+ if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
+ search(TC_BREAK, 0, NULL);
+ btell(&wp->w_end);
+ }
+ else {
+ bseek(&wp->w_end);
+ }
+ search(TC_GOTO, 0, lab);
+ /*
+ * Eliminate loops which were exited.
+ */
+ wfree();
+}
+
+/*ARGSUSED*/
+void
+doswitch(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp, *lp;
+
+ USE(c);
+ v++;
+ if (!*v || *(*v++) != '(')
+ stderror(ERR_SYNTAX);
+ cp = **v == ')' ? STRNULL : *v++;
+ if (*(*v++) != ')')
+ v--;
+ if (*v)
+ stderror(ERR_SYNTAX);
+ search(TC_SWITCH, 0, lp = globone(cp, G_ERROR));
+ xfree((ptr_t) lp);
+}
+
+/*ARGSUSED*/
+void
+dobreak(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(v);
+ USE(c);
+ if (whyles)
+ toend();
+ else
+ stderror(ERR_NAME | ERR_NOTWHILE);
+}
+
+/*ARGSUSED*/
+void
+doexit(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+
+ if (chkstop == 0 && (intty || intact) && evalvec == 0)
+ panystop(0);
+ /*
+ * Don't DEMAND parentheses here either.
+ */
+ v++;
+ if (*v) {
+ set(STRstatus, putn(expr(&v)), VAR_READWRITE);
+ if (*v)
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ }
+ btoeof();
+#if 0
+ if (intty)
+#endif
+ /* Always close, why only on ttys? */
+ (void) close(SHIN);
+}
+
+/*ARGSUSED*/
+void
+doforeach(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp, *sp;
+ register struct whyle *nwp;
+
+ USE(c);
+ v++;
+ sp = cp = strip(*v);
+ if (!letter(*sp))
+ stderror(ERR_NAME | ERR_VARBEGIN);
+ while (*cp && alnum(*cp))
+ cp++;
+ if (*cp)
+ stderror(ERR_NAME | ERR_VARALNUM);
+ if ((cp - sp) > MAXVARLEN)
+ stderror(ERR_NAME | ERR_VARTOOLONG);
+ cp = *v++;
+ if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
+ stderror(ERR_NAME | ERR_NOPAREN);
+ v++;
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+ nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
+ nwp->w_fe = nwp->w_fe0 = v;
+ gargv = 0;
+ btell(&nwp->w_start);
+ nwp->w_fename = Strsave(cp);
+ nwp->w_next = whyles;
+ nwp->w_end.type = F_SEEK;
+ whyles = nwp;
+ /*
+ * Pre-read the loop so as to be more comprehensible to a terminal user.
+ */
+ zlast = TC_FOREACH;
+ if (intty)
+ preread();
+ doagain();
+}
+
+/*ARGSUSED*/
+void
+dowhile(v, c)
+ Char **v;
+ struct command *c;
+{
+ register int status;
+ register bool again = whyles != 0 &&
+ SEEKEQ(&whyles->w_start, &lineloc) &&
+ whyles->w_fename == 0;
+
+ USE(c);
+ v++;
+ /*
+ * Implement prereading here also, taking care not to evaluate the
+ * expression before the loop has been read up from a terminal.
+ */
+ if (intty && !again)
+ status = !exp0(&v, 1);
+ else
+ status = !expr(&v);
+ if (*v)
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ if (!again) {
+ register struct whyle *nwp =
+ (struct whyle *) xcalloc(1, sizeof(*nwp));
+
+ nwp->w_start = lineloc;
+ nwp->w_end.type = F_SEEK;
+ nwp->w_end.f_seek = 0;
+ nwp->w_next = whyles;
+ whyles = nwp;
+ zlast = TC_WHILE;
+ if (intty) {
+ /*
+ * The tty preread
+ */
+ preread();
+ doagain();
+ return;
+ }
+ }
+ if (status)
+ /* We ain't gonna loop no more, no more! */
+ toend();
+}
+
+static void
+preread()
+{
+ whyles->w_end.type = I_SEEK;
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ search(TC_BREAK, 0, NULL); /* read the expression in */
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ btell(&whyles->w_end);
+}
+
+/*ARGSUSED*/
+void
+doend(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(v);
+ USE(c);
+ if (!whyles)
+ stderror(ERR_NAME | ERR_NOTWHILE);
+ btell(&whyles->w_end);
+ doagain();
+}
+
+/*ARGSUSED*/
+void
+docontin(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(v);
+ USE(c);
+ if (!whyles)
+ stderror(ERR_NAME | ERR_NOTWHILE);
+ doagain();
+}
+
+static void
+doagain()
+{
+ /* Repeating a while is simple */
+ if (whyles->w_fename == 0) {
+ bseek(&whyles->w_start);
+ return;
+ }
+ /*
+ * The foreach variable list actually has a spurious word ")" at the end of
+ * the w_fe list. Thus we are at the of the list if one word beyond this
+ * is 0.
+ */
+ if (!whyles->w_fe[1]) {
+ dobreak(NULL, NULL);
+ return;
+ }
+ set(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE);
+ bseek(&whyles->w_start);
+}
+
+void
+dorepeat(v, kp)
+ Char **v;
+ struct command *kp;
+{
+ register int i;
+
+#ifdef BSDSIGS
+ register sigmask_t omask = 0;
+
+#endif /* BSDSIGS */
+
+ i = getn(v[1]);
+ if (setintr)
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ lshift(v, 2);
+ while (i > 0) {
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ reexecute(kp);
+ --i;
+ }
+ donefds();
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+}
+
+/*ARGSUSED*/
+void
+doswbrk(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(v);
+ USE(c);
+ search(TC_BRKSW, 0, NULL);
+}
+
+int
+srchx(cp)
+ Char *cp;
+{
+ struct srch *sp, *sp1, *sp2;
+ int i;
+
+ /*
+ * Ignore keywords inside heredocs
+ */
+ if (inheredoc)
+ return -1;
+
+ /*
+ * Binary search Sp1 is the beginning of the current search range. Sp2 is
+ * one past the end.
+ */
+ for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
+ sp = sp1 + ((sp2 - sp1) >> 1);
+ if ((i = *cp - *sp->s_name) == 0 &&
+ (i = Strcmp(cp, str2short(sp->s_name))) == 0)
+ return sp->s_value;
+ if (i < 0)
+ sp2 = sp;
+ else
+ sp1 = sp + 1;
+ }
+ return (-1);
+}
+
+static char *
+isrchx(n)
+ register int n;
+{
+ register struct srch *sp, *sp2;
+
+ for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++)
+ if (sp->s_value == n)
+ return (sp->s_name);
+ return ("");
+}
+
+
+static Char Stype;
+static Char *Sgoal;
+
+static void
+search(type, level, goal)
+ int type;
+ register int level;
+ Char *goal;
+{
+ Char wordbuf[BUFSIZE];
+ register Char *aword = wordbuf;
+ register Char *cp;
+
+ Stype = (Char) type;
+ Sgoal = goal;
+ if (type == TC_GOTO) {
+ struct Ain a;
+ a.type = F_SEEK;
+ a.f_seek = 0;
+ bseek(&a);
+ }
+ do {
+ if (intty && fseekp == feobp && aret == F_SEEK)
+ printprompt(1, isrchx(type == TC_BREAK ? zlast : type));
+ /* xprintf("? "), flush(); */
+ aword[0] = 0;
+ (void) getword(aword);
+ switch (srchx(aword)) {
+
+ case TC_ELSE:
+ if (level == 0 && type == TC_IF)
+ return;
+ break;
+
+ case TC_IF:
+ while (getword(aword))
+ continue;
+ if ((type == TC_IF || type == TC_ELSE) &&
+ eq(aword, STRthen))
+ level++;
+ break;
+
+ case TC_ENDIF:
+ if (type == TC_IF || type == TC_ELSE)
+ level--;
+ break;
+
+ case TC_FOREACH:
+ case TC_WHILE:
+ if (type == TC_BREAK)
+ level++;
+ break;
+
+ case TC_END:
+ if (type == TC_BREAK)
+ level--;
+ break;
+
+ case TC_SWITCH:
+ if (type == TC_SWITCH || type == TC_BRKSW)
+ level++;
+ break;
+
+ case TC_ENDSW:
+ if (type == TC_SWITCH || type == TC_BRKSW)
+ level--;
+ break;
+
+ case TC_LABEL:
+ if (type == TC_GOTO && getword(aword) && eq(aword, goal))
+ level = -1;
+ break;
+
+ default:
+ if (type != TC_GOTO && (type != TC_SWITCH || level != 0))
+ break;
+ if (lastchr(aword) != ':')
+ break;
+ aword[Strlen(aword) - 1] = 0;
+ if ((type == TC_GOTO && eq(aword, goal)) ||
+ (type == TC_SWITCH && eq(aword, STRdefault)))
+ level = -1;
+ break;
+
+ case TC_CASE:
+ if (type != TC_SWITCH || level != 0)
+ break;
+ (void) getword(aword);
+ if (lastchr(aword) == ':')
+ aword[Strlen(aword) - 1] = 0;
+ cp = strip(Dfix1(aword));
+ if (Gmatch(goal, cp))
+ level = -1;
+ xfree((ptr_t) cp);
+ break;
+
+ case TC_DEFAULT:
+ if (type == TC_SWITCH && level == 0)
+ level = -1;
+ break;
+ }
+ (void) getword(NULL);
+ } while (level >= 0);
+}
+
+static int
+getword(wp)
+ register Char *wp;
+{
+ int found = 0, first;
+ int c, d;
+
+ c = readc(1);
+ d = 0;
+ do {
+ while (c == ' ' || c == '\t')
+ c = readc(1);
+ if (c == '#')
+ do
+ c = readc(1);
+ while (c >= 0 && c != '\n');
+ if (c < 0)
+ goto past;
+ if (c == '\n') {
+ if (wp)
+ break;
+ return (0);
+ }
+ unreadc(c);
+ found = 1;
+ first = 1;
+ do {
+ c = readc(1);
+ if (c == '\\' && (c = readc(1)) == '\n')
+ c = ' ';
+ if (c == '\'' || c == '"') {
+ if (d == 0)
+ d = c;
+ else if (d == c)
+ d = 0;
+ }
+ if (c < 0)
+ goto past;
+ if (wp) {
+ *wp++ = (Char) c;
+ *wp = '\0';
+ }
+ if (!first && !d && c == '(') {
+ if (wp) {
+ unreadc(c);
+ *--wp = '\0';
+ return found;
+ }
+ else
+ break;
+ }
+ first = 0;
+ } while ((d || (c != ' ' && c != '\t')) && c != '\n');
+ } while (wp == 0);
+
+ unreadc(c);
+ if (found)
+ *--wp = '\0';
+
+ return (found);
+
+past:
+ switch (Stype) {
+
+ case TC_IF:
+ stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
+ break;
+
+ case TC_ELSE:
+ stderror(ERR_NAME | ERR_NOTFOUND, "endif");
+ break;
+
+ case TC_BRKSW:
+ case TC_SWITCH:
+ stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
+ break;
+
+ case TC_BREAK:
+ stderror(ERR_NAME | ERR_NOTFOUND, "end");
+ break;
+
+ case TC_GOTO:
+ setname(short2str(Sgoal));
+ stderror(ERR_NAME | ERR_NOTFOUND, "label");
+ break;
+
+ default:
+ break;
+ }
+ /* NOTREACHED */
+ return (0);
+}
+
+static void
+toend()
+{
+ if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
+ search(TC_BREAK, 0, NULL);
+ btell(&whyles->w_end);
+ whyles->w_end.f_seek--;
+ }
+ else {
+ bseek(&whyles->w_end);
+ }
+ wfree();
+}
+
+void
+wfree()
+{
+ struct Ain o;
+ struct whyle *nwp;
+#ifdef lint
+ nwp = NULL; /* sun lint is dumb! */
+#endif
+
+#ifdef FDEBUG
+ static char foo[] = "IAFE";
+#endif /* FDEBUG */
+
+ btell(&o);
+
+#ifdef FDEBUG
+ xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
+ foo[o.type + 1], o.a_seek, o.f_seek);
+#endif /* FDEBUG */
+
+ for (; whyles; whyles = nwp) {
+ register struct whyle *wp = whyles;
+ nwp = wp->w_next;
+
+#ifdef FDEBUG
+ xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
+ foo[wp->w_start.type+1],
+ wp->w_start.a_seek, wp->w_start.f_seek);
+ xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
+ foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek);
+#endif /* FDEBUG */
+
+ /*
+ * XXX: We free loops that have different seek types.
+ */
+ if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
+ wp->w_start.type == o.type) {
+ if (wp->w_end.type == F_SEEK) {
+ if (o.f_seek >= wp->w_start.f_seek &&
+ (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
+ break;
+ }
+ else {
+ if (o.a_seek >= wp->w_start.a_seek &&
+ (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
+ break;
+ }
+ }
+
+ if (wp->w_fe0)
+ blkfree(wp->w_fe0);
+ if (wp->w_fename)
+ xfree((ptr_t) wp->w_fename);
+ xfree((ptr_t) wp);
+ }
+}
+
+/*ARGSUSED*/
+void
+doecho(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ xecho(' ', v);
+}
+
+/*ARGSUSED*/
+void
+doglob(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+ xecho(0, v);
+ flush();
+}
+
+static void
+xecho(sep, v)
+ int sep;
+ register Char **v;
+{
+ register Char *cp;
+ int nonl = 0;
+#ifdef ECHO_STYLE
+ int echo_style = ECHO_STYLE;
+#else /* !ECHO_STYLE */
+# if SYSVREL > 0
+ int echo_style = SYSV_ECHO;
+# else /* SYSVREL == 0 */
+ int echo_style = BSD_ECHO;
+# endif /* SYSVREL */
+#endif /* ECHO_STYLE */
+ struct varent *vp;
+
+ if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL &&
+ vp->vec[0] != NULL) {
+ if (Strcmp(vp->vec[0], STRbsd) == 0)
+ echo_style = BSD_ECHO;
+ else if (Strcmp(vp->vec[0], STRsysv) == 0)
+ echo_style = SYSV_ECHO;
+ else if (Strcmp(vp->vec[0], STRboth) == 0)
+ echo_style = BOTH_ECHO;
+ else if (Strcmp(vp->vec[0], STRnone) == 0)
+ echo_style = NONE_ECHO;
+ }
+
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ v++;
+ if (*v == 0)
+ return;
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+
+ if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn))
+ nonl++, v++;
+
+ while ((cp = *v++) != 0) {
+ register int c;
+
+ while ((c = *cp++) != 0) {
+ if ((echo_style & SYSV_ECHO) != 0 && c == '\\') {
+ switch (c = *cp++) {
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'c':
+ nonl = 1;
+ goto done;
+ case 'e':
+#if 0 /* Windows does not understand \e */
+ c = '\e';
+#else
+ c = '\033';
+#endif
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case '0':
+ c = 0;
+ if (*cp >= '0' && *cp < '8')
+ c = c * 8 + *cp++ - '0';
+ if (*cp >= '0' && *cp < '8')
+ c = c * 8 + *cp++ - '0';
+ if (*cp >= '0' && *cp < '8')
+ c = c * 8 + *cp++ - '0';
+ break;
+ case '\0':
+ c = '\\';
+ cp--;
+ break;
+ default:
+ xputchar('\\' | QUOTE);
+ break;
+ }
+ }
+ xputchar(c | QUOTE);
+
+ }
+ if (*v)
+ xputchar(sep | QUOTE);
+ }
+done:
+ if (sep && nonl == 0)
+ xputchar('\n');
+ else
+ flush();
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+}
+
+/* check whether an environment variable should invoke 'set_locale()' */
+static bool
+islocale_var(var)
+ Char *var;
+{
+ static Char *locale_vars[] = {
+ STRLANG, STRLC_CTYPE, STRLC_NUMERIC, STRLC_TIME,
+ STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0
+ };
+ register Char **v;
+
+ for (v = locale_vars; *v; ++v)
+ if (eq(var, *v))
+ return 1;
+ return 0;
+}
+
+/*ARGSUSED*/
+void
+doprintenv(v, c)
+ register Char **v;
+ struct command *c;
+{
+ Char *e;
+ extern bool output_raw;
+ extern bool xlate_cr;
+
+ USE(c);
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+
+ v++;
+ if (*v == 0) {
+ register Char **ep;
+
+ xlate_cr = 1;
+ for (ep = STR_environ; *ep; ep++)
+ xprintf("%S\n", *ep);
+ xlate_cr = 0;
+ }
+ else if ((e = tgetenv(*v)) != NULL) {
+ output_raw = 1;
+ xprintf("%S\n", e);
+ output_raw = 0;
+ }
+ else
+ set(STRstatus, Strsave(STR1), VAR_READWRITE);
+}
+
+/* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
+ (and anything else with a modern compiler) */
+
+/*ARGSUSED*/
+void
+dosetenv(v, c)
+ register Char **v;
+ struct command *c;
+{
+ Char *vp, *lp;
+
+ USE(c);
+ if (*++v == 0) {
+ doprintenv(--v, 0);
+ return;
+ }
+
+ vp = *v++;
+
+ if ((lp = *v++) == 0)
+ lp = STRNULL;
+
+ tsetenv(vp, lp = globone(lp, G_APPEND));
+ if (eq(vp, STRKPATH)) {
+ importpath(lp);
+ dohash(NULL, NULL);
+ xfree((ptr_t) lp);
+ return;
+ }
+
+#ifdef apollo
+ if (eq(vp, STRSYSTYPE)) {
+ dohash(NULL, NULL);
+ xfree((ptr_t) lp);
+ return;
+ }
+#endif /* apollo */
+
+ /* dspkanji/dspmbyte autosetting */
+ /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
+#if defined(DSPMBYTE)
+ if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) {
+ autoset_dspmbyte(lp);
+ }
+#endif
+
+ if (islocale_var(vp)) {
+#ifdef NLS
+ int k;
+
+# ifdef SETLOCALEBUG
+ dont_free = 1;
+# endif /* SETLOCALEBUG */
+ (void) setlocale(LC_ALL, "");
+# ifdef LC_COLLATE
+ (void) setlocale(LC_COLLATE, "");
+# endif
+# ifdef NLS_CATALOGS
+# ifdef LC_MESSAGES
+ (void) setlocale(LC_MESSAGES, "");
+# endif /* LC_MESSAGES */
+ (void) catclose(catd);
+ nlsinit();
+# endif /* NLS_CATALOGS */
+# ifdef LC_CTYPE
+ (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
+# endif /* LC_CTYPE */
+# ifdef SETLOCALEBUG
+ dont_free = 0;
+# endif /* SETLOCALEBUG */
+# ifdef STRCOLLBUG
+ fix_strcoll_bug();
+# endif /* STRCOLLBUG */
+ tw_cmd_free(); /* since the collation sequence has changed */
+ for (k = 0200; k <= 0377 && !Isprint(k); k++)
+ continue;
+ AsciiOnly = k > 0377;
+#else /* !NLS */
+ AsciiOnly = 0;
+#endif /* NLS */
+ NLSMapsAreInited = 0;
+ ed_Init();
+ if (MapsAreInited && !NLSMapsAreInited)
+ ed_InitNLSMaps();
+ xfree((ptr_t) lp);
+ return;
+ }
+
+ if (eq(vp, STRNOREBIND)) {
+ NoNLSRebind = 1;
+ MapsAreInited = 0;
+ NLSMapsAreInited = 0;
+ ed_InitMaps();
+ xfree((ptr_t) lp);
+ return;
+ }
+#ifdef WINNT
+ if (eq(vp, STRtcshlang)) {
+ nlsinit();
+ xfree((ptr_t) lp);
+ return;
+ }
+ if (eq(vp, STRtcshonlystartexes)) {
+ __nt_only_start_exes = 1;
+ xfree((ptr_t) lp);
+ return;
+ }
+#endif /* WINNT */
+ if (eq(vp, STRKTERM)) {
+ char *t;
+ set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */
+ t = short2str(lp);
+ if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) {
+ editing = 1;
+ noediting = 0;
+ set(STRedit, Strsave(STRNULL), VAR_READWRITE);
+ }
+ GotTermCaps = 0;
+ ed_Init();
+ return;
+ }
+
+ if (eq(vp, STRKHOME)) {
+ /*
+ * convert to canonical pathname (possibly resolving symlinks)
+ */
+ lp = dcanon(lp, lp);
+ set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */
+
+ /* fix directory stack for new tilde home */
+ dtilde();
+ return;
+ }
+
+ if (eq(vp, STRKSHLVL)) {
+ /* lp memory used here */
+ set(STRshlvl, quote(lp), VAR_READWRITE);
+ return;
+ }
+
+ if (eq(vp, STRKUSER)) {
+ set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */
+ return;
+ }
+
+ if (eq(vp, STRKGROUP)) {
+ set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */
+ return;
+ }
+
+#ifdef COLOR_LS_F
+ if (eq(vp, STRLS_COLORS)) {
+ parseLS_COLORS(lp);
+ return;
+ }
+#endif /* COLOR_LS_F */
+
+#ifdef SIG_WINDOW
+ /*
+ * Load/Update $LINES $COLUMNS
+ */
+ if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) ||
+ eq(vp, STRTERMCAP)) {
+ xfree((ptr_t) lp);
+ check_window_size(1);
+ return;
+ }
+
+ /*
+ * Change the size to the one directed by $LINES and $COLUMNS
+ */
+ if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) {
+#if 0
+ GotTermCaps = 0;
+#endif
+ xfree((ptr_t) lp);
+ ed_Init();
+ return;
+ }
+#endif /* SIG_WINDOW */
+ xfree((ptr_t) lp);
+}
+
+/*ARGSUSED*/
+void
+dounsetenv(v, c)
+ register Char **v;
+ struct command *c;
+{
+ Char **ep, *p, *n;
+ int i, maxi;
+ static Char *name = NULL;
+
+ USE(c);
+ if (name)
+ xfree((ptr_t) name);
+ /*
+ * Find the longest environment variable
+ */
+ for (maxi = 0, ep = STR_environ; *ep; ep++) {
+ for (i = 0, p = *ep; *p && *p != '='; p++, i++)
+ continue;
+ if (i > maxi)
+ maxi = i;
+ }
+
+ name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char)));
+
+ while (++v && *v)
+ for (maxi = 1; maxi;)
+ for (maxi = 0, ep = STR_environ; *ep; ep++) {
+ for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
+ continue;
+ *n = '\0';
+ if (!Gmatch(name, *v))
+ continue;
+ maxi = 1;
+
+ /* Unset the name. This wasn't being done until
+ * later but most of the stuff following won't
+ * work (particularly the setlocale() and getenv()
+ * stuff) as intended until the name is actually
+ * removed. (sg)
+ */
+ Unsetenv(name);
+
+ if (eq(name, STRNOREBIND)) {
+ NoNLSRebind = 0;
+ MapsAreInited = 0;
+ NLSMapsAreInited = 0;
+ ed_InitMaps();
+ }
+#ifdef apollo
+ else if (eq(name, STRSYSTYPE))
+ dohash(NULL, NULL);
+#endif /* apollo */
+ else if (islocale_var(name)) {
+#ifdef NLS
+ int k;
+
+# ifdef SETLOCALEBUG
+ dont_free = 1;
+# endif /* SETLOCALEBUG */
+ (void) setlocale(LC_ALL, "");
+# ifdef LC_COLLATE
+ (void) setlocale(LC_COLLATE, "");
+# endif
+# ifdef NLS_CATALOGS
+# ifdef LC_MESSAGES
+ (void) setlocale(LC_MESSAGES, "");
+# endif /* LC_MESSAGES */
+ (void) catclose(catd);
+ nlsinit();
+# endif /* NLS_CATALOGS */
+# ifdef LC_CTYPE
+ (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
+# endif /* LC_CTYPE */
+# ifdef SETLOCALEBUG
+ dont_free = 0;
+# endif /* SETLOCALEBUG */
+# ifdef STRCOLLBUG
+ fix_strcoll_bug();
+# endif /* STRCOLLBUG */
+ tw_cmd_free();/* since the collation sequence has changed */
+ for (k = 0200; k <= 0377 && !Isprint(k); k++)
+ continue;
+ AsciiOnly = k > 0377;
+#else /* !NLS */
+ AsciiOnly = getenv("LANG") == NULL &&
+ getenv("LC_CTYPE") == NULL;
+#endif /* NLS */
+ NLSMapsAreInited = 0;
+ ed_Init();
+ if (MapsAreInited && !NLSMapsAreInited)
+ ed_InitNLSMaps();
+
+ }
+#ifdef WINNT
+ else if (eq(name,(STRtcshlang))) {
+ nls_dll_unload();
+ nlsinit();
+ }
+ else if (eq(name,(STRtcshonlystartexes))) {
+ __nt_only_start_exes = 0;
+ }
+#endif /* WINNT */
+#ifdef COLOR_LS_F
+ else if (eq(name, STRLS_COLORS))
+ parseLS_COLORS(n);
+#endif /* COLOR_LS_F */
+ /*
+ * start again cause the environment changes
+ */
+ break;
+ }
+ xfree((ptr_t) name); name = NULL;
+}
+
+void
+tsetenv(name, val)
+ Char *name, *val;
+{
+#ifdef SETENV_IN_LIB
+/*
+ * XXX: This does not work right, since tcsh cannot track changes to
+ * the environment this way. (the builtin setenv without arguments does
+ * not print the right stuff neither does unsetenv). This was for Mach,
+ * it is not needed anymore.
+ */
+#undef setenv
+ char nameBuf[BUFSIZE];
+ char *cname = short2str(name);
+
+ if (cname == NULL)
+ return;
+ (void) strcpy(nameBuf, cname);
+ setenv(nameBuf, short2str(val), 1);
+#else /* !SETENV_IN_LIB */
+ register Char **ep = STR_environ;
+ register Char *cp, *dp;
+ Char *blk[2];
+ Char **oep = ep;
+
+#ifdef WINNT
+ nt_set_env(name,val);
+#endif /* WINNT */
+ for (; *ep; ep++) {
+#ifdef WINNT
+ for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp);
+ cp++, dp++)
+#else
+ for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++)
+#endif /* WINNT */
+ continue;
+ if (*cp != 0 || *dp != '=')
+ continue;
+ cp = Strspl(STRequal, val);
+ xfree((ptr_t) * ep);
+ *ep = strip(Strspl(name, cp));
+ xfree((ptr_t) cp);
+ blkfree((Char **) environ);
+ environ = short2blk(STR_environ);
+ return;
+ }
+ cp = Strspl(name, STRequal);
+ blk[0] = strip(Strspl(cp, val));
+ xfree((ptr_t) cp);
+ blk[1] = 0;
+ STR_environ = blkspl(STR_environ, blk);
+ blkfree((Char **) environ);
+ environ = short2blk(STR_environ);
+ xfree((ptr_t) oep);
+#endif /* SETENV_IN_LIB */
+}
+
+void
+Unsetenv(name)
+ Char *name;
+{
+ register Char **ep = STR_environ;
+ register Char *cp, *dp;
+ Char **oep = ep;
+
+#ifdef WINNT
+ nt_set_env(name,NULL);
+#endif /*WINNT */
+ for (; *ep; ep++) {
+ for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
+ continue;
+ if (*cp != 0 || *dp != '=')
+ continue;
+ cp = *ep;
+ *ep = 0;
+ STR_environ = blkspl(STR_environ, ep + 1);
+ blkfree((Char **) environ);
+ environ = short2blk(STR_environ);
+ *ep = cp;
+ xfree((ptr_t) cp);
+ xfree((ptr_t) oep);
+ return;
+ }
+}
+
+/*ARGSUSED*/
+void
+doumask(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp = v[1];
+ register int i;
+
+ USE(c);
+ if (cp == 0) {
+ i = umask(0);
+ (void) umask(i);
+ xprintf("%o\n", i);
+ return;
+ }
+ i = 0;
+ while (Isdigit(*cp) && *cp != '8' && *cp != '9')
+ i = i * 8 + *cp++ - '0';
+ if (*cp || i < 0 || i > 0777)
+ stderror(ERR_NAME | ERR_MASK);
+ (void) umask(i);
+}
+
+#ifndef HAVENOLIMIT
+# ifndef BSDLIMIT
+ typedef long RLIM_TYPE;
+# ifndef RLIM_INFINITY
+# if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
+ extern RLIM_TYPE ulimit();
+# endif /* ! _MINIX && !__clipper__ */
+# define RLIM_INFINITY 0x003fffff
+# define RLIMIT_FSIZE 1
+# endif /* RLIM_INFINITY */
+# ifdef aiws
+# define toset(a) (((a) == 3) ? 1004 : (a) + 1)
+# define RLIMIT_DATA 3
+# define RLIMIT_STACK 1005
+# else /* aiws */
+# define toset(a) ((a) + 1)
+# endif /* aiws */
+# else /* BSDLIMIT */
+# if defined(BSD4_4) && !defined(__386BSD__)
+ typedef quad_t RLIM_TYPE;
+# else
+# if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
+ typedef rlim_t RLIM_TYPE;
+# else
+# if defined(_SX)
+ typedef long long RLIM_TYPE;
+# else /* _SX */
+ typedef unsigned long RLIM_TYPE;
+# endif /* _SX */
+# endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
+# endif /* BSD4_4 && !__386BSD__ */
+# endif /* BSDLIMIT */
+
+# if (HPUXVERSION > 700) && defined(BSDLIMIT)
+/* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
+/* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
+# ifndef RLIMIT_CPU
+# define RLIMIT_CPU 0
+# define RLIMIT_FSIZE 1
+# define RLIMIT_DATA 2
+# define RLIMIT_STACK 3
+# define RLIMIT_CORE 4
+# define RLIMIT_RSS 5
+# define RLIMIT_NOFILE 6
+# endif /* RLIMIT_CPU */
+# ifndef RLIM_INFINITY
+# define RLIM_INFINITY 0x7fffffff
+# endif /* RLIM_INFINITY */
+ /*
+ * old versions of HP/UX counted limits in 512 bytes
+ */
+# ifndef SIGRTMIN
+# define FILESIZE512
+# endif /* SIGRTMIN */
+# endif /* (HPUXVERSION > 700) && BSDLIMIT */
+
+# if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
+/* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
+/* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
+/* than include both and get warnings, we define the extra SVR4 limits here. */
+# ifndef RLIMIT_VMEM
+# define RLIMIT_VMEM 6
+# endif
+# ifndef RLIMIT_AS
+# define RLIMIT_AS RLIMIT_VMEM
+# endif
+# endif /* SYSVREL > 3 && BSDLIMIT */
+
+struct limits limits[] =
+{
+# ifdef RLIMIT_CPU
+ { RLIMIT_CPU, "cputime", 1, "seconds" },
+# endif /* RLIMIT_CPU */
+
+# ifdef RLIMIT_FSIZE
+# ifndef aiws
+ { RLIMIT_FSIZE, "filesize", 1024, "kbytes" },
+# else
+ { RLIMIT_FSIZE, "filesize", 512, "blocks" },
+# endif /* aiws */
+# endif /* RLIMIT_FSIZE */
+
+# ifdef RLIMIT_DATA
+ { RLIMIT_DATA, "datasize", 1024, "kbytes" },
+# endif /* RLIMIT_DATA */
+
+# ifdef RLIMIT_STACK
+# ifndef aiws
+ { RLIMIT_STACK, "stacksize", 1024, "kbytes" },
+# else
+ { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"},
+# endif /* aiws */
+# endif /* RLIMIT_STACK */
+
+# ifdef RLIMIT_CORE
+ { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" },
+# endif /* RLIMIT_CORE */
+
+# ifdef RLIMIT_RSS
+ { RLIMIT_RSS, "memoryuse", 1024, "kbytes" },
+# endif /* RLIMIT_RSS */
+
+# ifdef RLIMIT_UMEM
+ { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" },
+# endif /* RLIMIT_UMEM */
+
+# ifdef RLIMIT_VMEM
+ { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" },
+# endif /* RLIMIT_VMEM */
+
+# ifdef RLIMIT_NOFILE
+ { RLIMIT_NOFILE, "descriptors", 1, "" },
+# endif /* RLIMIT_NOFILE */
+
+# ifdef RLIMIT_CONCUR
+ { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" },
+# endif /* RLIMIT_CONCUR */
+
+# ifdef RLIMIT_MEMLOCK
+ { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" },
+# endif /* RLIMIT_MEMLOCK */
+
+# ifdef RLIMIT_NPROC
+ { RLIMIT_NPROC, "maxproc", 1, "" },
+# endif /* RLIMIT_NPROC */
+
+# ifdef RLIMIT_OFILE
+ { RLIMIT_OFILE, "openfiles", 1, "" },
+# endif /* RLIMIT_OFILE */
+
+ { -1, NULL, 0, NULL }
+};
+
+static struct limits *findlim __P((Char *));
+static RLIM_TYPE getval __P((struct limits *, Char **));
+static void limtail __P((Char *, char*));
+static void plim __P((struct limits *, int));
+static int setlim __P((struct limits *, int, RLIM_TYPE));
+
+#ifdef convex
+static RLIM_TYPE
+restrict_limit(value)
+ double value;
+{
+ /*
+ * is f too large to cope with? return the maximum or minimum int
+ */
+ if (value > (double) INT_MAX)
+ return (RLIM_TYPE) INT_MAX;
+ else if (value < (double) INT_MIN)
+ return (RLIM_TYPE) INT_MIN;
+ else
+ return (RLIM_TYPE) value;
+}
+#else /* !convex */
+# define restrict_limit(x) ((RLIM_TYPE) (x))
+#endif /* convex */
+
+
+static struct limits *
+findlim(cp)
+ Char *cp;
+{
+ register struct limits *lp, *res;
+
+ res = (struct limits *) NULL;
+ for (lp = limits; lp->limconst >= 0; lp++)
+ if (prefix(cp, str2short(lp->limname))) {
+ if (res)
+ stderror(ERR_NAME | ERR_AMBIG);
+ res = lp;
+ }
+ if (res)
+ return (res);
+ stderror(ERR_NAME | ERR_LIMIT);
+ /* NOTREACHED */
+ return (0);
+}
+
+/*ARGSUSED*/
+void
+dolimit(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register struct limits *lp;
+ register RLIM_TYPE limit;
+ int hard = 0;
+
+ USE(c);
+ v++;
+ if (*v && eq(*v, STRmh)) {
+ hard = 1;
+ v++;
+ }
+ if (*v == 0) {
+ for (lp = limits; lp->limconst >= 0; lp++)
+ plim(lp, hard);
+ return;
+ }
+ lp = findlim(v[0]);
+ if (v[1] == 0) {
+ plim(lp, hard);
+ return;
+ }
+ limit = getval(lp, v + 1);
+ if (setlim(lp, hard, limit) < 0)
+ stderror(ERR_SILENT);
+}
+
+static RLIM_TYPE
+getval(lp, v)
+ register struct limits *lp;
+ Char **v;
+{
+ register float f;
+#ifndef atof /* This can be a macro on linux */
+ extern double atof __P((const char *));
+#endif /* atof */
+ Char *cp = *v++;
+
+ f = atof(short2str(cp));
+
+# ifdef convex
+ /*
+ * is f too large to cope with. limit f to minint, maxint - X-6768 by
+ * strike
+ */
+ if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) {
+ stderror(ERR_NAME | ERR_TOOLARGE);
+ }
+# endif /* convex */
+
+ while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
+ cp++;
+ if (*cp == 0) {
+ if (*v == 0)
+ return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5) * lp->limdiv);
+ cp = *v;
+ }
+ switch (*cp) {
+# ifdef RLIMIT_CPU
+ case ':':
+ if (lp->limconst != RLIMIT_CPU)
+ goto badscal;
+ return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1))));
+ case 'h':
+ if (lp->limconst != RLIMIT_CPU)
+ goto badscal;
+ limtail(cp, "hours");
+ f *= 3600.0;
+ break;
+ case 'm':
+ if (lp->limconst == RLIMIT_CPU) {
+ limtail(cp, "minutes");
+ f *= 60.0;
+ break;
+ }
+ *cp = 'm';
+ limtail(cp, "megabytes");
+ f *= 1024.0 * 1024.0;
+ break;
+ case 's':
+ if (lp->limconst != RLIMIT_CPU)
+ goto badscal;
+ limtail(cp, "seconds");
+ break;
+# endif /* RLIMIT_CPU */
+ case 'M':
+# ifdef RLIMIT_CPU
+ if (lp->limconst == RLIMIT_CPU)
+ goto badscal;
+# endif /* RLIMIT_CPU */
+ *cp = 'm';
+ limtail(cp, "megabytes");
+ f *= 1024.0 * 1024.0;
+ break;
+ case 'k':
+# ifdef RLIMIT_CPU
+ if (lp->limconst == RLIMIT_CPU)
+ goto badscal;
+# endif /* RLIMIT_CPU */
+ limtail(cp, "kbytes");
+ f *= 1024.0;
+ break;
+ case 'b':
+# ifdef RLIMIT_CPU
+ if (lp->limconst == RLIMIT_CPU)
+ goto badscal;
+# endif /* RLIMIT_CPU */
+ limtail(cp, "blocks");
+ f *= 512.0;
+ break;
+ case 'u':
+ limtail(cp, "unlimited");
+ return ((RLIM_TYPE) RLIM_INFINITY);
+ default:
+# ifdef RLIMIT_CPU
+badscal:
+# endif /* RLIMIT_CPU */
+ stderror(ERR_NAME | ERR_SCALEF);
+ }
+# ifdef convex
+ return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5));
+# else
+ f += 0.5;
+ if (f > (float) RLIM_INFINITY)
+ return ((RLIM_TYPE) RLIM_INFINITY);
+ else
+ return ((RLIM_TYPE) f);
+# endif /* convex */
+}
+
+static void
+limtail(cp, str)
+ Char *cp;
+ char *str;
+{
+ while (*cp && *cp == *str)
+ cp++, str++;
+ if (*cp)
+ stderror(ERR_BADSCALE, str);
+}
+
+
+/*ARGSUSED*/
+static void
+plim(lp, hard)
+ register struct limits *lp;
+ int hard;
+{
+# ifdef BSDLIMIT
+ struct rlimit rlim;
+# endif /* BSDLIMIT */
+ RLIM_TYPE limit;
+ int div = lp->limdiv;
+
+ xprintf("%s \t", lp->limname);
+
+# ifndef BSDLIMIT
+ limit = ulimit(lp->limconst, 0);
+# ifdef aiws
+ if (lp->limconst == RLIMIT_DATA)
+ limit -= 0x20000000;
+# endif /* aiws */
+# else /* BSDLIMIT */
+ (void) getrlimit(lp->limconst, &rlim);
+ limit = hard ? rlim.rlim_max : rlim.rlim_cur;
+# endif /* BSDLIMIT */
+
+# if !defined(BSDLIMIT) || defined(FILESIZE512)
+ /*
+ * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
+ * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
+ */
+ if (lp->limconst == RLIMIT_FSIZE) {
+ if (limit >= (RLIM_INFINITY / 512))
+ limit = RLIM_INFINITY;
+ else
+ div = (div == 1024 ? 2 : 1);
+ }
+# endif /* !BSDLIMIT || FILESIZE512 */
+
+ if (limit == RLIM_INFINITY)
+ xprintf("unlimited");
+ else
+# ifdef RLIMIT_CPU
+ if (lp->limconst == RLIMIT_CPU)
+ psecs((long) limit);
+ else
+# endif /* RLIMIT_CPU */
+ xprintf("%ld %s", (long) (limit / div), lp->limscale);
+ xputchar('\n');
+}
+
+/*ARGSUSED*/
+void
+dounlimit(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register struct limits *lp;
+ int lerr = 0;
+ int hard = 0;
+ int force = 0;
+
+ USE(c);
+ while (*++v && **v == '-') {
+ Char *vp = *v;
+ while (*++vp)
+ switch (*vp) {
+ case 'f':
+ force = 1;
+ break;
+ case 'h':
+ hard = 1;
+ break;
+ default:
+ stderror(ERR_ULIMUS);
+ break;
+ }
+ }
+
+ if (*v == 0) {
+ for (lp = limits; lp->limconst >= 0; lp++)
+ if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
+ lerr++;
+ if (!force && lerr)
+ stderror(ERR_SILENT);
+ return;
+ }
+ while (*v) {
+ lp = findlim(*v++);
+ if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force)
+ stderror(ERR_SILENT);
+ }
+}
+
+static int
+setlim(lp, hard, limit)
+ register struct limits *lp;
+ int hard;
+ RLIM_TYPE limit;
+{
+# ifdef BSDLIMIT
+ struct rlimit rlim;
+
+ (void) getrlimit(lp->limconst, &rlim);
+
+# ifdef FILESIZE512
+ /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
+ if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
+ limit /= 512;
+# endif /* FILESIZE512 */
+ if (hard)
+ rlim.rlim_max = limit;
+ else if (limit == RLIM_INFINITY && euid != 0)
+ rlim.rlim_cur = rlim.rlim_max;
+ else
+ rlim.rlim_cur = limit;
+
+ if (setrlimit(lp->limconst, &rlim) < 0) {
+# else /* BSDLIMIT */
+ if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
+ limit /= 512;
+# ifdef aiws
+ if (lp->limconst == RLIMIT_DATA)
+ limit += 0x20000000;
+# endif /* aiws */
+ if (ulimit(toset(lp->limconst), limit) < 0) {
+# endif /* BSDLIMIT */
+ xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit\n"), bname, lp->limname,
+ limit == RLIM_INFINITY ? CGETS(15, 2, "remove") :
+ CGETS(15, 3, "set"),
+ hard ? CGETS(14, 4, " hard") : "");
+ return (-1);
+ }
+ return (0);
+}
+
+#endif /* !HAVENOLIMIT */
+
+/*ARGSUSED*/
+void
+dosuspend(v, c)
+ Char **v;
+ struct command *c;
+{
+#ifdef BSDJOBS
+ int ctpgrp;
+
+ signalfun_t old;
+#endif /* BSDJOBS */
+
+ USE(c);
+ USE(v);
+
+ if (loginsh)
+ stderror(ERR_SUSPLOG);
+ untty();
+
+#ifdef BSDJOBS
+ old = signal(SIGTSTP, SIG_DFL);
+ (void) kill(0, SIGTSTP);
+ /* the shell stops here */
+ (void) signal(SIGTSTP, old);
+#else /* !BSDJOBS */
+ stderror(ERR_JOBCONTROL);
+#endif /* BSDJOBS */
+
+#ifdef BSDJOBS
+ if (tpgrp != -1) {
+retry:
+ ctpgrp = tcgetpgrp(FSHTTY);
+ if (ctpgrp != opgrp) {
+ old = signal(SIGTTIN, SIG_DFL);
+ (void) kill(0, SIGTTIN);
+ (void) signal(SIGTTIN, old);
+ goto retry;
+ }
+ (void) setpgid(0, shpgrp);
+ (void) tcsetpgrp(FSHTTY, shpgrp);
+ }
+#endif /* BSDJOBS */
+ (void) setdisc(FSHTTY);
+}
+
+/* This is the dreaded EVAL built-in.
+ * If you don't fiddle with file descriptors, and reset didfds,
+ * this command will either ignore redirection inside or outside
+ * its arguments, e.g. eval "date >x" vs. eval "date" >x
+ * The stuff here seems to work, but I did it by trial and error rather
+ * than really knowing what was going on. If tpgrp is zero, we are
+ * probably a background eval, e.g. "eval date &", and we want to
+ * make sure that any processes we start stay in our pgrp.
+ * This is also the case for "time eval date" -- stay in same pgrp.
+ * Otherwise, under stty tostop, processes will stop in the wrong
+ * pgrp, with no way for the shell to get them going again. -IAN!
+ */
+
+static Char **gv = NULL, **gav = NULL;
+
+/*ARGSUSED*/
+void
+doeval(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char **oevalvec;
+ Char *oevalp;
+ int odidfds;
+#ifndef CLOSE_ON_EXEC
+ int odidcch;
+#endif /* CLOSE_ON_EXEC */
+ jmp_buf_t osetexit;
+ int my_reenter;
+ Char **savegv;
+ int saveIN, saveOUT, saveDIAG;
+ int oSHIN, oSHOUT, oSHDIAG;
+
+ USE(c);
+ oevalvec = evalvec;
+ oevalp = evalp;
+ odidfds = didfds;
+#ifndef CLOSE_ON_EXEC
+ odidcch = didcch;
+#endif /* CLOSE_ON_EXEC */
+ oSHIN = SHIN;
+ oSHOUT = SHOUT;
+ oSHDIAG = SHDIAG;
+
+ savegv = gv;
+ gav = v;
+
+ gav++;
+ if (*gav == 0)
+ return;
+ gflag = 0, tglob(gav);
+ if (gflag) {
+ gv = gav = globall(gav);
+ gargv = 0;
+ if (gav == 0)
+ stderror(ERR_NOMATCH);
+ gav = copyblk(gav);
+ }
+ else {
+ gv = NULL;
+ gav = copyblk(gav);
+ trim(gav);
+ }
+
+ saveIN = dcopy(SHIN, -1);
+ saveOUT = dcopy(SHOUT, -1);
+ saveDIAG = dcopy(SHDIAG, -1);
+
+ getexit(osetexit);
+
+ /* PWP: setjmp/longjmp bugfix for optimizing compilers */
+#ifdef cray
+ my_reenter = 1; /* assume non-zero return val */
+ if (setexit() == 0) {
+ my_reenter = 0; /* Oh well, we were wrong */
+#else /* !cray */
+ if ((my_reenter = setexit()) == 0) {
+#endif /* cray */
+ evalvec = gav;
+ evalp = 0;
+ SHIN = dcopy(0, -1);
+ SHOUT = dcopy(1, -1);
+ SHDIAG = dcopy(2, -1);
+#ifndef CLOSE_ON_EXEC
+ didcch = 0;
+#endif /* CLOSE_ON_EXEC */
+ didfds = 0;
+ process(0);
+ }
+
+ evalvec = oevalvec;
+ evalp = oevalp;
+ doneinp = 0;
+#ifndef CLOSE_ON_EXEC
+ didcch = odidcch;
+#endif /* CLOSE_ON_EXEC */
+ didfds = odidfds;
+ (void) close(SHIN);
+ (void) close(SHOUT);
+ (void) close(SHDIAG);
+ SHIN = dmove(saveIN, oSHIN);
+ SHOUT = dmove(saveOUT, oSHOUT);
+ SHDIAG = dmove(saveDIAG, oSHDIAG);
+
+ if (gv)
+ blkfree(gv);
+
+ gv = savegv;
+ resexit(osetexit);
+ if (my_reenter)
+ stderror(ERR_SILENT);
+}
+
+/*************************************************************************/
+/* print list of builtin commands */
+
+/*ARGSUSED*/
+void
+dobuiltins(v, c)
+Char **v;
+struct command *c;
+{
+ /* would use print_by_column() in tw.parse.c but that assumes
+ * we have an array of Char * to pass.. (sg)
+ */
+ extern int Tty_raw_mode;
+ extern int TermH; /* from the editor routines */
+ extern int lbuffed; /* from sh.print.c */
+
+ register struct biltins *b;
+ register int row, col, columns, rows;
+ unsigned int w, maxwidth;
+
+ USE(c);
+ USE(v);
+ lbuffed = 0; /* turn off line buffering */
+
+ /* find widest string */
+ for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b)
+ maxwidth = max(maxwidth, strlen(b->bname));
+ ++maxwidth; /* for space */
+
+ columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */
+ if (!columns)
+ columns = 1;
+ rows = (nbfunc + (columns - 1)) / columns;
+
+ for (b = bfunc, row = 0; row < rows; row++) {
+ for (col = 0; col < columns; col++) {
+ if (b < &bfunc[nbfunc]) {
+ w = strlen(b->bname);
+ xprintf("%s", b->bname);
+ if (col < (columns - 1)) /* Not last column? */
+ for (; w < maxwidth; w++)
+ xputchar(' ');
+ ++b;
+ }
+ }
+ if (row < (rows - 1)) {
+ if (Tty_raw_mode)
+ xputchar('\r');
+ xputchar('\n');
+ }
+ }
+#ifdef WINNT
+ nt_print_builtins(maxwidth);
+#else
+ if (Tty_raw_mode)
+ xputchar('\r');
+ xputchar('\n');
+#endif /* WINNT */
+
+ lbuffed = 1; /* turn back on line buffering */
+ flush();
+}
+
+void
+nlsinit()
+{
+#ifdef NLS_CATALOGS
+ catd = catopen("tcsh", MCLoadBySet);
+#endif
+#ifdef WINNT
+ nls_dll_init();
+#endif /* WINNT */
+ errinit(); /* init the errorlist in correct locale */
+ mesginit(); /* init the messages for signals */
+ dateinit(); /* init the messages for dates */
+ editinit(); /* init the editor messages */
+ terminit(); /* init the termcap messages */
+}
diff --git a/contrib/tcsh/sh.glob.c b/contrib/tcsh/sh.glob.c
new file mode 100644
index 0000000..20faaee
--- /dev/null
+++ b/contrib/tcsh/sh.glob.c
@@ -0,0 +1,1111 @@
+/* $Header: /src/pub/tcsh/sh.glob.c,v 3.43 1998/10/25 15:10:14 christos Exp $ */
+/*
+ * sh.glob.c: Regular expression expansion
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.glob.c,v 3.43 1998/10/25 15:10:14 christos Exp $")
+
+#include "tc.h"
+
+#include "glob.h"
+
+static int noglob;
+static int pargsiz, gargsiz;
+
+/*
+ * Values for gflag
+ */
+#define G_NONE 0 /* No globbing needed */
+#define G_GLOB 1 /* string contains *?[] characters */
+#define G_CSH 2 /* string contains ~`{ characters */
+
+#define GLOBSPACE 100 /* Alloc increment */
+#define LONGBSIZE 10240 /* Backquote expansion buffer size */
+
+
+#define LBRC '{'
+#define RBRC '}'
+#define LBRK '['
+#define RBRK ']'
+#define EOS '\0'
+
+Char **gargv = NULL;
+int gargc = 0;
+Char **pargv = NULL;
+static int pargc = 0;
+
+/*
+ * globbing is now done in two stages. In the first pass we expand
+ * csh globbing idioms ~`{ and then we proceed doing the normal
+ * globbing if needed ?*[
+ *
+ * Csh type globbing is handled in globexpand() and the rest is
+ * handled in glob() which is part of the 4.4BSD libc.
+ *
+ */
+static Char *globtilde __P((Char **, Char *));
+static Char *handleone __P((Char *, Char **, int));
+static Char **libglob __P((Char **));
+static Char **globexpand __P((Char **));
+static int globbrace __P((Char *, Char *, Char ***));
+static void expbrace __P((Char ***, Char ***, int));
+static int pmatch __P((Char *, Char *, Char **));
+static void pword __P((int));
+static void psave __P((int));
+static void backeval __P((Char *, bool));
+
+static Char *
+globtilde(nv, s)
+ Char **nv, *s;
+{
+ Char gbuf[BUFSIZE], *gstart, *b, *u, *e;
+#ifdef apollo
+ int slash;
+#endif
+
+ gstart = gbuf;
+ *gstart++ = *s++;
+ u = s;
+ for (b = gstart, e = &gbuf[BUFSIZE - 1];
+ *s && *s != '/' && *s != ':' && b < e;
+ *b++ = *s++)
+ continue;
+ *b = EOS;
+ if (gethdir(gstart)) {
+ if (adrof(STRnonomatch))
+ return (--u);
+ blkfree(nv);
+ if (*gstart)
+ stderror(ERR_UNKUSER, short2str(gstart));
+ else
+ stderror(ERR_NOHOME);
+ }
+ b = &gstart[Strlen(gstart)];
+#ifdef apollo
+ slash = gstart[0] == '/' && gstart[1] == '\0';
+#endif
+ while (*s)
+ *b++ = *s++;
+ *b = EOS;
+ --u;
+ xfree((ptr_t) u);
+#ifdef apollo
+ if (slash && gstart[1] == '/')
+ gstart++;
+#endif
+ return (Strsave(gstart));
+}
+
+Char *
+globequal(new, old)
+ Char *new, *old;
+{
+ int dig;
+ Char *b, *d;
+
+ /*
+ * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
+ * in stack. PWP: let =foobar pass through (for X windows)
+ */
+ if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
+ /* =- */
+ dig = -1;
+ b = &old[2];
+ }
+ else if (Isdigit(old[1])) {
+ /* =<number> */
+ dig = old[1] - '0';
+ for (b = &old[2]; Isdigit(*b); b++)
+ dig = dig * 10 + (*b - '0');
+ if (*b != '\0' && *b != '/')
+ /* =<number>foobar */
+ return old;
+ }
+ else
+ /* =foobar */
+ return old;
+
+ if (!getstakd(new, dig))
+ return NULL;
+
+ /* Copy the rest of the string */
+ for (d = &new[Strlen(new)];
+ d < &new[BUFSIZE - 1] && (*d++ = *b++) != '\0';)
+ continue;
+ *d = '\0';
+
+ return new;
+}
+
+static int
+globbrace(s, p, bl)
+ Char *s, *p, ***bl;
+{
+ int i, len;
+ Char *pm, *pe, *lm, *pl;
+ Char **nv, **vl;
+ Char gbuf[BUFSIZE];
+ int size = GLOBSPACE;
+
+ nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size));
+ *vl = NULL;
+
+ len = 0;
+ /* copy part up to the brace */
+ for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
+ continue;
+
+ /* check for balanced braces */
+ for (i = 0, pe = ++p; *pe; pe++)
+ if (*pe == LBRK) {
+ /* Ignore everything between [] */
+ for (++pe; *pe != RBRK && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ blkfree(nv);
+ return (-RBRK);
+ }
+ }
+ else if (*pe == LBRC)
+ i++;
+ else if (*pe == RBRC) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ if (i != 0 || *pe == '\0') {
+ blkfree(nv);
+ return (-RBRC);
+ }
+
+ for (i = 0, pl = pm = p; pm <= pe; pm++)
+ switch (*pm) {
+ case LBRK:
+ for (++pm; *pm != RBRK && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ *vl = NULL;
+ blkfree(nv);
+ return (-RBRK);
+ }
+ break;
+ case LBRC:
+ i++;
+ break;
+ case RBRC:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case ',':
+ if (i && *pm == ',')
+ break;
+ else {
+ Char savec = *pm;
+
+ *pm = EOS;
+ (void) Strcpy(lm, pl);
+ (void) Strcat(gbuf, pe + 1);
+ *pm = savec;
+ *vl++ = Strsave(gbuf);
+ len++;
+ pl = pm + 1;
+ if (vl == &nv[size]) {
+ size += GLOBSPACE;
+ nv = (Char **) xrealloc((ptr_t) nv,
+ (size_t) (size * sizeof(Char *)));
+ vl = &nv[size - GLOBSPACE];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ *vl = NULL;
+ *bl = nv;
+ return (len);
+}
+
+
+static void
+expbrace(nvp, elp, size)
+ Char ***nvp, ***elp;
+ int size;
+{
+ Char **vl, **el, **nv, *s;
+
+ vl = nv = *nvp;
+ if (elp != NULL)
+ el = *elp;
+ else
+ for (el = vl; *el; el++)
+ continue;
+
+ for (s = *vl; s; s = *++vl) {
+ Char *b;
+ Char **vp, **bp;
+
+ /* leave {} untouched for find */
+ if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
+ continue;
+ if ((b = Strchr(s, '{')) != NULL) {
+ Char **bl;
+ int len;
+
+ if ((len = globbrace(s, b, &bl)) < 0) {
+ xfree((ptr_t) nv);
+ stderror(ERR_MISSING, -len);
+ }
+ xfree((ptr_t) s);
+ if (len == 1) {
+ *vl-- = *bl;
+ xfree((ptr_t) bl);
+ continue;
+ }
+ if (&el[len] >= &nv[size]) {
+ int l, e;
+ l = (int) (&el[len] - &nv[size]);
+ size += GLOBSPACE > l ? GLOBSPACE : l;
+ l = (int) (vl - nv);
+ e = (int) (el - nv);
+ nv = (Char **) xrealloc((ptr_t) nv,
+ (size_t) (size * sizeof(Char *)));
+ vl = nv + l;
+ el = nv + e;
+ }
+ /* nv vl el bl
+ * | | | |
+ * -.--..-- x--
+ * | len
+ * vp
+ */
+ vp = vl--;
+ *vp = *bl;
+ len--;
+ for (bp = el; bp != vp; bp--)
+ bp[len] = *bp;
+ el += len;
+ /* nv vl el bl
+ * | | | |
+ * -.-x --- --
+ * |len
+ * vp
+ */
+ vp++;
+ for (bp = bl + 1; *bp; *vp++ = *bp++)
+ continue;
+ xfree((ptr_t) bl);
+ }
+
+ }
+ if (elp != NULL)
+ *elp = el;
+ *nvp = nv;
+}
+
+static Char **
+globexpand(v)
+ Char **v;
+{
+ Char *s;
+ Char **nv, **vl, **el;
+ int size = GLOBSPACE;
+
+
+ nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size));
+ *vl = NULL;
+
+ /*
+ * Step 1: expand backquotes.
+ */
+ while ((s = *v++) != '\0') {
+ if (Strchr(s, '`')) {
+ int i;
+
+ (void) dobackp(s, 0);
+ for (i = 0; i < pargc; i++) {
+ *vl++ = pargv[i];
+ if (vl == &nv[size]) {
+ size += GLOBSPACE;
+ nv = (Char **) xrealloc((ptr_t) nv,
+ (size_t) (size * sizeof(Char *)));
+ vl = &nv[size - GLOBSPACE];
+ }
+ }
+ xfree((ptr_t) pargv);
+ pargv = NULL;
+ }
+ else {
+ *vl++ = Strsave(s);
+ if (vl == &nv[size]) {
+ size += GLOBSPACE;
+ nv = (Char **) xrealloc((ptr_t) nv,
+ (size_t) (size * sizeof(Char *)));
+ vl = &nv[size - GLOBSPACE];
+ }
+ }
+ }
+ *vl = NULL;
+
+ if (noglob)
+ return (nv);
+
+ /*
+ * Step 2: expand braces
+ */
+ el = vl;
+ expbrace(&nv, &el, size);
+
+
+ /*
+ * Step 3: expand ~ =
+ */
+ vl = nv;
+ for (s = *vl; s; s = *++vl)
+ switch (*s) {
+ Char gp[BUFSIZE], *ns;
+ case '~':
+ *vl = globtilde(nv, s);
+ break;
+ case '=':
+ if ((ns = globequal(gp, s)) == NULL) {
+ if (!adrof(STRnonomatch)) {
+ /* Error */
+ blkfree(nv);
+ stderror(ERR_DEEP);
+ }
+ }
+ if (ns && ns != s) {
+ /* Expansion succeeded */
+ xfree((ptr_t) s);
+ *vl = Strsave(gp);
+ }
+ break;
+ default:
+ break;
+ }
+ vl = nv;
+
+ /*
+ * Step 4: expand .. if the variable symlinks==expand is set
+ */
+ if ( symlinks == SYM_EXPAND )
+ for (s = *vl; s; s = *++vl) {
+ *vl = dnormalize(s, 1);
+ xfree((ptr_t) s);
+ }
+ vl = nv;
+
+ return (vl);
+}
+
+static Char *
+handleone(str, vl, action)
+ Char *str, **vl;
+ int action;
+{
+
+ Char **vlp = vl;
+ int chars;
+ Char **t, *p, *strp;
+
+ switch (action) {
+ case G_ERROR:
+ setname(short2str(str));
+ blkfree(vl);
+ stderror(ERR_NAME | ERR_AMBIG);
+ break;
+ case G_APPEND:
+ chars = 0;
+ for (t = vlp; (p = *t++) != '\0'; chars++)
+ while (*p++)
+ chars++;
+ str = (Char *)xmalloc((size_t)(chars * sizeof(Char)));
+ for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) {
+ while (*p)
+ *strp++ = *p++ & TRIM;
+ *strp++ = ' ';
+ }
+ *--strp = '\0';
+ blkfree(vl);
+ break;
+ case G_IGNORE:
+ str = Strsave(strip(*vlp));
+ blkfree(vl);
+ break;
+ default:
+ break;
+ }
+ return (str);
+}
+
+static Char **
+libglob(vl)
+ Char **vl;
+{
+ int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
+ glob_t globv;
+ char *ptr;
+ int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
+
+ if (!vl || !vl[0])
+ return(vl);
+
+ globv.gl_offs = 0;
+ globv.gl_pathv = 0;
+ globv.gl_pathc = 0;
+
+ if (nonomatch)
+ gflgs |= GLOB_NOCHECK;
+
+ do {
+ ptr = short2qstr(*vl);
+ switch (glob(ptr, gflgs, 0, &globv)) {
+ case GLOB_ABEND:
+ globfree(&globv);
+ setname(ptr);
+ stderror(ERR_NAME | ERR_GLOB);
+ /* NOTREACHED */
+ case GLOB_NOSPACE:
+ globfree(&globv);
+ stderror(ERR_NOMEM);
+ /* NOTREACHED */
+ default:
+ break;
+ }
+ if (globv.gl_flags & GLOB_MAGCHAR) {
+ match |= (globv.gl_matchc != 0);
+ magic = 1;
+ }
+ gflgs |= GLOB_APPEND;
+ }
+ while (*++vl);
+ vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
+ NULL : blk2short(globv.gl_pathv);
+ globfree(&globv);
+ return (vl);
+}
+
+Char *
+globone(str, action)
+ Char *str;
+ int action;
+{
+
+ Char *v[2], **vl, **vo;
+ int gflg;
+
+ noglob = adrof(STRnoglob) != 0;
+ gflag = 0;
+ v[0] = str;
+ v[1] = 0;
+ tglob(v);
+ gflg = gflag;
+ if (gflg == G_NONE)
+ return (strip(Strsave(str)));
+
+ if (gflg & G_CSH) {
+ /*
+ * Expand back-quote, tilde and brace
+ */
+ vo = globexpand(v);
+ if (noglob || (gflg & G_GLOB) == 0) {
+ if (vo[0] == NULL) {
+ xfree((ptr_t) vo);
+ return (Strsave(STRNULL));
+ }
+ if (vo[1] != NULL)
+ return (handleone(str, vo, action));
+ else {
+ str = strip(vo[0]);
+ xfree((ptr_t) vo);
+ return (str);
+ }
+ }
+ }
+ else if (noglob || (gflg & G_GLOB) == 0)
+ return (strip(Strsave(str)));
+ else
+ vo = v;
+
+ vl = libglob(vo);
+ if ((gflg & G_CSH) && vl != vo)
+ blkfree(vo);
+ if (vl == NULL) {
+ setname(short2str(str));
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ if (vl[0] == NULL) {
+ xfree((ptr_t) vl);
+ return (Strsave(STRNULL));
+ }
+ if (vl[1])
+ return (handleone(str, vl, action));
+ else {
+ str = strip(*vl);
+ xfree((ptr_t) vl);
+ return (str);
+ }
+}
+
+Char **
+globall(v)
+ Char **v;
+{
+ Char **vl, **vo;
+ int gflg = gflag;
+
+ if (!v || !v[0]) {
+ gargv = saveblk(v);
+ gargc = blklen(gargv);
+ return (gargv);
+ }
+
+ noglob = adrof(STRnoglob) != 0;
+
+ if (gflg & G_CSH)
+ /*
+ * Expand back-quote, tilde and brace
+ */
+ vl = vo = globexpand(v);
+ else
+ vl = vo = saveblk(v);
+
+ if (!noglob && (gflg & G_GLOB)) {
+ vl = libglob(vo);
+ if (vl != vo)
+ blkfree(vo);
+ }
+ else
+ trim(vl);
+
+ gargc = vl ? blklen(vl) : 0;
+ return (gargv = vl);
+}
+
+void
+ginit()
+{
+ gargsiz = GLOBSPACE;
+ gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz));
+ gargv[0] = 0;
+ gargc = 0;
+}
+
+void
+rscan(t, f)
+ register Char **t;
+ void (*f) __P((int));
+{
+ register Char *p;
+
+ while ((p = *t++) != '\0')
+ while (*p)
+ (*f) (*p++);
+}
+
+void
+trim(t)
+ register Char **t;
+{
+ register Char *p;
+
+ while ((p = *t++) != '\0')
+ while (*p)
+ *p++ &= TRIM;
+}
+
+void
+tglob(t)
+ register Char **t;
+{
+ register Char *p, *c;
+
+ while ((p = *t++) != '\0') {
+ if (*p == '~' || *p == '=')
+ gflag |= G_CSH;
+ else if (*p == '{' &&
+ (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
+ continue;
+ /*
+ * The following line used to be *(c = p++), but hp broke their
+ * optimizer in 9.01, so we break the assignment into two pieces
+ * The careful reader here will note that *most* compiler workarounds
+ * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence?
+ */
+ while ( *(c = p) != '\0') {
+ p++;
+ if (*c == '`') {
+ gflag |= G_CSH;
+#ifdef notdef
+ /*
+ * We do want to expand echo `echo '*'`, so we don't\
+ * use this piece of code anymore.
+ */
+ while (*p && *p != '`')
+ if (*p++ == '\\') {
+ if (*p) /* Quoted chars */
+ p++;
+ else
+ break;
+ }
+ if (*p) /* The matching ` */
+ p++;
+ else
+ break;
+#endif
+ }
+ else if (*c == '{')
+ gflag |= G_CSH;
+ else if (isglob(*c))
+ gflag |= G_GLOB;
+ else if (symlinks == SYM_EXPAND &&
+ *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') )
+ gflag |= G_CSH;
+ }
+ }
+}
+
+/*
+ * Command substitute cp. If literal, then this is a substitution from a
+ * << redirection, and so we should not crunch blanks and tabs, separating
+ * words only at newlines.
+ */
+Char **
+dobackp(cp, literal)
+ Char *cp;
+ bool literal;
+{
+ register Char *lp, *rp;
+ Char *ep, word[LONGBSIZE];
+
+ if (pargv) {
+#ifdef notdef
+ abort();
+#endif
+ blkfree(pargv);
+ }
+ pargsiz = GLOBSPACE;
+ pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz));
+ pargv[0] = NULL;
+ pargcp = pargs = word;
+ pargc = 0;
+ pnleft = LONGBSIZE - 4;
+ for (;;) {
+ for (lp = cp; *lp != '`'; lp++) {
+ if (*lp == 0) {
+ if (pargcp != pargs)
+ pword(LONGBSIZE);
+ return (pargv);
+ }
+ psave(*lp);
+ }
+ lp++;
+ for (rp = lp; *rp && *rp != '`'; rp++)
+ if (*rp == '\\') {
+ rp++;
+ if (!*rp)
+ goto oops;
+ }
+ if (!*rp)
+ oops: stderror(ERR_UNMATCHED, '`');
+ ep = Strsave(lp);
+ ep[rp - lp] = 0;
+ backeval(ep, literal);
+ cp = rp + 1;
+ }
+}
+
+
+static void
+backeval(cp, literal)
+ Char *cp;
+ bool literal;
+{
+ register int icnt, c;
+ register Char *ip;
+ struct command faket;
+ bool hadnl;
+ int pvec[2], quoted;
+ Char *fakecom[2], ibuf[BUFSIZE];
+ char tibuf[BUFSIZE];
+
+ hadnl = 0;
+ icnt = 0;
+ quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
+ faket.t_dtyp = NODE_COMMAND;
+ faket.t_dflg = F_BACKQ;
+ faket.t_dlef = 0;
+ faket.t_drit = 0;
+ faket.t_dspr = 0;
+ faket.t_dcom = fakecom;
+ fakecom[0] = STRfakecom1;
+ fakecom[1] = 0;
+
+ /*
+ * We do the psave job to temporarily change the current job so that the
+ * following fork is considered a separate job. This is so that when
+ * backquotes are used in a builtin function that calls glob the "current
+ * job" is not corrupted. We only need one level of pushed jobs as long as
+ * we are sure to fork here.
+ */
+ psavejob();
+
+ /*
+ * It would be nicer if we could integrate this redirection more with the
+ * routines in sh.sem.c by doing a fake execute on a builtin function that
+ * was piped out.
+ */
+ mypipe(pvec);
+ if (pfork(&faket, -1) == 0) {
+ struct command *t;
+
+ (void) close(pvec[0]);
+ (void) dmove(pvec[1], 1);
+ (void) dmove(SHDIAG, 2);
+ initdesc();
+ /*
+ * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
+ * posted to comp.bugs.4bsd 12 Sep. 1989.
+ */
+ if (pargv) /* mg, 21.dec.88 */
+ blkfree(pargv), pargv = 0, pargsiz = 0;
+ /* mg, 21.dec.88 */
+ arginp = cp;
+ while (*cp)
+ *cp++ &= TRIM;
+
+ /*
+ * In the child ``forget'' everything about current aliases or
+ * eval vectors.
+ */
+ alvec = NULL;
+ evalvec = NULL;
+ alvecp = NULL;
+ evalp = NULL;
+ (void) lex(&paraml);
+ if (seterr)
+ stderror(ERR_OLD);
+ alias(&paraml);
+ t = syntax(paraml.next, &paraml, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+ if (t)
+ t->t_dflg |= F_NOFORK;
+#ifdef SIGTSTP
+ (void) sigignore(SIGTSTP);
+#endif
+#ifdef SIGTTIN
+ (void) sigignore(SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ (void) sigignore(SIGTTOU);
+#endif
+ execute(t, -1, NULL, NULL);
+ exitstat();
+ }
+ xfree((ptr_t) cp);
+ (void) close(pvec[1]);
+ c = 0;
+ ip = NULL;
+ do {
+ int cnt = 0;
+
+ for (;;) {
+ if (icnt == 0) {
+ int i;
+
+ ip = ibuf;
+ do
+ icnt = read(pvec[0], tibuf, BUFSIZE);
+ while (icnt == -1 && errno == EINTR);
+ if (icnt <= 0) {
+ c = -1;
+ break;
+ }
+ for (i = 0; i < icnt; i++)
+ ip[i] = (unsigned char) tibuf[i];
+ }
+ if (hadnl)
+ break;
+ --icnt;
+ c = (*ip++ & TRIM);
+ if (c == 0)
+ break;
+#ifdef WINNT
+ if (c == '\r')
+ c = ' ';
+#endif /* WINNT */
+ if (c == '\n') {
+ /*
+ * Continue around the loop one more time, so that we can eat
+ * the last newline without terminating this word.
+ */
+ hadnl = 1;
+ continue;
+ }
+ if (!quoted && (c == ' ' || c == '\t'))
+ break;
+ cnt++;
+ psave(c | quoted);
+ }
+ /*
+ * Unless at end-of-file, we will form a new word here if there were
+ * characters in the word, or in any case when we take text literally.
+ * If we didn't make empty words here when literal was set then we
+ * would lose blank lines.
+ */
+ if (c != -1 && (cnt || literal))
+ pword(BUFSIZE);
+ hadnl = 0;
+ } while (c >= 0);
+ (void) close(pvec[0]);
+ pwait();
+ prestjob();
+}
+
+static void
+psave(c)
+ int c;
+{
+ if (--pnleft <= 0)
+ stderror(ERR_WTOOLONG);
+ *pargcp++ = (Char) c;
+}
+
+static void
+pword(bufsiz)
+ int bufsiz;
+{
+ psave(0);
+ if (pargc == pargsiz - 1) {
+ pargsiz += GLOBSPACE;
+ pargv = (Char **) xrealloc((ptr_t) pargv,
+ (size_t) (pargsiz * sizeof(Char *)));
+ }
+ pargv[pargc++] = Strsave(pargs);
+ pargv[pargc] = NULL;
+ pargcp = pargs;
+ pnleft = bufsiz - 4;
+}
+
+int
+Gmatch(string, pattern)
+ Char *string, *pattern;
+{
+ return Gnmatch(string, pattern, NULL);
+}
+
+int
+Gnmatch(string, pattern, endstr)
+ Char *string, *pattern, **endstr;
+{
+ Char **blk, **p, *tstring = string;
+ int gpol = 1, gres = 0;
+
+ if (*pattern == '^') {
+ gpol = 0;
+ pattern++;
+ }
+
+ blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *)));
+ blk[0] = Strsave(pattern);
+ blk[1] = NULL;
+
+ expbrace(&blk, NULL, GLOBSPACE);
+
+ if (endstr == NULL)
+ /* Exact matches only */
+ for (p = blk; *p; p++)
+ gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0;
+ else {
+ /* partial matches */
+ int minc = 0x7fffffff;
+ for (p = blk; *p; p++)
+ if (pmatch(string, *p, &tstring) != 0) {
+ int t = (int) (tstring - string);
+ gres |= 1;
+ if (minc == -1 || minc > t)
+ minc = t;
+ }
+ *endstr = string + minc;
+ }
+
+ blkfree(blk);
+ return(gres == gpol);
+}
+
+/* pmatch():
+ * Return 2 on exact match,
+ * Return 1 on substring match.
+ * Return 0 on no match.
+ * *estr will point to the end of the longest exact or substring match.
+ */
+static int
+pmatch(string, pattern, estr)
+ register Char *string, *pattern, **estr;
+{
+ register Char stringc, patternc;
+ int match, negate_range;
+ Char rangec, *oestr, *pestr;
+
+ for (;; ++string) {
+ stringc = *string & TRIM;
+ /*
+ * apollo compiler bug: switch (patternc = *pattern++) dies
+ */
+ patternc = *pattern++;
+ switch (patternc) {
+ case 0:
+ *estr = string;
+ return (stringc == 0 ? 2 : 1);
+ case '?':
+ if (stringc == 0)
+ return (0);
+ *estr = string;
+ break;
+ case '*':
+ if (!*pattern) {
+ while (*string) string++;
+ *estr = string;
+ return (2);
+ }
+ oestr = *estr;
+ pestr = NULL;
+
+ do {
+ switch(pmatch(string, pattern, estr)) {
+ case 0:
+ break;
+ case 1:
+ pestr = *estr;
+ break;
+ case 2:
+ return 2;
+ default:
+ abort(); /* Cannot happen */
+ }
+ *estr = string;
+ }
+ while (*string++);
+
+ if (pestr) {
+ *estr = pestr;
+ return 1;
+ }
+ else {
+ *estr = oestr;
+ return 0;
+ }
+
+ case '[':
+ match = 0;
+ if ((negate_range = (*pattern == '^')) != 0)
+ pattern++;
+ while ((rangec = *pattern++) != '\0') {
+ if (rangec == ']')
+ break;
+ if (match)
+ continue;
+ if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') {
+ match = (globcharcoll(stringc, *pattern & TRIM) <= 0 &&
+ globcharcoll(*(pattern-2) & TRIM, stringc) <= 0);
+ pattern++;
+ }
+ else
+ match = (stringc == (rangec & TRIM));
+ }
+ if (rangec == 0)
+ stderror(ERR_NAME | ERR_MISSING, ']');
+ if (match == negate_range)
+ return (0);
+ *estr = string;
+ break;
+ default:
+ if ((patternc & TRIM) != stringc)
+ return (0);
+ *estr = string;
+ break;
+ }
+ }
+}
+
+void
+Gcat(s1, s2)
+ Char *s1, *s2;
+{
+ register Char *p, *q;
+ int n;
+
+ for (p = s1; *p++;)
+ continue;
+ for (q = s2; *q++;)
+ continue;
+ n = (int) ((p - s1) + (q - s2) - 1);
+ if (++gargc >= gargsiz) {
+ gargsiz += GLOBSPACE;
+ gargv = (Char **) xrealloc((ptr_t) gargv,
+ (size_t) (gargsiz * sizeof(Char *)));
+ }
+ gargv[gargc] = 0;
+ p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char)));
+ for (q = s1; (*p++ = *q++) != '\0';)
+ continue;
+ for (p--, q = s2; (*p++ = *q++) != '\0';)
+ continue;
+}
+
+#ifdef FILEC
+int
+sortscmp(a, b)
+ register Char **a, **b;
+{
+ if (!a) /* check for NULL */
+ return (b ? 1 : 0);
+ if (!b)
+ return (-1);
+
+ if (!*a) /* check for NULL */
+ return (*b ? 1 : 0);
+ if (!*b)
+ return (-1);
+
+ return (int) collate(*a, *b);
+}
+
+#endif
diff --git a/contrib/tcsh/sh.h b/contrib/tcsh/sh.h
new file mode 100644
index 0000000..0192f84
--- /dev/null
+++ b/contrib/tcsh/sh.h
@@ -0,0 +1,1228 @@
+/* $Header: /src/pub/tcsh/sh.h,v 3.86 1998/10/25 15:10:16 christos Exp $ */
+/*
+ * sh.h: Catch it all globals and includes file!
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh
+#define _h_sh
+
+#include "config.h"
+
+#ifndef EXTERN
+# define EXTERN extern
+#else /* !EXTERN */
+# ifdef WINNT
+# define IZERO = 0
+# define IZERO_STRUCT = {0}
+# endif /* WINNT */
+#endif /* EXTERN */
+
+#ifndef IZERO
+# define IZERO
+#endif /* IZERO */
+#ifndef IZERO_STRUCT
+# define IZERO_STRUCT
+# endif /* IZERO_STRUCT */
+
+#ifndef WINNT
+# define INIT_ZERO
+# define INIT_ZERO_STRUCT
+# define force_read read
+#endif /*!WINNT */
+/*
+ * Sanity
+ */
+#if defined(_POSIX_SOURCE) && !defined(POSIX)
+# define POSIX
+#endif
+
+#if defined(POSIXJOBS) && !defined(BSDJOBS)
+# define BSDJOBS
+#endif
+
+#if defined(POSIXSIGS) && !defined(BSDSIGS)
+# define BSDSIGS
+#endif
+
+#ifdef SHORT_STRINGS
+typedef short Char;
+typedef unsigned short uChar;
+# define SAVE(a) (Strsave(str2short(a)))
+#else
+typedef char Char;
+typedef unsigned char uChar;
+# define SAVE(a) (strsave(a))
+#endif
+
+/* Elide unused argument warnings */
+#define USE(a) (void) (a)
+/*
+ * If your compiler complains, then you can either
+ * throw it away and get gcc or, use the following define
+ * and get rid of the typedef.
+ * [The 4.2/3BSD vax compiler does not like that]
+ * Both MULTIFLOW and PCC compilers exhbit this bug. -- sterling@netcom.com
+ */
+#ifdef SIGVOID
+# if (defined(vax) || defined(uts) || defined(MULTIFLOW) || defined(PCC)) && !defined(__GNUC__)
+# define sigret_t void
+# else /* !((vax || uts || MULTIFLOW || PCC) && !__GNUC__) */
+typedef void sigret_t;
+# endif /* (vax || uts || MULTIFLOW || PCC) && !__GNUC__ */
+#else /* !SIGVOID */
+typedef int sigret_t;
+#endif /* SIGVOID */
+
+/*
+ * Return true if the path is absolute
+ */
+#ifndef WINNT
+# define ABSOLUTEP(p) (*(p) == '/')
+#else /* WINNT */
+# define ABSOLUTEP(p) ((p)[0] == '/' || \
+ (Isalpha((p)[0]) && (p)[1] == ':' && (p)[2] == '/'))
+#endif /* WINNT */
+
+/*
+ * Fundamental definitions which may vary from system to system.
+ *
+ * BUFSIZE The i/o buffering size; also limits word size
+ * MAILINTVL How often to mailcheck; more often is more expensive
+ */
+#ifdef BUFSIZE
+# if BUFSIZE < 1024
+# undef BUFSIZE
+# define BUFSIZE 1024 /* buffer size should be no less than this */
+# endif
+#else
+# define BUFSIZE 1024
+#endif /* BUFSIZE */
+
+#define FORKSLEEP 10 /* delay loop on non-interactive fork failure */
+#define MAILINTVL 600 /* 10 minutes */
+
+#ifndef INBUFSIZE
+# define INBUFSIZE 2*BUFSIZE /* Num input characters on the command line */
+#endif /* INBUFSIZE */
+
+
+/*
+ * What our builtin echo looks like
+ */
+#define NONE_ECHO 0
+#define BSD_ECHO 1
+#define SYSV_ECHO 2
+#define BOTH_ECHO (BSD_ECHO|SYSV_ECHO)
+
+#ifndef ECHO_STYLE
+# if SYSVREL > 0
+# define ECHO_STYLE SYSV_ECHO
+# else /* SYSVREL == 0 */
+# define ECHO_STYLE BSD_ECHO
+# endif /* SYSVREL */
+#endif /* ECHO_STYLE */
+
+/*
+ * The shell moves std in/out/diag and the old std input away from units
+ * 0, 1, and 2 so that it is easy to set up these standards for invoked
+ * commands.
+ */
+#define FSHTTY 15 /* /dev/tty when manip pgrps */
+#define FSHIN 16 /* Preferred desc for shell input */
+#define FSHOUT 17 /* ... shell output */
+#define FSHDIAG 18 /* ... shell diagnostics */
+#define FOLDSTD 19 /* ... old std input */
+
+#ifdef PROF
+#define xexit(n) done(n)
+#endif
+
+#ifdef cray
+# define word word_t /* sys/types.h defines word.. bad move! */
+#endif
+
+#include <sys/types.h>
+
+#ifdef cray
+# undef word
+#endif
+
+/*
+ * Path separator in environment variables
+ */
+#ifndef PATHSEP
+# if defined(__EMX__) || defined(WINNT)
+# define PATHSEP ';'
+# else /* unix */
+# define PATHSEP ':'
+# endif /* __EMX__ || WINNT */
+#endif /* !PATHSEP */
+
+#ifdef __HP_CXD_SPP
+# include <sys/cnx_stat.h>
+# define stat stat64
+# define fstat fstat64
+# define lstat lstat64
+#endif /* __HP_CXD_SPP */
+
+/*
+ * This macro compares the st_dev field of struct stat. On aix on ibmESA
+ * st_dev is a structure, so comparison does not work.
+ */
+#ifndef DEV_DEV_COMPARE
+# define DEV_DEV_COMPARE(x,y) ((x) == (y))
+#endif /* DEV_DEV_COMPARE */
+
+#ifdef _SEQUENT_
+# include <sys/procstats.h>
+#endif /* _SEQUENT_ */
+#if (defined(POSIX) || SYSVREL > 0) && !WINNT
+# include <sys/times.h>
+#endif /* (POSIX || SYSVREL > 0) && !WINNT */
+
+#ifdef NLS
+# include <locale.h>
+#endif /* NLS */
+
+
+#if !defined(_MINIX) && !defined(_VMS_POSIX) && !defined(WINNT)
+# include <sys/param.h>
+#endif /* !_MINIX && !_VMS_POSIX && !WINNT */
+#include <sys/stat.h>
+
+#if defined(BSDTIMES) || defined(BSDLIMIT)
+# include <sys/time.h>
+# if SYSVREL>3 && !defined(SCO) && !defined(sgi) && !defined(SNI) && !defined(sun) && !(defined(__alpha) && defined(__osf__)) && !defined(_SX)
+# include "/usr/ucbinclude/sys/resource.h"
+# else
+# ifdef convex
+# define sysrusage cvxrusage
+# include <sys/sysinfo.h>
+# else
+# define sysrusage rusage
+# include <sys/resource.h>
+# endif /* convex */
+# endif /* SYSVREL>3 */
+#endif /* BSDTIMES */
+
+#ifndef WINNT
+# ifndef POSIX
+# ifdef TERMIO
+# include <termio.h>
+# else /* SGTTY */
+# include <sgtty.h>
+# endif /* TERMIO */
+# else /* POSIX */
+# ifndef _UWIN
+# include <termios.h>
+# else
+# include <termio.h>
+# endif /* _UWIN */
+# if SYSVREL > 3
+# undef TIOCGLTC /* we don't need those, since POSIX has them */
+# undef TIOCSLTC
+# undef CSWTCH
+# define CSWTCH _POSIX_VDISABLE /* So job control works */
+# endif /* SYSVREL > 3 */
+# endif /* POSIX */
+#endif /* WINNT */
+
+#ifdef sonyrisc
+# include <sys/ttold.h>
+#endif /* sonyrisc */
+
+#if defined(POSIX) && !defined(WINNT)
+/*
+ * We should be using setpgid and setpgid
+ * by now, but in some systems we use the
+ * old routines...
+ */
+# define getpgrp __getpgrp
+# define setpgrp __setpgrp
+# include <unistd.h>
+# undef getpgrp
+# undef setpgrp
+
+/*
+ * the gcc+protoize version of <stdlib.h>
+ * redefines malloc(), so we define the following
+ * to avoid it.
+ */
+# if defined(linux) || defined(sgi) || defined(_OSD_POSIX)
+# define NO_FIX_MALLOC
+# include <stdlib.h>
+# else /* linux */
+# define _GNU_STDLIB_H
+# define malloc __malloc
+# define free __free
+# define calloc __calloc
+# define realloc __realloc
+# include <stdlib.h>
+# undef malloc
+# undef free
+# undef calloc
+# undef realloc
+# endif /* linux || sgi */
+# include <limits.h>
+#endif /* POSIX && !WINNT */
+
+#if SYSVREL > 0 || defined(_IBMR2) || defined(_MINIX)
+# if !defined(pyr) && !defined(stellar)
+# include <time.h>
+# ifdef _MINIX
+# define HZ CLOCKS_PER_SEC
+# endif /* _MINIX */
+# endif /* !pyr && !stellar */
+#endif /* SYSVREL > 0 || _IBMR2 */
+
+/* In the following ifdef the DECOSF1 has been commented so that later
+ * versions of DECOSF1 will get TIOCGWINSZ. This might break older versions...
+ */
+#if !((defined(SUNOS4) || defined(_MINIX) /* || defined(DECOSF1) */) && defined(TERMIO))
+# if !defined(COHERENT) && !defined(_VMS_POSIX) && !defined(WINNT)
+# include <sys/ioctl.h>
+# endif
+#endif
+
+#if (defined(__DGUX__) && defined(POSIX)) || defined(DGUX)
+#undef CSWTCH
+#define CSWTCH _POSIX_VDISABLE
+#endif
+
+#if (!defined(FIOCLEX) && defined(SUNOS4)) || ((SYSVREL == 4) && !defined(_SEQUENT_) && !defined(SCO) && !defined(_SX))
+# include <sys/filio.h>
+#endif /* (!FIOCLEX && SUNOS4) || (SYSVREL == 4 && !_SEQUENT_ && !SCO && !_SX ) */
+
+#if !defined(_MINIX) && !defined(COHERENT) && !defined(supermax) && !defined(WINNT)
+# include <sys/file.h>
+#endif /* !_MINIX && !COHERENT && !supermax && !WINNT */
+
+#if !defined(O_RDONLY) || !defined(O_NDELAY)
+# include <fcntl.h>
+#endif
+
+#include <errno.h>
+
+#include <setjmp.h>
+
+#if __STDC__ || defined(FUNCPROTO)
+# include <stdarg.h>
+#else
+#ifdef _MINIX
+# include "mi.varargs.h"
+#else
+# include <varargs.h>
+#endif /* _MINIX */
+#endif
+
+#ifdef DIRENT
+# include <dirent.h>
+#else
+# ifdef hp9000s500
+# include <ndir.h>
+# else
+# include <sys/dir.h>
+# endif
+# define dirent direct
+#endif /* DIRENT */
+#if defined(hpux) || defined(sgi) || defined(OREO) || defined(COHERENT)
+# include <stdio.h> /* So the fgetpwent() prototypes work */
+#endif /* hpux || sgi || OREO || COHERENT */
+#ifndef WINNT
+#include <pwd.h>
+#include <grp.h>
+#endif /* WINNT */
+#ifdef PW_SHADOW
+# include <shadow.h>
+#endif /* PW_SHADOW */
+#ifdef PW_AUTH
+# include <auth.h>
+#endif /* PW_AUTH */
+#if defined(BSD) && !defined(POSIX)
+# include <strings.h>
+# define strchr(a, b) index(a, b)
+# define strrchr(a, b) rindex(a, b)
+#else
+# include <string.h>
+#endif /* BSD */
+
+/*
+ * IRIX-5.0 has <sys/cdefs.h>, but most system include files do not
+ * include it yet, so we include it here
+ */
+#if defined(sgi) && SYSVREL > 3
+# include <sys/cdefs.h>
+#endif /* sgi && SYSVREL > 3 */
+
+#ifdef REMOTEHOST
+# ifdef ISC
+# undef MAXHOSTNAMELEN /* Busted headers? */
+# endif
+
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <sys/socket.h>
+# include <sys/uio.h> /* For struct iovec */
+#endif /* REMOTEHOST */
+
+/*
+ * ANSIisms... These must be *after* the system include and
+ * *before* our includes, so that BSDreno has time to define __P
+ */
+#undef __P
+#ifndef __P
+# if __STDC__ || defined(FUNCPROTO)
+# ifndef FUNCPROTO
+# define FUNCPROTO
+# endif
+# define __P(a) a
+# else
+# define __P(a) ()
+# if !__STDC__
+# define const
+# ifndef apollo
+# define volatile /* Apollo 'c' extensions need this */
+# endif /* apollo */
+# endif
+# endif
+#endif
+
+
+#ifdef PURIFY
+/* exit normally, allowing purify to trace leaks */
+# define _exit exit
+typedef int pret_t;
+#else /* !PURIFY */
+/*
+ * If your compiler complains, then you can either
+ * throw it away and get gcc or, use the following define
+ * and get rid of the typedef.
+ * [The 4.2/3BSD vax compiler does not like that]
+ * Both MULTIFLOW and PCC compilers exhbit this bug. -- sterling@netcom.com
+ */
+# if (defined(vax) || defined(uts) || defined(MULTIFLOW) || defined(PCC)) && !defined(__GNUC__)
+# define pret_t void
+# else /* !((vax || uts || MULTIFLOW || PCC) && !__GNUC__) */
+typedef void pret_t;
+# endif /* (vax || uts || MULTIFLOW || PCC) && !__GNUC__ */
+#endif /* PURIFY */
+
+typedef int bool;
+
+#include "sh.types.h"
+
+#ifndef WINNT
+# ifndef POSIX
+extern pid_t getpgrp __P((int));
+# else /* POSIX */
+# if (defined(BSD) && !defined(BSD4_4)) || defined(SUNOS4) || defined(IRIS4D) || defined(DGUX)
+extern pid_t getpgrp __P((int));
+# else /* !(BSD || SUNOS4 || IRIS4D || DGUX) */
+extern pid_t getpgrp __P((void));
+# endif /* BSD || SUNOS4 || IRISD || DGUX */
+# endif /* POSIX */
+extern pid_t setpgrp __P((pid_t, pid_t));
+#endif /* !WINNT */
+
+typedef sigret_t (*signalfun_t) __P((int));
+
+#ifndef lint
+typedef ptr_t memalign_t;
+#else
+typedef union {
+ char am_char, *am_char_p;
+ short am_short, *am_short_p;
+ int am_int, *am_int_p;
+ long am_long, *am_long_p;
+ float am_float, *am_float_p;
+ double am_double, *am_double_p;
+} *memalign_t;
+
+# define malloc lint_malloc
+# define free lint_free
+# define realloc lint_realloc
+# define calloc lint_calloc
+#endif
+
+#ifdef MDEBUG
+extern memalign_t DebugMalloc __P((unsigned, char *, int));
+extern memalign_t DebugRealloc __P((ptr_t, unsigned, char *, int));
+extern memalign_t DebugCalloc __P((unsigned, unsigned, char *, int));
+extern void DebugFree __P((ptr_t, char *, int));
+# define xmalloc(i) DebugMalloc(i, __FILE__, __LINE__)
+# define xrealloc(p, i)((p) ? DebugRealloc(p, i, __FILE__, __LINE__) : \
+ DebugMalloc(i, __FILE__, __LINE__))
+# define xcalloc(n, s) DebugCalloc(n, s, __FILE__, __LINE__)
+# define xfree(p) if (p) DebugFree(p, __FILE__, __LINE__)
+#else
+# ifdef SYSMALLOC
+# define xmalloc(i) smalloc(i)
+# define xrealloc(p, i) srealloc(p, i)
+# define xcalloc(n, s) scalloc(n, s)
+# define xfree(p) sfree(p)
+# else
+# define xmalloc(i) malloc(i)
+# define xrealloc(p, i) realloc(p, i)
+# define xcalloc(n, s) calloc(n, s)
+# define xfree(p) free(p)
+# endif /* SYSMALLOC */
+#endif /* MDEBUG */
+#include "sh.char.h"
+#include "sh.err.h"
+#include "sh.dir.h"
+#include "sh.proc.h"
+
+#include "pathnames.h"
+
+
+/*
+ * C shell
+ *
+ * Bill Joy, UC Berkeley
+ * October, 1978; May 1980
+ *
+ * Jim Kulp, IIASA, Laxenburg Austria
+ * April, 1980
+ */
+
+#if !defined(MAXNAMLEN) && defined(_D_NAME_MAX)
+# define MAXNAMLEN _D_NAME_MAX
+#endif /* MAXNAMLEN */
+
+#ifdef HESIOD
+# include <hesiod.h>
+#endif /* HESIOD */
+
+#ifdef REMOTEHOST
+# include <netdb.h>
+#endif /* REMOTEHOST */
+
+#ifndef MAXHOSTNAMELEN
+# if defined(SCO) && (SYSVREL > 3)
+# include <sys/socket.h>
+# else
+# define MAXHOSTNAMELEN 255
+# endif
+#endif /* MAXHOSTNAMELEN */
+
+
+
+#define eq(a, b) (Strcmp(a, b) == 0)
+
+/* globone() flags */
+#define G_ERROR 0 /* default action: error if multiple words */
+#define G_IGNORE 1 /* ignore the rest of the words */
+#define G_APPEND 2 /* make a sentence by cat'ing the words */
+
+/*
+ * Global flags
+ */
+EXTERN bool chkstop IZERO; /* Warned of stopped jobs... allow exit */
+
+#if (defined(FIOCLEX) && defined(FIONCLEX)) || defined(F_SETFD)
+# define CLOSE_ON_EXEC
+#else
+EXTERN bool didcch IZERO; /* Have closed unused fd's for child */
+#endif /* (FIOCLEX && FIONCLEX) || F_SETFD */
+
+EXTERN bool didfds IZERO; /* Have setup i/o fd's for child */
+EXTERN bool doneinp IZERO; /* EOF indicator after reset from readc */
+EXTERN bool exiterr IZERO; /* Exit if error or non-zero exit status */
+EXTERN bool child IZERO; /* Child shell ... errors cause exit */
+EXTERN bool haderr IZERO; /* Reset was because of an error */
+EXTERN bool intty IZERO; /* Input is a tty */
+EXTERN bool intact IZERO; /* We are interactive... therefore prompt */
+EXTERN bool justpr IZERO; /* Just print because of :p hist mod */
+EXTERN bool loginsh IZERO; /* We are a loginsh -> .login/.logout */
+EXTERN bool neednote IZERO; /* Need to pnotify() */
+EXTERN bool noexec IZERO; /* Don't execute, just syntax check */
+EXTERN bool pjobs IZERO; /* want to print jobs if interrupted */
+EXTERN bool setintr IZERO; /* Set interrupts on/off -> Wait intr... */
+EXTERN bool timflg IZERO; /* Time the next waited for command */
+EXTERN bool havhash IZERO; /* path hashing is available */
+EXTERN bool editing IZERO; /* doing filename expansion and line editing */
+EXTERN bool noediting IZERO; /* initial $term defaulted to noedit */
+EXTERN bool bslash_quote IZERO;/* PWP: tcsh-style quoting? (in sh.c) */
+EXTERN bool isoutatty IZERO; /* is SHOUT a tty */
+EXTERN bool isdiagatty IZERO;/* is SHDIAG a tty */
+EXTERN bool is1atty IZERO; /* is file descriptor 1 a tty (didfds mode) */
+EXTERN bool is2atty IZERO; /* is file descriptor 2 a tty (didfds mode) */
+EXTERN bool arun IZERO; /* Currently running multi-line-aliases */
+EXTERN int implicit_cd IZERO;/* implicit cd enabled?(1=enabled,2=verbose) */
+EXTERN bool inheredoc IZERO; /* Currently parsing a heredoc */
+
+/*
+ * Global i/o info
+ */
+EXTERN Char *arginp IZERO; /* Argument input for sh -c and internal `xx` */
+EXTERN int onelflg IZERO; /* 2 -> need line for -t, 1 -> exit on read */
+extern Char *ffile; /* Name of shell file for $0 */
+extern bool dolzero; /* if $?0 should return true... */
+
+extern char *seterr; /* Error message from scanner/parser */
+extern int errno; /* Error from C library routines */
+EXTERN Char *shtemp IZERO; /* Temp name for << shell files in /tmp */
+
+#ifdef BSDTIMES
+EXTERN struct timeval time0; /* Time at which the shell started */
+EXTERN struct sysrusage ru0;
+#else
+# ifdef _SEQUENT_
+EXTERN timeval_t time0; /* time at which shell started */
+EXTERN struct process_stats ru0;
+# else /* _SEQUENT_ */
+# ifndef POSIX
+EXTERN time_t time0; /* time at which shell started */
+# else /* POSIX */
+EXTERN clock_t time0; /* time at which shell started */
+EXTERN clock_t clk_tck;
+# endif /* POSIX */
+EXTERN struct tms shtimes; /* shell and child times for process timing */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+
+#ifndef HZ
+# define HZ 100 /* for division into seconds */
+#endif
+
+/*
+ * Miscellany
+ */
+EXTERN Char *doldol; /* Character pid for $$ */
+EXTERN int backpid; /* pid of the last background job */
+
+/*
+ * Ideally these should be uid_t, gid_t, pid_t. I cannot do that right now
+ * cause pid's could be unsigned and that would break our -1 flag, and
+ * uid_t and gid_t are not defined in all the systems so I would have to
+ * make special cases for them. In the future...
+ */
+EXTERN int uid, euid, /* Invokers real and effective */
+ gid, egid; /* User and group ids */
+EXTERN int opgrp, /* Initial pgrp and tty pgrp */
+ shpgrp, /* Pgrp of shell */
+ tpgrp; /* Terminal process group */
+ /* If tpgrp is -1, leave tty alone! */
+
+EXTERN Char PromptBuf[INBUFSIZE*2]; /* buffer for the actual printed prompt.
+ * this must be large enough to contain
+ * the input line and the prompt, in
+ * case a correction occurred...
+ */
+EXTERN Char RPromptBuf[INBUFSIZE]; /* buffer for right-hand side prompt */
+
+/*
+ * To be able to redirect i/o for builtins easily, the shell moves the i/o
+ * descriptors it uses away from 0,1,2.
+ * Ideally these should be in units which are closed across exec's
+ * (this saves work) but for version 6, this is not usually possible.
+ * The desired initial values for these descriptors are defined in
+ * sh.local.h.
+ */
+EXTERN int SHIN IZERO; /* Current shell input (script) */
+EXTERN int SHOUT IZERO; /* Shell output */
+EXTERN int SHDIAG IZERO; /* Diagnostic output... shell errs go here */
+EXTERN int OLDSTD IZERO; /* Old standard input (def for cmds) */
+
+
+#if SYSVREL == 4 && defined(_UTS)
+/*
+ * From: fadden@uts.amdahl.com (Andy McFadden)
+ * we need sigsetjmp for UTS4, but not UTS2.1
+ */
+# define SIGSETJMP
+#endif
+
+/*
+ * Error control
+ *
+ * Errors in scanning and parsing set up an error message to be printed
+ * at the end and complete. Other errors always cause a reset.
+ * Because of source commands and .cshrc we need nested error catches.
+ */
+
+#ifdef NO_STRUCT_ASSIGNMENT
+
+# ifdef SIGSETJMP
+ typedef sigjmp_buf jmp_buf_t;
+ /* bugfix by Jak Kirman @ Brown U.: remove the (void) cast here, see sh.c */
+# define setexit() sigsetjmp(reslab)
+# define reset() siglongjmp(reslab, 1)
+# else
+ typedef jmp_buf jmp_buf_t;
+ /* bugfix by Jak Kirman @ Brown U.: remove the (void) cast here, see sh.c */
+# define setexit() setjmp(reslab)
+# define reset() longjmp(reslab, 1)
+# endif
+# define getexit(a) (void) memmove((ptr_t)&(a), (ptr_t)&reslab, sizeof(reslab))
+# define resexit(a) (void) memmove((ptr_t)&reslab, (ptr_t)&(a), sizeof(reslab))
+
+# define cpybin(a, b) (void) memmove((ptr_t)&(a), (ptr_t)&(b), sizeof(Bin))
+
+#else
+
+# ifdef SIGSETJMP
+ typedef struct { sigjmp_buf j; } jmp_buf_t;
+# define setexit() sigsetjmp(reslab.j)
+# define reset() siglongjmp(reslab.j, 1)
+# else
+ typedef struct { jmp_buf j; } jmp_buf_t;
+# define setexit() setjmp(reslab.j)
+# define reset() longjmp(reslab.j, 1)
+# endif
+
+# define getexit(a) (void) ((a) = reslab)
+# define resexit(a) (void) (reslab = (a))
+
+# define cpybin(a, b) (void) ((a) = (b))
+
+#endif /* NO_STRUCT_ASSIGNMENT */
+
+extern jmp_buf_t reslab;
+
+EXTERN Char *gointr; /* Label for an onintr transfer */
+
+extern signalfun_t parintr; /* Parents interrupt catch */
+extern signalfun_t parterm; /* Parents terminate catch */
+
+/*
+ * Lexical definitions.
+ *
+ * All lexical space is allocated dynamically.
+ * The eighth/sixteenth bit of characters is used to prevent recognition,
+ * and eventually stripped.
+ */
+#define META 0200
+#define ASCII 0177
+#ifdef SHORT_STRINGS
+# define QUOTE ((Char) 0100000)/* 16nth char bit used for 'ing */
+# define TRIM 0077777 /* Mask to strip quote bit */
+# define UNDER 0040000 /* Underline flag */
+# define BOLD 0020000 /* Bold flag */
+# define STANDOUT 0010000 /* Standout flag */
+# define LITERAL 0004000 /* Literal character flag */
+# define ATTRIBUTES 0074000 /* The bits used for attributes */
+# define CHAR 0000377 /* Mask to mask out the character */
+#else
+# define QUOTE ((Char) 0200) /* Eighth char bit used for 'ing */
+# define TRIM 0177 /* Mask to strip quote bit */
+# define UNDER 0000000 /* No extra bits to do both */
+# define BOLD 0000000 /* Bold flag */
+# define STANDOUT META /* Standout flag */
+# define LITERAL 0000000 /* Literal character flag */
+# define ATTRIBUTES 0200 /* The bits used for attributes */
+# define CHAR 0000177 /* Mask to mask out the character */
+#endif
+
+EXTERN int AsciiOnly; /* If set only 7 bits expected in characters */
+
+/*
+ * Each level of input has a buffered input structure.
+ * There are one or more blocks of buffered input for each level,
+ * exactly one if the input is seekable and tell is available.
+ * In other cases, the shell buffers enough blocks to keep all loops
+ * in the buffer.
+ */
+EXTERN struct Bin {
+ off_t Bfseekp; /* Seek pointer */
+ off_t Bfbobp; /* Seekp of beginning of buffers */
+ off_t Bfeobp; /* Seekp of end of buffers */
+ int Bfblocks; /* Number of buffer blocks */
+ Char **Bfbuf; /* The array of buffer blocks */
+} B;
+
+/*
+ * This structure allows us to seek inside aliases
+ */
+struct Ain {
+ int type;
+#define I_SEEK -1 /* Invalid seek */
+#define A_SEEK 0 /* Alias seek */
+#define F_SEEK 1 /* File seek */
+#define E_SEEK 2 /* Eval seek */
+ union {
+ off_t _f_seek;
+ Char* _c_seek;
+ } fc;
+#define f_seek fc._f_seek
+#define c_seek fc._c_seek
+ Char **a_seek;
+} ;
+
+extern int aret; /* Type of last char returned */
+#define SEEKEQ(a, b) ((a)->type == (b)->type && \
+ (a)->f_seek == (b)->f_seek && \
+ (a)->a_seek == (b)->a_seek)
+
+#define fseekp B.Bfseekp
+#define fbobp B.Bfbobp
+#define feobp B.Bfeobp
+#define fblocks B.Bfblocks
+#define fbuf B.Bfbuf
+
+/*
+ * The shell finds commands in loops by reseeking the input
+ * For whiles, in particular, it reseeks to the beginning of the
+ * line the while was on; hence the while placement restrictions.
+ */
+EXTERN struct Ain lineloc;
+
+EXTERN bool cantell; /* Is current source tellable ? */
+
+/*
+ * Input lines are parsed into doubly linked circular
+ * lists of words of the following form.
+ */
+struct wordent {
+ Char *word;
+ struct wordent *prev;
+ struct wordent *next;
+};
+
+/*
+ * During word building, both in the initial lexical phase and
+ * when expanding $ variable substitutions, expansion by `!' and `$'
+ * must be inhibited when reading ahead in routines which are themselves
+ * processing `!' and `$' expansion or after characters such as `\' or in
+ * quotations. The following flags are passed to the getC routines
+ * telling them which of these substitutions are appropriate for the
+ * next character to be returned.
+ */
+#define DODOL 1
+#define DOEXCL 2
+#define DOALL DODOL|DOEXCL
+
+/*
+ * Labuf implements a general buffer for lookahead during lexical operations.
+ * Text which is to be placed in the input stream can be stuck here.
+ * We stick parsed ahead $ constructs during initial input,
+ * process id's from `$$', and modified variable values (from qualifiers
+ * during expansion in sh.dol.c) here.
+ */
+EXTERN Char *lap;
+
+/*
+ * Parser structure
+ *
+ * Each command is parsed to a tree of command structures and
+ * flags are set bottom up during this process, to be propagated down
+ * as needed during the semantics/exeuction pass (sh.sem.c).
+ */
+struct command {
+ unsigned char t_dtyp; /* Type of node */
+#define NODE_COMMAND 1 /* t_dcom <t_dlef >t_drit */
+#define NODE_PAREN 2 /* ( t_dspr ) <t_dlef >t_drit */
+#define NODE_PIPE 3 /* t_dlef | t_drit */
+#define NODE_LIST 4 /* t_dlef ; t_drit */
+#define NODE_OR 5 /* t_dlef || t_drit */
+#define NODE_AND 6 /* t_dlef && t_drit */
+ unsigned char t_nice; /* Nice value */
+#ifdef apollo
+ unsigned char t_systype; /* System environment */
+#endif
+ unsigned long t_dflg; /* Flags, e.g. F_AMPERSAND|... */
+/* save these when re-doing */
+#ifndef apollo
+#define F_SAVE (F_NICE|F_TIME|F_NOHUP|F_HUP)
+#else
+#define F_SAVE (F_NICE|F_TIME|F_NOHUP||F_HUP|F_VER)
+#endif
+#define F_AMPERSAND (1<<0) /* executes in background */
+#define F_APPEND (1<<1) /* output is redirected >> */
+#define F_PIPEIN (1<<2) /* input is a pipe */
+#define F_PIPEOUT (1<<3) /* output is a pipe */
+#define F_NOFORK (1<<4) /* don't fork, last ()ized cmd */
+#define F_NOINTERRUPT (1<<5) /* should be immune from intr's */
+/* spare */
+#define F_STDERR (1<<7) /* redirect unit 2 with unit 1 */
+#define F_OVERWRITE (1<<8) /* output was ! */
+#define F_READ (1<<9) /* input redirection is << */
+#define F_REPEAT (1<<10) /* reexec aft if, repeat,... */
+#define F_NICE (1<<11) /* t_nice is meaningful */
+#define F_NOHUP (1<<12) /* nohup this command */
+#define F_TIME (1<<13) /* time this command */
+#define F_BACKQ (1<<14) /* command is in `` */
+#define F_HUP (1<<15) /* hup this command */
+#ifdef apollo
+#define F_VER (1<<16) /* execute command under SYSTYPE */
+#endif
+ union {
+ Char *T_dlef; /* Input redirect word */
+ struct command *T_dcar; /* Left part of list/pipe */
+ } L;
+ union {
+ Char *T_drit; /* Output redirect word */
+ struct command *T_dcdr; /* Right part of list/pipe */
+ } R;
+#define t_dlef L.T_dlef
+#define t_dcar L.T_dcar
+#define t_drit R.T_drit
+#define t_dcdr R.T_dcdr
+ Char **t_dcom; /* Command/argument vector */
+ struct command *t_dspr; /* Pointer to ()'d subtree */
+};
+
+
+/*
+ * The keywords for the parser
+ */
+#define TC_BREAK 0
+#define TC_BRKSW 1
+#define TC_CASE 2
+#define TC_DEFAULT 3
+#define TC_ELSE 4
+#define TC_END 5
+#define TC_ENDIF 6
+#define TC_ENDSW 7
+#define TC_EXIT 8
+#define TC_FOREACH 9
+#define TC_GOTO 10
+#define TC_IF 11
+#define TC_LABEL 12
+#define TC_LET 13
+#define TC_SET 14
+#define TC_SWITCH 15
+#define TC_TEST 16
+#define TC_THEN 17
+#define TC_WHILE 18
+
+/*
+ * These are declared here because they want to be
+ * initialized in sh.init.c (to allow them to be made readonly)
+ */
+
+#if defined(hpux) && defined(__STDC__) && !defined(__GNUC__)
+ /* Avoid hpux ansi mode spurious warnings */
+typedef void (*bfunc_t) ();
+#else
+typedef void (*bfunc_t) __P((Char **, struct command *));
+#endif /* hpux && __STDC__ && !__GNUC__ */
+
+extern struct biltins {
+ char *bname;
+ bfunc_t bfunct;
+ int minargs, maxargs;
+} bfunc[];
+extern int nbfunc;
+#ifdef WINNT
+extern struct biltins nt_bfunc[];
+extern int nt_nbfunc;
+#endif /* WINNT*/
+
+extern struct srch {
+ char *s_name;
+ int s_value;
+} srchn[];
+extern int nsrchn;
+
+/*
+ * Structure defining the existing while/foreach loops at this
+ * source level. Loops are implemented by seeking back in the
+ * input. For foreach (fe), the word list is attached here.
+ */
+EXTERN struct whyle {
+ struct Ain w_start; /* Point to restart loop */
+ struct Ain w_end; /* End of loop (0 if unknown) */
+ Char **w_fe, **w_fe0; /* Current/initial wordlist for fe */
+ Char *w_fename; /* Name for fe */
+ struct whyle *w_next; /* Next (more outer) loop */
+} *whyles;
+
+/*
+ * Variable structure
+ *
+ * Aliases and variables are stored in AVL balanced binary trees.
+ */
+EXTERN struct varent {
+ Char **vec; /* Array of words which is the value */
+ Char *v_name; /* Name of variable/alias */
+ int v_flags; /* Flags */
+#define VAR_ALL -1
+#define VAR_READONLY 1
+#define VAR_READWRITE 2
+#define VAR_NOGLOB 4
+#define VAR_FIRST 32
+#define VAR_LAST 64
+ struct varent *v_link[3]; /* The links, see below */
+ int v_bal; /* Balance factor */
+} shvhed IZERO_STRUCT, aliases IZERO_STRUCT;
+
+#define v_left v_link[0]
+#define v_right v_link[1]
+#define v_parent v_link[2]
+
+#define adrof(v) adrof1(v, &shvhed)
+#define varval(v) value1(v, &shvhed)
+
+/*
+ * The following are for interfacing redo substitution in
+ * aliases to the lexical routines.
+ */
+EXTERN struct wordent *alhistp IZERO_STRUCT;/* Argument list (first) */
+EXTERN struct wordent *alhistt IZERO_STRUCT;/* Node after last in arg list */
+EXTERN Char **alvec IZERO_STRUCT,
+ *alvecp IZERO_STRUCT;/* The (remnants of) alias vector */
+
+/*
+ * Filename/command name expansion variables
+ */
+EXTERN int gflag; /* After tglob -> is globbing needed? */
+
+#define MAXVARLEN 30 /* Maximum number of char in a variable name */
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 2048
+#endif /* MAXPATHLEN */
+
+#ifndef MAXNAMLEN
+# define MAXNAMLEN 512
+#endif /* MAXNAMLEN */
+
+#ifndef HAVENOLIMIT
+/*
+ * resource limits
+ */
+extern struct limits {
+ int limconst;
+ char *limname;
+ int limdiv;
+ char *limscale;
+} limits[];
+#endif /* !HAVENOLIMIT */
+
+/*
+ * Variables for filename expansion
+ */
+extern Char **gargv; /* Pointer to the (stack) arglist */
+extern int gargc; /* Number args in gargv */
+
+/*
+ * Variables for command expansion.
+ */
+extern Char **pargv; /* Pointer to the argv list space */
+EXTERN Char *pargs; /* Pointer to start current word */
+EXTERN long pnleft; /* Number of chars left in pargs */
+EXTERN Char *pargcp; /* Current index into pargs */
+
+/*
+ * History list
+ *
+ * Each history list entry contains an embedded wordlist
+ * from the scanner, a number for the event, and a reference count
+ * to aid in discarding old entries.
+ *
+ * Essentially "invisible" entries are put on the history list
+ * when history substitution includes modifiers, and thrown away
+ * at the next discarding since their event numbers are very negative.
+ */
+EXTERN struct Hist {
+ struct wordent Hlex;
+ int Hnum;
+ int Href;
+ time_t Htime;
+ Char *histline;
+ struct Hist *Hnext;
+} Histlist IZERO_STRUCT;
+
+EXTERN struct wordent paraml; /* Current lexical word list */
+EXTERN int eventno; /* Next events number */
+EXTERN int lastev; /* Last event reference (default) */
+
+EXTERN Char HIST; /* history invocation character */
+EXTERN Char HISTSUB; /* auto-substitute character */
+EXTERN Char PRCH; /* Prompt symbol for regular users */
+EXTERN Char PRCHROOT; /* Prompt symbol for root */
+
+/*
+ * For operating systems with single case filenames (OS/2)
+ */
+#ifdef CASE_INSENSITIVE
+# define samecase(x) (isupper((unsigned char)(x)) ? \
+ tolower((unsigned char)(x)) : (x))
+#else
+# define samecase(x) (x)
+#endif /* CASE_INSENSITIVE */
+
+/*
+ * strings.h:
+ */
+#ifndef SHORT_STRINGS
+#define Strchr(a, b) strchr(a, b)
+#define Strrchr(a, b) strrchr(a, b)
+#define Strcat(a, b) strcat(a, b)
+#define Strncat(a, b, c) strncat(a, b, c)
+#define Strcpy(a, b) strcpy(a, b)
+#define Strncpy(a, b, c) strncpy(a, b, c)
+#define Strlen(a) strlen(a)
+#define Strcmp(a, b) strcmp(a, b)
+#define Strncmp(a, b, c) strncmp(a, b, c)
+
+#define Strspl(a, b) strspl(a, b)
+#define Strsave(a) strsave(a)
+#define Strend(a) strend(a)
+#define Strstr(a, b) strstr(a, b)
+
+#define str2short(a) (a)
+#define blk2short(a) saveblk(a)
+#define short2blk(a) saveblk(a)
+#define short2str(a) strip(a)
+#else
+#define Strchr(a, b) s_strchr(a, b)
+#define Strrchr(a, b) s_strrchr(a, b)
+#define Strcat(a, b) s_strcat(a, b)
+#define Strncat(a, b, c) s_strncat(a, b, c)
+#define Strcpy(a, b) s_strcpy(a, b)
+#define Strncpy(a, b, c) s_strncpy(a, b, c)
+#define Strlen(a) s_strlen(a)
+#define Strcmp(a, b) s_strcmp(a, b)
+#define Strncmp(a, b, c) s_strncmp(a, b, c)
+
+#define Strspl(a, b) s_strspl(a, b)
+#define Strsave(a) s_strsave(a)
+#define Strend(a) s_strend(a)
+#define Strstr(a, b) s_strstr(a, b)
+#endif
+
+/*
+ * setname is a macro to save space (see sh.err.c)
+ */
+EXTERN char *bname;
+
+#define setname(a) (bname = (a))
+
+#ifdef VFORK
+EXTERN Char *Vsav;
+EXTERN Char *Vdp;
+EXTERN Char *Vexpath;
+EXTERN char **Vt;
+#endif /* VFORK */
+
+EXTERN Char **evalvec;
+EXTERN Char *evalp;
+
+extern struct mesg {
+ char *iname; /* name from /usr/include */
+ char *pname; /* print name */
+} mesg[];
+
+/* word_chars is set by default to WORD_CHARS but can be overridden by
+ the worchars variable--if unset, reverts to WORD_CHARS */
+
+EXTERN Char *word_chars;
+
+#define WORD_CHARS "*?_-.[]~=" /* default chars besides alnums in words */
+
+EXTERN Char *STR_SHELLPATH;
+
+#ifdef _PATH_BSHELL
+EXTERN Char *STR_BSHELL;
+#endif
+EXTERN Char *STR_WORD_CHARS;
+EXTERN Char **STR_environ IZERO;
+
+extern int dont_free; /* Tell free that we are in danger if we free */
+
+extern Char *INVPTR;
+extern Char **INVPPTR;
+
+extern char *progname;
+extern int tcsh;
+
+#include "tc.h"
+#include "sh.decls.h"
+
+/*
+ * To print system call errors...
+ */
+#ifdef BSD4_4
+# include <errno.h>
+#else
+# ifndef linux
+# ifdef NEEDstrerror
+extern char *sys_errlist[];
+# endif
+extern int errno, sys_nerr;
+# endif /* !linux */
+#endif
+
+#ifndef WINNT
+# ifdef NLS_CATALOGS
+# ifdef linux
+# include <locale.h>
+# ifdef notdef
+# include <localeinfo.h> /* Has this changed ? */
+# endif
+# include <features.h>
+# endif
+# ifdef SUNOS4
+ /* Who stole my nl_types.h? :-(
+ * All this stuff is in the man pages, but nowhere else?
+ * This does not link right now...
+ */
+ typedef void *nl_catd;
+ extern const char * catgets __P((nl_catd, int, int, const char *));
+ nl_catd catopen __P((const char *, int));
+ int catclose __P((nl_catd));
+# else
+# ifdef __uxps__
+# define gettxt gettxt_ds
+# endif
+# include <nl_types.h>
+# ifdef __uxps__
+# undef gettxt
+# endif
+# endif
+# ifndef MCLoadBySet
+# define MCLoadBySet 0
+# endif
+EXTERN nl_catd catd;
+# define CGETS(b, c, d) catgets(catd, b, c, d)
+# define CSAVS(b, c, d) strsave(CGETS(b, c, d))
+# else
+# define CGETS(b, c, d) d
+# define CSAVS(b, c, d) d
+# endif
+#else /* WINNT */
+# define CGETS(b, c, d) nt_cgets( b, c, d)
+# define CSAVS(b, c, d) strsave(CGETS(b, c, d))
+#endif /* WINNT */
+
+/*
+ * Since on some machines characters are unsigned, and the signed
+ * keyword is not universally implemented, we treat all characters
+ * as unsigned and sign extend them where we need.
+ */
+#define SIGN_EXTEND_CHAR(a) (((a) & 0x80) ? ((a) | ~0x7f) : (a))
+
+#endif /* _h_sh */
diff --git a/contrib/tcsh/sh.hist.c b/contrib/tcsh/sh.hist.c
new file mode 100644
index 0000000..a2889dd
--- /dev/null
+++ b/contrib/tcsh/sh.hist.c
@@ -0,0 +1,477 @@
+/* $Header: /src/pub/tcsh/sh.hist.c,v 3.26 1999/02/06 15:01:23 christos Exp $ */
+/*
+ * sh.hist.c: Shell history expansions and substitutions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.hist.c,v 3.26 1999/02/06 15:01:23 christos Exp $")
+
+#include "tc.h"
+
+extern bool histvalid;
+extern Char histline[];
+Char HistLit = 0;
+
+static bool heq __P((struct wordent *, struct wordent *));
+static void hfree __P((struct Hist *));
+static void dohist1 __P((struct Hist *, int *, int));
+static void phist __P((struct Hist *, int));
+
+#define HIST_ONLY 0x01
+#define HIST_SAVE 0x02
+#define HIST_LOAD 0x04
+#define HIST_REV 0x08
+#define HIST_CLEAR 0x10
+#define HIST_MERGE 0x20
+#define HIST_TIME 0x40
+
+/*
+ * C shell
+ */
+
+void
+savehist(sp, mflg)
+ struct wordent *sp;
+ bool mflg;
+{
+ register struct Hist *hp, *np;
+ register int histlen = 0;
+ Char *cp;
+
+ /* throw away null lines */
+ if (sp && sp->next->word[0] == '\n')
+ return;
+ cp = varval(STRhistory);
+ if (*cp) {
+ register Char *p = cp;
+
+ while (*p) {
+ if (!Isdigit(*p)) {
+ histlen = 0;
+ break;
+ }
+ histlen = histlen * 10 + *p++ - '0';
+ }
+ }
+ if (sp)
+ (void) enthist(++eventno, sp, 1, mflg);
+ for (hp = &Histlist; (np = hp->Hnext) != NULL;)
+ if (eventno - np->Href >= histlen || histlen == 0)
+ hp->Hnext = np->Hnext, hfree(np);
+ else
+ hp = np;
+}
+
+static bool
+heq(a0, b0)
+ struct wordent *a0, *b0;
+{
+ struct wordent *a = a0->next, *b = b0->next;
+
+ for (;;) {
+ if (Strcmp(a->word, b->word) != 0)
+ return 0;
+ a = a->next;
+ b = b->next;
+ if (a == a0)
+ return (b == b0) ? 1 : 0;
+ if (b == b0)
+ return 0;
+ }
+}
+
+
+struct Hist *
+enthist(event, lp, docopy, mflg)
+ int event;
+ register struct wordent *lp;
+ bool docopy;
+ bool mflg;
+{
+ extern time_t Htime;
+ struct Hist *p = NULL, *pp = &Histlist;
+ int n, r;
+ register struct Hist *np;
+ Char *dp;
+
+ if ((dp = varval(STRhistdup)) != STRNULL) {
+ if (eq(dp, STRerase)) {
+ /* masaoki@akebono.tky.hp.com (Kobayashi Masaoki) */
+ struct Hist *px;
+ for (p = pp; (px = p, p = p->Hnext) != NULL;)
+ if (heq(lp, &(p->Hlex))){
+ px->Hnext = p->Hnext;
+ if (Htime != 0 && p->Htime > Htime)
+ Htime = p->Htime;
+ n = p->Href;
+ hfree(p);
+ for (p = px->Hnext; p != NULL; p = p->Hnext)
+ p->Href = n--;
+ break;
+ }
+ }
+ else if (eq(dp, STRall)) {
+ for (p = pp; (p = p->Hnext) != NULL;)
+ if (heq(lp, &(p->Hlex))) {
+ eventno--;
+ break;
+ }
+ }
+ else if (eq(dp, STRprev)) {
+ if (pp->Hnext && heq(lp, &(pp->Hnext->Hlex))) {
+ p = pp->Hnext;
+ eventno--;
+ }
+ }
+ }
+
+ np = p ? p : (struct Hist *) xmalloc((size_t) sizeof(*np));
+
+ /* Pick up timestamp set by lex() in Htime if reading saved history */
+ if (Htime != (time_t) 0) {
+ np->Htime = Htime;
+ Htime = 0;
+ }
+ else
+ (void) time(&(np->Htime));
+
+ if (p == np)
+ return np;
+
+ np->Hnum = np->Href = event;
+ if (docopy) {
+ copylex(&np->Hlex, lp);
+ if (histvalid)
+ np->histline = Strsave(histline);
+ else
+ np->histline = NULL;
+ }
+ else {
+ np->Hlex.next = lp->next;
+ lp->next->prev = &np->Hlex;
+ np->Hlex.prev = lp->prev;
+ lp->prev->next = &np->Hlex;
+ np->histline = NULL;
+ }
+ if (mflg)
+ {
+ while ((p = pp->Hnext) && (p->Htime > np->Htime))
+ pp = p;
+ while (p && p->Htime == np->Htime)
+ {
+ if (heq(&p->Hlex, &np->Hlex))
+ {
+ eventno--;
+ hfree(np);
+ return (p);
+ }
+ pp = p;
+ p = p->Hnext;
+ }
+ for (p = Histlist.Hnext; p != pp->Hnext; p = p->Hnext)
+ {
+ n = p->Hnum; r = p->Href;
+ p->Hnum = np->Hnum; p->Href = np->Href;
+ np->Hnum = n; np->Href = r;
+ }
+ }
+ np->Hnext = pp->Hnext;
+ pp->Hnext = np;
+ return (np);
+}
+
+static void
+hfree(hp)
+ register struct Hist *hp;
+{
+
+ freelex(&hp->Hlex);
+ if (hp->histline)
+ xfree((ptr_t) hp->histline);
+ xfree((ptr_t) hp);
+}
+
+
+/*ARGSUSED*/
+void
+dohist(vp, c)
+ Char **vp;
+ struct command *c;
+{
+ int n, hflg = 0;
+
+ USE(c);
+ if (getn(varval(STRhistory)) == 0)
+ return;
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ while (*++vp && **vp == '-') {
+ Char *vp2 = *vp;
+
+ while (*++vp2)
+ switch (*vp2) {
+ case 'c':
+ hflg |= HIST_CLEAR;
+ break;
+ case 'h':
+ hflg |= HIST_ONLY;
+ break;
+ case 'r':
+ hflg |= HIST_REV;
+ break;
+ case 'S':
+ hflg |= HIST_SAVE;
+ break;
+ case 'L':
+ hflg |= HIST_LOAD;
+ break;
+ case 'M':
+ hflg |= HIST_MERGE;
+ break;
+ case 'T':
+ hflg |= HIST_TIME;
+ break;
+ default:
+ stderror(ERR_HISTUS, "chrSLMT");
+ break;
+ }
+ }
+
+ if (hflg & HIST_CLEAR) {
+ struct Hist *np, *hp;
+ for (hp = &Histlist; (np = hp->Hnext) != NULL;)
+ hp->Hnext = np->Hnext, hfree(np);
+ }
+
+ if (hflg & (HIST_LOAD | HIST_MERGE)) {
+ loadhist(*vp, (hflg & HIST_MERGE) ? 1 : 0);
+ return;
+ }
+ else if (hflg & HIST_SAVE) {
+ rechist(*vp, 1);
+ return;
+ }
+ if (*vp)
+ n = getn(*vp);
+ else {
+ n = getn(varval(STRhistory));
+ }
+ dohist1(Histlist.Hnext, &n, hflg);
+}
+
+static void
+dohist1(hp, np, hflg)
+ struct Hist *hp;
+ int *np, hflg;
+{
+ bool print = (*np) > 0;
+
+ for (; hp != 0; hp = hp->Hnext) {
+ (*np)--;
+ if ((hflg & HIST_REV) == 0) {
+ dohist1(hp->Hnext, np, hflg);
+ if (print)
+ phist(hp, hflg);
+ return;
+ }
+ if (*np >= 0)
+ phist(hp, hflg);
+ }
+}
+
+static void
+phist(hp, hflg)
+ register struct Hist *hp;
+ int hflg;
+{
+ extern bool output_raw;
+ if (hflg & HIST_ONLY) {
+ /*
+ * Control characters have to be written as is (output_raw).
+ * This way one can preserve special characters (like tab) in
+ * the history file.
+ * From: mveksler@vnet.ibm.com (Veksler Michael)
+ */
+ output_raw= 1;
+ if (hflg & HIST_TIME)
+ /*
+ * Make file entry with history time in format:
+ * "+NNNNNNNNNN" (10 digits, left padded with ascii '0')
+ */
+
+ xprintf("#+%010lu\n", hp->Htime);
+
+ if (HistLit && hp->histline)
+ xprintf("%S\n", hp->histline);
+ else
+ prlex(&hp->Hlex);
+ output_raw= 0;
+ }
+ else {
+ Char *cp = str2short("%h\t%T\t%R\n");
+ Char buf[INBUFSIZE];
+ struct varent *vp = adrof(STRhistory);
+
+ if (vp && vp->vec[0] && vp->vec[1])
+ cp = vp->vec[1];
+
+ tprintf(FMT_HISTORY, buf, cp, INBUFSIZE, NULL, hp->Htime, (ptr_t) hp);
+ for (cp = buf; *cp;)
+ xputchar(*cp++);
+ }
+}
+
+
+void
+fmthist(fmt, ptr, buf, bufsiz)
+ int fmt;
+ ptr_t ptr;
+ char *buf;
+ size_t bufsiz;
+{
+ struct Hist *hp = (struct Hist *) ptr;
+ switch (fmt) {
+ case 'h':
+ (void) xsnprintf(buf, bufsiz, "%6d", hp->Hnum);
+ break;
+ case 'R':
+ if (HistLit && hp->histline)
+ (void) xsnprintf(buf, bufsiz, "%S", hp->histline);
+ else {
+ Char ibuf[INBUFSIZE], *ip;
+ char *p;
+ (void) sprlex(ibuf, sizeof(ibuf), &hp->Hlex);
+ for (p = buf, ip = ibuf; (*p++ = (CHAR & *ip++)) != '\0'; )
+ continue;
+ }
+ break;
+ default:
+ buf[0] = '\0';
+ break;
+ }
+
+}
+
+void
+rechist(fname, ref)
+ Char *fname;
+ int ref;
+{
+ Char *snum;
+ int fp, ftmp, oldidfds;
+ struct varent *shist;
+ static Char *dumphist[] = {STRhistory, STRmhT, 0, 0};
+
+ if (fname == NULL && !ref)
+ return;
+ /*
+ * If $savehist is just set, we use the value of $history
+ * else we use the value in $savehist
+ */
+ if (((snum = varval(STRsavehist)) == STRNULL) &&
+ ((snum = varval(STRhistory)) == STRNULL))
+ snum = STRmaxint;
+
+
+ if (fname == NULL) {
+ if ((fname = varval(STRhistfile)) == STRNULL)
+ fname = Strspl(varval(STRhome), &STRtildothist[1]);
+ else
+ fname = Strsave(fname);
+ }
+ else
+ fname = globone(fname, G_ERROR);
+
+ /*
+ * The 'savehist merge' feature is intended for an environment
+ * with numerous shells beeing in simultaneous use. Imagine
+ * any kind of window system. All these shells 'share' the same
+ * ~/.history file for recording their command line history.
+ * Currently the automatic merge can only succeed when the shells
+ * nicely quit one after another.
+ *
+ * Users that like to nuke their environment require here an atomic
+ * loadhist-creat-dohist(dumphist)-close
+ * sequence.
+ *
+ * jw.
+ */
+ /*
+ * We need the didfds stuff before loadhist otherwise
+ * exec in a script will fail to print if merge is set.
+ * From: mveksler@iil.intel.com (Veksler Michael)
+ */
+ oldidfds = didfds;
+ didfds = 0;
+ if ((shist = adrof(STRsavehist)) != NULL)
+ if (shist->vec[1] && eq(shist->vec[1], STRmerge))
+ loadhist(fname, 1);
+ fp = creat(short2str(fname), 0600);
+ if (fp == -1) {
+ didfds = oldidfds;
+ return;
+ }
+ ftmp = SHOUT;
+ SHOUT = fp;
+ dumphist[2] = snum;
+ dohist(dumphist, NULL);
+ (void) close(fp);
+ SHOUT = ftmp;
+ didfds = oldidfds;
+ xfree((ptr_t) fname);
+}
+
+
+void
+loadhist(fname, mflg)
+ Char *fname;
+ bool mflg;
+{
+ static Char *loadhist_cmd[] = {STRsource, NULL, NULL, NULL};
+ loadhist_cmd[1] = mflg ? STRmm : STRmh;
+
+ if (fname != NULL)
+ loadhist_cmd[2] = fname;
+ else if ((fname = varval(STRhistfile)) != STRNULL)
+ loadhist_cmd[2] = fname;
+ else
+ loadhist_cmd[2] = STRtildothist;
+
+ dosource(loadhist_cmd, NULL);
+}
diff --git a/contrib/tcsh/sh.init.c b/contrib/tcsh/sh.init.c
new file mode 100644
index 0000000..62e9d8c
--- /dev/null
+++ b/contrib/tcsh/sh.init.c
@@ -0,0 +1,1074 @@
+/* $Header: /src/pub/tcsh/sh.init.c,v 3.48 1999/02/11 16:18:36 christos Exp $ */
+/*
+ * sh.init.c: Function and signal tables
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.init.c,v 3.48 1999/02/11 16:18:36 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+
+/*
+ * C shell
+ */
+
+#define INF 0x7fffffff
+
+struct biltins bfunc[] = {
+ { ":", dozip, 0, INF },
+ { "@", dolet, 0, INF },
+ { "alias", doalias, 0, INF },
+#ifdef OBSOLETE
+ { "aliases", doaliases, 0, 1, },
+#endif /* OBSOLETE */
+ { "alloc", showall, 0, 1 },
+#if defined(_CX_UX)
+ { "att", doatt, 0, INF },
+#endif /* _CX_UX */
+ { "bg", dobg, 0, INF },
+#ifdef OBSOLETE
+ { "bind", dobind, 0, 2 },
+#endif /* OBSOLETE */
+ { "bindkey", dobindkey, 0, 8 },
+ { "break", dobreak, 0, 0 },
+ { "breaksw", doswbrk, 0, 0 },
+ { "builtins", dobuiltins, 0, 0 },
+#ifdef KAI
+ { "bye", goodbye, 0, 0 },
+#endif /* KAI */
+ { "case", dozip, 0, 1 },
+ { "cd", dochngd, 0, INF },
+ { "chdir", dochngd, 0, INF },
+ { "complete", docomplete, 0, INF },
+ { "continue", docontin, 0, 0 },
+ { "default", dozip, 0, 0 },
+ { "dirs", dodirs, 0, INF },
+#if defined(_CRAY) && !defined(_CRAYMPP)
+ { "dmmode", dodmmode, 0, 1 },
+#endif /* _CRAY && !_CRAYMPP */
+ { "echo", doecho, 0, INF },
+ { "echotc", doechotc, 0, INF },
+ { "else", doelse, 0, INF },
+ { "end", doend, 0, 0 },
+ { "endif", dozip, 0, 0 },
+ { "endsw", dozip, 0, 0 },
+ { "eval", doeval, 0, INF },
+ { "exec", execash, 1, INF },
+ { "exit", doexit, 0, INF },
+ { "fg", dofg, 0, INF },
+ { "filetest", dofiletest, 2, INF },
+ { "foreach", doforeach, 3, INF },
+#ifdef TCF
+ { "getspath", dogetspath, 0, 0 },
+ { "getxvers", dogetxvers, 0, 0 },
+#endif /* TCF */
+ { "glob", doglob, 0, INF },
+ { "goto", dogoto, 1, 1 },
+ { "hashstat", hashstat, 0, 0 },
+ { "history", dohist, 0, 2 },
+ { "hup", dohup, 0, INF },
+ { "if", doif, 1, INF },
+#ifdef apollo
+ { "inlib", doinlib, 1, INF },
+#endif /* apollo */
+ { "jobs", dojobs, 0, 1 },
+ { "kill", dokill, 1, INF },
+#ifndef HAVENOLIMIT
+ { "limit", dolimit, 0, 3 },
+#endif /* !HAVENOLIMIT */
+#ifdef OBSOLETE
+ { "linedit", doecho, 0, INF },
+#endif /* OBSOLETE */
+#if !defined(HAVENOUTMP) && !defined(KAI)
+ { "log", dolog, 0, 0 },
+#endif /* !HAVENOUTMP && !KAI */
+ { "login", dologin, 0, 1 },
+ { "logout", dologout, 0, 0 },
+ { "ls-F", dolist, 0, INF },
+#ifdef TCF
+ { "migrate", domigrate, 1, INF },
+#endif /* TCF */
+#ifdef NEWGRP
+ { "newgrp", donewgrp, 1, 2 },
+#endif /* NEWGRP */
+ { "nice", donice, 0, INF },
+ { "nohup", donohup, 0, INF },
+ { "notify", donotify, 0, INF },
+ { "onintr", doonintr, 0, 2 },
+ { "popd", dopopd, 0, INF },
+ { "printenv", doprintenv, 0, 1 },
+ { "pushd", dopushd, 0, INF },
+ { "rehash", dohash, 0, 3 },
+ { "repeat", dorepeat, 2, INF },
+#ifdef apollo
+ { "rootnode", dorootnode, 1, 1 },
+#endif /* apollo */
+ { "sched", dosched, 0, INF },
+ { "set", doset, 0, INF },
+ { "setenv", dosetenv, 0, 2 },
+#ifdef MACH
+ { "setpath", dosetpath, 0, INF },
+#endif /* MACH */
+#ifdef TCF
+ { "setspath", dosetspath, 1, INF },
+#endif /* TCF */
+ { "settc", dosettc, 2, 2 },
+ { "setty", dosetty, 0, INF },
+#ifdef TCF
+ { "setxvers", dosetxvers, 0, 1 },
+#endif /* TCF */
+ { "shift", shift, 0, 1 },
+ { "source", dosource, 1, INF },
+ { "stop", dostop, 1, INF },
+ { "suspend", dosuspend, 0, 0 },
+ { "switch", doswitch, 1, INF },
+ { "telltc", dotelltc, 0, INF },
+ { "time", dotime, 0, INF },
+#if defined(_CX_UX)
+ { "ucb", doucb, 0, INF },
+#endif /* _CX_UX */
+ { "umask", doumask, 0, 1 },
+ { "unalias", unalias, 1, INF },
+ { "uncomplete", douncomplete, 1, INF },
+ { "unhash", dounhash, 0, 0 },
+#if defined(masscomp) || defined(_CX_UX)
+ { "universe", douniverse, 0, INF },
+#endif /* masscomp || _CX_UX */
+#ifndef HAVENOLIMIT
+ { "unlimit", dounlimit, 0, INF },
+#endif /* !HAVENOLIMIT */
+ { "unset", unset, 1, INF },
+ { "unsetenv", dounsetenv, 1, INF },
+#ifdef apollo
+ { "ver", dover, 0, INF },
+#endif /* apollo */
+ { "wait", dowait, 0, 0 },
+#ifdef WARP
+ { "warp", dowarp, 0, 2 },
+#endif /* WARP */
+#if !defined(HAVENOUTMP) && defined(KAI)
+ { "watchlog", dolog, 0, 0 },
+#endif /* !HAVENOUTMP && KAI */
+ { "where", dowhere, 1, INF },
+ { "which", dowhich, 1, INF },
+ { "while", dowhile, 1, INF }
+};
+int nbfunc = sizeof bfunc / sizeof *bfunc;
+
+struct srch srchn[] = {
+ { "@", TC_LET },
+ { "break", TC_BREAK },
+ { "breaksw", TC_BRKSW },
+ { "case", TC_CASE },
+ { "default", TC_DEFAULT },
+ { "else", TC_ELSE },
+ { "end", TC_END },
+ { "endif", TC_ENDIF },
+ { "endsw", TC_ENDSW },
+ { "exit", TC_EXIT },
+ { "foreach", TC_FOREACH },
+ { "goto", TC_GOTO },
+ { "if", TC_IF },
+ { "label", TC_LABEL },
+ { "set", TC_SET },
+ { "switch", TC_SWITCH },
+ { "while", TC_WHILE }
+};
+int nsrchn = sizeof srchn / sizeof *srchn;
+
+
+/*
+ * Note: For some machines, (hpux eg.)
+ * NSIG = number of signals + 1...
+ * so we define 33 or 65 (POSIX) signals for
+ * everybody
+ */
+
+/* We define NUMSIG to avoid changing NSIG or MAXSIG */
+#ifdef POSIX
+# define NUMSIG 65
+#else /* !POSIX */
+# define NUMSIG 33
+#endif /* POSIX */
+
+int nsig = NUMSIG - 1; /* This should be the number of real signals */
+ /* not counting signal 0 */
+struct mesg mesg[NUMSIG]; /* Arrays start at [0] so we initialize from */
+ /* 0 to 32 or 64, the max real signal number */
+
+void
+mesginit()
+{
+
+#ifdef NLS_CATALOGS
+ int i;
+
+ for (i = 0; i < NUMSIG; i++) {
+ xfree((ptr_t) mesg[i].pname);
+ mesg[i].pname = NULL;
+ }
+#endif /* NLS_CATALOGS */
+
+#if defined(SIGNULL) || defined(DECOSF1)
+# ifndef SIGNULL
+# define SIGNULL 0
+# endif /* !SIGNULL */
+ if (mesg[SIGNULL].pname == NULL) {
+ mesg[SIGNULL].iname = "NULL";
+ mesg[SIGNULL].pname = CSAVS(2, 1, "Null signal");
+ }
+#endif /* SIGNULL || DECOSF1 */
+
+#ifdef SIGHUP
+ if (mesg[SIGHUP].pname == NULL) {
+ mesg[SIGHUP].iname = "HUP";
+ mesg[SIGHUP].pname = CSAVS(2, 2, "Hangup");
+ }
+#endif /* SIGHUP */
+
+#ifdef SIGINT
+ if (mesg[SIGINT].pname == NULL) {
+ mesg[SIGINT].iname = "INT";
+ mesg[SIGINT].pname = CSAVS(2, 3, "Interrupt");
+ }
+#endif /* SIGINT */
+
+#ifdef SIGQUIT
+ if (mesg[SIGQUIT].pname == NULL) {
+ mesg[SIGQUIT].iname = "QUIT";
+ mesg[SIGQUIT].pname = CSAVS(2, 4, "Quit");
+ }
+#endif /* SIGQUIT */
+
+#ifdef SIGILL
+ if (mesg[SIGILL].pname == NULL) {
+ mesg[SIGILL].iname = "ILL";
+ mesg[SIGILL].pname = CSAVS(2, 5, "Illegal instruction");
+ }
+#endif /* SIGILL */
+
+#ifdef SIGTRAP
+ if (mesg[SIGTRAP].pname == NULL) {
+ mesg[SIGTRAP].iname = "TRAP";
+ mesg[SIGTRAP].pname = CSAVS(2, 6, "Trace/BPT trap");
+ }
+#endif /* SIGTRAP */
+
+#ifdef SIGABRT
+ if (mesg[SIGABRT].pname == NULL) {
+ mesg[SIGABRT].iname = "ABRT";
+ mesg[SIGABRT].pname = CSAVS(2, 7, "Abort");
+ }
+#endif /* SIGABRT */
+
+#ifdef SIGIOT
+ if (mesg[SIGIOT].pname == NULL) {
+ mesg[SIGIOT].iname = "IOT";
+ mesg[SIGIOT].pname = CSAVS(2, 8, "IOT trap");
+ }
+#endif /* SIGIOT */
+
+#ifdef SIGDANGER
+ /* aiws */
+ if (mesg[SIGDANGER].pname == NULL) {
+ mesg[SIGDANGER].iname = "DANGER";
+ mesg[SIGDANGER].pname = CSAVS(2, 9, "System Crash Imminent");
+ }
+#endif /* SIGDANGER */
+
+#ifdef SIGERR
+ /* _CRAY */
+ if (mesg[SIGERR].pname == NULL) {
+ mesg[SIGERR].iname = "ERR";
+ mesg[SIGERR].pname = CSAVS(2, 10, "Error exit");
+ }
+#endif /* SIGERR */
+
+#ifdef SIGEMT
+ if (mesg[SIGEMT].pname == NULL) {
+ mesg[SIGEMT].iname = "EMT";
+ mesg[SIGEMT].pname = CSAVS(2, 11, "EMT trap");
+ }
+#endif /* SIGEMT */
+
+#ifdef SIGFPE
+ if (mesg[SIGFPE].pname == NULL) {
+ mesg[SIGFPE].iname = "FPE";
+ mesg[SIGFPE].pname = CSAVS(2, 12, "Floating exception");
+ }
+#endif /* SIGFPE */
+
+#ifdef SIGKILL
+ if (mesg[SIGKILL].pname == NULL) {
+ mesg[SIGKILL].iname = "KILL";
+ mesg[SIGKILL].pname = CSAVS(2, 13, "Killed");
+ }
+#endif /* SIGKILL */
+
+#ifdef SIGUSR1
+ if (mesg[SIGUSR1].pname == NULL) {
+ mesg[SIGUSR1].iname = "USR1";
+ mesg[SIGUSR1].pname = CSAVS(2, 14, "User signal 1");
+ }
+#endif /* SIGUSR1 */
+
+#ifdef SIGUSR2
+ if (mesg[SIGUSR2].pname == NULL) {
+ mesg[SIGUSR2].iname = "USR2";
+ mesg[SIGUSR2].pname = CSAVS(2, 15, "User signal 2");
+ }
+#endif /* SIGUSR2 */
+
+#ifdef SIGSEGV
+ if (mesg[SIGSEGV].pname == NULL) {
+ mesg[SIGSEGV].iname = "SEGV";
+ mesg[SIGSEGV].pname = CSAVS(2, 16, "Segmentation fault");
+ }
+#endif /* SIGSEGV */
+
+#ifdef SIGBUS
+ if (mesg[SIGBUS].pname == NULL) {
+ mesg[SIGBUS].iname = "BUS";
+ mesg[SIGBUS].pname = CSAVS(2, 17, "Bus error");
+ }
+#endif /* SIGBUS */
+
+#ifdef SIGPRE
+ /* _CRAY || IBMAIX */
+ if (mesg[SIGPRE].pname == NULL) {
+ mesg[SIGPRE].iname = "PRE";
+ mesg[SIGPRE].pname = CSAVS(2, 18, "Program range error");
+ }
+#endif /* SIGPRE */
+
+#ifdef SIGORE
+ /* _CRAY */
+ if (mesg[SIGORE].pname == NULL) {
+ mesg[SIGORE].iname = "ORE";
+ mesg[SIGORE].pname = CSAVS(2, 19, "Operand range error");
+ }
+#endif /* SIGORE */
+
+#ifdef SIGSYS
+ if (mesg[SIGSYS].pname == NULL) {
+ mesg[SIGSYS].iname = "SYS";
+ mesg[SIGSYS].pname = CSAVS(2, 20, "Bad system call");
+ }
+#endif /* SIGSYS */
+
+#ifdef SIGPIPE
+ if (mesg[SIGPIPE].pname == NULL) {
+ mesg[SIGPIPE].iname = "PIPE";
+ mesg[SIGPIPE].pname = CSAVS(2, 21, "Broken pipe");
+ }
+#endif /* SIGPIPE */
+
+#ifdef SIGALRM
+ if (mesg[SIGALRM].pname == NULL) {
+ mesg[SIGALRM].iname = "ALRM";
+ mesg[SIGALRM].pname = CSAVS(2, 22, "Alarm clock");
+ }
+#endif /* SIGALRM */
+
+#ifdef SIGTERM
+ if (mesg[SIGTERM].pname == NULL) {
+ mesg[SIGTERM].iname = "TERM";
+ mesg[SIGTERM].pname = CSAVS(2, 23, "Terminated");
+ }
+#endif /* SIGTERM */
+
+/* SIGCLD vs SIGCHLD */
+#if !defined(SIGCHLD) || defined(SOLARIS2) || defined(apollo) || defined(__EMX__)
+ /* If we don't define SIGCHLD, or our OS prefers SIGCLD to SIGCHLD, */
+ /* check for SIGCLD */
+# ifdef SIGCLD
+ if (mesg[SIGCLD].pname == NULL) {
+ mesg[SIGCLD].iname = "CLD";
+# ifdef BSDJOBS
+ mesg[SIGCLD].pname = CSAVS(2, 24, "Child status change");
+# else /* !BSDJOBS */
+ mesg[SIGCLD].pname = CSAVS(2, 25, "Death of child");
+# endif /* BSDJOBS */
+ }
+# endif /* SIGCLD */
+#else /* !(!SIGCHLD || SOLARIS2 || apollo || __EMX__) */
+ /* We probably define SIGCHLD */
+# ifdef SIGCHLD
+ if (mesg[SIGCHLD].pname == NULL) {
+ mesg[SIGCHLD].iname = "CHLD";
+# ifdef BSDJOBS
+ mesg[SIGCHLD].pname = CSAVS(2, 27, "Child stopped or exited");
+# else /* !BSDJOBS */
+ mesg[SIGCHLD].pname = CSAVS(2, 28, "Child exited");
+# endif /* BSDJOBS */
+ }
+# endif /* SIGCHLD */
+#endif /* !SIGCHLD || SOLARIS2 || apollo || __EMX__ */
+
+#ifdef SIGAPOLLO
+ /* apollo */
+ if (mesg[SIGAPOLLO].pname == NULL) {
+ mesg[SIGAPOLLO].iname = "APOLLO";
+ mesg[SIGAPOLLO].pname = CSAVS(2, 26, "Apollo-specific fault");
+ }
+#endif /* SIGAPOLLO */
+
+#ifdef SIGPWR
+ if (mesg[SIGPWR].pname == NULL) {
+ mesg[SIGPWR].iname = "PWR";
+ mesg[SIGPWR].pname = CSAVS(2, 29, "Power failure");
+ }
+#endif /* SIGPWR */
+
+#ifdef SIGLOST
+ if (mesg[SIGLOST].pname == NULL) {
+ mesg[SIGLOST].iname = "LOST";
+ mesg[SIGLOST].pname = CSAVS(2, 30, "Resource Lost");
+ }
+#endif /* SIGLOST */
+
+#ifdef SIGBREAK
+ /* __EMX__ */
+ if (mesg[SIGBREAK].pname == NULL) {
+ mesg[SIGBREAK].iname = "BREAK";
+ mesg[SIGBREAK].pname = CSAVS(2, 31, "Break (Ctrl-Break)");
+ }
+#endif /* SIGBREAK */
+
+#ifdef SIGIO
+# if !defined(SIGPOLL) || SIGPOLL != SIGIO
+ if (mesg[SIGIO].pname == NULL) {
+ mesg[SIGIO].iname = "IO";
+# ifdef cray
+ mesg[SIGIO].pname = CSAVS(2, 32, "Input/output possible signal");
+# else /* !cray */
+ mesg[SIGIO].pname = CSAVS(2, 33, "Asynchronous I/O (select)");
+# endif /* cray */
+ }
+# endif /* !SIGPOLL || SIGPOLL != SIGIO */
+#endif /* SIGIO */
+
+#ifdef SIGURG
+ if (mesg[SIGURG].pname == NULL) {
+ mesg[SIGURG].iname = "URG";
+ mesg[SIGURG].pname = CSAVS(2, 34, "Urgent condition on I/O channel");
+ }
+#endif /* SIGURG */
+
+#ifdef SIGMT
+ /* cray */
+ if (mesg[SIGMT].pname == NULL) {
+ mesg[SIGMT].iname = "MT";
+ mesg[SIGMT].pname = CSAVS(2, 35, "Multitasking wake-up");
+ }
+#endif /* SIGMT */
+
+#ifdef SIGMTKILL
+ /* cray */
+ if (mesg[SIGMTKILL].pname == NULL) {
+ mesg[SIGMTKILL].iname = "MTKILL";
+ mesg[SIGMTKILL].pname = CSAVS(2, 36, "Multitasking kill");
+ }
+#endif /* SIGMTKILL */
+
+#ifdef SIGBUFIO
+ /* _CRAYCOM */
+ if (mesg[SIGBUFIO].pname == NULL) {
+ mesg[SIGBUFIO].iname = "BUFIO";
+ mesg[SIGBUFIO].pname = CSAVS(2, 37,
+ "Fortran asynchronous I/O completion");
+ }
+#endif /* SIGBUFIO */
+
+#ifdef SIGRECOVERY
+ /* _CRAYCOM */
+ if (mesg[SIGRECOVERY].pname == NULL) {
+ mesg[SIGRECOVERY].iname = "RECOVERY";
+ mesg[SIGRECOVERY].pname = CSAVS(2, 38, "Recovery");
+ }
+#endif /* SIGRECOVERY */
+
+#ifdef SIGUME
+ /* _CRAYCOM */
+ if (mesg[SIGUME].pname == NULL) {
+ mesg[SIGUME].iname = "UME";
+ mesg[SIGUME].pname = CSAVS(2, 39, "Uncorrectable memory error");
+ }
+#endif /* SIGUME */
+
+#ifdef SIGCPULIM
+ /* _CRAYCOM */
+ if (mesg[SIGCPULIM].pname == NULL) {
+ mesg[SIGCPULIM].iname = "CPULIM";
+ mesg[SIGCPULIM].pname = CSAVS(2, 40, "CPU time limit exceeded");
+ }
+#endif /* SIGCPULIM */
+
+#ifdef SIGSHUTDN
+ /* _CRAYCOM */
+ if (mesg[SIGSHUTDN].pname == NULL) {
+ mesg[SIGSHUTDN].iname = "SHUTDN";
+ mesg[SIGSHUTDN].pname = CSAVS(2, 41, "System shutdown imminent");
+ }
+#endif /* SIGSHUTDN */
+
+#ifdef SIGNOWAK
+ /* _CRAYCOM */
+ if (mesg[SIGNOWAK].pname == NULL) {
+ mesg[SIGNOWAK].iname = "NOWAK";
+ mesg[SIGNOWAK].pname = CSAVS(2, 42,
+ "Micro-tasking group-no wakeup flag set");
+ }
+#endif /* SIGNOWAK */
+
+#ifdef SIGTHERR
+ /* _CRAYCOM */
+ if (mesg[SIGTHERR].pname == NULL) {
+ mesg[SIGTHERR].iname = "THERR";
+ mesg[SIGTHERR].pname = CSAVS(2, 43,
+ "Thread error - (use cord -T for detailed info)");
+ }
+#endif /* SIGTHERR */
+
+#ifdef SIGRPE
+ /* cray */
+ if (mesg[SIGRPE].pname == NULL) {
+ mesg[SIGRPE].pname = CSAVS(2, 44, "CRAY Y-MP register parity error");
+ mesg[SIGRPE].iname = "RPE";
+ }
+#endif /* SIGRPE */
+
+#ifdef SIGINFO
+ if (mesg[SIGINFO].pname == NULL) {
+ mesg[SIGINFO].iname = "INFO";
+ mesg[SIGINFO].pname = CSAVS(2, 45, "Information request");
+ }
+#endif /* SIGINFO */
+
+#ifdef SIGSTOP
+ if (mesg[SIGSTOP].pname == NULL) {
+ mesg[SIGSTOP].iname = "STOP";
+# ifdef SUSPENDED
+ mesg[SIGSTOP].pname = CSAVS(2, 46, "Suspended (signal)");
+# else /* !SUSPENDED */
+ mesg[SIGSTOP].pname = CSAVS(2, 47, "Stopped (signal)");
+# endif /* SUSPENDED */
+ }
+#endif /* SIGSTOP */
+
+#ifdef SIGTSTP
+ if (mesg[SIGTSTP].pname == NULL) {
+ mesg[SIGTSTP].iname = "TSTP";
+# ifdef SUSPENDED
+ mesg[SIGTSTP].pname = CSAVS(2, 48, "Suspended");
+# else /* !SUSPENDED */
+ mesg[SIGTSTP].pname = CSAVS(2, 49, "Stopped");
+# endif /* SUSPENDED */
+ }
+#endif /* SIGTSTP */
+
+#ifdef SIGCONT
+ if (mesg[SIGCONT].pname == NULL) {
+ mesg[SIGCONT].iname = "CONT";
+ mesg[SIGCONT].pname = CSAVS(2, 50, "Continued");
+ }
+#endif /* SIGCONT */
+
+#ifdef SIGTTIN
+ if (mesg[SIGTTIN].pname == NULL) {
+ mesg[SIGTTIN].iname = "TTIN";
+# ifdef SUSPENDED
+ mesg[SIGTTIN].pname = CSAVS(2, 51, "Suspended (tty input)");
+# else /* !SUSPENDED */
+ mesg[SIGTTIN].pname = CSAVS(2, 52, "Stopped (tty input)");
+# endif /* SUSPENDED */
+ }
+#endif /* SIGTTIN */
+
+#ifdef SIGTTOU
+ if (mesg[SIGTTOU].pname == NULL) {
+ mesg[SIGTTOU].iname = "TTOU";
+# ifdef SUSPENDED
+ mesg[SIGTTOU].pname = CSAVS(2, 53, "Suspended (tty output)");
+# else /* SUSPENDED */
+ mesg[SIGTTOU].pname = CSAVS(2, 54, "Stopped (tty output)");
+# endif /* SUSPENDED */
+ }
+#endif /* SIGTTOU */
+
+#ifdef SIGWIND
+ /* UNIXPC */
+ if (mesg[SIGWIND].pname == NULL) {
+ mesg[SIGWIND].iname = "WIND";
+ mesg[SIGWIND].pname = CSAVS(2, 55, "Window status changed");
+ }
+#endif /* SIGWIND */
+
+#ifdef SIGWINDOW
+ if (mesg[SIGWINDOW].pname == NULL) {
+ mesg[SIGWINDOW].iname = "WINDOW";
+ mesg[SIGWINDOW].pname = CSAVS(2, 56, "Window size changed");
+ }
+#endif /* SIGWINDOW */
+
+#ifdef SIGWINCH
+ if (mesg[SIGWINCH].pname == NULL) {
+ mesg[SIGWINCH].iname = "WINCH";
+ mesg[SIGWINCH].pname = CSAVS(2, 56, "Window size changed");
+ }
+#endif /* SIGWINCH */
+
+#ifdef SIGPHONE
+ /* UNIXPC */
+ if (mesg[SIGPHONE].pname == NULL) {
+ mesg[SIGPHONE].iname = "PHONE";
+ mesg[SIGPHONE].pname = CSAVS(2, 57, "Phone status changed");
+ }
+# endif /* SIGPHONE */
+
+#ifdef SIGXCPU
+ if (mesg[SIGXCPU].pname == NULL) {
+ mesg[SIGXCPU].iname = "XCPU";
+ mesg[SIGXCPU].pname = CSAVS(2, 58, "Cputime limit exceeded");
+ }
+#endif /* SIGXCPU */
+
+#ifdef SIGXFSZ
+ if (mesg[SIGXFSZ].pname == NULL) {
+ mesg[SIGXFSZ].iname = "XFSZ";
+ mesg[SIGXFSZ].pname = CSAVS(2, 59, "Filesize limit exceeded");
+ }
+#endif /* SIGXFSZ */
+
+#ifdef SIGVTALRM
+ if (mesg[SIGVTALRM].pname == NULL) {
+ mesg[SIGVTALRM].iname = "VTALRM";
+ mesg[SIGVTALRM].pname = CSAVS(2, 60, "Virtual time alarm");
+ }
+#endif /* SIGVTALRM */
+
+#ifdef SIGPROF
+ if (mesg[SIGPROF].pname == NULL) {
+ mesg[SIGPROF].iname = "PROF";
+ mesg[SIGPROF].pname = CSAVS(2, 61, "Profiling time alarm");
+ }
+#endif /* SIGPROF */
+
+#ifdef SIGDIL
+ /* hpux */
+ if (mesg[SIGDIL].pname == NULL) {
+ mesg[SIGDIL].iname = "DIL";
+ mesg[SIGDIL].pname = CSAVS(2, 62, "DIL signal");
+ }
+#endif /* SIGDIL */
+
+#ifdef SIGPOLL
+ if (mesg[SIGPOLL].pname == NULL) {
+ mesg[SIGPOLL].iname = "POLL";
+ mesg[SIGPOLL].pname = CSAVS(2, 63, "Pollable event occured");
+ }
+#endif /* SIGPOLL */
+
+#ifdef SIGWAITING
+ /* solaris */
+ if (mesg[SIGWAITING].pname == NULL) {
+ mesg[SIGWAITING].iname = "WAITING";
+ mesg[SIGWAITING].pname = CSAVS(2, 64, "Process's lwps are blocked");
+ }
+#endif /* SIGWAITING */
+
+#ifdef SIGLWP
+ /* solaris */
+ if (mesg[SIGLWP].pname == NULL) {
+ mesg[SIGLWP].iname = "LWP";
+ mesg[SIGLWP].pname = CSAVS(2, 65, "Special LWP signal");
+ }
+#endif /* SIGLWP */
+
+#ifdef SIGFREEZE
+ /* solaris */
+ if (mesg[SIGFREEZE].pname == NULL) {
+ mesg[SIGFREEZE].iname = "FREEZE";
+ mesg[SIGFREEZE].pname = CSAVS(2, 66, "Special CPR Signal");
+ }
+#endif /* SIGFREEZE */
+
+#ifdef SIGTHAW
+ /* solaris */
+ if (mesg[SIGTHAW].pname == NULL) {
+ mesg[SIGTHAW].iname = "THAW";
+ mesg[SIGTHAW].pname = CSAVS(2, 67, "Special CPR Signal");
+ }
+#endif /* SIGTHAW */
+
+#ifdef SIGCANCEL
+ /* solaris */
+ if (mesg[SIGCANCEL].pname == NULL) {
+ mesg[SIGCANCEL].iname = "CANCEL";
+ mesg[SIGCANCEL].pname = CSAVS(2, 109,
+ "Thread cancellation signal used by libthread");
+ }
+#endif /* SIGCANCEL */
+
+/*
+ * Careful, some OS's (HP/UX 10.0) define these as -1
+ */
+#ifdef SIGRTMIN
+ /*
+ * Cannot do this at compile time; Solaris2 uses _sysconf for these
+ */
+ if (SIGRTMIN > 0 && SIGRTMIN < NUMSIG) {
+ if (mesg[SIGRTMIN].pname == NULL) {
+ mesg[SIGRTMIN].iname = "RTMIN";
+ mesg[SIGRTMIN].pname = CSAVS(2, 68, "First Realtime Signal");
+ }
+
+ if (mesg[SIGRTMIN+1].pname == NULL) {
+ mesg[SIGRTMIN+1].iname = "RTMIN+1";
+ mesg[SIGRTMIN+1].pname = CSAVS(2, 69, "Second Realtime Signal");
+ }
+
+ if (mesg[SIGRTMIN+2].pname == NULL) {
+ mesg[SIGRTMIN+2].iname = "RTMIN+2";
+ mesg[SIGRTMIN+2].pname = CSAVS(2, 70, "Third Realtime Signal");
+ }
+
+ if (mesg[SIGRTMIN+3].pname == NULL) {
+ mesg[SIGRTMIN+3].iname = "RTMIN+3";
+ mesg[SIGRTMIN+3].pname = CSAVS(2, 71, "Fourth Realtime Signal");
+ }
+ }
+#endif /* SIGRTMIN */
+
+#ifdef SIGRTMAX
+ /*
+ * Cannot do this at compile time; Solaris2 uses _sysconf for these
+ */
+ if (SIGRTMAX > 0 && SIGRTMAX < NUMSIG) {
+ if (mesg[SIGRTMAX-3].pname == NULL) {
+ mesg[SIGRTMAX-3].iname = "RTMAX-3";
+ mesg[SIGRTMAX-3].pname = CSAVS(2, 72,
+ "Fourth Last Realtime Signal");
+ }
+
+ if (mesg[SIGRTMAX-2].pname == NULL) {
+ mesg[SIGRTMAX-2].iname = "RTMAX-2";
+ mesg[SIGRTMAX-2].pname = CSAVS(2, 73,
+ "Third Last Realtime Signal");
+ }
+
+ if (mesg[SIGRTMAX-1].pname == NULL) {
+ mesg[SIGRTMAX-1].iname = "RTMAX-1";
+ mesg[SIGRTMAX-1].pname = CSAVS(2, 74,
+ "Second Last Realtime Signal");
+ }
+
+ if (mesg[SIGRTMAX].pname == NULL) {
+ mesg[SIGRTMAX].iname = "RTMAX";
+ mesg[SIGRTMAX].pname = CSAVS(2, 75,
+ "Last Realtime Signal");
+ }
+ }
+#endif /* SIGRTMAX */
+
+
+#ifdef SIGAIO
+ /* aiws */
+ if (mesg[SIGAIO].pname == NULL) {
+ mesg[SIGAIO].iname = "AIO";
+ mesg[SIGAIO].pname = CSAVS(2, 76, "LAN Asyncronous I/O");
+ }
+#endif /* SIGAIO */
+
+#ifdef SIGPTY
+ /* aiws */
+ if (mesg[SIGPTY].pname == NULL) {
+ mesg[SIGPTY].iname = "PTY";
+ mesg[SIGPTY].pname = CSAVS(2, 77, "PTY read/write availability");
+ }
+#endif /* SIGPTY */
+
+#ifdef SIGIOINT
+ /* aiws */
+ if (mesg[SIGIOINT].pname == NULL) {
+ mesg[SIGIOINT].iname = "IOINT";
+ mesg[SIGIOINT].pname = CSAVS(2, 78, "I/O intervention required");
+ }
+#endif /* SIGIOINT */
+
+#ifdef SIGGRANT
+ /* aiws */
+ if (mesg[SIGGRANT].pname == NULL) {
+ mesg[SIGGRANT].iname = "GRANT";
+ mesg[SIGGRANT].pname = CSAVS(2, 79, "HFT monitor mode granted");
+ }
+#endif /* SIGGRANT */
+
+#ifdef SIGRETRACT
+ /* aiws */
+ if (mesg[SIGRETRACT].pname == NULL) {
+ mesg[SIGRETRACT].iname = "RETRACT";
+ mesg[SIGRETRACT].pname = CSAVS(2, 80,
+ "HFT monitor mode should be relinguished");
+ }
+#endif /* SIGRETRACT */
+
+#ifdef SIGSOUND
+ /* aiws */
+ if (mesg[SIGSOUND].pname == NULL) {
+ mesg[SIGSOUND].iname = "SOUND";
+ mesg[SIGSOUND].pname = CSAVS(2, 81, "HFT sound control has completed");
+ }
+#endif /* SIGSOUND */
+
+#ifdef SIGSMSG
+ /* aiws */
+ if (mesg[SIGSMSG].pname == NULL) {
+ mesg[SIGSMSG].iname = "SMSG";
+ mesg[SIGSMSG].pname = CSAVS(2, 82, "Data in HFT ring buffer");
+ }
+#endif /* SIGMSG */
+
+#ifdef SIGMIGRATE
+ /* IBMAIX */
+ if (mesg[SIGMIGRATE].pname == NULL) {
+ mesg[SIGMIGRATE].iname = "MIGRATE";
+ mesg[SIGMIGRATE].pname = CSAVS(2, 83, "Migrate process");
+ }
+#endif /* SIGMIGRATE */
+
+#ifdef SIGSAK
+ /* IBMAIX */
+ if (mesg[SIGSAK].pname == NULL) {
+ mesg[SIGSAK].iname = "SAK";
+ mesg[SIGSAK].pname = CSAVS(2, 84, "Secure attention key");
+ }
+#endif /* SIGSAK */
+
+#ifdef SIGRESCHED
+ /* CX/UX */
+ if (mesg[SIGRESCHED].pname == NULL) {
+ mesg[SIGRESCHED].iname = "RESCHED";
+ mesg[SIGRESCHED].pname = CSAVS(2, 85, "Reschedule");
+ }
+#endif /* SIGRESCHED */
+
+#ifdef SIGDEBUG
+ /* VMS_POSIX */
+ if (mesg[SIGDEBUG].pname == NULL) {
+ mesg[SIGDEBUG].iname = "DEBUG";
+ mesg[SIGDEBUG].pname = CSAVS(2, 86, "Signaling SS$_DEBUG");
+ }
+#endif /* SIGDEBUG */
+
+#ifdef SIGPRIO
+ /* Lynx */
+ if (mesg[SIGPRIO].pname == NULL) {
+ mesg[SIGPRIO].iname = "PRIO";
+ mesg[SIGPRIO].pname = CSAVS(2, 87, "Priority changed");
+ }
+#endif /* SIGPRIO */
+
+#ifdef SIGDLK
+ /* cray */
+ if (mesg[SIGDLK].pname == NULL) {
+ mesg[SIGDLK].iname = "DLK";
+ mesg[SIGDLK].pname = CSAVS(2, 88, "True deadlock detected");
+ }
+#endif /* SIGDLK */
+
+#ifdef SIGTINT
+ /* masscomp */
+ if (mesg[SIGTINT].pname == NULL) {
+ mesg[SIGTINT].iname = "TINT";
+ mesg[SIGTINT].pname = CSAVS(2, 89, "New input character");
+ }
+#endif /* SIGTINT */
+
+#ifdef SIGSTKFLT
+ if (mesg[SIGSTKFLT].pname == NULL) {
+ mesg[SIGSTKFLT].iname = "STKFLT";
+ mesg[SIGSTKFLT].pname = CSAVS(2, 90, "Stack limit exceeded");
+ }
+#endif /* SIGSTKFLT */
+
+#ifdef SIGUNUSED
+ if (mesg[SIGUNUSED].pname == NULL) {
+ mesg[SIGUNUSED].iname = "UNUSED";
+ mesg[SIGUNUSED].pname = CSAVS(2, 91, "Unused signal");
+ }
+#endif /* SIGUNUSED */
+
+#ifdef SIGOVLY
+ /* SX-4 */
+ if (mesg[SIGOVLY].pname == NULL) {
+ mesg[SIGOVLY].iname = "OVLY";
+ mesg[SIGOVLY].pname = CSAVS(2, 92, "LM overlay");
+ }
+#endif /* SIGOVLY */
+
+#ifdef SIGFRZ
+ /* SX-4 */
+ if (mesg[SIGFRZ].pname == NULL) {
+ mesg[SIGFRZ].iname = "FRZ";
+ mesg[SIGFRZ].pname = CSAVS(2, 93, "system freeze");
+ }
+#endif /* SIGFRZ */
+
+#ifdef SIGDFRZ
+ /* SX-4 */
+ if (mesg[SIGDFRZ].pname == NULL) {
+ mesg[SIGDFRZ].iname = "DFRZ";
+ mesg[SIGDFRZ].pname = CSAVS(2, 94, "system defreeze");
+ }
+#endif /* SIGDFRZ */
+
+#ifdef SIGDEAD
+ /* SX-4 */
+ if (mesg[SIGDEAD].pname == NULL) {
+ mesg[SIGDEAD].iname = "DEAD";
+ mesg[SIGDEAD].pname = CSAVS(2, 95, "dead lock");
+ }
+#endif /* SIGDEAD */
+
+#ifdef SIGXMEM
+ /* SX-4 */
+ if (mesg[SIGXMEM].pname == NULL) {
+ mesg[SIGXMEM].iname = "XMEM";
+ mesg[SIGXMEM].pname = CSAVS(2, 96, "exceeded memory size limit");
+ }
+#endif /* SIGXMEM */
+
+#ifdef SIGXDSZ
+ /* SX-4 */
+ if (mesg[SIGXDSZ].pname == NULL) {
+ mesg[SIGXDSZ].iname = "XDSZ";
+ mesg[SIGXDSZ].pname = CSAVS(2, 97, "exceeded data size limit");
+ }
+#endif /* SIGXDSZ */
+
+#ifdef SIGMEM32
+ /* SX-4 */
+ if (mesg[SIGMEM32].pname == NULL) {
+ mesg[SIGMEM32].iname = "MEM32";
+ mesg[SIGMEM32].pname = CSAVS(2, 98, "exceeded memory size limit of 32KB");
+ }
+#endif /* SIGMEM32 */
+
+#ifdef SIGNMEM
+ /* SX-4 */
+ if (mesg[SIGNMEM].pname == NULL) {
+ mesg[SIGNMEM].iname = "NMEM";
+ mesg[SIGNMEM].pname = CSAVS(2, 99, "exce error for no memory");
+ }
+#endif /* SIGNMEM */
+
+#ifdef SIGCHKP
+ /* SX-4 */
+ if (mesg[SIGCHKP].pname == NULL) {
+ mesg[SIGCHKP].iname = "CHKP";
+ mesg[SIGCHKP].pname = CSAVS(2, 100, "check point start");
+ }
+#endif /* SIGCHKP */
+
+#ifdef SIGKCHKP
+#if 0
+ /* SX-4 */
+ if (mesg[SIGKCHKP].pname == NULL) {
+ mesg[SIGKCHKP].iname = "KCHKP";
+ mesg[SIGKCHKP].pname = CSAVS(2, 101, "check point start of kernel");
+ }
+#endif
+#endif /* SIGKCHKP */
+
+#ifdef SIGRSTA
+ /* SX-4 */
+ if (mesg[SIGRSTA].pname == NULL) {
+ mesg[SIGRSTA].iname = "RSTA";
+ mesg[SIGRSTA].pname = CSAVS(2, 102, "restart start");
+ }
+#endif /* SIGRSTA */
+
+#ifdef SIGKRSTA
+#if 0
+ /* SX-4 */
+ if (mesg[SIGKRSTA].pname == NULL) {
+ mesg[SIGKRSTA].iname = "KRSTA";
+ mesg[SIGKRSTA].pname = CSAVS(2, 103, "restart of kernel");
+ }
+#endif
+#endif /* SIGKRSTA */
+
+#ifdef SIGXXMU
+ /* SX-4 */
+ if (mesg[SIGXXMU].pname == NULL) {
+ mesg[SIGXXMU].iname = "XXMU";
+ mesg[SIGXXMU].pname = CSAVS(2, 104, "exeeded XMU size limit");
+ }
+#endif /* SIGXXMU */
+
+#ifdef SIGXRLG0
+ /* SX-4 */
+ if (mesg[SIGXRLG0].pname == NULL) {
+ mesg[SIGXRLG0].iname = "XRLG0";
+ mesg[SIGXRLG0].pname = CSAVS(2, 105, "exeeded RLG0 limit");
+ }
+#endif /* SIGXRLG0 */
+
+#ifdef SIGXRLG1
+ /* SX-4 */
+ if (mesg[SIGXRLG1].pname == NULL) {
+ mesg[SIGXRLG1].iname = "XRLG1";
+ mesg[SIGXRLG1].pname = CSAVS(2, 106, "exeeded RLG1 limit");
+ }
+#endif /* SIGXRLG1 */
+
+#ifdef SIGXRLG2
+ /* SX-4 */
+ if (mesg[SIGXRLG2].pname == NULL) {
+ mesg[SIGXRLG2].iname = "XRLG2";
+ mesg[SIGXRLG2].pname = CSAVS(2, 107, "exeeded RLG2 limit");
+ }
+#endif /* SIGXRLG2 */
+
+#ifdef SIGXRLG3
+ /* SX-4 */
+ if (mesg[SIGXRLG3].pname == NULL) {
+ mesg[SIGXRLG3].iname = "XRLG3";
+ mesg[SIGXRLG3].pname = CSAVS(2, 108, "exeeded RLG3 limit");
+ }
+#endif /* SIGXRLG3 */
+}
diff --git a/contrib/tcsh/sh.lex.c b/contrib/tcsh/sh.lex.c
new file mode 100644
index 0000000..caf202c
--- /dev/null
+++ b/contrib/tcsh/sh.lex.c
@@ -0,0 +1,1891 @@
+/* $Header: /src/pub/tcsh/sh.lex.c,v 3.49 1998/04/08 13:58:54 christos Exp $ */
+/*
+ * sh.lex.c: Lexical analysis into tokens
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.lex.c,v 3.49 1998/04/08 13:58:54 christos Exp $")
+
+#include "ed.h"
+/* #define DEBUG_INP */
+/* #define DEBUG_SEEK */
+
+/*
+ * C shell
+ */
+
+/*
+ * These lexical routines read input and form lists of words.
+ * There is some involved processing here, because of the complications
+ * of input buffering, and especially because of history substitution.
+ */
+static Char *word __P((void));
+static int getC1 __P((int));
+static void getdol __P((void));
+static void getexcl __P((int));
+static struct Hist *findev __P((Char *, bool));
+static void setexclp __P((Char *));
+static int bgetc __P((void));
+static void balloc __P((int));
+static void bfree __P((void));
+static struct wordent *gethent __P((int));
+static int matchs __P((Char *, Char *));
+static int getsel __P((int *, int *, int));
+static struct wordent *getsub __P((struct wordent *));
+static Char *subword __P((Char *, int, bool *));
+static struct wordent *dosub __P((int, struct wordent *, bool));
+
+/*
+ * Peekc is a peek character for getC, peekread for readc.
+ * There is a subtlety here in many places... history routines
+ * will read ahead and then insert stuff into the input stream.
+ * If they push back a character then they must push it behind
+ * the text substituted by the history substitution. On the other
+ * hand in several places we need 2 peek characters. To make this
+ * all work, the history routines read with getC, and make use both
+ * of ungetC and unreadc. The key observation is that the state
+ * of getC at the call of a history reference is such that calls
+ * to getC from the history routines will always yield calls of
+ * readc, unless this peeking is involved. That is to say that during
+ * getexcl the variables lap, exclp, and exclnxt are all zero.
+ *
+ * Getdol invokes history substitution, hence the extra peek, peekd,
+ * which it can ungetD to be before history substitutions.
+ */
+static Char peekc = 0, peekd = 0;
+static Char peekread = 0;
+
+/* (Tail of) current word from ! subst */
+static Char *exclp = NULL;
+
+/* The rest of the ! subst words */
+static struct wordent *exclnxt = NULL;
+
+/* Count of remaining words in ! subst */
+static int exclc = 0;
+
+/* "Globp" for alias resubstitution */
+int aret = F_SEEK;
+
+/*
+ * Labuf implements a general buffer for lookahead during lexical operations.
+ * Text which is to be placed in the input stream can be stuck here.
+ * We stick parsed ahead $ constructs during initial input,
+ * process id's from `$$', and modified variable values (from qualifiers
+ * during expansion in sh.dol.c) here.
+ */
+static Char labuf[BUFSIZE];
+
+/*
+ * Lex returns to its caller not only a wordlist (as a "var" parameter)
+ * but also whether a history substitution occurred. This is used in
+ * the main (process) routine to determine whether to echo, and also
+ * when called by the alias routine to determine whether to keep the
+ * argument list.
+ */
+static bool hadhist = 0;
+
+/*
+ * Avoid alias expansion recursion via \!#
+ */
+int hleft;
+
+Char histline[BUFSIZE + 2]; /* last line input */
+
+ /* The +2 is to fool hp's optimizer */
+bool histvalid = 0; /* is histline valid */
+static Char *histlinep = NULL; /* current pointer into histline */
+
+static Char getCtmp;
+
+#define getC(f) (((getCtmp = peekc) != '\0') ? (peekc = 0, getCtmp) : getC1(f))
+#define ungetC(c) peekc = (Char) c
+#define ungetD(c) peekd = (Char) c
+
+/* Use Htime to store timestamps picked up from history file for enthist()
+ * if reading saved history (sg)
+ */
+time_t Htime = (time_t)0;
+static time_t a2time_t __P((Char *));
+
+/*
+ * for history event processing
+ * in the command 'echo !?foo?:1 !$' we want the !$ to expand from the line
+ * 'foo' was found instead of the last command
+ */
+static int uselastevent = 1;
+
+int
+lex(hp)
+ struct wordent *hp;
+{
+ struct wordent *wdp;
+ int c;
+
+
+ uselastevent = 1;
+ histvalid = 0;
+ histlinep = histline;
+ *histlinep = '\0';
+
+ btell(&lineloc);
+ hp->next = hp->prev = hp;
+ hp->word = STRNULL;
+ hadhist = 0;
+ do
+ c = readc(0);
+ while (c == ' ' || c == '\t');
+ if (c == HISTSUB && intty)
+ /* ^lef^rit from tty is short !:s^lef^rit */
+ getexcl(c);
+ else
+ unreadc(c);
+ wdp = hp;
+ /*
+ * The following loop is written so that the links needed by freelex will
+ * be ready and rarin to go even if it is interrupted.
+ */
+ do {
+ struct wordent *new;
+
+ new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));
+ new->word = STRNULL;
+ new->prev = wdp;
+ new->next = hp;
+ wdp->next = new;
+ hp->prev = new;
+ wdp = new;
+ wdp->word = word();
+ } while (wdp->word[0] != '\n');
+ if (histlinep < histline + BUFSIZE) {
+ *histlinep = '\0';
+ if (histlinep > histline && histlinep[-1] == '\n')
+ histlinep[-1] = '\0';
+ histvalid = 1;
+ }
+ else {
+ histline[BUFSIZE - 1] = '\0';
+ }
+
+ return (hadhist);
+}
+
+static time_t
+a2time_t(word)
+ Char *word;
+{
+ /* Attempt to distinguish timestamps from other possible entries.
+ * Format: "+NNNNNNNNNN" (10 digits, left padded with ascii '0') */
+
+ time_t ret;
+ Char *s;
+ int ct;
+
+ if (!word || *(s = word) != '+')
+ return (time_t)0;
+
+ for (++s, ret = 0, ct = 0; *s; ++s, ++ct)
+ {
+ if (!isdigit((unsigned char)*s))
+ return (time_t)0;
+ ret = ret * 10 + (time_t)((unsigned char)*s - '0');
+ }
+
+ if (ct != 10)
+ return (time_t)0;
+
+ return ret;
+}
+
+void
+prlex(sp0)
+ struct wordent *sp0;
+{
+ struct wordent *sp = sp0->next;
+
+ for (;;) {
+ xprintf("%S", sp->word);
+ sp = sp->next;
+ if (sp == sp0)
+ break;
+ if (sp->word[0] != '\n')
+ xputchar(' ');
+ }
+}
+
+void
+copylex(hp, fp)
+ struct wordent *hp;
+ struct wordent *fp;
+{
+ struct wordent *wdp;
+
+ wdp = hp;
+ fp = fp->next;
+ do {
+ struct wordent *new;
+
+ new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));
+ new->word = STRNULL;
+ new->prev = wdp;
+ new->next = hp;
+ wdp->next = new;
+ hp->prev = new;
+ wdp = new;
+ wdp->word = Strsave(fp->word);
+ fp = fp->next;
+ } while (wdp->word[0] != '\n');
+}
+
+void
+freelex(vp)
+ struct wordent *vp;
+{
+ struct wordent *fp;
+
+ while (vp->next != vp) {
+ fp = vp->next;
+ vp->next = fp->next;
+ if (fp->word != STRNULL)
+ xfree((ptr_t) fp->word);
+ xfree((ptr_t) fp);
+ }
+ vp->prev = vp;
+}
+
+static Char *
+word()
+{
+ Char c, c1;
+ Char *wp;
+ Char wbuf[BUFSIZE];
+ Char hbuf[12];
+ int h;
+ bool dolflg;
+ int i;
+
+ wp = wbuf;
+ i = BUFSIZE - 4;
+loop:
+ while ((c = getC(DOALL)) == ' ' || c == '\t')
+ continue;
+ if (cmap(c, _META | _ESC))
+ switch (c) {
+ case '&':
+ case '|':
+ case '<':
+ case '>':
+ *wp++ = c;
+ c1 = getC(DOALL);
+ if (c1 == c)
+ *wp++ = c1;
+ else
+ ungetC(c1);
+ goto ret;
+
+ case '#':
+ if (intty)
+ break;
+ c = 0;
+ h = 0;
+ do {
+ c1 = c;
+ c = getC(0);
+ if (h < 12)
+ hbuf[h++] = c;
+ } while (c != '\n');
+ hbuf[11] = '\0';
+ Htime = a2time_t(hbuf);
+ if (c1 == '\\')
+ goto loop;
+ /*FALLTHROUGH*/
+
+ case ';':
+ case '(':
+ case ')':
+ case '\n':
+ *wp++ = c;
+ goto ret;
+
+ case '\\':
+ c = getC(0);
+ if (c == '\n') {
+ if (onelflg == 1)
+ onelflg = 2;
+ goto loop;
+ }
+ if (c != HIST)
+ *wp++ = '\\', --i;
+ c |= QUOTE;
+ default:
+ break;
+ }
+ c1 = 0;
+ dolflg = DOALL;
+ for (;;) {
+ if (c1) {
+ if (c == c1) {
+ c1 = 0;
+ dolflg = DOALL;
+ }
+ else if (c == '\\') {
+ c = getC(0);
+/*
+ * PWP: this is dumb, but how all of the other shells work. If \ quotes
+ * a character OUTSIDE of a set of ''s, why shouldn't it quote EVERY
+ * following character INSIDE a set of ''s.
+ *
+ * Actually, all I really want to be able to say is 'foo\'bar' --> foo'bar
+ */
+ if (c == HIST)
+ c |= QUOTE;
+ else {
+ if (bslash_quote &&
+ ((c == '\'') || (c == '"') ||
+ (c == '\\'))) {
+ c |= QUOTE;
+ }
+ else {
+ if (c == '\n')
+ /*
+ * if (c1 == '`') c = ' '; else
+ */
+ c |= QUOTE;
+ ungetC(c);
+ c = '\\';
+ }
+ }
+ }
+ else if (c == '\n') {
+ seterror(ERR_UNMATCHED, c1);
+ ungetC(c);
+ break;
+ }
+ }
+ else if (cmap(c, _META | _QF | _QB | _ESC)) {
+ if (c == '\\') {
+ c = getC(0);
+ if (c == '\n') {
+ if (onelflg == 1)
+ onelflg = 2;
+ break;
+ }
+ if (c != HIST)
+ *wp++ = '\\', --i;
+ c |= QUOTE;
+ }
+ else if (cmap(c, _QF | _QB)) { /* '"` */
+ c1 = c;
+ dolflg = c == '"' ? DOALL : DOEXCL;
+ }
+ else if (c != '#' || !intty) {
+ ungetC(c);
+ break;
+ }
+ }
+ if (--i > 0) {
+ *wp++ = c;
+ c = getC(dolflg);
+ }
+ else {
+ seterror(ERR_WTOOLONG);
+ wp = &wbuf[1];
+ break;
+ }
+ }
+ret:
+ *wp = 0;
+ return (Strsave(wbuf));
+}
+
+static int
+getC1(flag)
+ int flag;
+{
+ Char c;
+
+ for (;;) {
+ if ((c = peekc) != 0) {
+ peekc = 0;
+ return (c);
+ }
+ if (lap) {
+ if ((c = *lap++) == 0)
+ lap = 0;
+ else {
+ if (cmap(c, _META | _QF | _QB))
+ c |= QUOTE;
+ return (c);
+ }
+ }
+ if ((c = peekd) != 0) {
+ peekd = 0;
+ return (c);
+ }
+ if (exclp) {
+ if ((c = *exclp++) != 0)
+ return (c);
+ if (exclnxt && --exclc >= 0) {
+ exclnxt = exclnxt->next;
+ setexclp(exclnxt->word);
+ return (' ');
+ }
+ exclp = 0;
+ exclnxt = 0;
+ /* this will throw away the dummy history entries */
+ savehist(NULL, 0);
+
+ }
+ if (exclnxt) {
+ exclnxt = exclnxt->next;
+ if (--exclc < 0)
+ exclnxt = 0;
+ else
+ setexclp(exclnxt->word);
+ continue;
+ }
+ c = readc(0);
+ if (c == '$' && (flag & DODOL)) {
+ getdol();
+ continue;
+ }
+ if (c == HIST && (flag & DOEXCL)) {
+ getexcl(0);
+ continue;
+ }
+ break;
+ }
+ return (c);
+}
+
+static void
+getdol()
+{
+ Char *np, *ep;
+ Char name[4 * MAXVARLEN + 1];
+ int c;
+ int sc;
+ bool special = 0, toolong;
+
+ np = name, *np++ = '$';
+ c = sc = getC(DOEXCL);
+ if (any("\t \n", c)) {
+ ungetD(c);
+ ungetC('$' | QUOTE);
+ return;
+ }
+ if (c == '{')
+ *np++ = (Char) c, c = getC(DOEXCL);
+ if (c == '#' || c == '?' || c == '%')
+ special++, *np++ = (Char) c, c = getC(DOEXCL);
+ *np++ = (Char) c;
+ switch (c) {
+
+ case '<':
+ case '$':
+ case '!':
+ if (special)
+ seterror(ERR_SPDOLLT);
+ *np = 0;
+ addla(name);
+ return;
+
+ case '\n':
+ ungetD(c);
+ np--;
+ if (!special)
+ seterror(ERR_NEWLINE);
+ *np = 0;
+ addla(name);
+ return;
+
+ case '*':
+ if (special)
+ seterror(ERR_SPSTAR);
+ *np = 0;
+ addla(name);
+ return;
+
+ default:
+ toolong = 0;
+ if (Isdigit(c)) {
+#ifdef notdef
+ /* let $?0 pass for now */
+ if (special) {
+ seterror(ERR_DIGIT);
+ *np = 0;
+ addla(name);
+ return;
+ }
+#endif
+ /* we know that np < &name[4] */
+ ep = &np[MAXVARLEN];
+ while ((c = getC(DOEXCL)) != 0) {
+ if (!Isdigit(c))
+ break;
+ if (np < ep)
+ *np++ = (Char) c;
+ else
+ toolong = 1;
+ }
+ }
+ else if (letter(c)) {
+ /* we know that np < &name[4] */
+ ep = &np[MAXVARLEN];
+ toolong = 0;
+ while ((c = getC(DOEXCL)) != 0) {
+ /* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */
+ if (!letter(c) && !Isdigit(c))
+ break;
+ if (np < ep)
+ *np++ = (Char) c;
+ else
+ toolong = 1;
+ }
+ }
+ else {
+ if (!special)
+ seterror(ERR_VARILL);
+ else {
+ ungetD(c);
+ --np;
+ }
+ *np = 0;
+ addla(name);
+ return;
+ }
+ if (toolong) {
+ seterror(ERR_VARTOOLONG);
+ *np = 0;
+ addla(name);
+ return;
+ }
+ break;
+ }
+ if (c == '[') {
+ *np++ = (Char) c;
+ /*
+ * Name up to here is a max of MAXVARLEN + 8.
+ */
+ ep = &np[2 * MAXVARLEN + 8];
+ do {
+ /*
+ * Michael Greim: Allow $ expansion to take place in selector
+ * expressions. (limits the number of characters returned)
+ */
+ c = getC(DOEXCL | DODOL);
+ if (c == '\n') {
+ ungetD(c);
+ np--;
+ seterror(ERR_NLINDEX);
+ *np = 0;
+ addla(name);
+ return;
+ }
+ if (np < ep)
+ *np++ = (Char) c;
+ } while (c != ']');
+ *np = '\0';
+ if (np >= ep) {
+ seterror(ERR_SELOVFL);
+ addla(name);
+ return;
+ }
+ c = getC(DOEXCL);
+ }
+ /*
+ * Name up to here is a max of 2 * MAXVARLEN + 8.
+ */
+ if (c == ':') {
+ /*
+ * if the :g modifier is followed by a newline, then error right away!
+ * -strike
+ */
+
+ int gmodflag = 0, amodflag = 0;
+
+#ifndef COMPAT
+ do {
+#endif /* COMPAT */
+ *np++ = (Char) c, c = getC(DOEXCL);
+ if (c == 'g' || c == 'a') {
+ if (c == 'g')
+ gmodflag++;
+ else
+ amodflag++;
+ *np++ = (Char) c; c = getC(DOEXCL);
+ }
+ if ((c == 'g' && !gmodflag) || (c == 'a' && !amodflag)) {
+ if (c == 'g')
+ gmodflag++;
+ else
+ amodflag++;
+ *np++ = (Char) c; c = getC(DOEXCL);
+ }
+ *np++ = (Char) c;
+ /* scan s// [eichin:19910926.0512EST] */
+ if (c == 's') {
+ int delimcnt = 2;
+ int delim = getC(0);
+ *np++ = (Char) delim;
+
+ if (!delim || letter(delim)
+ || Isdigit(delim) || any(" \t\n", delim)) {
+ seterror(ERR_BADSUBST);
+ break;
+ }
+ while ((c = getC(0)) != (-1)) {
+ *np++ = (Char) c;
+ if(c == delim) delimcnt--;
+ if(!delimcnt) break;
+ }
+ if(delimcnt) {
+ seterror(ERR_BADSUBST);
+ break;
+ }
+ c = 's';
+ }
+ if (!any("htrqxesul", c)) {
+ if ((amodflag || gmodflag) && c == '\n')
+ stderror(ERR_VARSYN); /* strike */
+ seterror(ERR_BADMOD, c);
+ *np = 0;
+ addla(name);
+ return;
+ }
+#ifndef COMPAT
+ }
+ while ((c = getC(DOEXCL)) == ':');
+ ungetD(c);
+#endif /* COMPAT */
+ }
+ else
+ ungetD(c);
+ if (sc == '{') {
+ c = getC(DOEXCL);
+ if (c != '}') {
+ ungetD(c);
+ seterror(ERR_MISSING, '}');
+ *np = 0;
+ addla(name);
+ return;
+ }
+ *np++ = (Char) c;
+ }
+ *np = 0;
+ addla(name);
+ return;
+}
+
+void
+addla(cp)
+ Char *cp;
+{
+ Char buf[BUFSIZE];
+
+ if (Strlen(cp) + (lap ? Strlen(lap) : 0) >=
+ (sizeof(labuf) - 4) / sizeof(Char)) {
+ seterror(ERR_EXPOVFL);
+ return;
+ }
+ if (lap)
+ (void) Strcpy(buf, lap);
+ (void) Strcpy(labuf, cp);
+ if (lap)
+ (void) Strcat(labuf, buf);
+ lap = labuf;
+}
+
+static Char lhsb[32];
+static Char slhs[32];
+static Char rhsb[64];
+static int quesarg;
+
+static void
+getexcl(sc)
+ int sc;
+{
+ struct wordent *hp, *ip;
+ int left, right, dol;
+ int c;
+
+ if (sc == 0) {
+ sc = getC(0);
+ if (sc != '{') {
+ ungetC(sc);
+ sc = 0;
+ }
+ }
+ quesarg = -1;
+
+ if (uselastevent) {
+ uselastevent = 0;
+ lastev = eventno;
+ }
+ else
+ lastev = eventno;
+ hp = gethent(sc);
+ if (hp == 0)
+ return;
+ hadhist = 1;
+ dol = 0;
+ if (hp == alhistp)
+ for (ip = hp->next->next; ip != alhistt; ip = ip->next)
+ dol++;
+ else
+ for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
+ dol++;
+ left = 0, right = dol;
+ if (sc == HISTSUB) {
+ ungetC('s'), unreadc(HISTSUB), c = ':';
+ goto subst;
+ }
+ c = getC(0);
+ if (!any(":^$*-%", c))
+ goto subst;
+ left = right = -1;
+ if (c == ':') {
+ c = getC(0);
+ unreadc(c);
+ if (letter(c) || c == '&') {
+ c = ':';
+ left = 0, right = dol;
+ goto subst;
+ }
+ }
+ else
+ ungetC(c);
+ if (!getsel(&left, &right, dol))
+ return;
+ c = getC(0);
+ if (c == '*')
+ ungetC(c), c = '-';
+ if (c == '-') {
+ if (!getsel(&left, &right, dol))
+ return;
+ c = getC(0);
+ }
+subst:
+ exclc = right - left + 1;
+ while (--left >= 0)
+ hp = hp->next;
+ if (sc == HISTSUB || c == ':') {
+ do {
+ hp = getsub(hp);
+ c = getC(0);
+ } while (c == ':');
+ }
+ unreadc(c);
+ if (sc == '{') {
+ c = getC(0);
+ if (c != '}')
+ seterror(ERR_BADBANG);
+ }
+ exclnxt = hp;
+}
+
+static struct wordent *
+getsub(en)
+ struct wordent *en;
+{
+ Char *cp;
+ int delim;
+ int c;
+ int sc;
+ bool global;
+ Char orhsb[sizeof(rhsb) / sizeof(Char)];
+
+#ifndef COMPAT
+ do {
+#endif /* COMPAT */
+ exclnxt = 0;
+ global = 0;
+ sc = c = getC(0);
+ if (c == 'g' || c == 'a') {
+ global |= (c == 'g') ? 1 : 2;
+ sc = c = getC(0);
+ }
+ if (((c =='g') && !(global & 1)) || ((c == 'a') && !(global & 2))) {
+ global |= (c == 'g') ? 1 : 2;
+ sc = c = getC(0);
+ }
+
+ switch (c) {
+ case 'p':
+ justpr++;
+ return (en);
+
+ case 'x':
+ case 'q':
+ global |= 1;
+ /*FALLTHROUGH*/
+
+ case 'h':
+ case 'r':
+ case 't':
+ case 'e':
+ case 'u':
+ case 'l':
+ break;
+
+ case '&':
+ if (slhs[0] == 0) {
+ seterror(ERR_NOSUBST);
+ return (en);
+ }
+ (void) Strcpy(lhsb, slhs);
+ break;
+
+#ifdef notdef
+ case '~':
+ if (lhsb[0] == 0)
+ goto badlhs;
+ break;
+#endif
+
+ case 's':
+ delim = getC(0);
+ if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) {
+ unreadc(delim);
+ lhsb[0] = 0;
+ seterror(ERR_BADSUBST);
+ return (en);
+ }
+ cp = lhsb;
+ for (;;) {
+ c = getC(0);
+ if (c == '\n') {
+ unreadc(c);
+ break;
+ }
+ if (c == delim)
+ break;
+ if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) {
+ lhsb[0] = 0;
+ seterror(ERR_BADSUBST);
+ return (en);
+ }
+ if (c == '\\') {
+ c = getC(0);
+ if (c != delim && c != '\\')
+ *cp++ = '\\';
+ }
+ *cp++ = (Char) c;
+ }
+ if (cp != lhsb)
+ *cp++ = 0;
+ else if (lhsb[0] == 0) {
+ seterror(ERR_LHS);
+ return (en);
+ }
+ cp = rhsb;
+ (void) Strcpy(orhsb, cp);
+ for (;;) {
+ c = getC(0);
+ if (c == '\n') {
+ unreadc(c);
+ break;
+ }
+ if (c == delim)
+ break;
+#ifdef notdef
+ if (c == '~') {
+ if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) /
+ sizeof(Char) - 2])
+ goto toorhs;
+ (void) Strcpy(cp, orhsb);
+ cp = Strend(cp);
+ continue;
+ }
+#endif
+ if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) {
+ seterror(ERR_RHSLONG);
+ return (en);
+ }
+ if (c == '\\') {
+ c = getC(0);
+ if (c != delim /* && c != '~' */ )
+ *cp++ = '\\';
+ }
+ *cp++ = (Char) c;
+ }
+ *cp++ = 0;
+ break;
+
+ default:
+ if (c == '\n')
+ unreadc(c);
+ seterror(ERR_BADBANGMOD, c);
+ return (en);
+ }
+ (void) Strcpy(slhs, lhsb);
+ if (exclc)
+ en = dosub(sc, en, global);
+#ifndef COMPAT
+ }
+ while ((c = getC(0)) == ':');
+ unreadc(c);
+#endif /* COMPAT */
+ return (en);
+}
+
+/*
+ *
+ * From Beto Appleton (beto@aixwiz.austin.ibm.com)
+ *
+ * when using history substitution, and the variable
+ * 'history' is set to a value higher than 1000,
+ * the shell might either freeze (hang) or core-dump.
+ * We raise the limit to 50000000
+ */
+
+#define HIST_PURGE -50000000
+static struct wordent *
+dosub(sc, en, global)
+ int sc;
+ struct wordent *en;
+ bool global;
+{
+ struct wordent lexi;
+ bool didsub = 0, didone = 0;
+ struct wordent *hp = &lexi;
+ struct wordent *wdp;
+ int i = exclc;
+ struct Hist *hst;
+
+ wdp = hp;
+ while (--i >= 0) {
+ struct wordent *new =
+ (struct wordent *) xcalloc(1, sizeof *wdp);
+
+ new->word = 0;
+ new->prev = wdp;
+ new->next = hp;
+ wdp->next = new;
+ wdp = new;
+ en = en->next;
+ if (en->word) {
+ Char *tword, *otword;
+
+ if ((global & 1) || didsub == 0) {
+ tword = subword(en->word, sc, &didone);
+ if (didone)
+ didsub = 1;
+ if (global & 2) {
+ while (didone && tword != STRNULL) {
+ otword = tword;
+ tword = subword(otword, sc, &didone);
+ if (Strcmp(tword, otword) == 0) {
+ xfree((ptr_t) otword);
+ break;
+ }
+ else
+ xfree((ptr_t) otword);
+ }
+ }
+ }
+ else
+ tword = Strsave(en->word);
+ wdp->word = tword;
+ }
+ }
+ if (didsub == 0)
+ seterror(ERR_MODFAIL);
+ hp->prev = wdp;
+ /*
+ * ANSI mode HP/UX compiler chokes on
+ * return &enthist(HIST_PURGE, &lexi, 0)->Hlex;
+ */
+ hst = enthist(HIST_PURGE, &lexi, 0, 0);
+ return &(hst->Hlex);
+}
+
+static Char *
+subword(cp, type, adid)
+ Char *cp;
+ int type;
+ bool *adid;
+{
+ Char wbuf[BUFSIZE];
+ Char *wp, *mp, *np;
+ int i;
+
+ *adid = 0;
+ switch (type) {
+
+ case 'r':
+ case 'e':
+ case 'h':
+ case 't':
+ case 'q':
+ case 'x':
+ case 'u':
+ case 'l':
+ wp = domod(cp, type);
+ if (wp == 0)
+ return (Strsave(cp));
+ *adid = 1;
+ return (wp);
+
+ default:
+ wp = wbuf;
+ i = BUFSIZE - 4;
+ for (mp = cp; *mp; mp++)
+ if (matchs(mp, lhsb)) {
+ for (np = cp; np < mp;)
+ *wp++ = *np++, --i;
+ for (np = rhsb; *np; np++)
+ switch (*np) {
+
+ case '\\':
+ if (np[1] == '&')
+ np++;
+ /* fall into ... */
+
+ default:
+ if (--i < 0) {
+ seterror(ERR_SUBOVFL);
+ return (STRNULL);
+ }
+ *wp++ = *np;
+ continue;
+
+ case '&':
+ i -= Strlen(lhsb);
+ if (i < 0) {
+ seterror(ERR_SUBOVFL);
+ return (STRNULL);
+ }
+ *wp = 0;
+ (void) Strcat(wp, lhsb);
+ wp = Strend(wp);
+ continue;
+ }
+ mp += Strlen(lhsb);
+ i -= Strlen(mp);
+ if (i < 0) {
+ seterror(ERR_SUBOVFL);
+ return (STRNULL);
+ }
+ *wp = 0;
+ (void) Strcat(wp, mp);
+ *adid = 1;
+ return (Strsave(wbuf));
+ }
+ return (Strsave(cp));
+ }
+}
+
+Char *
+domod(cp, type)
+ Char *cp;
+ int type;
+{
+ Char *wp, *xp;
+ int c;
+
+ switch (type) {
+
+ case 'x':
+ case 'q':
+ wp = Strsave(cp);
+ for (xp = wp; (c = *xp) != 0; xp++)
+ if ((c != ' ' && c != '\t') || type == 'q')
+ *xp |= QUOTE;
+ return (wp);
+
+ case 'l':
+ wp = Strsave(cp);
+ for (cp = wp; *cp; cp++)
+ if (Isupper(*cp)) {
+ *cp = Tolower(*cp);
+ return wp;
+ }
+ return wp;
+
+ case 'u':
+ wp = Strsave(cp);
+ for (cp = wp; *cp; cp++)
+ if (Islower(*cp)) {
+ *cp = Toupper(*cp);
+ return wp;
+ }
+ return wp;
+
+ case 'h':
+ case 't':
+ if (!any(short2str(cp), '/'))
+ return (type == 't' ? Strsave(cp) : 0);
+ wp = Strend(cp);
+ while (*--wp != '/')
+ continue;
+ if (type == 'h')
+ xp = Strsave(cp), xp[wp - cp] = 0;
+ else
+ xp = Strsave(wp + 1);
+ return (xp);
+
+ case 'e':
+ case 'r':
+ wp = Strend(cp);
+ for (wp--; wp >= cp && *wp != '/'; wp--)
+ if (*wp == '.') {
+ if (type == 'e')
+ xp = Strsave(wp + 1);
+ else
+ xp = Strsave(cp), xp[wp - cp] = 0;
+ return (xp);
+ }
+ return (Strsave(type == 'e' ? STRNULL : cp));
+ default:
+ break;
+ }
+ return (0);
+}
+
+static int
+matchs(str, pat)
+ Char *str, *pat;
+{
+ while (*str && *pat && *str == *pat)
+ str++, pat++;
+ return (*pat == 0);
+}
+
+static int
+getsel(al, ar, dol)
+ int *al, *ar;
+ int dol;
+{
+ int c = getC(0);
+ int i;
+ bool first = *al < 0;
+
+ switch (c) {
+
+ case '%':
+ if (quesarg == -1) {
+ seterror(ERR_BADBANGARG);
+ return (0);
+ }
+ if (*al < 0)
+ *al = quesarg;
+ *ar = quesarg;
+ break;
+
+ case '-':
+ if (*al < 0) {
+ *al = 0;
+ *ar = dol - 1;
+ unreadc(c);
+ }
+ return (1);
+
+ case '^':
+ if (*al < 0)
+ *al = 1;
+ *ar = 1;
+ break;
+
+ case '$':
+ if (*al < 0)
+ *al = dol;
+ *ar = dol;
+ break;
+
+ case '*':
+ if (*al < 0)
+ *al = 1;
+ *ar = dol;
+ if (*ar < *al) {
+ *ar = 0;
+ *al = 1;
+ return (1);
+ }
+ break;
+
+ default:
+ if (Isdigit(c)) {
+ i = 0;
+ while (Isdigit(c)) {
+ i = i * 10 + c - '0';
+ c = getC(0);
+ }
+ if (i < 0)
+ i = dol + 1;
+ if (*al < 0)
+ *al = i;
+ *ar = i;
+ }
+ else if (*al < 0)
+ *al = 0, *ar = dol;
+ else
+ *ar = dol - 1;
+ unreadc(c);
+ break;
+ }
+ if (first) {
+ c = getC(0);
+ unreadc(c);
+ if (any("-$*", c))
+ return (1);
+ }
+ if (*al > *ar || *ar > dol) {
+ seterror(ERR_BADBANGARG);
+ return (0);
+ }
+ return (1);
+
+}
+
+static struct wordent *
+gethent(sc)
+ int sc;
+{
+ struct Hist *hp;
+ Char *np;
+ int c;
+ int event;
+ bool back = 0;
+
+ c = sc == HISTSUB ? HIST : getC(0);
+ if (c == HIST) {
+ if (alhistp)
+ return (alhistp);
+ event = eventno;
+ }
+ else
+ switch (c) {
+
+ case ':':
+ case '^':
+ case '$':
+ case '*':
+ case '%':
+ ungetC(c);
+ if (lastev == eventno && alhistp)
+ return (alhistp);
+ event = lastev;
+ break;
+
+ case '#': /* !# is command being typed in (mrh) */
+ if (--hleft == 0) {
+ seterror(ERR_HISTLOOP);
+ return (0);
+ }
+ else
+ return (&paraml);
+ /* NOTREACHED */
+
+ case '-':
+ back = 1;
+ c = getC(0);
+ /* FALLSTHROUGH */
+
+ default:
+ if (any("(=~", c)) {
+ unreadc(c);
+ ungetC(HIST);
+ return (0);
+ }
+ np = lhsb;
+ event = 0;
+ while (!cmap(c, _ESC | _META | _QF | _QB) && !any("^*-%${}:#", c)) {
+ if (event != -1 && Isdigit(c))
+ event = event * 10 + c - '0';
+ else
+ event = -1;
+ if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2])
+ *np++ = (Char) c;
+ c = getC(0);
+ }
+ unreadc(c);
+ if (np == lhsb) {
+ ungetC(HIST);
+ return (0);
+ }
+ *np++ = 0;
+ if (event != -1) {
+ /*
+ * History had only digits
+ */
+ if (back)
+ event = eventno + (alhistp == 0) - (event ? event : 0);
+ break;
+ }
+ if (back) {
+ event = sizeof(lhsb) / sizeof(lhsb[0]);
+ np = &lhsb[--event];
+ *np-- = '\0';
+ for (event--; np > lhsb; *np-- = lhsb[--event])
+ continue;
+ *np = '-';
+ }
+ hp = findev(lhsb, 0);
+ if (hp)
+ lastev = hp->Hnum;
+ return (&hp->Hlex);
+
+ case '?':
+ np = lhsb;
+ for (;;) {
+ c = getC(0);
+ if (c == '\n') {
+ unreadc(c);
+ break;
+ }
+ if (c == '?')
+ break;
+ if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2])
+ *np++ = (Char) c;
+ }
+ if (np == lhsb) {
+ if (lhsb[0] == 0) {
+ seterror(ERR_NOSEARCH);
+ return (0);
+ }
+ }
+ else
+ *np++ = 0;
+ hp = findev(lhsb, 1);
+ if (hp)
+ lastev = hp->Hnum;
+ return (&hp->Hlex);
+ }
+
+ for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
+ if (hp->Hnum == event) {
+ hp->Href = eventno;
+ lastev = hp->Hnum;
+ return (&hp->Hlex);
+ }
+ np = putn(event);
+ seterror(ERR_NOEVENT, short2str(np));
+ return (0);
+}
+
+static struct Hist *
+findev(cp, anyarg)
+ Char *cp;
+ bool anyarg;
+{
+ struct Hist *hp;
+
+ for (hp = Histlist.Hnext; hp; hp = hp->Hnext) {
+ Char *dp;
+ Char *p, *q;
+ struct wordent *lp = hp->Hlex.next;
+ int argno = 0;
+
+ /*
+ * The entries added by alias substitution don't have a newline but do
+ * have a negative event number. Savehist() trims off these entries,
+ * but it happens before alias expansion, too early to delete those
+ * from the previous command.
+ */
+ if (hp->Hnum < 0)
+ continue;
+ if (lp->word[0] == '\n')
+ continue;
+ if (!anyarg) {
+ p = cp;
+ q = lp->word;
+ do
+ if (!*p)
+ return (hp);
+ while (*p++ == *q++);
+ continue;
+ }
+ do {
+ for (dp = lp->word; *dp; dp++) {
+ p = cp;
+ q = dp;
+ do
+ if (!*p) {
+ quesarg = argno;
+ return (hp);
+ }
+ while (*p++ == *q++);
+ }
+ lp = lp->next;
+ argno++;
+ } while (lp->word[0] != '\n');
+ }
+ seterror(ERR_NOEVENT, short2str(cp));
+ return (0);
+}
+
+
+static void
+setexclp(cp)
+ Char *cp;
+{
+ if (cp && cp[0] == '\n')
+ return;
+ exclp = cp;
+}
+
+void
+unreadc(c)
+ int c;
+{
+ peekread = (Char) c;
+}
+
+int
+readc(wanteof)
+ bool wanteof;
+{
+ int c;
+ static int sincereal; /* Number of real EOFs we've seen */
+ Char *ptr; /* For STRignoreeof */
+ int numeof = 0; /* Value of STRignoreeof */
+
+#ifdef DEBUG_INP
+ xprintf("readc\n");
+#endif
+ if ((c = peekread) != 0) {
+ peekread = 0;
+ return (c);
+ }
+
+ /* Compute the value of EOFs */
+ if ((ptr = varval(STRignoreeof)) != STRNULL) {
+ while (*ptr) {
+ if (!Isdigit(*ptr)) {
+ numeof = 0;
+ break;
+ }
+ numeof = numeof * 10 + *ptr++ - '0';
+ }
+ }
+ if (numeof < 1) numeof = 26; /* Sanity check */
+
+top:
+ aret = F_SEEK;
+ if (alvecp) {
+ arun = 1;
+#ifdef DEBUG_INP
+ xprintf("alvecp %c\n", *alvecp & 0xff);
+#endif
+ aret = A_SEEK;
+ if ((c = *alvecp++) != 0)
+ return (c);
+ if (alvec && *alvec) {
+ alvecp = *alvec++;
+ return (' ');
+ }
+ else {
+ alvecp = NULL;
+ aret = F_SEEK;
+ return('\n');
+ }
+ }
+ if (alvec) {
+ arun = 1;
+ if ((alvecp = *alvec) != 0) {
+ alvec++;
+ goto top;
+ }
+ /* Infinite source! */
+ return ('\n');
+ }
+ arun = 0;
+ if (evalp) {
+ aret = E_SEEK;
+ if ((c = *evalp++) != 0)
+ return (c);
+ if (evalvec && *evalvec) {
+ evalp = *evalvec++;
+ return (' ');
+ }
+ aret = F_SEEK;
+ evalp = 0;
+ }
+ if (evalvec) {
+ if (evalvec == INVPPTR) {
+ doneinp = 1;
+ reset();
+ }
+ if ((evalp = *evalvec) != 0) {
+ evalvec++;
+ goto top;
+ }
+ evalvec = INVPPTR;
+ return ('\n');
+ }
+ do {
+ if (arginp == INVPTR || onelflg == 1) {
+ if (wanteof)
+ return (-1);
+ exitstat();
+ }
+ if (arginp) {
+ if ((c = *arginp++) == 0) {
+ arginp = INVPTR;
+ return ('\n');
+ }
+ return (c);
+ }
+#ifdef BSDJOBS
+reread:
+#endif /* BSDJOBS */
+ c = bgetc();
+ if (c < 0) {
+#ifndef WINNT
+# ifndef POSIX
+# ifdef TERMIO
+ struct termio tty;
+# else /* SGTTYB */
+ struct sgttyb tty;
+# endif /* TERMIO */
+# else /* POSIX */
+ struct termios tty;
+# endif /* POSIX */
+#endif /* !WINNT */
+ if (wanteof)
+ return (-1);
+ /* was isatty but raw with ignoreeof yields problems */
+#ifndef WINNT
+# ifndef POSIX
+# ifdef TERMIO
+ if (ioctl(SHIN, TCGETA, (ioctl_t) & tty) == 0 &&
+ (tty.c_lflag & ICANON))
+# else /* GSTTYB */
+ if (ioctl(SHIN, TIOCGETP, (ioctl_t) & tty) == 0 &&
+ (tty.sg_flags & RAW) == 0)
+# endif /* TERMIO */
+# else /* POSIX */
+ if (tcgetattr(SHIN, &tty) == 0 &&
+ (tty.c_lflag & ICANON))
+# endif /* POSIX */
+#else /* WINNT */
+ if (isatty(SHIN))
+#endif /* !WINNT */
+ {
+ /* was 'short' for FILEC */
+#ifdef BSDJOBS
+ int ctpgrp;
+#endif /* BSDJOBS */
+
+ if (++sincereal >= numeof) /* Too many EOFs? Bye! */
+ goto oops;
+#ifdef BSDJOBS
+ if (tpgrp != -1 &&
+ (ctpgrp = tcgetpgrp(FSHTTY)) != -1 &&
+ tpgrp != ctpgrp) {
+ (void) tcsetpgrp(FSHTTY, tpgrp);
+# ifdef _SEQUENT_
+ if (ctpgrp)
+# endif /* _SEQUENT */
+ (void) killpg((pid_t) ctpgrp, SIGHUP);
+# ifdef notdef
+ /*
+ * With the walking process group fix, this message
+ * is now obsolete. As the foreground process group
+ * changes, the shell needs to adjust. Well too bad.
+ */
+ xprintf(CGETS(16, 1, "Reset tty pgrp from %d to %d\n"),
+ ctpgrp, tpgrp);
+# endif /* notdef */
+ goto reread;
+ }
+#endif /* BSDJOBS */
+ /* What follows is complicated EOF handling -- sterling@netcom.com */
+ /* First, we check to see if we have ignoreeof set */
+ if (adrof(STRignoreeof)) {
+ /* If so, we check for any stopped jobs only on the first EOF */
+ if ((sincereal == 1) && (chkstop == 0)) {
+ panystop(1);
+ }
+ } else {
+ /* If we don't have ignoreeof set, always check for stopped jobs */
+ if (chkstop == 0) {
+ panystop(1);
+ }
+ }
+ /* At this point, if there were stopped jobs, we would have already
+ * called reset(). If we got this far, assume we can print an
+ * exit/logout message if we ignoreeof, or just exit.
+ */
+ if (adrof(STRignoreeof)) {
+ /* If so, tell the user to use exit or logout */
+ if (loginsh) {
+ xprintf(CGETS(16, 2,
+ "\nUse \"logout\" to logout.\n"));
+ } else {
+ xprintf(CGETS(16, 3,
+ "\nUse \"exit\" to leave %s.\n"),
+ progname);
+ }
+ reset();
+ } else {
+ /* If we don't have ignoreeof set, just fall through */
+ ; /* EMPTY */
+ }
+ }
+ oops:
+ doneinp = 1;
+ reset();
+ }
+ sincereal = 0;
+ if (c == '\n' && onelflg)
+ onelflg--;
+ } while (c == 0);
+ if (histlinep < histline + BUFSIZE)
+ *histlinep++ = (Char) c;
+ return (c);
+}
+
+static void
+balloc(buf)
+ int buf;
+{
+ Char **nfbuf;
+
+ while (buf >= fblocks) {
+ nfbuf = (Char **) xcalloc((size_t) (fblocks + 2),
+ sizeof(Char **));
+ if (fbuf) {
+ (void) blkcpy(nfbuf, fbuf);
+ xfree((ptr_t) fbuf);
+ }
+ fbuf = nfbuf;
+ fbuf[fblocks] = (Char *) xcalloc(BUFSIZE, sizeof(Char));
+ fblocks++;
+ }
+}
+
+static int
+bgetc()
+{
+ int c, off, buf;
+ int numleft = 0, roomleft;
+ char tbuf[BUFSIZE + 1];
+
+ if (cantell) {
+ if (fseekp < fbobp || fseekp > feobp) {
+ fbobp = feobp = fseekp;
+ (void) lseek(SHIN, fseekp, L_SET);
+ }
+ if (fseekp == feobp) {
+ int i;
+
+ fbobp = feobp;
+ do
+ c = read(SHIN, tbuf, BUFSIZE);
+ while (c < 0 && errno == EINTR);
+#ifdef convex
+ if (c < 0)
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#endif /* convex */
+ if (c <= 0)
+ return (-1);
+ for (i = 0; i < c; i++)
+ fbuf[0][i] = (unsigned char) tbuf[i];
+ feobp += c;
+ }
+#ifndef WINNT
+ c = fbuf[0][fseekp - fbobp];
+ fseekp++;
+#else
+ do {
+ c = fbuf[0][fseekp - fbobp];
+ fseekp++;
+ } while(c == '\r');
+#endif /* !WINNT */
+ return (c);
+ }
+
+ while (fseekp >= feobp) {
+ if (editing && intty) { /* then use twenex routine */
+ fseekp = feobp; /* where else? */
+ c = numleft = Inputl(); /* PWP: get a line */
+ while (numleft > 0) {
+ off = (int) feobp % BUFSIZE;
+ buf = (int) feobp / BUFSIZE;
+ balloc(buf);
+ roomleft = BUFSIZE - off;
+ if (roomleft > numleft)
+ roomleft = numleft;
+ (void) memmove((ptr_t) (fbuf[buf] + off), (ptr_t) (InputBuf + c - numleft), (size_t) (roomleft * sizeof(Char)));
+ numleft -= roomleft;
+ feobp += roomleft;
+ }
+ }
+ else {
+ off = (int) feobp % BUFSIZE;
+ buf = (int) feobp / BUFSIZE;
+ balloc(buf);
+ roomleft = BUFSIZE - off;
+ c = read(SHIN, tbuf, (size_t) roomleft);
+ if (c > 0) {
+ int i;
+ Char *ptr = fbuf[buf] + off;
+
+ for (i = 0; i < c; i++)
+ ptr[i] = (unsigned char) tbuf[i];
+ feobp += c;
+ }
+ }
+ if (c == 0 || (c < 0 && fixio(SHIN, errno) == -1))
+ return (-1);
+ }
+#ifndef WINNT
+ c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE];
+ fseekp++;
+#else
+ do {
+ c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE];
+ fseekp++;
+ } while(c == '\r');
+#endif /* !WINNT */
+ return (c);
+}
+
+static void
+bfree()
+{
+ int sb, i;
+
+ if (cantell)
+ return;
+ if (whyles)
+ return;
+ sb = (int) (fseekp - 1) / BUFSIZE;
+ if (sb > 0) {
+ for (i = 0; i < sb; i++)
+ xfree((ptr_t) fbuf[i]);
+ (void) blkcpy(fbuf, &fbuf[sb]);
+ fseekp -= BUFSIZE * sb;
+ feobp -= BUFSIZE * sb;
+ fblocks -= sb;
+ }
+}
+
+void
+bseek(l)
+ struct Ain *l;
+{
+ switch (aret = l->type) {
+ case E_SEEK:
+ evalvec = l->a_seek;
+ evalp = l->c_seek;
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 4, "seek to eval %x %x\n"), evalvec, evalp);
+#endif
+ return;
+ case A_SEEK:
+ alvec = l->a_seek;
+ alvecp = l->c_seek;
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 5, "seek to alias %x %x\n"), alvec, alvecp);
+#endif
+ return;
+ case F_SEEK:
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 6, "seek to file %x\n"), fseekp);
+#endif
+ fseekp = l->f_seek;
+ return;
+ default:
+ xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret);
+ abort();
+ }
+}
+
+/* any similarity to bell telephone is purely accidental */
+void
+btell(l)
+struct Ain *l;
+{
+ switch (l->type = aret) {
+ case E_SEEK:
+ l->a_seek = evalvec;
+ l->c_seek = evalp;
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 8, "tell eval %x %x\n"), evalvec, evalp);
+#endif
+ return;
+ case A_SEEK:
+ l->a_seek = alvec;
+ l->c_seek = alvecp;
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 9, "tell alias %x %x\n"), alvec, alvecp);
+#endif
+ return;
+ case F_SEEK:
+ /*SUPPRESS 112*/
+ l->f_seek = fseekp;
+ l->a_seek = NULL;
+#ifdef DEBUG_SEEK
+ xprintf(CGETS(16, 10, "tell file %x\n"), fseekp);
+#endif
+ return;
+ default:
+ xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret);
+ abort();
+ }
+}
+
+void
+btoeof()
+{
+ (void) lseek(SHIN, (off_t) 0, L_XTND);
+ aret = F_SEEK;
+ fseekp = feobp;
+ alvec = NULL;
+ alvecp = NULL;
+ evalvec = NULL;
+ evalp = NULL;
+ wfree();
+ bfree();
+}
+
+void
+settell()
+{
+ off_t x;
+ cantell = 0;
+ if (arginp || onelflg || intty)
+ return;
+ if ((x = lseek(SHIN, (off_t) 0, L_INCR)) == -1)
+ return;
+ fbuf = (Char **) xcalloc(2, sizeof(Char **));
+ fblocks = 1;
+ fbuf[0] = (Char *) xcalloc(BUFSIZE, sizeof(Char));
+ fseekp = fbobp = feobp = x;
+ cantell = 1;
+}
diff --git a/contrib/tcsh/sh.misc.c b/contrib/tcsh/sh.misc.c
new file mode 100644
index 0000000..5b35953
--- /dev/null
+++ b/contrib/tcsh/sh.misc.c
@@ -0,0 +1,516 @@
+/* $Header: /src/pub/tcsh/sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $ */
+/*
+ * sh.misc.c: Miscelaneous functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $")
+
+static int renum __P((int, int));
+static Char **blkend __P((Char **));
+static Char **blkcat __P((Char **, Char **));
+
+/*
+ * C Shell
+ */
+
+int
+any(s, c)
+ register char *s;
+ register int c;
+{
+ if (!s)
+ return (0); /* Check for nil pointer */
+ while (*s)
+ if (*s++ == c)
+ return (1);
+ return (0);
+}
+
+void
+setzero(cp, i)
+ char *cp;
+ int i;
+{
+ if (i != 0)
+ do
+ *cp++ = 0;
+ while (--i);
+}
+
+char *
+strsave(s)
+ register const char *s;
+{
+ char *n;
+ register char *p;
+
+ if (s == NULL)
+ s = (const char *) "";
+ for (p = (char *) s; *p++ != '\0';)
+ continue;
+ n = p = (char *) xmalloc((size_t)
+ ((((const char *) p) - s) * sizeof(char)));
+ while ((*p++ = *s++) != '\0')
+ continue;
+ return (n);
+}
+
+static Char **
+blkend(up)
+ register Char **up;
+{
+
+ while (*up)
+ up++;
+ return (up);
+}
+
+
+void
+blkpr(av)
+ register Char **av;
+{
+
+ for (; *av; av++) {
+ xprintf("%S", *av);
+ if (av[1])
+ xprintf(" ");
+ }
+}
+
+void
+blkexpand(av, str)
+ register Char **av;
+ Char *str;
+{
+ *str = '\0';
+ for (; *av; av++) {
+ (void) Strcat(str, *av);
+ if (av[1])
+ (void) Strcat(str, STRspace);
+ }
+}
+
+int
+blklen(av)
+ register Char **av;
+{
+ register int i = 0;
+
+ while (*av++)
+ i++;
+ return (i);
+}
+
+Char **
+blkcpy(oav, bv)
+ Char **oav;
+ register Char **bv;
+{
+ register Char **av = oav;
+
+ while ((*av++ = *bv++) != NULL)
+ continue;
+ return (oav);
+}
+
+static Char **
+blkcat(up, vp)
+ Char **up, **vp;
+{
+
+ (void) blkcpy(blkend(up), vp);
+ return (up);
+}
+
+void
+blkfree(av0)
+ Char **av0;
+{
+ register Char **av = av0;
+
+ if (!av0)
+ return;
+ for (; *av; av++)
+ xfree((ptr_t) * av);
+ xfree((ptr_t) av0);
+}
+
+Char **
+saveblk(v)
+ register Char **v;
+{
+ register Char **newv =
+ (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
+ Char **onewv = newv;
+
+ while (*v)
+ *newv++ = Strsave(*v++);
+ return (onewv);
+}
+
+#if !defined(SHORT_STRINGS) && !defined(POSIX)
+char *
+strstr(s, t)
+ register const char *s, *t;
+{
+ do {
+ register const char *ss = s;
+ register const char *tt = t;
+
+ do
+ if (*tt == '\0')
+ return ((char *) s);
+ while (*ss++ == *tt++);
+ } while (*s++ != '\0');
+ return (NULL);
+}
+
+#endif /* !SHORT_STRINGS && !POSIX */
+
+#ifndef SHORT_STRINGS
+char *
+strspl(cp, dp)
+ char *cp, *dp;
+{
+ char *ep;
+ register char *p, *q;
+
+ if (!cp)
+ cp = "";
+ if (!dp)
+ dp = "";
+ for (p = cp; *p++ != '\0';)
+ continue;
+ for (q = dp; *q++ != '\0';)
+ continue;
+ ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
+ for (p = ep, q = cp; (*p++ = *q++) != '\0';)
+ continue;
+ for (p--, q = dp; (*p++ = *q++) != '\0';)
+ continue;
+ return (ep);
+}
+
+#endif /* !SHORT_STRINGS */
+
+Char **
+blkspl(up, vp)
+ register Char **up, **vp;
+{
+ register Char **wp =
+ (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
+ sizeof(Char **));
+
+ (void) blkcpy(wp, up);
+ return (blkcat(wp, vp));
+}
+
+Char
+lastchr(cp)
+ register Char *cp;
+{
+
+ if (!cp)
+ return (0);
+ if (!*cp)
+ return (0);
+ while (cp[1])
+ cp++;
+ return (*cp);
+}
+
+/*
+ * This routine is called after an error to close up
+ * any units which may have been left open accidentally.
+ */
+void
+closem()
+{
+ register int f;
+
+#ifdef YPBUGS
+ /* suggested by Justin Bur; thanks to Karl Kleinpaste */
+ fix_yp_bugs();
+#endif /* YPBUGS */
+ for (f = 0; f < NOFILE; f++)
+ if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
+ f != FSHTTY
+#ifdef MALLOC_TRACE
+ && f != 25
+#endif /* MALLOC_TRACE */
+ )
+ {
+ (void) close(f);
+#ifdef NISPLUS
+ if(f < 3)
+ (void) open(_PATH_DEVNULL, O_RDONLY);
+#endif /* NISPLUS */
+ }
+}
+
+#ifndef CLOSE_ON_EXEC
+/*
+ * Close files before executing a file.
+ * We could be MUCH more intelligent, since (on a version 7 system)
+ * we need only close files here during a source, the other
+ * shell fd's being in units 16-19 which are closed automatically!
+ */
+void
+closech()
+{
+ register int f;
+
+ if (didcch)
+ return;
+ didcch = 1;
+ SHIN = 0;
+ SHOUT = 1;
+ SHDIAG = 2;
+ OLDSTD = 0;
+ isoutatty = isatty(SHOUT);
+ isdiagatty = isatty(SHDIAG);
+ for (f = 3; f < NOFILE; f++)
+ (void) close(f);
+}
+
+#endif /* CLOSE_ON_EXEC */
+
+void
+donefds()
+{
+
+ (void) close(0);
+ (void) close(1);
+ (void) close(2);
+ didfds = 0;
+#ifdef NISPLUS
+ {
+ int fd = open(_PATH_DEVNULL, O_RDONLY);
+ (void) dup2(fd, 1);
+ (void) dup2(fd, 2);
+ if (fd != 0) {
+ (void) dup2(fd, 0);
+ (void) close(fd);
+ }
+ }
+#endif /*NISPLUS*/
+}
+
+/*
+ * Move descriptor i to j.
+ * If j is -1 then we just want to get i to a safe place,
+ * i.e. to a unit > 2. This also happens in dcopy.
+ */
+int
+dmove(i, j)
+ register int i, j;
+{
+
+ if (i == j || i < 0)
+ return (i);
+#ifdef HAVEDUP2
+ if (j >= 0) {
+ (void) dup2(i, j);
+ if (j != i)
+ (void) close(i);
+ return (j);
+ }
+#endif
+ j = dcopy(i, j);
+ if (j != i)
+ (void) close(i);
+ return (j);
+}
+
+int
+dcopy(i, j)
+ register int i, j;
+{
+
+ if (i == j || i < 0 || (j < 0 && i > 2))
+ return (i);
+ if (j >= 0) {
+#ifdef HAVEDUP2
+ (void) dup2(i, j);
+ return (j);
+#else
+ (void) close(j);
+#endif
+ }
+ return (renum(i, j));
+}
+
+static int
+renum(i, j)
+ register int i, j;
+{
+ register int k = dup(i);
+
+ if (k < 0)
+ return (-1);
+ if (j == -1 && k > 2)
+ return (k);
+ if (k != j) {
+ j = renum(k, j);
+ (void) close(k);
+ return (j);
+ }
+ return (k);
+}
+
+/*
+ * Left shift a command argument list, discarding
+ * the first c arguments. Used in "shift" commands
+ * as well as by commands like "repeat".
+ */
+void
+lshift(v, c)
+ register Char **v;
+ register int c;
+{
+ register Char **u;
+
+ for (u = v; *u && --c >= 0; u++)
+ xfree((ptr_t) *u);
+ (void) blkcpy(v, u);
+}
+
+int
+number(cp)
+ Char *cp;
+{
+ if (!cp)
+ return (0);
+ if (*cp == '-') {
+ cp++;
+ if (!Isdigit(*cp))
+ return (0);
+ cp++;
+ }
+ while (*cp && Isdigit(*cp))
+ cp++;
+ return (*cp == 0);
+}
+
+Char **
+copyblk(v)
+ register Char **v;
+{
+ register Char **nv =
+ (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
+
+ return (blkcpy(nv, v));
+}
+
+#ifndef SHORT_STRINGS
+char *
+strend(cp)
+ register char *cp;
+{
+ if (!cp)
+ return (cp);
+ while (*cp)
+ cp++;
+ return (cp);
+}
+
+#endif /* SHORT_STRINGS */
+
+Char *
+strip(cp)
+ Char *cp;
+{
+ register Char *dp = cp;
+
+ if (!cp)
+ return (cp);
+ while ((*dp++ &= TRIM) != '\0')
+ continue;
+ return (cp);
+}
+
+Char *
+quote(cp)
+ Char *cp;
+{
+ register Char *dp = cp;
+
+ if (!cp)
+ return (cp);
+ while (*dp != '\0')
+ *dp++ |= QUOTE;
+ return (cp);
+}
+
+Char *
+quote_meta(d, s)
+ Char *d;
+ const Char *s;
+{
+ Char *r = d;
+ while (*s != '\0') {
+ if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
+ *d++ = '\\';
+ *d++ = *s++;
+ }
+ *d = '\0';
+ return r;
+}
+
+void
+udvar(name)
+ Char *name;
+{
+
+ setname(short2str(name));
+ stderror(ERR_NAME | ERR_UNDVAR);
+}
+
+int
+prefix(sub, str)
+ register Char *sub, *str;
+{
+
+ for (;;) {
+ if (*sub == 0)
+ return (1);
+ if (*str == 0)
+ return (0);
+ if ((*sub++ & TRIM) != (*str++ & TRIM))
+ return (0);
+ }
+}
diff --git a/contrib/tcsh/sh.parse.c b/contrib/tcsh/sh.parse.c
new file mode 100644
index 0000000..ac91ed8
--- /dev/null
+++ b/contrib/tcsh/sh.parse.c
@@ -0,0 +1,706 @@
+/* $Header: /src/pub/tcsh/sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $ */
+/*
+ * sh.parse.c: Interpret a list of tokens
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $")
+
+/*
+ * C shell
+ */
+static void asyntax __P((struct wordent *, struct wordent *));
+static void asyn0 __P((struct wordent *, struct wordent *));
+static void asyn3 __P((struct wordent *, struct wordent *));
+static struct wordent *freenod __P((struct wordent *, struct wordent *));
+static struct command *syn0 __P((struct wordent *, struct wordent *, int));
+static struct command *syn1 __P((struct wordent *, struct wordent *, int));
+static struct command *syn1a __P((struct wordent *, struct wordent *, int));
+static struct command *syn1b __P((struct wordent *, struct wordent *, int));
+static struct command *syn2 __P((struct wordent *, struct wordent *, int));
+static struct command *syn3 __P((struct wordent *, struct wordent *, int));
+
+#define ALEFT 51 /* max of 50 alias expansions */
+#define HLEFT 11 /* max of 10 history expansions */
+/*
+ * Perform aliasing on the word list lexp
+ * Do a (very rudimentary) parse to separate into commands.
+ * If word 0 of a command has an alias, do it.
+ * Repeat a maximum of 50 times.
+ */
+static int aleft;
+extern int hleft;
+void
+alias(lexp)
+ register struct wordent *lexp;
+{
+ jmp_buf_t osetexit;
+
+ aleft = ALEFT;
+ hleft = HLEFT;
+ getexit(osetexit);
+ (void) setexit();
+ if (haderr) {
+ resexit(osetexit);
+ reset();
+ }
+ if (--aleft == 0)
+ stderror(ERR_ALIASLOOP);
+ asyntax(lexp->next, lexp);
+ resexit(osetexit);
+}
+
+static void
+asyntax(p1, p2)
+ register struct wordent *p1, *p2;
+{
+ while (p1 != p2)
+ if (any(";&\n", p1->word[0]))
+ p1 = p1->next;
+ else {
+ asyn0(p1, p2);
+ return;
+ }
+}
+
+static void
+asyn0(p1, p2)
+ struct wordent *p1;
+ register struct wordent *p2;
+{
+ register struct wordent *p;
+ register int l = 0;
+
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ if (l < 0)
+ stderror(ERR_TOOMANYRP);
+ continue;
+
+ case '>':
+ if (p->next != p2 && eq(p->next->word, STRand))
+ p = p->next;
+ continue;
+
+ case '&':
+ case '|':
+ case ';':
+ case '\n':
+ if (l != 0)
+ continue;
+ asyn3(p1, p);
+ asyntax(p->next, p2);
+ return;
+
+ default:
+ break;
+ }
+ if (l == 0)
+ asyn3(p1, p2);
+}
+
+static void
+asyn3(p1, p2)
+ struct wordent *p1;
+ register struct wordent *p2;
+{
+ register struct varent *ap;
+ struct wordent alout;
+ register bool redid;
+
+ if (p1 == p2)
+ return;
+ if (p1->word[0] == '(') {
+ for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
+ if (p2 == p1)
+ return;
+ if (p2 == p1->next)
+ return;
+ asyn0(p1->next, p2);
+ return;
+ }
+ ap = adrof1(p1->word, &aliases);
+ if (ap == 0)
+ return;
+ alhistp = p1->prev;
+ alhistt = p2;
+ alvec = ap->vec;
+ redid = lex(&alout);
+ alhistp = alhistt = 0;
+ alvec = 0;
+ if (seterr) {
+ freelex(&alout);
+ stderror(ERR_OLD);
+ }
+ if (p1->word[0] && eq(p1->word, alout.next->word)) {
+ Char *cp = alout.next->word;
+
+ alout.next->word = Strspl(STRQNULL, cp);
+ xfree((ptr_t) cp);
+ }
+ p1 = freenod(p1, redid ? p2 : p1->next);
+ if (alout.next != &alout) {
+ p1->next->prev = alout.prev->prev;
+ alout.prev->prev->next = p1->next;
+ alout.next->prev = p1;
+ p1->next = alout.next;
+ xfree((ptr_t) alout.prev->word);
+ xfree((ptr_t) (alout.prev));
+ }
+ reset(); /* throw! */
+}
+
+static struct wordent *
+freenod(p1, p2)
+ register struct wordent *p1, *p2;
+{
+ register struct wordent *retp = p1->prev;
+
+ while (p1 != p2) {
+ xfree((ptr_t) p1->word);
+ p1 = p1->next;
+ xfree((ptr_t) (p1->prev));
+ }
+ retp->next = p2;
+ p2->prev = retp;
+ return (retp);
+}
+
+#define P_HERE 1
+#define P_IN 2
+#define P_OUT 4
+#define P_DIAG 8
+
+/*
+ * syntax
+ * empty
+ * syn0
+ */
+struct command *
+syntax(p1, p2, flags)
+ register struct wordent *p1, *p2;
+ int flags;
+{
+
+ while (p1 != p2)
+ if (any(";&\n", p1->word[0]))
+ p1 = p1->next;
+ else
+ return (syn0(p1, p2, flags));
+ return (0);
+}
+
+/*
+ * syn0
+ * syn1
+ * syn1 & syntax
+ */
+static struct command *
+syn0(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p;
+ register struct command *t, *t1;
+ int l;
+
+ l = 0;
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ if (l < 0)
+ seterror(ERR_TOOMANYRP);
+ continue;
+
+ case '|':
+ if (p->word[1] == '|')
+ continue;
+ /*FALLTHROUGH*/
+
+ case '>':
+ if (p->next != p2 && eq(p->next->word, STRand))
+ p = p->next;
+ continue;
+
+ case '&':
+ if (l != 0)
+ break;
+ if (p->word[1] == '&')
+ continue;
+ t1 = syn1(p1, p, flags);
+ if (t1->t_dtyp == NODE_LIST ||
+ t1->t_dtyp == NODE_AND ||
+ t1->t_dtyp == NODE_OR) {
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ t->t_dtyp = NODE_PAREN;
+ t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
+ t->t_dspr = t1;
+ t1 = t;
+ }
+ else
+ t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ t->t_dtyp = NODE_LIST;
+ t->t_dflg = 0;
+ t->t_dcar = t1;
+ t->t_dcdr = syntax(p, p2, flags);
+ return (t);
+ default:
+ break;
+ }
+ if (l == 0)
+ return (syn1(p1, p2, flags));
+ seterror(ERR_TOOMANYLP);
+ return (0);
+}
+
+/*
+ * syn1
+ * syn1a
+ * syn1a ; syntax
+ */
+static struct command *
+syn1(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p;
+ register struct command *t;
+ int l;
+
+ l = 0;
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ continue;
+
+ case ';':
+ case '\n':
+ if (l != 0)
+ break;
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ t->t_dtyp = NODE_LIST;
+ t->t_dcar = syn1a(p1, p, flags);
+ t->t_dcdr = syntax(p->next, p2, flags);
+ if (t->t_dcdr == 0)
+ t->t_dcdr = t->t_dcar, t->t_dcar = 0;
+ return (t);
+
+ default:
+ break;
+ }
+ return (syn1a(p1, p2, flags));
+}
+
+/*
+ * syn1a
+ * syn1b
+ * syn1b || syn1a
+ */
+static struct command *
+syn1a(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p;
+ register struct command *t;
+ register int l = 0;
+
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ continue;
+
+ case '|':
+ if (p->word[1] != '|')
+ continue;
+ if (l == 0) {
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ t->t_dtyp = NODE_OR;
+ t->t_dcar = syn1b(p1, p, flags);
+ t->t_dcdr = syn1a(p->next, p2, flags);
+ t->t_dflg = 0;
+ return (t);
+ }
+ continue;
+
+ default:
+ break;
+ }
+ return (syn1b(p1, p2, flags));
+}
+
+/*
+ * syn1b
+ * syn2
+ * syn2 && syn1b
+ */
+static struct command *
+syn1b(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p;
+ register struct command *t;
+ register int l = 0;
+
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ continue;
+
+ case '&':
+ if (p->word[1] == '&' && l == 0) {
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ t->t_dtyp = NODE_AND;
+ t->t_dcar = syn2(p1, p, flags);
+ t->t_dcdr = syn1b(p->next, p2, flags);
+ t->t_dflg = 0;
+ return (t);
+ }
+ continue;
+
+ default:
+ break;
+ }
+ return (syn2(p1, p2, flags));
+}
+
+/*
+ * syn2
+ * syn3
+ * syn3 | syn2
+ * syn3 |& syn2
+ */
+static struct command *
+syn2(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p, *pn;
+ register struct command *t;
+ register int l = 0;
+ int f;
+
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ l++;
+ continue;
+
+ case ')':
+ l--;
+ continue;
+
+ case '|':
+ if (l != 0)
+ continue;
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ f = flags | P_OUT;
+ pn = p->next;
+ if (pn != p2 && pn->word[0] == '&') {
+ f |= P_DIAG;
+ t->t_dflg |= F_STDERR;
+ }
+ t->t_dtyp = NODE_PIPE;
+ t->t_dcar = syn3(p1, p, f);
+ if (pn != p2 && pn->word[0] == '&')
+ p = pn;
+ t->t_dcdr = syn2(p->next, p2, flags | P_IN);
+ return (t);
+
+ default:
+ break;
+ }
+ return (syn3(p1, p2, flags));
+}
+
+static char RELPAR[] = {'<', '>', '(', ')', '\0'};
+
+/*
+ * syn3
+ * ( syn0 ) [ < in ] [ > out ]
+ * word word* [ < in ] [ > out ]
+ * KEYWORD ( word* ) word* [ < in ] [ > out ]
+ *
+ * KEYWORD = (@ exit foreach if set switch test while)
+ */
+static struct command *
+syn3(p1, p2, flags)
+ struct wordent *p1, *p2;
+ int flags;
+{
+ register struct wordent *p;
+ struct wordent *lp, *rp;
+ register struct command *t;
+ register int l;
+ Char **av;
+ int n, c;
+ bool specp = 0;
+
+ if (p1 != p2) {
+ p = p1;
+again:
+ switch (srchx(p->word)) {
+
+ case TC_ELSE:
+ p = p->next;
+ if (p != p2)
+ goto again;
+ break;
+
+ case TC_EXIT:
+ case TC_FOREACH:
+ case TC_IF:
+ case TC_LET:
+ case TC_SET:
+ case TC_SWITCH:
+ case TC_WHILE:
+ specp = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ n = 0;
+ l = 0;
+ for (p = p1; p != p2; p = p->next)
+ switch (p->word[0]) {
+
+ case '(':
+ if (specp)
+ n++;
+ l++;
+ continue;
+
+ case ')':
+ if (specp)
+ n++;
+ l--;
+ continue;
+
+ case '>':
+ case '<':
+ if (l != 0) {
+ if (specp)
+ n++;
+ continue;
+ }
+ if (p->next == p2)
+ continue;
+ if (any(RELPAR, p->next->word[0]))
+ continue;
+ n--;
+ continue;
+
+ default:
+ if (!specp && l != 0)
+ continue;
+ n++;
+ continue;
+ }
+ if (n < 0)
+ n = 0;
+ t = (struct command *) xcalloc(1, sizeof(*t));
+ av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
+ t->t_dcom = av;
+ n = 0;
+ if (p2->word[0] == ')')
+ t->t_dflg = F_NOFORK;
+ lp = 0;
+ rp = 0;
+ l = 0;
+ for (p = p1; p != p2; p = p->next) {
+ c = p->word[0];
+ switch (c) {
+
+ case '(':
+ if (l == 0) {
+ if (lp != 0 && !specp)
+ seterror(ERR_BADPLP);
+ lp = p->next;
+ }
+ l++;
+ goto savep;
+
+ case ')':
+ l--;
+ if (l == 0)
+ rp = p;
+ goto savep;
+
+ case '>':
+ if (l != 0)
+ goto savep;
+ if (p->word[1] == '>')
+ t->t_dflg |= F_APPEND;
+ if (p->next != p2 && eq(p->next->word, STRand)) {
+ t->t_dflg |= F_STDERR, p = p->next;
+ if (flags & (P_OUT | P_DIAG)) {
+ seterror(ERR_OUTRED);
+ continue;
+ }
+ }
+ if (p->next != p2 && eq(p->next->word, STRbang))
+ t->t_dflg |= F_OVERWRITE, p = p->next;
+ if (p->next == p2) {
+ seterror(ERR_MISRED);
+ continue;
+ }
+ p = p->next;
+ if (any(RELPAR, p->word[0])) {
+ seterror(ERR_MISRED);
+ continue;
+ }
+ if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
+ seterror(ERR_OUTRED);
+ else
+ t->t_drit = Strsave(p->word);
+ continue;
+
+ case '<':
+ if (l != 0)
+ goto savep;
+ if (p->word[1] == '<')
+ t->t_dflg |= F_READ;
+ if (p->next == p2) {
+ seterror(ERR_MISRED);
+ continue;
+ }
+ p = p->next;
+ if (any(RELPAR, p->word[0])) {
+ seterror(ERR_MISRED);
+ continue;
+ }
+ if ((flags & P_HERE) && (t->t_dflg & F_READ))
+ seterror(ERR_REDPAR);
+ else if ((flags & P_IN) || t->t_dlef)
+ seterror(ERR_INRED);
+ else
+ t->t_dlef = Strsave(p->word);
+ continue;
+
+ savep:
+ if (!specp)
+ continue;
+ default:
+ if (l != 0 && !specp)
+ continue;
+ if (seterr == 0)
+ av[n] = Strsave(p->word);
+ n++;
+ continue;
+ }
+ }
+ if (lp != 0 && !specp) {
+ if (n != 0)
+ seterror(ERR_BADPLPS);
+ t->t_dtyp = NODE_PAREN;
+ t->t_dspr = syn0(lp, rp, P_HERE);
+ }
+ else {
+ if (n == 0)
+ seterror(ERR_NULLCOM);
+ t->t_dtyp = NODE_COMMAND;
+ }
+ return (t);
+}
+
+void
+freesyn(t)
+ register struct command *t;
+{
+ register Char **v;
+
+ if (t == 0)
+ return;
+ switch (t->t_dtyp) {
+
+ case NODE_COMMAND:
+ for (v = t->t_dcom; *v; v++)
+ xfree((ptr_t) * v);
+ xfree((ptr_t) (t->t_dcom));
+ xfree((ptr_t) t->t_dlef);
+ xfree((ptr_t) t->t_drit);
+ break;
+ case NODE_PAREN:
+ freesyn(t->t_dspr);
+ xfree((ptr_t) t->t_dlef);
+ xfree((ptr_t) t->t_drit);
+ break;
+
+ case NODE_AND:
+ case NODE_OR:
+ case NODE_PIPE:
+ case NODE_LIST:
+ freesyn(t->t_dcar), freesyn(t->t_dcdr);
+ break;
+ default:
+ break;
+ }
+ xfree((ptr_t) t);
+}
diff --git a/contrib/tcsh/sh.print.c b/contrib/tcsh/sh.print.c
new file mode 100644
index 0000000..047ab5d
--- /dev/null
+++ b/contrib/tcsh/sh.print.c
@@ -0,0 +1,278 @@
+/* $Header: /src/pub/tcsh/sh.print.c,v 3.18 1999/05/11 13:07:51 christos Exp $ */
+/*
+ * sh.print.c: Primitive Output routines.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.print.c,v 3.18 1999/05/11 13:07:51 christos Exp $")
+
+#include "ed.h"
+
+extern int Tty_eight_bit;
+extern int Tty_raw_mode;
+extern Char GettingInput;
+
+int lbuffed = 1; /* true if line buffered */
+
+static void p2dig __P((int));
+
+/*
+ * C Shell
+ */
+
+#if defined(BSDLIMIT) || defined(RLIMIT_CPU)
+void
+psecs(l)
+ long l;
+{
+ register int i;
+
+ i = (int) (l / 3600);
+ if (i) {
+ xprintf("%d:", i);
+ i = (int) (l % 3600);
+ p2dig(i / 60);
+ goto minsec;
+ }
+ i = (int) l;
+ xprintf("%d", i / 60);
+minsec:
+ i %= 60;
+ xprintf(":");
+ p2dig(i);
+}
+
+#endif
+
+void
+pcsecs(l) /* PWP: print mm:ss.dd, l is in sec*100 */
+#ifdef BSDTIMES
+ long l;
+#else /* BSDTIMES */
+# ifndef POSIX
+ time_t l;
+# else /* POSIX */
+ clock_t l;
+# endif /* POSIX */
+#endif /* BSDTIMES */
+{
+ register int i;
+
+ i = (int) (l / 360000);
+ if (i) {
+ xprintf("%d:", i);
+ i = (int) ((l % 360000) / 100);
+ p2dig(i / 60);
+ goto minsec;
+ }
+ i = (int) (l / 100);
+ xprintf("%d", i / 60);
+minsec:
+ i %= 60;
+ xprintf(":");
+ p2dig(i);
+ xprintf(".");
+ p2dig((int) (l % 100));
+}
+
+static void
+p2dig(i)
+ register int i;
+{
+
+ xprintf("%d%d", i / 10, i % 10);
+}
+
+char linbuf[2048]; /* was 128 */
+char *linp = linbuf;
+bool output_raw = 0; /* PWP */
+bool xlate_cr = 0; /* HE */
+
+void
+xputchar(c)
+ register int c;
+{
+ int atr = 0;
+
+ atr |= c & ATTRIBUTES & TRIM;
+ c &= CHAR | QUOTE;
+ if (!output_raw && (c & QUOTE) == 0) {
+ if (Iscntrl(c)) {
+#ifdef COLORCAT
+ if (c != '\t' && c != '\n' && !(adrof(STRcolorcat) && c=='\033') && (xlate_cr || c != '\r')) {
+#else
+ if (c != '\t' && c != '\n' && (xlate_cr || c != '\r')) {
+#endif
+ xputchar('^' | atr);
+#ifndef _OSD_POSIX
+ if (c == ASCII)
+ c = '?';
+ else
+ c |= 0100;
+#else /*_OSD_POSIX*/
+ if (c == CTL_ESC('\177'))
+ c = '?';
+ else
+ c =_toebcdic[_toascii[c]|0100];
+#endif /*_OSD_POSIX*/
+
+ }
+ }
+ else if (!Isprint(c)) {
+ xputchar('\\' | atr);
+ xputchar((((c >> 6) & 7) + '0') | atr);
+ xputchar((((c >> 3) & 7) + '0') | atr);
+ c = (c & 7) + '0';
+ }
+ (void) putraw(c | atr);
+ }
+ else {
+ c &= TRIM;
+ if (haderr ? (didfds ? is2atty : isdiagatty) :
+ (didfds ? is1atty : isoutatty))
+ SetAttributes(c | atr);
+ (void) putpure(c);
+ }
+ if (lbuffed && (c & CHAR) == '\n')
+ flush();
+}
+
+int
+putraw(c)
+ register int c;
+{
+ if (haderr ? (didfds ? is2atty : isdiagatty) :
+ (didfds ? is1atty : isoutatty)) {
+ if (Tty_eight_bit == -1)
+ ed_set_tty_eight_bit();
+ if (!Tty_eight_bit && (c & META)) {
+ c = (c & ~META) | STANDOUT;
+ }
+ SetAttributes(c);
+ }
+ return putpure(c);
+}
+
+int
+putpure(c)
+ register int c;
+{
+ c &= CHAR;
+
+ *linp++ = (char) c;
+ if (linp >= &linbuf[sizeof linbuf - 10])
+ flush();
+ return (1);
+}
+
+void
+drainoline()
+{
+ linp = linbuf;
+}
+
+void
+flush()
+{
+ int unit;
+ static int interrupted = 0;
+ size_t sz;
+
+ /* int lmode; */
+
+ if (linp == linbuf)
+ return;
+ if (GettingInput && !Tty_raw_mode && linp < &linbuf[sizeof linbuf - 10])
+ return;
+ if (interrupted) {
+ interrupted = 0;
+ linp = linbuf; /* avoid resursion as stderror calls flush */
+ stderror(ERR_SILENT);
+ }
+ interrupted = 1;
+ if (haderr)
+ unit = didfds ? 2 : SHDIAG;
+ else
+ unit = didfds ? 1 : SHOUT;
+#ifdef COMMENT
+#ifdef TIOCLGET
+ if (didfds == 0 && ioctl(unit, TIOCLGET, (ioctl_t) & lmode) == 0 &&
+ lmode & LFLUSHO) {
+ lmode = LFLUSHO;
+ (void) ioctl(unit, TIOCLBIC, (ioclt_t) & lmode);
+ (void) write(unit, "\n", 1);
+ }
+#endif
+#endif
+ sz = (size_t) (linp - linbuf);
+ if (write(unit, linbuf, sz) == -1)
+ switch (errno) {
+#ifdef EIO
+ /* We lost our tty */
+ case EIO:
+#endif
+#ifdef ENXIO
+ /*
+ * Deal with Digital Unix 4.0D bogocity, returning ENXIO when
+ * we lose our tty.
+ */
+ case ENXIO:
+#endif
+ /*
+ * IRIX 6.4 bogocity?
+ */
+#ifdef ENOTTY
+ case ENOTTY:
+#endif
+#ifdef EBADF
+ case EBADF:
+#endif
+ /*
+ * Over our quota, writing the history file
+ */
+#ifdef EDQUOT
+ case EDQUOT:
+#endif
+ /* Nothing to do, but die */
+ xexit(1);
+ break;
+ default:
+ stderror(ERR_SILENT);
+ break;
+ }
+
+ linp = linbuf;
+ interrupted = 0;
+}
diff --git a/contrib/tcsh/sh.proc.c b/contrib/tcsh/sh.proc.c
new file mode 100644
index 0000000..ed6b2ac
--- /dev/null
+++ b/contrib/tcsh/sh.proc.c
@@ -0,0 +1,2184 @@
+/* $Header: /src/pub/tcsh/sh.proc.c,v 3.70 1998/10/25 15:10:22 christos Exp $ */
+/*
+ * sh.proc.c: Job manipulations
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.proc.c,v 3.70 1998/10/25 15:10:22 christos Exp $")
+
+#include "ed.h"
+#include "tc.h"
+#include "tc.wait.h"
+
+#ifdef WINNT
+#undef POSIX
+#define POSIX
+#endif /* WINNT */
+#ifdef aiws
+# undef HZ
+# define HZ 16
+#endif /* aiws */
+
+#if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(linux)
+# define BSDWAIT
+#endif /* _BSD || (IRIS4D && __STDC__) || __lucid || linux */
+#ifndef WTERMSIG
+# define WTERMSIG(w) (((union wait *) &(w))->w_termsig)
+# ifndef BSDWAIT
+# define BSDWAIT
+# endif /* !BSDWAIT */
+#endif /* !WTERMSIG */
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(w) (((union wait *) &(w))->w_retcode)
+#endif /* !WEXITSTATUS */
+#ifndef WSTOPSIG
+# define WSTOPSIG(w) (((union wait *) &(w))->w_stopsig)
+#endif /* !WSTOPSIG */
+
+#ifdef __osf__
+# ifndef WCOREDUMP
+# define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG)
+# endif
+#endif
+
+#ifndef WCOREDUMP
+# ifdef BSDWAIT
+# define WCOREDUMP(w) (((union wait *) &(w))->w_coredump)
+# else /* !BSDWAIT */
+# define WCOREDUMP(w) ((w) & 0200)
+# endif /* !BSDWAIT */
+#endif /* !WCOREDUMP */
+
+/*
+ * C Shell - functions that manage processes, handling hanging, termination
+ */
+
+#define BIGINDEX 9 /* largest desirable job index */
+
+#ifdef BSDTIMES
+# ifdef convex
+/* use 'cvxrusage' to get parallel statistics */
+static struct cvxrusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
+ {0L, 0L}, 0LL, 0LL, 0LL, 0LL, 0L, 0L, 0L,
+ 0LL, 0LL, {0L, 0L, 0L, 0L, 0L}};
+# else
+# if defined(SUNOS4) || defined(hp9000) || (defined(__alpha) && defined(__osf__))
+static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
+ 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
+
+# else /* !SUNOS4 && !hp9000 && !(__alpha && __osf__) */
+# ifdef masscomp
+/*
+ * Initialization of this structure under RTU 4.1A & RTU 5.0 is problematic
+ * because the first two elements are unions of a time_t and a struct timeval.
+ * So we'll just have to trust the loader to do the "right thing", DAS DEC-90.
+ */
+static struct rusage zru;
+# else /* masscomp */
+static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0};
+# endif /* masscomp */
+# endif /* SUNOS4 || hp9000 || (__alpha && __osf__) */
+# endif /* convex */
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+# else /* !_SEQUENT_ */
+# ifdef _SX
+static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0};
+# else /* !_SX */
+static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
+# endif /* !_SX */
+# endif /* !_SEQUENT_ */
+#endif /* !BSDTIMES */
+
+#ifndef RUSAGE_CHILDREN
+# define RUSAGE_CHILDREN -1
+#endif /* RUSAGE_CHILDREN */
+
+static void pflushall __P((void));
+static void pflush __P((struct process *));
+static void pfree __P((struct process *));
+static void pclrcurr __P((struct process *));
+static void padd __P((struct command *));
+static int pprint __P((struct process *, int));
+static void ptprint __P((struct process *));
+static void pads __P((Char *));
+static void pkill __P((Char **, int));
+static struct process *pgetcurr __P((struct process *));
+static void okpcntl __P((void));
+static void setttypgrp __P((int));
+
+/*
+ * pchild - called at interrupt level by the SIGCHLD signal
+ * indicating that at least one child has terminated or stopped
+ * thus at least one wait system call will definitely return a
+ * childs status. Top level routines (like pwait) must be sure
+ * to mask interrupts when playing with the proclist data structures!
+ */
+sigret_t
+/*ARGSUSED*/
+pchild(snum)
+int snum;
+{
+ register struct process *pp;
+ register struct process *fp;
+ register int pid;
+#if defined(BSDJOBS) || (!defined(BSDTIMES) && (defined(ODT) || defined(aiws) || defined(uts)))
+ extern int insource;
+#endif /* BSDJOBS || (!BSDTIMES && (ODT || aiws || uts)) */
+#ifdef BSDWAIT
+ union wait w;
+#else /* !BSDWAIT */
+ int w;
+#endif /* !BSDWAIT */
+ int jobflags;
+#ifdef BSDTIMES
+ struct sysrusage ru;
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ struct process_stats ru;
+ struct process_stats cpst1, cpst2;
+ timeval_t tv;
+# else /* !_SEQUENT_ */
+ struct tms proctimes;
+
+ USE(snum);
+ if (!timesdone) {
+ timesdone++;
+ (void) times(&shtimes);
+ }
+# endif /* !_SEQUENT_ */
+#endif /* !BSDTIMES */
+
+#ifdef JOBDEBUG
+ xprintf("pchild()\n");
+#endif /* JOBDEBUG */
+
+/* Christos on where the signal(SIGCHLD, pchild) shoud be:
+ *
+ * I think that it should go *after* the wait, unlike most signal handlers.
+ *
+ * In release two (for which I have manuals), it says that wait will remove
+ * the first child from the queue of dead children.
+ * All the rest of the children that die while in the signal handler of the
+ * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
+ * the signal handler, and there are items in the queue, the process will
+ * receive another SIGC(H)LD before signal returns. BTW this is from the
+ * manual page on comp-sim... Maybe it is not applicable to the hp's, but
+ * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
+ * that another person was claiming the the signal() call should be after
+ * the wait().
+ */
+
+loop:
+ errno = 0; /* reset, just in case */
+#ifdef JOBDEBUG
+ xprintf("Waiting...\n");
+ flush();
+#endif /* JOBDEBUG */
+#ifndef WINNT
+# ifdef BSDJOBS
+# ifdef BSDTIMES
+# ifdef convex
+ /* use 'cvxwait' to get parallel statistics */
+ pid = cvxwait(&w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
+# else
+ /* both a wait3 and rusage */
+# if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(linux) || (defined(IRIS4D) && (__STDC__ || defined(FUNCPROTO)) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__)
+ pid = wait3(&w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
+# else /* BSDWAIT */
+ pid = wait3(&w.w_status,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
+# endif /* BSDWAIT */
+# endif /* convex */
+# else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
+ pid = waitpid(-1, &w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
+ (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
+ pr_stat_sub(&cpst2, &cpst1, &ru);
+# else /* !_SEQUENT_ */
+# ifndef POSIX
+ /* we have a wait3, but no rusage stuff */
+ pid = wait3(&w.w_status,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
+# else /* POSIX */
+ pid = waitpid(-1, &w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
+# endif /* POSIX */
+# endif /* !_SEQUENT_ */
+# endif /* !BSDTIMES */
+# else /* !BSDJOBS */
+# ifdef BSDTIMES
+# define HAVEwait3
+ /* both a wait3 and rusage */
+# ifdef hpux
+ pid = wait3(&w.w_status, WNOHANG, 0);
+# else /* !hpux */
+ pid = wait3(&w.w_status, WNOHANG, &ru);
+# endif /* !hpux */
+# else /* !BSDTIMES */
+# ifdef ODT /* For Sco Unix 3.2.0 or ODT 1.0 */
+# define HAVEwait3
+ pid = waitpid(-1, &w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
+# endif /* ODT */
+# if defined(aiws) || defined(uts)
+# define HAVEwait3
+ pid = wait3(&w.w_status,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
+# endif /* aiws || uts */
+# ifndef HAVEwait3
+# ifdef UNRELSIGS
+ /* no wait3, therefore no rusage */
+ /* on Sys V, this may hang. I hope it's not going to be a problem */
+# ifdef _MINIX
+ pid = wait(&w);
+# else /* !_MINIX */
+ pid = ourwait(&w.w_status);
+# endif /* _MINIX */
+# else /* !UNRELSIGS */
+ /*
+ * XXX: for greater than 3 we should use waitpid().
+ * but then again, SVR4 falls into the POSIX/BSDJOBS category.
+ */
+ pid = wait(&w.w_status);
+# endif /* !UNRELSIGS */
+# endif /* !HAVEwait3 */
+# endif /* !BSDTIMES */
+# ifndef BSDSIGS
+ (void) sigset(SIGCHLD, pchild);
+# endif /* !BSDSIGS */
+# endif /* !BSDJOBS */
+#else /* WINNT */
+ {
+ extern int insource;
+ pid = waitpid(-1, &w,
+ (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
+ }
+#endif /* WINNT */
+
+#ifdef JOBDEBUG
+ xprintf("parent %d pid %d, retval %x termsig %x retcode %x\n",
+ getpid(), pid, w, WTERMSIG(w), WEXITSTATUS(w));
+ flush();
+#endif /* JOBDEBUG */
+
+ if ((pid == 0) || (pid == -1)) {
+#ifdef JOBDEBUG
+ xprintf("errno == %d\n", errno);
+#endif /* JOBDEBUG */
+ if (errno == EINTR) {
+ errno = 0;
+ goto loop;
+ }
+ pnoprocesses = pid == -1;
+#ifndef SIGVOID
+ return (0);
+#else /* !SIGVOID */
+ return;
+#endif /* !SIGVOID */
+ }
+ for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
+ if (pid == pp->p_procid)
+ goto found;
+#if !defined(BSDJOBS) && !defined(WINNT)
+ /* this should never have happened */
+ stderror(ERR_SYNC, pid);
+ xexit(0);
+#else /* BSDJOBS || WINNT */
+ goto loop;
+#endif /* !BSDJOBS && !WINNT */
+found:
+ pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
+ if (WIFSTOPPED(w)) {
+ pp->p_flags |= PSTOPPED;
+ pp->p_reason = WSTOPSIG(w);
+ }
+ else {
+ if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
+#ifndef BSDTIMES
+# ifdef _SEQUENT_
+ (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
+# else /* !_SEQUENT_ */
+# ifndef COHERENT
+ pp->p_etime = times(&proctimes);
+# else /* COHERENT */
+ pp->p_etime = HZ * time(NULL);
+ times(&proctimes);
+# endif /* COHERENT */
+# endif /* !_SEQUENT_ */
+#else /* BSDTIMES */
+ (void) gettimeofday(&pp->p_etime, NULL);
+#endif /* BSDTIMES */
+
+
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+ pp->p_rusage = ru;
+#else /* !BSDTIMES && !_SEQUENT_ */
+ (void) times(&proctimes);
+ pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
+ pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
+ shtimes = proctimes;
+#endif /* !BSDTIMES && !_SEQUENT_ */
+ if (WIFSIGNALED(w)) {
+ if (WTERMSIG(w) == SIGINT)
+ pp->p_flags |= PINTERRUPTED;
+ else
+ pp->p_flags |= PSIGNALED;
+ if (WCOREDUMP(w))
+ pp->p_flags |= PDUMPED;
+ pp->p_reason = WTERMSIG(w);
+ }
+ else {
+ pp->p_reason = WEXITSTATUS(w);
+ if (pp->p_reason != 0)
+ pp->p_flags |= PAEXITED;
+ else
+ pp->p_flags |= PNEXITED;
+ }
+ }
+ jobflags = 0;
+ fp = pp;
+ do {
+ if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
+ !child && adrof(STRtime) &&
+#ifdef BSDTIMES
+ fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
+# else /* !_SEQUENT_ */
+# ifndef POSIX
+ (fp->p_utime + fp->p_stime) / HZ
+# else /* POSIX */
+ (fp->p_utime + fp->p_stime) / clk_tck
+# endif /* POSIX */
+# endif /* !_SEQUENT_ */
+#endif /* !BSDTIMES */
+ >= atoi(short2str(varval(STRtime))))
+ fp->p_flags |= PTIME;
+ jobflags |= fp->p_flags;
+ } while ((fp = fp->p_friends) != pp);
+ pp->p_flags &= ~PFOREGND;
+ if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
+ pp->p_flags &= ~PPTIME;
+ pp->p_flags |= PTIME;
+ }
+ if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
+ fp = pp;
+ do {
+ if (fp->p_flags & PSTOPPED)
+ fp->p_flags |= PREPORTED;
+ } while ((fp = fp->p_friends) != pp);
+ while (fp->p_procid != fp->p_jobid)
+ fp = fp->p_friends;
+ if (jobflags & PSTOPPED) {
+ if (pcurrent && pcurrent != fp)
+ pprevious = pcurrent;
+ pcurrent = fp;
+ }
+ else
+ pclrcurr(fp);
+ if (jobflags & PFOREGND) {
+ if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
+#ifdef notdef
+ jobflags & PAEXITED ||
+#endif /* notdef */
+ !eq(dcwd->di_name, fp->p_cwd->di_name))) {
+ /* PWP: print a newline after ^C */
+ if (jobflags & PINTERRUPTED) {
+#ifdef SHORT_STRINGS
+ xputchar('\r' | QUOTE), xputchar('\n');
+#else /* !SHORT_STRINGS */
+ xprintf("\215\n"); /* \215 is a quoted ^M */
+#endif /* !SHORT_STRINGS */
+ }
+#ifdef notdef
+ else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
+ ptprint(fp);
+#endif /* notdef */
+ }
+ }
+ else {
+ if (jobflags & PNOTIFY || adrof(STRnotify)) {
+#ifdef SHORT_STRINGS
+ xputchar('\r' | QUOTE), xputchar('\n');
+#else /* !SHORT_STRINGS */
+ xprintf("\215\n"); /* \215 is a quoted ^M */
+#endif /* !SHORT_STRINGS */
+ (void) pprint(pp, NUMBER | NAME | REASON);
+ if ((jobflags & PSTOPPED) == 0)
+ pflush(pp);
+ {
+ extern Char GettingInput;
+
+ if (GettingInput) {
+ errno = 0;
+ (void) Rawmode();
+#ifdef notdef
+ /*
+ * don't really want to do that, because it
+ * will erase our message in case of multi-line
+ * input
+ */
+ ClearLines();
+#endif /* notdef */
+ ClearDisp();
+ Refresh();
+ }
+ }
+ }
+ else {
+ fp->p_flags |= PNEEDNOTE;
+ neednote++;
+ }
+ }
+ }
+#if defined(BSDJOBS) || defined(HAVEwait3)
+ goto loop;
+#endif /* BSDJOBS || HAVEwait3 */
+}
+
+void
+pnote()
+{
+ register struct process *pp;
+ int flags;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+
+ neednote = 0;
+ for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
+ if (pp->p_flags & PNEEDNOTE) {
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+ pp->p_flags &= ~PNEEDNOTE;
+ flags = pprint(pp, NUMBER | NAME | REASON);
+ if ((flags & (PRUNNING | PSTOPPED)) == 0)
+ pflush(pp);
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+ }
+ }
+}
+
+
+static void
+pfree(pp)
+ struct process *pp;
+{
+ xfree((ptr_t) pp->p_command);
+ if (pp->p_cwd && --pp->p_cwd->di_count == 0)
+ if (pp->p_cwd->di_next == 0)
+ dfree(pp->p_cwd);
+ xfree((ptr_t) pp);
+}
+
+
+/*
+ * pwait - wait for current job to terminate, maintaining integrity
+ * of current and previous job indicators.
+ */
+void
+pwait()
+{
+ register struct process *fp, *pp;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+
+ /*
+ * Here's where dead procs get flushed.
+ */
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+ for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
+ if (pp->p_procid == 0) {
+ fp->p_next = pp->p_next;
+ pfree(pp);
+ pp = fp;
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+# ifdef notdef
+ if (setintr)
+ sigignore(SIGINT);
+# endif /* notdef */
+#endif /* !BSDSIGS */
+ pjwait(pcurrjob);
+}
+
+
+/*
+ * pjwait - wait for a job to finish or become stopped
+ * It is assumed to be in the foreground state (PFOREGND)
+ */
+void
+pjwait(pp)
+ register struct process *pp;
+{
+ register struct process *fp;
+ int jobflags, reason;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+#ifdef UNRELSIGS
+ signalfun_t inthandler;
+#endif /* UNRELSIGS */
+ while (pp->p_procid != pp->p_jobid)
+ pp = pp->p_friends;
+ fp = pp;
+
+ do {
+ if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
+ xprintf(CGETS(17, 1, "BUG: waiting for background job!\n"));
+ } while ((fp = fp->p_friends) != pp);
+ /*
+ * Now keep pausing as long as we are not interrupted (SIGINT), and the
+ * target process, or any of its friends, are running
+ */
+ fp = pp;
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+#endif /* BSDSIGS */
+#ifdef UNRELSIGS
+ if (setintr)
+ inthandler = signal(SIGINT, SIG_IGN);
+#endif /* UNRELSIGS */
+ for (;;) {
+#ifndef BSDSIGS
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+ jobflags = 0;
+ do
+ jobflags |= fp->p_flags;
+ while ((fp = (fp->p_friends)) != pp);
+ if ((jobflags & PRUNNING) == 0)
+ break;
+#ifdef JOBDEBUG
+ xprintf("%d starting to sigpause for SIGCHLD on %d\n",
+ getpid(), fp->p_procid);
+#endif /* JOBDEBUG */
+#ifdef BSDSIGS
+ /* (void) sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
+ (void) sigpause(omask & ~sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sigpause(SIGCHLD);
+#endif /* !BSDSIGS */
+ }
+#ifdef JOBDEBUG
+ xprintf("%d returned from sigpause loop\n", getpid());
+#endif /* JOBDEBUG */
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+#ifdef UNRELSIGS
+ if (setintr)
+ (void) signal(SIGINT, inthandler);
+#endif /* UNRELSIGS */
+#ifdef BSDJOBS
+ if (tpgrp > 0) /* get tty back */
+ (void) tcsetpgrp(FSHTTY, tpgrp);
+#endif /* BSDJOBS */
+ if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
+ !eq(dcwd->di_name, fp->p_cwd->di_name)) {
+ if (jobflags & PSTOPPED) {
+ xputchar('\n');
+ if (adrof(STRlistjobs)) {
+ Char *jobcommand[3];
+
+ jobcommand[0] = STRjobs;
+ if (eq(varval(STRlistjobs), STRlong))
+ jobcommand[1] = STRml;
+ else
+ jobcommand[1] = NULL;
+ jobcommand[2] = NULL;
+
+ dojobs(jobcommand, NULL);
+ (void) pprint(pp, SHELLDIR);
+ }
+ else
+ (void) pprint(pp, AREASON | SHELLDIR);
+ }
+ else
+ (void) pprint(pp, AREASON | SHELLDIR);
+ }
+ if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
+ (!gointr || !eq(gointr, STRminus))) {
+ if ((jobflags & PSTOPPED) == 0)
+ pflush(pp);
+ pintr1(0);
+ /* NOTREACHED */
+ }
+ reason = 0;
+ fp = pp;
+ do {
+ if (fp->p_reason)
+ reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
+ fp->p_reason | META : fp->p_reason;
+ } while ((fp = fp->p_friends) != pp);
+ /*
+ * Don't report on backquoted jobs, cause it will mess up
+ * their output.
+ */
+ if ((reason != 0) && (adrof(STRprintexitvalue)) &&
+ (pp->p_flags & PBACKQ) == 0)
+ xprintf(CGETS(17, 2, "Exit %d\n"), reason);
+ set(STRstatus, putn(reason), VAR_READWRITE);
+ if (reason && exiterr)
+ exitstat();
+ pflush(pp);
+}
+
+/*
+ * dowait - wait for all processes to finish
+ */
+
+/*ARGSUSED*/
+void
+dowait(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+
+ USE(c);
+ USE(v);
+ pjobs++;
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+loop:
+#else /* !BSDSIGS */
+ if (setintr)
+ (void) sigrelse(SIGINT);
+loop:
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */
+ pp->p_flags & PRUNNING) {
+#ifdef BSDSIGS
+ (void) sigpause((sigmask_t) 0);
+#else /* !BSDSIGS */
+ (void) sigpause(SIGCHLD);
+#endif /* !BSDSIGS */
+ goto loop;
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+ pjobs = 0;
+}
+
+/*
+ * pflushall - flush all jobs from list (e.g. at fork())
+ */
+static void
+pflushall()
+{
+ register struct process *pp;
+
+ for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
+ if (pp->p_procid)
+ pflush(pp);
+}
+
+/*
+ * pflush - flag all process structures in the same job as the
+ * the argument process for deletion. The actual free of the
+ * space is not done here since pflush is called at interrupt level.
+ */
+static void
+pflush(pp)
+ register struct process *pp;
+{
+ register struct process *np;
+ register int idx;
+
+ if (pp->p_procid == 0) {
+ xprintf(CGETS(17, 3, "BUG: process flushed twice"));
+ return;
+ }
+ while (pp->p_procid != pp->p_jobid)
+ pp = pp->p_friends;
+ pclrcurr(pp);
+ if (pp == pcurrjob)
+ pcurrjob = 0;
+ idx = pp->p_index;
+ np = pp;
+ do {
+ np->p_index = np->p_procid = 0;
+ np->p_flags &= ~PNEEDNOTE;
+ } while ((np = np->p_friends) != pp);
+ if (idx == pmaxindex) {
+ for (np = proclist.p_next, idx = 0; np; np = np->p_next)
+ if (np->p_index > idx)
+ idx = np->p_index;
+ pmaxindex = idx;
+ }
+}
+
+/*
+ * pclrcurr - make sure the given job is not the current or previous job;
+ * pp MUST be the job leader
+ */
+static void
+pclrcurr(pp)
+ register struct process *pp;
+{
+ if (pp == pcurrent) {
+ if (pprevious != NULL) {
+ pcurrent = pprevious;
+ pprevious = pgetcurr(pp);
+ }
+ else {
+ pcurrent = pgetcurr(pp);
+ pprevious = pgetcurr(pp);
+ }
+ }
+ else if (pp == pprevious)
+ pprevious = pgetcurr(pp);
+}
+
+/* +4 here is 1 for '\0', 1 ea for << >& >> */
+static Char command[PMAXLEN + 4];
+static int cmdlen;
+static Char *cmdp;
+
+/*
+ * palloc - allocate a process structure and fill it up.
+ * an important assumption is made that the process is running.
+ */
+void
+palloc(pid, t)
+ int pid;
+ register struct command *t;
+{
+ register struct process *pp;
+ int i;
+
+ pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
+ pp->p_procid = pid;
+ pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING;
+ if (t->t_dflg & F_TIME)
+ pp->p_flags |= PPTIME;
+ if (t->t_dflg & F_BACKQ)
+ pp->p_flags |= PBACKQ;
+ if (t->t_dflg & F_HUP)
+ pp->p_flags |= PHUP;
+ cmdp = command;
+ cmdlen = 0;
+ padd(t);
+ *cmdp++ = 0;
+ if (t->t_dflg & F_PIPEOUT) {
+ pp->p_flags |= PPOU;
+ if (t->t_dflg & F_STDERR)
+ pp->p_flags |= PDIAG;
+ }
+ pp->p_command = Strsave(command);
+ if (pcurrjob) {
+ struct process *fp;
+
+ /* careful here with interrupt level */
+ pp->p_cwd = 0;
+ pp->p_index = pcurrjob->p_index;
+ pp->p_friends = pcurrjob;
+ pp->p_jobid = pcurrjob->p_procid;
+ for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
+ continue;
+ fp->p_friends = pp;
+ }
+ else {
+ pcurrjob = pp;
+ pp->p_jobid = pid;
+ pp->p_friends = pp;
+ pp->p_cwd = dcwd;
+ dcwd->di_count++;
+ if (pmaxindex < BIGINDEX)
+ pp->p_index = ++pmaxindex;
+ else {
+ struct process *np;
+
+ for (i = 1;; i++) {
+ for (np = proclist.p_next; np; np = np->p_next)
+ if (np->p_index == i)
+ goto tryagain;
+ pp->p_index = i;
+ if (i > pmaxindex)
+ pmaxindex = i;
+ break;
+ tryagain:;
+ }
+ }
+ if (pcurrent == NULL)
+ pcurrent = pp;
+ else if (pprevious == NULL)
+ pprevious = pp;
+ }
+ pp->p_next = proclist.p_next;
+ proclist.p_next = pp;
+#ifdef BSDTIMES
+ (void) gettimeofday(&pp->p_btime, NULL);
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
+# else /* !_SEQUENT_ */
+ {
+ struct tms tmptimes;
+
+# ifndef COHERENT
+ pp->p_btime = times(&tmptimes);
+# else /* !COHERENT */
+ pp->p_btime = HZ * time(NULL);
+ times(&tmptimes);
+# endif /* !COHERENT */
+ }
+# endif /* !_SEQUENT_ */
+#endif /* !BSDTIMES */
+}
+
+static void
+padd(t)
+ register struct command *t;
+{
+ Char **argp;
+
+ if (t == 0)
+ return;
+ switch (t->t_dtyp) {
+
+ case NODE_PAREN:
+ pads(STRLparensp);
+ padd(t->t_dspr);
+ pads(STRspRparen);
+ break;
+
+ case NODE_COMMAND:
+ for (argp = t->t_dcom; *argp; argp++) {
+ pads(*argp);
+ if (argp[1])
+ pads(STRspace);
+ }
+ break;
+
+ case NODE_OR:
+ case NODE_AND:
+ case NODE_PIPE:
+ case NODE_LIST:
+ padd(t->t_dcar);
+ switch (t->t_dtyp) {
+ case NODE_OR:
+ pads(STRspor2sp);
+ break;
+ case NODE_AND:
+ pads(STRspand2sp);
+ break;
+ case NODE_PIPE:
+ pads(STRsporsp);
+ break;
+ case NODE_LIST:
+ pads(STRsemisp);
+ break;
+ default:
+ break;
+ }
+ padd(t->t_dcdr);
+ return;
+
+ default:
+ break;
+ }
+ if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
+ pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
+ pads(t->t_dlef);
+ }
+ if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
+ pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
+ if (t->t_dflg & F_STDERR)
+ pads(STRand);
+ pads(STRspace);
+ pads(t->t_drit);
+ }
+}
+
+static void
+pads(cp)
+ Char *cp;
+{
+ register int i;
+
+ /*
+ * Avoid the Quoted Space alias hack! Reported by:
+ * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
+ */
+ if (cp[0] == STRQNULL[0])
+ cp++;
+
+ i = (int) Strlen(cp);
+
+ if (cmdlen >= PMAXLEN)
+ return;
+ if (cmdlen + i >= PMAXLEN) {
+ (void) Strcpy(cmdp, STRsp3dots);
+ cmdlen = PMAXLEN;
+ cmdp += 4;
+ return;
+ }
+ (void) Strcpy(cmdp, cp);
+ cmdp += i;
+ cmdlen += i;
+}
+
+/*
+ * psavejob - temporarily save the current job on a one level stack
+ * so another job can be created. Used for { } in exp6
+ * and `` in globbing.
+ */
+void
+psavejob()
+{
+ pholdjob = pcurrjob;
+ pcurrjob = NULL;
+}
+
+/*
+ * prestjob - opposite of psavejob. This may be missed if we are interrupted
+ * somewhere, but pendjob cleans up anyway.
+ */
+void
+prestjob()
+{
+ pcurrjob = pholdjob;
+ pholdjob = NULL;
+}
+
+/*
+ * pendjob - indicate that a job (set of commands) has been completed
+ * or is about to begin.
+ */
+void
+pendjob()
+{
+ register struct process *pp, *tp;
+
+ if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
+ pp = pcurrjob;
+ while (pp->p_procid != pp->p_jobid)
+ pp = pp->p_friends;
+ xprintf("[%d]", pp->p_index);
+ tp = pp;
+ do {
+ xprintf(" %d", pp->p_procid);
+ pp = pp->p_friends;
+ } while (pp != tp);
+ xputchar('\n');
+ }
+ pholdjob = pcurrjob = 0;
+}
+
+/*
+ * pprint - print a job
+ */
+
+/*
+ * Hacks have been added for SVR4 to deal with pipe's being spawned in
+ * reverse order
+ *
+ * David Dawes (dawes@physics.su.oz.au) Oct 1991
+ */
+
+static int
+pprint(pp, flag)
+ register struct process *pp;
+ bool flag;
+{
+ int status, reason;
+ struct process *tp;
+ extern char *linp, linbuf[];
+ int jobflags, pstatus, pcond;
+ char *format;
+
+#ifdef BACKPIPE
+ struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL;
+ int inpipe = 0;
+#endif /* BACKPIPE */
+
+ while (pp->p_procid != pp->p_jobid)
+ pp = pp->p_friends;
+ if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
+ pp->p_flags &= ~PPTIME;
+ pp->p_flags |= PTIME;
+ }
+ tp = pp;
+ status = reason = -1;
+ jobflags = 0;
+ do {
+#ifdef BACKPIPE
+ /*
+ * The pipeline is reversed, so locate the real head of the pipeline
+ * if pp is at the tail of a pipe (and not already in a pipeline)
+ */
+ if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
+ inpipe = 1;
+ pipetail = pp;
+ do
+ pp = pp->p_friends;
+ while (pp->p_friends->p_flags & PPOU);
+ pipehead = pp;
+ pmarker = pp;
+ /*
+ * pmarker is used to hold the place of the proc being processed, so
+ * we can search for the next one downstream later.
+ */
+ }
+ pcond = (int) (tp != pp || (inpipe && tp == pp));
+#else /* !BACKPIPE */
+ pcond = (int) (tp != pp);
+#endif /* BACKPIPE */
+
+ jobflags |= pp->p_flags;
+ pstatus = (int) (pp->p_flags & PALLSTATES);
+ if (pcond && linp != linbuf && !(flag & FANCY) &&
+ ((pstatus == status && pp->p_reason == reason) ||
+ !(flag & REASON)))
+ xputchar(' ');
+ else {
+ if (pcond && linp != linbuf)
+ xputchar('\n');
+ if (flag & NUMBER) {
+#ifdef BACKPIPE
+ pcond = ((pp == tp && !inpipe) ||
+ (inpipe && pipetail == tp && pp == pipehead));
+#else /* BACKPIPE */
+ pcond = (pp == tp);
+#endif /* BACKPIPE */
+ if (pcond)
+ xprintf("[%d]%s %c ", pp->p_index,
+ pp->p_index < 10 ? " " : "",
+ pp == pcurrent ? '+' :
+ (pp == pprevious ? '-' : ' '));
+ else
+ xprintf(" ");
+ }
+ if (flag & FANCY) {
+#ifdef TCF
+ extern char *sitename();
+
+#endif /* TCF */
+ xprintf("%5d ", pp->p_procid);
+#ifdef TCF
+ xprintf("%11s ", sitename(pp->p_procid));
+#endif /* TCF */
+ }
+ if (flag & (REASON | AREASON)) {
+ if (flag & NAME)
+ format = "%-30s";
+ else
+ format = "%s";
+ if (pstatus == status) {
+ if (pp->p_reason == reason) {
+ xprintf(format, "");
+ goto prcomd;
+ }
+ else
+ reason = (int) pp->p_reason;
+ }
+ else {
+ status = pstatus;
+ reason = (int) pp->p_reason;
+ }
+ switch (status) {
+
+ case PRUNNING:
+ xprintf(format, CGETS(17, 4, "Running "));
+ break;
+
+ case PINTERRUPTED:
+ case PSTOPPED:
+ case PSIGNALED:
+ /*
+ * tell what happened to the background job
+ * From: Michael Schroeder
+ * <mlschroe@immd4.informatik.uni-erlangen.de>
+ */
+ if ((flag & REASON)
+ || ((flag & AREASON)
+ && reason != SIGINT
+ && (reason != SIGPIPE
+ || (pp->p_flags & PPOU) == 0))) {
+ char *ptr;
+ char buf[1024];
+
+ if ((ptr = mesg[pp->p_reason & ASCII].pname) == NULL)
+ xsnprintf(ptr = buf, sizeof(buf), "%s %d",
+ CGETS(17, 5, "Signal"), pp->p_reason & ASCII);
+ xprintf(format, ptr);
+ }
+ else
+ reason = -1;
+ break;
+
+ case PNEXITED:
+ case PAEXITED:
+ if (flag & REASON) {
+ if (pp->p_reason)
+ xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason);
+ else
+ xprintf(format, CGETS(17, 7, "Done"));
+ }
+ break;
+
+ default:
+ xprintf(CGETS(17, 8, "BUG: status=%-9o"),
+ status);
+ }
+ }
+ }
+prcomd:
+ if (flag & NAME) {
+ xprintf("%S", pp->p_command);
+ if (pp->p_flags & PPOU)
+ xprintf(" |");
+ if (pp->p_flags & PDIAG)
+ xprintf("&");
+ }
+ if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
+ xprintf(CGETS(17, 9, " (core dumped)"));
+ if (tp == pp->p_friends) {
+ if (flag & AMPERSAND)
+ xprintf(" &");
+ if (flag & JOBDIR &&
+ !eq(tp->p_cwd->di_name, dcwd->di_name)) {
+ xprintf(CGETS(17, 10, " (wd: "));
+ dtildepr(tp->p_cwd->di_name);
+ xprintf(")");
+ }
+ }
+ if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
+ if (linp != linbuf)
+ xprintf("\n\t");
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+ prusage(&zru, &pp->p_rusage, &pp->p_etime,
+ &pp->p_btime);
+#else /* !BSDTIMES && !SEQUENT */
+ lru.tms_utime = pp->p_utime;
+ lru.tms_stime = pp->p_stime;
+ lru.tms_cutime = 0;
+ lru.tms_cstime = 0;
+ prusage(&zru, &lru, pp->p_etime,
+ pp->p_btime);
+#endif /* !BSDTIMES && !SEQUENT */
+
+ }
+#ifdef BACKPIPE
+ pcond = ((tp == pp->p_friends && !inpipe) ||
+ (inpipe && pipehead->p_friends == tp && pp == pipetail));
+#else /* !BACKPIPE */
+ pcond = (tp == pp->p_friends);
+#endif /* BACKPIPE */
+ if (pcond) {
+ if (linp != linbuf)
+ xputchar('\n');
+ if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
+ xprintf(CGETS(17, 11, "(wd now: "));
+ dtildepr(dcwd->di_name);
+ xprintf(")\n");
+ }
+ }
+#ifdef BACKPIPE
+ if (inpipe) {
+ /*
+ * if pmaker == pipetail, we are finished that pipeline, and
+ * can now skip to past the head
+ */
+ if (pmarker == pipetail) {
+ inpipe = 0;
+ pp = pipehead;
+ }
+ else {
+ /*
+ * set pp to one before the one we want next, so the while below
+ * increments to the correct spot.
+ */
+ do
+ pp = pp->p_friends;
+ while (pp->p_friends->p_friends != pmarker);
+ pmarker = pp->p_friends;
+ }
+ }
+ pcond = ((pp = pp->p_friends) != tp || inpipe);
+#else /* !BACKPIPE */
+ pcond = ((pp = pp->p_friends) != tp);
+#endif /* BACKPIPE */
+ } while (pcond);
+
+ if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
+ if (jobflags & NUMBER)
+ xprintf(" ");
+ ptprint(tp);
+ }
+ return (jobflags);
+}
+
+/*
+ * All 4.3 BSD derived implementations are buggy and I've had enough.
+ * The following implementation produces similar code and works in all
+ * cases. The 4.3BSD one works only for <, >, !=
+ */
+# undef timercmp
+# define timercmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+
+static void
+ptprint(tp)
+ register struct process *tp;
+{
+#ifdef BSDTIMES
+ struct timeval tetime, diff;
+ static struct timeval ztime;
+ struct sysrusage ru;
+ register struct process *pp = tp;
+
+ ru = zru;
+ tetime = ztime;
+ do {
+ ruadd(&ru, &pp->p_rusage);
+ tvsub(&diff, &pp->p_etime, &pp->p_btime);
+ if (timercmp(&diff, &tetime, >))
+ tetime = diff;
+ } while ((pp = pp->p_friends) != tp);
+ prusage(&zru, &ru, &tetime, &ztime);
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ timeval_t tetime, diff;
+ static timeval_t ztime;
+ struct process_stats ru;
+ register struct process *pp = tp;
+
+ ru = zru;
+ tetime = ztime;
+ do {
+ ruadd(&ru, &pp->p_rusage);
+ tvsub(&diff, &pp->p_etime, &pp->p_btime);
+ if (timercmp(&diff, &tetime, >))
+ tetime = diff;
+ } while ((pp = pp->p_friends) != tp);
+ prusage(&zru, &ru, &tetime, &ztime);
+# else /* !_SEQUENT_ */
+# ifndef POSIX
+ static time_t ztime = 0;
+ static time_t zu_time = 0;
+ static time_t zs_time = 0;
+ time_t tetime, diff;
+ time_t u_time, s_time;
+
+# else /* POSIX */
+ static clock_t ztime = 0;
+ static clock_t zu_time = 0;
+ static clock_t zs_time = 0;
+ clock_t tetime, diff;
+ clock_t u_time, s_time;
+
+# endif /* POSIX */
+ struct tms zts, rts;
+ register struct process *pp = tp;
+
+ u_time = zu_time;
+ s_time = zs_time;
+ tetime = ztime;
+ do {
+ u_time += pp->p_utime;
+ s_time += pp->p_stime;
+ diff = pp->p_etime - pp->p_btime;
+ if (diff > tetime)
+ tetime = diff;
+ } while ((pp = pp->p_friends) != tp);
+ zts.tms_utime = zu_time;
+ zts.tms_stime = zs_time;
+ zts.tms_cutime = 0;
+ zts.tms_cstime = 0;
+ rts.tms_utime = u_time;
+ rts.tms_stime = s_time;
+ rts.tms_cutime = 0;
+ rts.tms_cstime = 0;
+ prusage(&zts, &rts, tetime, ztime);
+# endif /* !_SEQUENT_ */
+#endif /* !BSDTIMES */
+}
+
+/*
+ * dojobs - print all jobs
+ */
+/*ARGSUSED*/
+void
+dojobs(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+ register int flag = NUMBER | NAME | REASON;
+ int i;
+
+ USE(c);
+ if (chkstop)
+ chkstop = 2;
+ if (*++v) {
+ if (v[1] || !eq(*v, STRml))
+ stderror(ERR_JOBS);
+ flag |= FANCY | JOBDIR;
+ }
+ for (i = 1; i <= pmaxindex; i++)
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
+ pp->p_flags &= ~PNEEDNOTE;
+ if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
+ pflush(pp);
+ break;
+ }
+}
+
+/*
+ * dofg - builtin - put the job into the foreground
+ */
+/*ARGSUSED*/
+void
+dofg(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+
+ USE(c);
+ okpcntl();
+ ++v;
+ do {
+ pp = pfind(*v);
+ if (!pstart(pp, 1)) {
+ pp->p_procid = 0;
+ stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
+ continue;
+ }
+#ifndef BSDSIGS
+# ifdef notdef
+ if (setintr)
+ sigignore(SIGINT);
+# endif
+#endif /* !BSDSIGS */
+ pjwait(pp);
+ } while (*v && *++v);
+}
+
+/*
+ * %... - builtin - put the job into the foreground
+ */
+/*ARGSUSED*/
+void
+dofg1(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+
+ USE(c);
+ okpcntl();
+ pp = pfind(v[0]);
+ if (!pstart(pp, 1)) {
+ pp->p_procid = 0;
+ stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
+ return;
+ }
+#ifndef BSDSIGS
+# ifdef notdef
+ if (setintr)
+ sigignore(SIGINT);
+# endif
+#endif /* !BSDSIGS */
+ pjwait(pp);
+}
+
+/*
+ * dobg - builtin - put the job into the background
+ */
+/*ARGSUSED*/
+void
+dobg(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+
+ USE(c);
+ okpcntl();
+ ++v;
+ do {
+ pp = pfind(*v);
+ if (!pstart(pp, 0)) {
+ pp->p_procid = 0;
+ stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
+ }
+ } while (*v && *++v);
+}
+
+/*
+ * %... & - builtin - put the job into the background
+ */
+/*ARGSUSED*/
+void
+dobg1(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+
+ USE(c);
+ pp = pfind(v[0]);
+ if (!pstart(pp, 0)) {
+ pp->p_procid = 0;
+ stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
+ }
+}
+
+/*
+ * dostop - builtin - stop the job
+ */
+/*ARGSUSED*/
+void
+dostop(v, c)
+ Char **v;
+ struct command *c;
+{
+ USE(c);
+#ifdef BSDJOBS
+ pkill(++v, SIGSTOP);
+#endif /* BSDJOBS */
+}
+
+/*
+ * dokill - builtin - superset of kill (1)
+ */
+/*ARGSUSED*/
+void
+dokill(v, c)
+ Char **v;
+ struct command *c;
+{
+ register int signum, len = 0;
+ register char *name;
+ extern int T_Cols;
+ extern int nsig;
+
+ USE(c);
+ v++;
+ if (v[0] && v[0][0] == '-') {
+ if (v[0][1] == 'l') {
+ for (signum = 0; signum <= nsig; signum++) {
+ if ((name = mesg[signum].iname) != NULL) {
+ len += strlen(name) + 1;
+ if (len >= T_Cols - 1) {
+ xputchar('\n');
+ len = strlen(name) + 1;
+ }
+ xprintf("%s ", name);
+ }
+ }
+ xputchar('\n');
+ return;
+ }
+ if (Isdigit(v[0][1])) {
+ signum = atoi(short2str(v[0] + 1));
+ if (signum < 0 || signum > (MAXSIG-1))
+ stderror(ERR_NAME | ERR_BADSIG);
+ }
+ else {
+ for (signum = 0; signum <= nsig; signum++)
+ if (mesg[signum].iname &&
+ eq(&v[0][1], str2short(mesg[signum].iname)))
+ goto gotsig;
+ setname(short2str(&v[0][1]));
+ stderror(ERR_NAME | ERR_UNKSIG);
+ }
+gotsig:
+ v++;
+ }
+ else
+ signum = SIGTERM;
+ pkill(v, signum);
+}
+
+static void
+pkill(v, signum)
+ Char **v;
+ int signum;
+{
+ register struct process *pp, *np;
+ int jobflags = 0, err1 = 0;
+ pid_t pid;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+ Char *cp, **vp;
+
+#ifdef BSDSIGS
+ omask = sigmask(SIGCHLD);
+ if (setintr)
+ omask |= sigmask(SIGINT);
+ omask = sigblock(omask) & ~omask;
+#else /* !BSDSIGS */
+ if (setintr)
+ (void) sighold(SIGINT);
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+
+ /* Avoid globbing %?x patterns */
+ for (vp = v; vp && *vp; vp++)
+ if (**vp == '%')
+ (void) quote(*vp);
+
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+
+
+ while (v && (cp = *v)) {
+ if (*cp == '%') {
+ np = pp = pfind(cp);
+ do
+ jobflags |= np->p_flags;
+ while ((np = np->p_friends) != pp);
+#ifdef BSDJOBS
+ switch (signum) {
+
+ case SIGSTOP:
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+ if ((jobflags & PRUNNING) == 0) {
+# ifdef SUSPENDED
+ xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp);
+# else /* !SUSPENDED */
+ xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp);
+# endif /* !SUSPENDED */
+ err1++;
+ goto cont;
+ }
+ break;
+ /*
+ * suspend a process, kill -CONT %, then type jobs; the shell
+ * says it is suspended, but it is running; thanks jaap..
+ */
+ case SIGCONT:
+ if (!pstart(pp, 0)) {
+ pp->p_procid = 0;
+ stderror(ERR_NAME|ERR_BADJOB, pp->p_command,
+ strerror(errno));
+ }
+ goto cont;
+ default:
+ break;
+ }
+#endif /* BSDJOBS */
+ if (killpg(pp->p_jobid, signum) < 0) {
+ xprintf("%S: %s\n", cp, strerror(errno));
+ err1++;
+ }
+#ifdef BSDJOBS
+ if (signum == SIGTERM || signum == SIGHUP)
+ (void) killpg(pp->p_jobid, SIGCONT);
+#endif /* BSDJOBS */
+ }
+ else if (!(Isdigit(*cp) || *cp == '-'))
+ stderror(ERR_NAME | ERR_JOBARGS);
+ else {
+#ifndef WINNT
+ pid = atoi(short2str(cp));
+#else
+ pid = strtoul(short2str(cp),NULL,0);
+#endif /* WINNT */
+ if (kill(pid, signum) < 0) {
+ xprintf("%d: %s\n", pid, strerror(errno));
+ err1++;
+ goto cont;
+ }
+#ifdef BSDJOBS
+ if (signum == SIGTERM || signum == SIGHUP)
+ (void) kill(pid, SIGCONT);
+#endif /* BSDJOBS */
+ }
+cont:
+ v++;
+ }
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+ if (setintr)
+ (void) sigrelse(SIGINT);
+#endif /* !BSDSIGS */
+ if (err1)
+ stderror(ERR_SILENT);
+}
+
+/*
+ * pstart - start the job in foreground/background
+ */
+int
+pstart(pp, foregnd)
+ register struct process *pp;
+ int foregnd;
+{
+ int rv = 0;
+ register struct process *np;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+ /* We don't use jobflags in this function right now (see below) */
+ /* long jobflags = 0; */
+
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+#endif
+ np = pp;
+ do {
+ /* We don't use jobflags in this function right now (see below) */
+ /* jobflags |= np->p_flags; */
+ if (np->p_flags & (PRUNNING | PSTOPPED)) {
+ np->p_flags |= PRUNNING;
+ np->p_flags &= ~PSTOPPED;
+ if (foregnd)
+ np->p_flags |= PFOREGND;
+ else
+ np->p_flags &= ~PFOREGND;
+ }
+ } while ((np = np->p_friends) != pp);
+ if (!foregnd)
+ pclrcurr(pp);
+ (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
+#ifdef BSDJOBS
+ if (foregnd) {
+ rv = tcsetpgrp(FSHTTY, pp->p_jobid);
+ }
+ /*
+ * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
+ * 2. parent process (csh) receives SIGCHLD
+ * 3. The "csh" signal handling function pchild() is invoked
+ * with a SIGCHLD signal.
+ * 4. pchild() calls wait3(WNOHANG) which returns 0.
+ * The child process is NOT ready to be waited for at this time.
+ * pchild() returns without picking-up the correct status
+ * for the child process which generated the SIGCHILD.
+ * 5. CONSEQUENCE : csh is UNaware that the process is stopped
+ * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
+ * (beto@aixwiz.austin.ibm.com - aug/03/91)
+ * 7. I removed the line completely and added extra checks for
+ * pstart, so that if a job gets attached to and dies inside
+ * a debugger it does not confuse the shell. [christos]
+ * 8. on the nec sx-4 there seems to be a problem, which requires
+ * a syscall(151, getpid(), getpid()) in osinit. Don't ask me
+ * what this is doing. [schott@rzg.mpg.de]
+ */
+
+ if (rv != -1)
+ rv = killpg(pp->p_jobid, SIGCONT);
+#endif /* BSDJOBS */
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+ return rv != -1;
+}
+
+void
+panystop(neednl)
+ bool neednl;
+{
+ register struct process *pp;
+
+ chkstop = 2;
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_flags & PSTOPPED)
+ stderror(ERR_STOPPED, neednl ? "\n" : "");
+}
+
+struct process *
+pfind(cp)
+ Char *cp;
+{
+ register struct process *pp, *np;
+
+ if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
+ if (pcurrent == NULL)
+ stderror(ERR_NAME | ERR_JOBCUR);
+ return (pcurrent);
+ }
+ if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
+ if (pprevious == NULL)
+ stderror(ERR_NAME | ERR_JOBPREV);
+ return (pprevious);
+ }
+ if (Isdigit(cp[1])) {
+ int idx = atoi(short2str(cp + 1));
+
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
+ return (pp);
+ stderror(ERR_NAME | ERR_NOSUCHJOB);
+ }
+ np = NULL;
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_procid == pp->p_jobid) {
+ if (cp[1] == '?') {
+ register Char *dp;
+
+ for (dp = pp->p_command; *dp; dp++) {
+ if (*dp != cp[2])
+ continue;
+ if (prefix(cp + 2, dp))
+ goto match;
+ }
+ }
+ else if (prefix(cp + 1, pp->p_command)) {
+ match:
+ if (np)
+ stderror(ERR_NAME | ERR_AMBIG);
+ np = pp;
+ }
+ }
+ if (np)
+ return (np);
+ stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
+ /* NOTREACHED */
+ return (0);
+}
+
+
+/*
+ * pgetcurr - find most recent job that is not pp, preferably stopped
+ */
+static struct process *
+pgetcurr(pp)
+ register struct process *pp;
+{
+ register struct process *np;
+ register struct process *xp = NULL;
+
+ for (np = proclist.p_next; np; np = np->p_next)
+ if (np != pcurrent && np != pp && np->p_procid &&
+ np->p_procid == np->p_jobid) {
+ if (np->p_flags & PSTOPPED)
+ return (np);
+ if (xp == NULL)
+ xp = np;
+ }
+ return (xp);
+}
+
+/*
+ * donotify - flag the job so as to report termination asynchronously
+ */
+/*ARGSUSED*/
+void
+donotify(v, c)
+ Char **v;
+ struct command *c;
+{
+ register struct process *pp;
+
+ USE(c);
+ pp = pfind(*++v);
+ pp->p_flags |= PNOTIFY;
+}
+
+/*
+ * Do the fork and whatever should be done in the child side that
+ * should not be done if we are not forking at all (like for simple builtin's)
+ * Also do everything that needs any signals fiddled with in the parent side
+ *
+ * Wanttty tells whether process and/or tty pgrps are to be manipulated:
+ * -1: leave tty alone; inherit pgrp from parent
+ * 0: already have tty; manipulate process pgrps only
+ * 1: want to claim tty; manipulate process and tty pgrps
+ * It is usually just the value of tpgrp.
+ */
+
+int
+pfork(t, wanttty)
+ struct command *t; /* command we are forking for */
+ int wanttty;
+{
+ register int pid;
+ bool ignint = 0;
+ int pgrp;
+#ifdef BSDSIGS
+ sigmask_t omask = 0;
+#endif /* BSDSIGS */
+#ifdef SIGSYNCH
+ sigvec_t osv;
+ static sigvec_t nsv = {synch_handler, (sigset_t) ~0, 0};
+#endif /* SIGSYNCH */
+
+ /*
+ * A child will be uninterruptible only under very special conditions.
+ * Remember that the semantics of '&' is implemented by disconnecting the
+ * process from the tty so signals do not need to ignored just for '&'.
+ * Thus signals are set to default action for children unless: we have had
+ * an "onintr -" (then specifically ignored) we are not playing with
+ * signals (inherit action)
+ */
+ if (setintr)
+ ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
+ || (gointr && eq(gointr, STRminus));
+
+#ifdef COHERENT
+ ignint |= gointr && eq(gointr, STRminus);
+#endif /* COHERENT */
+
+ /*
+ * Check for maximum nesting of 16 processes to avoid Forking loops
+ */
+ if (child == 16)
+ stderror(ERR_NESTING, 16);
+#ifdef SIGSYNCH
+ if (mysigvec(SIGSYNCH, &nsv, &osv))
+ stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
+#endif /* SIGSYNCH */
+ /*
+ * Hold SIGCHLD until we have the process installed in our table.
+ */
+ if (wanttty < 0) {
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+#endif /* !BSDSIGS */
+ }
+ while ((pid = fork()) == -1)
+ if (setintr == 0)
+ (void) sleep(FORKSLEEP);
+ else {
+ if (wanttty < 0)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+ (void) sigrelse(SIGINT);
+#endif /* !BSDSIGS */
+ stderror(ERR_NOPROC);
+ }
+ if (pid == 0) {
+ settimes();
+ pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
+ pflushall();
+ pcurrjob = NULL;
+#if !defined(BSDTIMES) && !defined(_SEQUENT_)
+ timesdone = 0;
+#endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
+ child++;
+ if (setintr) {
+ setintr = 0; /* until I think otherwise */
+#ifndef BSDSIGS
+ if (wanttty < 0)
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+ /*
+ * Children just get blown away on SIGINT, SIGQUIT unless "onintr
+ * -" seen.
+ */
+ (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
+ (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
+#ifdef BSDJOBS
+ if (wanttty >= 0) {
+ /* make stoppable */
+ (void) signal(SIGTSTP, SIG_DFL);
+ (void) signal(SIGTTIN, SIG_DFL);
+ (void) signal(SIGTTOU, SIG_DFL);
+ }
+#endif /* BSDJOBS */
+ (void) signal(SIGTERM, parterm);
+ }
+ else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+ }
+#ifdef OREO
+ sigignore(SIGIO); /* ignore SIGIO in child too */
+#endif /* OREO */
+
+ pgetty(wanttty, pgrp);
+ /*
+ * Nohup and nice apply only to NODE_COMMAND's but it would be nice
+ * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
+ * to know about nice/nohup/time
+ */
+ if (t->t_dflg & F_NOHUP)
+ (void) signal(SIGHUP, SIG_IGN);
+ if (t->t_dflg & F_NICE) {
+ int nval = SIGN_EXTEND_CHAR(t->t_nice);
+#ifdef BSDNICE
+ (void) setpriority(PRIO_PROCESS, 0, nval);
+#else /* !BSDNICE */
+ (void) nice(nval);
+#endif /* !BSDNICE */
+ }
+#ifdef F_VER
+ if (t->t_dflg & F_VER) {
+ tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
+ dohash(NULL, NULL);
+ }
+#endif /* F_VER */
+#ifdef SIGSYNCH
+ /* rfw 8/89 now parent can continue */
+ if (kill(getppid(), SIGSYNCH))
+ stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
+#endif /* SIGSYNCH */
+
+ }
+ else {
+#ifdef POSIXJOBS
+ if (wanttty >= 0) {
+ /*
+ * `Walking' process group fix from Beto Appleton.
+ * (beto@aixwiz.austin.ibm.com)
+ * If setpgid fails at this point that means that
+ * our process leader has died. We flush the current
+ * job and become the process leader ourselves.
+ * The parent will figure that out later.
+ */
+ pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
+ if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
+ pcurrjob = NULL;
+ /*
+ * We don't care if this causes an error here;
+ * then we are already in the right process group
+ */
+ (void) setpgid(pid, pgrp = pid);
+ }
+ }
+#endif /* POSIXJOBS */
+ palloc(pid, t);
+#ifdef SIGSYNCH
+ /*
+ * rfw 8/89 Wait for child to own terminal. Solves half of ugly
+ * synchronization problem. With this change, we know that the only
+ * reason setpgrp to a previous process in a pipeline can fail is that
+ * the previous process has already exited. Without this hack, he may
+ * either have exited or not yet started to run. Two uglies become
+ * one.
+ */
+ (void) sigpause(omask & ~SYNCHMASK);
+ if (mysigvec(SIGSYNCH, &osv, NULL))
+ stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
+ strerror(errno));
+#endif /* SIGSYNCH */
+
+ if (wanttty < 0) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* !BSDSIGS */
+ }
+ }
+ return (pid);
+}
+
+static void
+okpcntl()
+{
+ if (tpgrp == -1)
+ stderror(ERR_JOBCONTROL);
+ if (tpgrp == 0)
+ stderror(ERR_JOBCTRLSUB);
+}
+
+
+static void
+setttypgrp(pgrp)
+ int pgrp;
+{
+ /*
+ * If we are piping out a builtin, eg. 'echo | more' things can go
+ * out of sequence, i.e. the more can run before the echo. This
+ * can happen even if we have vfork, since the echo will be forked
+ * with the regular fork. In this case, we need to set the tty
+ * pgrp ourselves. If that happens, then the process will be still
+ * alive. And the tty process group will already be set.
+ * This should fix the famous sequent problem as a side effect:
+ * The controlling terminal is lost if all processes in the
+ * terminal process group are zombies. In this case tcgetpgrp()
+ * returns 0. If this happens we must set the terminal process
+ * group again.
+ */
+ if (tcgetpgrp(FSHTTY) != pgrp) {
+#ifdef POSIXJOBS
+ /*
+ * tcsetpgrp will set SIGTTOU to all the the processes in
+ * the background according to POSIX... We ignore this here.
+ */
+ signalfun_t old = sigset(SIGTTOU, SIG_IGN);
+#endif
+ (void) tcsetpgrp(FSHTTY, pgrp);
+# ifdef POSIXJOBS
+ (void) sigset(SIGTTOU, old);
+# endif
+
+ }
+}
+
+
+/*
+ * if we don't have vfork(), things can still go in the wrong order
+ * resulting in the famous 'Stopped (tty output)'. But some systems
+ * don't permit the setpgid() call, (these are more recent secure
+ * systems such as ibm's aix), when they do. Then we'd rather print
+ * an error message than hang the shell!
+ * I am open to suggestions how to fix that.
+ */
+void
+pgetty(wanttty, pgrp)
+ int wanttty, pgrp;
+{
+#ifdef BSDJOBS
+# if defined(BSDSIGS) && defined(POSIXJOBS)
+ sigmask_t omask = 0;
+# endif /* BSDSIGS && POSIXJOBS */
+
+# ifdef JOBDEBUG
+ xprintf("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n",
+ wanttty, getpid(), pgrp, mygetpgrp(), tcgetpgrp(FSHTTY));
+# endif /* JOBDEBUG */
+# ifdef POSIXJOBS
+ /*
+ * christos: I am blocking the tty signals till I've set things
+ * correctly....
+ */
+ if (wanttty > 0)
+# ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN));
+# else /* !BSDSIGS */
+ {
+ (void) sighold(SIGTSTP);
+ (void) sighold(SIGTTIN);
+ }
+# endif /* !BSDSIGS */
+# endif /* POSIXJOBS */
+
+# ifndef POSIXJOBS
+ if (wanttty > 0)
+ setttypgrp(pgrp);
+# endif /* !POSIXJOBS */
+
+ /*
+ * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ * Don't check for tpgrp >= 0 so even non-interactive shells give
+ * background jobs process groups Same for the comparison in the other part
+ * of the #ifdef
+ */
+ if (wanttty >= 0) {
+ if (setpgid(0, pgrp) == -1) {
+# ifdef POSIXJOBS
+ /* Walking process group fix; see above */
+ if (setpgid(0, pgrp = getpid()) == -1) {
+# endif /* POSIXJOBS */
+ stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
+ xexit(0);
+# ifdef POSIXJOBS
+ }
+ wanttty = pgrp; /* Now we really want the tty, since we became the
+ * the process group leader
+ */
+# endif /* POSIXJOBS */
+ }
+ }
+
+# ifdef POSIXJOBS
+ if (wanttty > 0)
+ setttypgrp(pgrp);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else /* BSDSIGS */
+ (void) sigrelse(SIGTSTP);
+ (void) sigrelse(SIGTTIN);
+# endif /* !BSDSIGS */
+# endif /* POSIXJOBS */
+
+# ifdef JOBDEBUG
+ xprintf("wanttty %d pid %d pgrp %d tpgrp %d\n",
+ wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY));
+# endif /* JOBDEBUG */
+
+ if (tpgrp > 0)
+ tpgrp = 0; /* gave tty away */
+#endif /* BSDJOBS */
+}
diff --git a/contrib/tcsh/sh.proc.h b/contrib/tcsh/sh.proc.h
new file mode 100644
index 0000000..c6fb94a
--- /dev/null
+++ b/contrib/tcsh/sh.proc.h
@@ -0,0 +1,137 @@
+/* $Header: /src/pub/tcsh/sh.proc.h,v 3.9 1997/10/27 22:44:32 christos Exp $ */
+/*
+ * sh.proc.h: Process data structures and variables
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh_proc
+#define _h_sh_proc
+/*
+ * C shell - process structure declarations
+ */
+
+/*
+ * Structure for each process the shell knows about:
+ * allocated and filled by pcreate.
+ * flushed by pflush; freeing always happens at top level
+ * so the interrupt level has less to worry about.
+ * processes are related to "friends" when in a pipeline;
+ * p_friends links makes a circular list of such jobs
+ */
+struct process {
+ struct process *p_next; /* next in global "proclist" */
+ struct process *p_friends; /* next in job list (or self) */
+ struct directory *p_cwd; /* cwd of the job (only in head) */
+ unsigned long p_flags; /* various job status flags */
+ unsigned char p_reason; /* reason for entering this state */
+ int p_index; /* shorthand job index */
+ pid_t p_procid;
+ pid_t p_jobid; /* pid of job leader */
+ /* if a job is stopped/background p_jobid gives its pgrp */
+#ifdef BSDTIMES
+ struct timeval p_btime; /* begin time */
+ struct timeval p_etime; /* end time */
+ struct sysrusage p_rusage;
+#else /* BSDTIMES */
+# ifdef _SEQUENT_
+ timeval_t p_btime; /* begin time */
+ timeval_t p_etime; /* end time */
+ struct process_stats p_rusage;
+# else /* _SEQUENT_ */
+# ifndef POSIX
+ time_t p_btime; /* begin time */
+ time_t p_etime; /* end time */
+ time_t p_utime; /* user time */
+ time_t p_stime; /* system time */
+# else /* POSIX */
+ clock_t p_btime; /* begin time */
+ clock_t p_etime; /* end time */
+ clock_t p_utime; /* user time */
+ clock_t p_stime; /* system time */
+# endif /* POSIX */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+ Char *p_command; /* first PMAXLEN chars of command */
+};
+
+/* flag values for p_flags */
+#define PRUNNING (1<<0) /* running */
+#define PSTOPPED (1<<1) /* stopped */
+#define PNEXITED (1<<2) /* normally exited */
+#define PAEXITED (1<<3) /* abnormally exited */
+#define PSIGNALED (1<<4) /* terminated by a signal != SIGINT */
+
+#define PALLSTATES (PRUNNING|PSTOPPED|PNEXITED|PAEXITED| \
+ PSIGNALED|PINTERRUPTED)
+#define PNOTIFY (1<<5) /* notify async when done */
+#define PTIME (1<<6) /* job times should be printed */
+#define PAWAITED (1<<7) /* top level is waiting for it */
+#define PFOREGND (1<<8) /* started in shells pgrp */
+#define PDUMPED (1<<9) /* process dumped core */
+#define PDIAG (1<<10) /* diagnostic output also piped out */
+#define PPOU (1<<11) /* piped output */
+#define PREPORTED (1<<12) /* status has been reported */
+#define PINTERRUPTED (1<<13) /* job stopped via interrupt signal */
+#define PPTIME (1<<14) /* time individual process */
+#define PNEEDNOTE (1<<15) /* notify as soon as practical */
+#define PBACKQ (1<<16) /* Process is `` evaluation */
+#define PHUP (1<<17) /* Process is marked for SIGHUP on exit */
+
+#define PMAXLEN 80
+
+/* defines for arguments to pprint */
+#define NUMBER 01
+#define NAME 02
+#define REASON 04
+#define AMPERSAND 010
+#define FANCY 020
+#define SHELLDIR 040 /* print shell's dir if not the same */
+#define JOBDIR 0100 /* print job's dir if not the same */
+#define AREASON 0200
+
+EXTERN struct process proclist IZERO_STRUCT;/* list head of all processes */
+EXTERN bool pnoprocesses IZERO; /* pchild found nothing to wait for */
+
+EXTERN struct process *pholdjob IZERO; /* one level stack of current jobs */
+
+EXTERN struct process *pcurrjob IZERO; /* current job */
+EXTERN struct process *pcurrent IZERO; /* current job in table */
+EXTERN struct process *pprevious IZERO; /* previous job in table */
+
+EXTERN int pmaxindex IZERO; /* current maximum job index */
+
+#ifndef BSDTIMES
+EXTERN bool timesdone; /* shtimes buffer full ? */
+#endif /* BSDTIMES */
+
+#endif /* _h_sh_proc */
diff --git a/contrib/tcsh/sh.sem.c b/contrib/tcsh/sh.sem.c
new file mode 100644
index 0000000..4f4a637
--- /dev/null
+++ b/contrib/tcsh/sh.sem.c
@@ -0,0 +1,975 @@
+/* $Header: /src/pub/tcsh/sh.sem.c,v 3.48 1998/11/24 18:17:37 christos Exp $ */
+/*
+ * sh.sem.c: I/O redirections and job forking. A touchy issue!
+ * Most stuff with builtins is incorrect
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.sem.c,v 3.48 1998/11/24 18:17:37 christos Exp $")
+
+#include "tc.h"
+#include "tw.h"
+#ifdef WINNT
+#include "nt.const.h"
+#endif /*WINNT*/
+
+#ifdef CLOSE_ON_EXEC
+# ifndef SUNOS4
+# ifndef CLEX_DUPS
+# define CLEX_DUPS
+# endif /* CLEX_DUPS */
+# endif /* !SUNOS4 */
+#endif /* CLOSE_ON_EXEC */
+
+#if defined(__sparc__) || defined(sparc)
+# if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux)
+# include <vfork.h>
+# endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !linux */
+#endif /* __sparc__ || sparc */
+
+#ifdef VFORK
+static sigret_t vffree __P((int));
+#endif
+static Char *splicepipe __P((struct command *, Char *));
+static void doio __P((struct command *, int *, int *));
+static void chkclob __P((char *));
+
+/*
+ * C shell
+ */
+
+/*
+ * For SVR4, there are problems with pipelines having the first process as
+ * the group leader. The problem occurs when the first process exits before
+ * the others have a chance to setpgid(). This is because in SVR4 you can't
+ * have a zombie as a group leader. The solution I have used is to reverse
+ * the order in which pipelines are started, making the last process the
+ * group leader. (Note I am not using 'pipeline' in the generic sense -- I
+ * mean processes connected by '|'.) I don't know yet if this causes other
+ * problems.
+ *
+ * All the changes for this are in execute(), and are enclosed in
+ * '#ifdef BACKPIPE'
+ *
+ * David Dawes (dawes@physics.su.oz.au) Oct 1991
+ */
+
+/*VARARGS 1*/
+void
+execute(t, wanttty, pipein, pipeout)
+ register struct command *t;
+ int wanttty;
+ int *pipein, *pipeout;
+{
+#ifdef VFORK
+ extern bool use_fork; /* use fork() instead of vfork()? */
+#endif
+
+ bool forked = 0;
+ struct biltins *bifunc;
+ int pid = 0;
+ int pv[2];
+#ifdef BSDSIGS
+ static sigmask_t csigmask;
+#endif /* BSDSIGS */
+#ifdef VFORK
+ static int onosigchld = 0;
+#endif /* VFORK */
+ static int nosigchld = 0;
+
+ (void) &wanttty;
+ (void) &forked;
+ (void) &bifunc;
+
+ if (t == 0)
+ return;
+
+#ifdef WINNT
+ {
+ if ((varval(STRNTslowexec) == STRNULL) &&
+ !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds &&
+ (intty || intact) && (t->t_dtyp == NODE_COMMAND) &&
+ !isbfunc(t)) {
+ if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
+ (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
+ Dfix(t);
+ if (nt_try_fast_exec(t) == 0)
+ return;
+ }
+ }
+#endif /* WINNT */
+
+ /*
+ * Ed hutchins@sgi.com & Dominic dbg@sgi.com
+ * Sat Feb 25 03:13:11 PST 1995
+ * try implicit cd if we have a 1 word command
+ */
+ if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] &&
+ t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) {
+ Char sCName[MAXPATHLEN];
+ Char *pCN;
+ struct stat stbuf;
+ char *pathname;
+
+ dollar(sCName, t->t_dcom[0]);
+ pCN = sCName;
+ if (pCN[0] == '~') {
+ Char sCPath[MAXPATHLEN];
+ Char *pCP = sCPath;
+
+ ++pCN;
+ while (*pCN && *pCN != '/')
+ *pCP++ = *pCN++;
+ *pCP = 0;
+ if (sCPath[0])
+ gethdir(sCPath);
+ else
+ (void) Strcpy(sCPath, varval(STRhome));
+ catn(sCPath, pCN, MAXPATHLEN);
+ (void) Strcpy(sCName, sCPath);
+ }
+
+ pathname = short2str(sCName);
+ /* if this is a dir, tack a "cd" on as the first arg */
+ if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode))
+#ifdef WINNT
+ || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
+#endif /* WINNT */
+ ) {
+ Char *vCD[2];
+ Char **ot_dcom = t->t_dcom;
+
+ vCD[0] = Strsave(STRcd);
+ vCD[1] = NULL;
+ t->t_dcom = blkspl(vCD, ot_dcom);
+ if (implicit_cd > 1) {
+ blkpr(t->t_dcom);
+ xputchar( '\n' );
+ }
+ xfree((ptr_t) ot_dcom);
+ }
+ }
+
+ /*
+ * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ * Don't check for wantty > 0...
+ */
+ if (t->t_dflg & F_AMPERSAND)
+ wanttty = 0;
+ switch (t->t_dtyp) {
+
+ case NODE_COMMAND:
+ if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
+ (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
+ if ((t->t_dflg & F_REPEAT) == 0)
+ Dfix(t); /* $ " ' \ */
+ if (t->t_dcom[0] == 0) {
+ return;
+ }
+ /*FALLTHROUGH*/
+
+ case NODE_PAREN:
+#ifdef BACKPIPE
+ if (t->t_dflg & F_PIPEIN)
+ mypipe(pipein);
+#else /* !BACKPIPE */
+ if (t->t_dflg & F_PIPEOUT)
+ mypipe(pipeout);
+#endif /* BACKPIPE */
+ /*
+ * Must do << early so parent will know where input pointer should be.
+ * If noexec then this is all we do.
+ */
+ if (t->t_dflg & F_READ) {
+ (void) close(0);
+ heredoc(t->t_dlef);
+ if (noexec)
+ (void) close(0);
+ }
+
+ set(STRstatus, Strsave(STR0), VAR_READWRITE);
+
+ /*
+ * This mess is the necessary kludge to handle the prefix builtins:
+ * nice, nohup, time. These commands can also be used by themselves,
+ * and this is not handled here. This will also work when loops are
+ * parsed.
+ */
+ while (t->t_dtyp == NODE_COMMAND)
+ if (eq(t->t_dcom[0], STRnice)) {
+ if (t->t_dcom[1]) {
+ if (strchr("+-", t->t_dcom[1][0])) {
+ if (t->t_dcom[2]) {
+ setname("nice");
+ t->t_nice =
+ getn(t->t_dcom[1]);
+ lshift(t->t_dcom, 2);
+ t->t_dflg |= F_NICE;
+ }
+ else
+ break;
+ }
+ else {
+ t->t_nice = 4;
+ lshift(t->t_dcom, 1);
+ t->t_dflg |= F_NICE;
+ }
+ }
+ else
+ break;
+ }
+ else if (eq(t->t_dcom[0], STRnohup)) {
+ if (t->t_dcom[1]) {
+ t->t_dflg |= F_NOHUP;
+ lshift(t->t_dcom, 1);
+ }
+ else
+ break;
+ }
+ else if (eq(t->t_dcom[0], STRhup)) {
+ if (t->t_dcom[1]) {
+ t->t_dflg |= F_HUP;
+ lshift(t->t_dcom, 1);
+ }
+ else
+ break;
+ }
+ else if (eq(t->t_dcom[0], STRtime)) {
+ if (t->t_dcom[1]) {
+ t->t_dflg |= F_TIME;
+ lshift(t->t_dcom, 1);
+ }
+ else
+ break;
+ }
+#ifdef F_VER
+ else if (eq(t->t_dcom[0], STRver))
+ if (t->t_dcom[1] && t->t_dcom[2]) {
+ setname("ver");
+ t->t_systype = getv(t->t_dcom[1]);
+ lshift(t->t_dcom, 2);
+ t->t_dflg |= F_VER;
+ }
+ else
+ break;
+#endif /* F_VER */
+ else
+ break;
+
+ /* is it a command */
+ if (t->t_dtyp == NODE_COMMAND) {
+ /*
+ * Check if we have a builtin function and remember which one.
+ */
+ bifunc = isbfunc(t);
+ if (noexec && bifunc) {
+ /*
+ * Continue for builtins that are part of the scripting language
+ */
+ if (bifunc->bfunct != (bfunc_t)dobreak &&
+ bifunc->bfunct != (bfunc_t)docontin &&
+ bifunc->bfunct != (bfunc_t)doelse &&
+ bifunc->bfunct != (bfunc_t)doend &&
+ bifunc->bfunct != (bfunc_t)doforeach&&
+ bifunc->bfunct != (bfunc_t)dogoto &&
+ bifunc->bfunct != (bfunc_t)doif &&
+ bifunc->bfunct != (bfunc_t)dorepeat &&
+ bifunc->bfunct != (bfunc_t)doswbrk &&
+ bifunc->bfunct != (bfunc_t)doswitch &&
+ bifunc->bfunct != (bfunc_t)dowhile &&
+ bifunc->bfunct != (bfunc_t)dozip)
+ break;
+ }
+ }
+ else { /* not a command */
+ bifunc = NULL;
+ if (noexec)
+ break;
+ }
+
+ /*
+ * We fork only if we are timed, or are not the end of a parenthesized
+ * list and not a simple builtin function. Simple meaning one that is
+ * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
+ * fork in some of these cases.
+ */
+ /*
+ * Prevent forking cd, pushd, popd, chdir cause this will cause the
+ * shell not to change dir!
+ */
+#ifdef BACKPIPE
+ /*
+ * Can't have NOFORK for the tail of a pipe - because it is not the
+ * last command spawned (even if it is at the end of a parenthesised
+ * list).
+ */
+ if (t->t_dflg & F_PIPEIN)
+ t->t_dflg &= ~(F_NOFORK);
+#endif /* BACKPIPE */
+ if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd ||
+ bifunc->bfunct == (bfunc_t)dopushd ||
+ bifunc->bfunct == (bfunc_t)dopopd))
+ t->t_dflg &= ~(F_NICE);
+ if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
+ (!bifunc || t->t_dflg &
+ (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) ||
+ /*
+ * We have to fork for eval too.
+ */
+ (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
+ bifunc->bfunct == (bfunc_t)doeval))
+#ifdef VFORK
+ if (t->t_dtyp == NODE_PAREN ||
+ t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
+#endif /* VFORK */
+ {
+ forked++;
+ /*
+ * We need to block SIGCHLD here, so that if the process does
+ * not die before we can set the process group
+ */
+ if (wanttty >= 0 && !nosigchld) {
+#ifdef BSDSIGS
+ csigmask = sigblock(sigmask(SIGCHLD));
+#else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+#endif /* BSDSIGS */
+
+ nosigchld = 1;
+ }
+
+ pid = pfork(t, wanttty);
+ if (pid == 0 && nosigchld) {
+#ifdef BSDSIGS
+ (void) sigsetmask(csigmask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* BSDSIGS */
+ nosigchld = 0;
+ }
+ else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
+ backpid = pid;
+ }
+
+#ifdef VFORK
+ else {
+ int ochild, osetintr, ohaderr, odidfds;
+ int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
+ int oisoutatty, oisdiagatty;
+
+# ifndef CLOSE_ON_EXEC
+ int odidcch;
+# endif /* !CLOSE_ON_EXEC */
+# ifdef BSDSIGS
+ sigmask_t omask, ocsigmask;
+# endif /* BSDSIGS */
+
+ /*
+ * Prepare for the vfork by saving everything that the child
+ * corrupts before it exec's. Note that in some signal
+ * implementations which keep the signal info in user space
+ * (e.g. Sun's) it will also be necessary to save and restore
+ * the current sigvec's for the signals the child touches
+ * before it exec's.
+ */
+
+ /*
+ * Sooooo true... If this is a Sun, save the sigvec's. (Skip
+ * Gilbrech - 11/22/87)
+ */
+# ifdef SAVESIGVEC
+ sigvec_t savesv[NSIGSAVED];
+ sigmask_t savesm;
+
+# endif /* SAVESIGVEC */
+ if (wanttty >= 0 && !nosigchld && !noexec) {
+# ifdef BSDSIGS
+ csigmask = sigblock(sigmask(SIGCHLD));
+# else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+# endif /* BSDSIGS */
+ nosigchld = 1;
+ }
+# ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT));
+# else /* !BSDSIGS */
+ (void) sighold(SIGCHLD);
+ (void) sighold(SIGINT);
+# endif /* BSDSIGS */
+ ochild = child;
+ osetintr = setintr;
+ ohaderr = haderr;
+ odidfds = didfds;
+# ifndef CLOSE_ON_EXEC
+ odidcch = didcch;
+# endif /* !CLOSE_ON_EXEC */
+ oSHIN = SHIN;
+ oSHOUT = SHOUT;
+ oSHDIAG = SHDIAG;
+ oOLDSTD = OLDSTD;
+ otpgrp = tpgrp;
+ oisoutatty = isoutatty;
+ oisdiagatty = isdiagatty;
+# ifdef BSDSIGS
+ ocsigmask = csigmask;
+# endif /* BSDSIGS */
+ onosigchld = nosigchld;
+ Vsav = Vdp = 0;
+ Vexpath = 0;
+ Vt = 0;
+# ifdef SAVESIGVEC
+ savesm = savesigvec(savesv);
+# endif /* SAVESIGVEC */
+ if (use_fork)
+ pid = fork();
+ else
+ pid = vfork();
+
+ if (pid < 0) {
+# ifdef BSDSIGS
+# ifdef SAVESIGVEC
+ restoresigvec(savesv, savesm);
+# endif /* SAVESIGVEC */
+ (void) sigsetmask(omask);
+# else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+ (void) sigrelse(SIGINT);
+# endif /* BSDSIGS */
+ stderror(ERR_NOPROC);
+ }
+ forked++;
+ if (pid) { /* parent */
+# ifdef SAVESIGVEC
+ restoresigvec(savesv, savesm);
+# endif /* SAVESIGVEC */
+ child = ochild;
+ setintr = osetintr;
+ haderr = ohaderr;
+ didfds = odidfds;
+ SHIN = oSHIN;
+# ifndef CLOSE_ON_EXEC
+ didcch = odidcch;
+# endif /* !CLOSE_ON_EXEC */
+ SHOUT = oSHOUT;
+ SHDIAG = oSHDIAG;
+ OLDSTD = oOLDSTD;
+ tpgrp = otpgrp;
+ isoutatty = oisoutatty;
+ isdiagatty = oisdiagatty;
+# ifdef BSDSIGS
+ csigmask = ocsigmask;
+# endif /* BSDSIGS */
+ nosigchld = onosigchld;
+
+ xfree((ptr_t) Vsav);
+ Vsav = 0;
+ xfree((ptr_t) Vdp);
+ Vdp = 0;
+ xfree((ptr_t) Vexpath);
+ Vexpath = 0;
+ blkfree((Char **) Vt);
+ Vt = 0;
+ /* this is from pfork() */
+ palloc(pid, t);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+ (void) sigrelse(SIGINT);
+# endif /* BSDSIGS */
+ }
+ else { /* child */
+ /* this is from pfork() */
+ int pgrp;
+ bool ignint = 0;
+ if (nosigchld) {
+# ifdef BSDSIGS
+ (void) sigsetmask(csigmask);
+# else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+# endif /* BSDSIGS */
+ nosigchld = 0;
+ }
+
+ if (setintr)
+ ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
+ || (gointr && eq(gointr, STRminus));
+ pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
+ child++;
+ if (setintr) {
+ setintr = 0;
+/*
+ * casts made right for SunOS 4.0 by Douglas C. Schmidt
+ * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
+ * (thanks! -- PWP)
+ *
+ * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
+ * (thanks again)
+ */
+ if (ignint) {
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+ }
+ else {
+ (void) signal(SIGINT, vffree);
+ (void) signal(SIGQUIT, SIG_DFL);
+ }
+# ifdef BSDJOBS
+ if (wanttty >= 0) {
+ (void) signal(SIGTSTP, SIG_DFL);
+ (void) signal(SIGTTIN, SIG_DFL);
+ (void) signal(SIGTTOU, SIG_DFL);
+ }
+# endif /* BSDJOBS */
+
+ (void) signal(SIGTERM, parterm);
+ }
+ else if (tpgrp == -1 &&
+ (t->t_dflg & F_NOINTERRUPT)) {
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+ }
+
+ pgetty(wanttty, pgrp);
+
+ if (t->t_dflg & F_NOHUP)
+ (void) signal(SIGHUP, SIG_IGN);
+ if (t->t_dflg & F_HUP)
+ (void) signal(SIGHUP, SIG_DFL);
+ if (t->t_dflg & F_NICE) {
+ int nval = SIGN_EXTEND_CHAR(t->t_nice);
+# ifdef BSDNICE
+ (void) setpriority(PRIO_PROCESS, 0, nval);
+# else /* !BSDNICE */
+ (void) nice(nval);
+# endif /* BSDNICE */
+ }
+# ifdef F_VER
+ if (t->t_dflg & F_VER) {
+ tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
+ dohash(NULL, NULL);
+ }
+# endif /* F_VER */
+ }
+
+ }
+#endif /* VFORK */
+ if (pid != 0) {
+ /*
+ * It would be better if we could wait for the whole job when we
+ * knew the last process had been started. Pwait, in fact, does
+ * wait for the whole job anyway, but this test doesn't really
+ * express our intentions.
+ */
+#ifdef BACKPIPE
+ if (didfds == 0 && t->t_dflg & F_PIPEOUT) {
+ (void) close(pipeout[0]);
+ (void) close(pipeout[1]);
+ }
+ if ((t->t_dflg & F_PIPEIN) != 0)
+ break;
+#else /* !BACKPIPE */
+ if (didfds == 0 && t->t_dflg & F_PIPEIN) {
+ (void) close(pipein[0]);
+ (void) close(pipein[1]);
+ }
+ if ((t->t_dflg & F_PIPEOUT) != 0)
+ break;
+#endif /* BACKPIPE */
+
+ if (nosigchld) {
+#ifdef BSDSIGS
+ (void) sigsetmask(csigmask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGCHLD);
+#endif /* BSDSIGS */
+ nosigchld = 0;
+ }
+ if ((t->t_dflg & F_AMPERSAND) == 0)
+ pwait();
+ break;
+ }
+
+ doio(t, pipein, pipeout);
+#ifdef BACKPIPE
+ if (t->t_dflg & F_PIPEIN) {
+ (void) close(pipein[0]);
+ (void) close(pipein[1]);
+ }
+#else /* !BACKPIPE */
+ if (t->t_dflg & F_PIPEOUT) {
+ (void) close(pipeout[0]);
+ (void) close(pipeout[1]);
+ }
+#endif /* BACKPIPE */
+ /*
+ * Perform a builtin function. If we are not forked, arrange for
+ * possible stopping
+ */
+ if (bifunc) {
+ func(t, bifunc);
+ if (forked)
+ exitstat();
+ break;
+ }
+ if (t->t_dtyp != NODE_PAREN) {
+ doexec(t);
+ /* NOTREACHED */
+ }
+ /*
+ * For () commands must put new 0,1,2 in FSH* and recurse
+ */
+ OLDSTD = dcopy(0, FOLDSTD);
+ SHOUT = dcopy(1, FSHOUT);
+ isoutatty = isatty(SHOUT);
+ SHDIAG = dcopy(2, FSHDIAG);
+ isdiagatty = isatty(SHDIAG);
+ (void) close(SHIN);
+ SHIN = -1;
+#ifndef CLOSE_ON_EXEC
+ didcch = 0;
+#endif /* !CLOSE_ON_EXEC */
+ didfds = 0;
+ wanttty = -1;
+ t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
+ execute(t->t_dspr, wanttty, NULL, NULL);
+ exitstat();
+
+ case NODE_PIPE:
+#ifdef BACKPIPE
+ t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
+ (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
+ execute(t->t_dcdr, wanttty, pv, pipeout);
+ t->t_dcar->t_dflg |= F_PIPEOUT |
+ (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
+ execute(t->t_dcar, wanttty, pipein, pv);
+#else /* !BACKPIPE */
+ t->t_dcar->t_dflg |= F_PIPEOUT |
+ (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
+ execute(t->t_dcar, wanttty, pipein, pv);
+ t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
+ (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
+ execute(t->t_dcdr, wanttty, pv, pipeout);
+#endif /* BACKPIPE */
+ break;
+
+ case NODE_LIST:
+ if (t->t_dcar) {
+ t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
+ execute(t->t_dcar, wanttty, NULL, NULL);
+ /*
+ * In strange case of A&B make a new job after A
+ */
+ if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
+ (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
+ pendjob();
+ }
+ if (t->t_dcdr) {
+ t->t_dcdr->t_dflg |= t->t_dflg &
+ (F_NOFORK | F_NOINTERRUPT);
+ execute(t->t_dcdr, wanttty, NULL, NULL);
+ }
+ break;
+
+ case NODE_OR:
+ case NODE_AND:
+ if (t->t_dcar) {
+ t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
+ execute(t->t_dcar, wanttty, NULL, NULL);
+ if ((getn(varval(STRstatus)) == 0) !=
+ (t->t_dtyp == NODE_AND)) {
+ return;
+ }
+ }
+ if (t->t_dcdr) {
+ t->t_dcdr->t_dflg |= t->t_dflg &
+ (F_NOFORK | F_NOINTERRUPT);
+ execute(t->t_dcdr, wanttty, NULL, NULL);
+ }
+ break;
+
+ default:
+ break;
+ }
+ /*
+ * Fall through for all breaks from switch
+ *
+ * If there will be no more executions of this command, flush all file
+ * descriptors. Places that turn on the F_REPEAT bit are responsible for
+ * doing donefds after the last re-execution
+ */
+ if (didfds && !(t->t_dflg & F_REPEAT))
+ donefds();
+}
+
+#ifdef VFORK
+static sigret_t
+/*ARGSUSED*/
+vffree(snum)
+int snum;
+{
+ register Char **v;
+
+ USE(snum);
+ if ((v = gargv) != 0) {
+ gargv = 0;
+ xfree((ptr_t) v);
+ }
+
+ if ((v = pargv) != 0) {
+ pargv = 0;
+ xfree((ptr_t) v);
+ }
+
+ _exit(1);
+#ifndef SIGVOID
+ /*NOTREACHED*/
+ return(0);
+#endif /* SIGVOID */
+}
+#endif /* VFORK */
+
+/*
+ * Expand and glob the words after an i/o redirection.
+ * If more than one word is generated, then update the command vector.
+ *
+ * This is done differently in all the shells:
+ * 1. in the bourne shell and ksh globbing is not performed
+ * 2. Bash/csh say ambiguous
+ * 3. zsh does i/o to/from all the files
+ * 4. itcsh concatenates the words.
+ *
+ * I don't know what is best to do. I think that Ambiguous is better
+ * than restructuring the command vector, because the user can get
+ * unexpected results. In any case, the command vector restructuring
+ * code is present and the user can choose it by setting noambiguous
+ */
+static Char *
+splicepipe(t, cp)
+ register struct command *t;
+ Char *cp; /* word after < or > */
+{
+ Char *blk[2];
+
+ if (adrof(STRnoambiguous)) {
+ Char **pv;
+
+ blk[0] = Dfix1(cp); /* expand $ */
+ blk[1] = NULL;
+
+ gflag = 0, tglob(blk);
+ if (gflag) {
+ pv = globall(blk);
+ if (pv == NULL) {
+ setname(short2str(blk[0]));
+ xfree((ptr_t) blk[0]);
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ gargv = NULL;
+ if (pv[1] != NULL) { /* we need to fix the command vector */
+ Char **av = blkspl(t->t_dcom, &pv[1]);
+ xfree((ptr_t) t->t_dcom);
+ t->t_dcom = av;
+ }
+ xfree((ptr_t) blk[0]);
+ blk[0] = pv[0];
+ xfree((ptr_t) pv);
+ }
+ }
+ else {
+ Char buf[BUFSIZE];
+
+ (void) Strcpy(buf, blk[1] = Dfix1(cp));
+ xfree((ptr_t) blk[1]);
+ blk[0] = globone(buf, G_ERROR);
+ }
+ return(blk[0]);
+}
+
+/*
+ * Perform io redirection.
+ * We may or maynot be forked here.
+ */
+static void
+doio(t, pipein, pipeout)
+ register struct command *t;
+ int *pipein, *pipeout;
+{
+ register int fd;
+ register Char *cp;
+ register unsigned long flags = t->t_dflg;
+
+ if (didfds || (flags & F_REPEAT))
+ return;
+ if ((flags & F_READ) == 0) {/* F_READ already done */
+ if (t->t_dlef) {
+ char tmp[MAXPATHLEN+1];
+
+ /*
+ * so < /dev/std{in,out,err} work
+ */
+ (void) dcopy(SHIN, 0);
+ (void) dcopy(SHOUT, 1);
+ (void) dcopy(SHDIAG, 2);
+ cp = splicepipe(t, t->t_dlef);
+ (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
+ tmp[MAXPATHLEN] = '\0';
+ xfree((ptr_t) cp);
+ if ((fd = open(tmp, O_RDONLY)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+#ifdef O_LARGEFILE
+ /* allow input files larger than 2Gb */
+ (void) fcntl(fd, O_LARGEFILE, 0);
+#endif /* O_LARGEFILE */
+ (void) dmove(fd, 0);
+ }
+ else if (flags & F_PIPEIN) {
+ (void) close(0);
+ (void) dup(pipein[0]);
+ (void) close(pipein[0]);
+ (void) close(pipein[1]);
+ }
+ else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
+ (void) close(0);
+ (void) open(_PATH_DEVNULL, O_RDONLY);
+ }
+ else {
+ (void) close(0);
+ (void) dup(OLDSTD);
+#if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
+ /*
+ * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved
+ * across dup()s, so we have to UNSET it here or else we get a
+ * command with NO stdin, stdout, or stderr at all (a bad thing
+ * indeed)
+ */
+ (void) close_on_exec(0, 0);
+#endif /* CLOSE_ON_EXEC && CLEX_DUPS */
+ }
+ }
+ if (t->t_drit) {
+ char tmp[MAXPATHLEN+1];
+
+ cp = splicepipe(t, t->t_drit);
+ (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
+ tmp[MAXPATHLEN] = '\0';
+ xfree((ptr_t) cp);
+ /*
+ * so > /dev/std{out,err} work
+ */
+ (void) dcopy(SHOUT, 1);
+ (void) dcopy(SHDIAG, 2);
+ if ((flags & F_APPEND) != 0) {
+#ifdef O_APPEND
+ fd = open(tmp, O_WRONLY | O_APPEND);
+#else /* !O_APPEND */
+ fd = open(tmp, O_WRONLY);
+ (void) lseek(fd, (off_t) 0, L_XTND);
+#endif /* O_APPEND */
+ }
+ else
+ fd = 0;
+ if ((flags & F_APPEND) == 0 || fd == -1) {
+ if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
+ if (flags & F_APPEND)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+ chkclob(tmp);
+ }
+ if ((fd = creat(tmp, 0666)) < 0)
+ stderror(ERR_SYSTEM, tmp, strerror(errno));
+#ifdef O_LARGEFILE
+ /* allow input files larger than 2Gb */
+ (void) fcntl(fd, O_LARGEFILE, 0);
+#endif /* O_LARGEFILE */
+ }
+ (void) dmove(fd, 1);
+ is1atty = isatty(1);
+ }
+ else if (flags & F_PIPEOUT) {
+ (void) close(1);
+ (void) dup(pipeout[1]);
+ is1atty = 0;
+ }
+ else {
+ (void) close(1);
+ (void) dup(SHOUT);
+ is1atty = isoutatty;
+# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
+ (void) close_on_exec(1, 0);
+# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
+ }
+
+ (void) close(2);
+ if (flags & F_STDERR) {
+ (void) dup(1);
+ is2atty = is1atty;
+ }
+ else {
+ (void) dup(SHDIAG);
+ is2atty = isdiagatty;
+# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
+ (void) close_on_exec(2, 0);
+# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
+ }
+ didfds = 1;
+}
+
+void
+mypipe(pv)
+ register int *pv;
+{
+
+ if (pipe(pv) < 0)
+ goto oops;
+ pv[0] = dmove(pv[0], -1);
+ pv[1] = dmove(pv[1], -1);
+ if (pv[0] >= 0 && pv[1] >= 0)
+ return;
+oops:
+ stderror(ERR_PIPE);
+}
+
+static void
+chkclob(cp)
+ register char *cp;
+{
+ struct stat stb;
+
+ if (stat(cp, &stb) < 0)
+ return;
+ if (S_ISCHR(stb.st_mode))
+ return;
+ stderror(ERR_EXISTS, cp);
+}
diff --git a/contrib/tcsh/sh.set.c b/contrib/tcsh/sh.set.c
new file mode 100644
index 0000000..76fe77f
--- /dev/null
+++ b/contrib/tcsh/sh.set.c
@@ -0,0 +1,1209 @@
+/* $Header: /src/pub/tcsh/sh.set.c,v 3.35 1998/10/25 15:10:26 christos Exp $ */
+/*
+ * sh.set.c: Setting and Clearing of variables
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.set.c,v 3.35 1998/10/25 15:10:26 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+
+extern Char HistLit;
+extern bool GotTermCaps;
+
+static void update_vars __P((Char *));
+static Char *getinx __P((Char *, int *));
+static void asx __P((Char *, int, Char *));
+static struct varent *getvx __P((Char *, int));
+static Char *xset __P((Char *, Char ***));
+static Char *operate __P((int, Char *, Char *));
+static void putn1 __P((int));
+static struct varent *madrof __P((Char *, struct varent *));
+static void unsetv1 __P((struct varent *));
+static void exportpath __P((Char **));
+static void balance __P((struct varent *, int, int));
+
+/*
+ * C Shell
+ */
+
+static void
+update_vars(vp)
+ Char *vp;
+{
+ if (eq(vp, STRpath)) {
+ exportpath(adrof(STRpath)->vec);
+ dohash(NULL, NULL);
+ }
+ else if (eq(vp, STRhistchars)) {
+ register Char *pn = varval(vp);
+
+ HIST = *pn++;
+ HISTSUB = *pn;
+ }
+ else if (eq(vp, STRpromptchars)) {
+ register Char *pn = varval(vp);
+
+ PRCH = *pn++;
+ PRCHROOT = *pn;
+ }
+ else if (eq(vp, STRhistlit)) {
+ HistLit = 1;
+ }
+ else if (eq(vp, STRuser)) {
+ tsetenv(STRKUSER, varval(vp));
+ tsetenv(STRLOGNAME, varval(vp));
+ }
+ else if (eq(vp, STRgroup)) {
+ tsetenv(STRKGROUP, varval(vp));
+ }
+ else if (eq(vp, STRwordchars)) {
+ word_chars = varval(vp);
+ }
+ else if (eq(vp, STRloginsh)) {
+ loginsh = 1;
+ }
+ else if (eq(vp, STRsymlinks)) {
+ register Char *pn = varval(vp);
+
+ if (eq(pn, STRignore))
+ symlinks = SYM_IGNORE;
+ else if (eq(pn, STRexpand))
+ symlinks = SYM_EXPAND;
+ else if (eq(pn, STRchase))
+ symlinks = SYM_CHASE;
+ else
+ symlinks = 0;
+ }
+ else if (eq(vp, STRterm)) {
+ Char *cp = varval(vp);
+ tsetenv(STRKTERM, cp);
+#ifdef DOESNT_WORK_RIGHT
+ cp = getenv("TERMCAP");
+ if (cp && (*cp != '/')) /* if TERMCAP and not a path */
+ Unsetenv(STRTERMCAP);
+#endif /* DOESNT_WORK_RIGHT */
+ GotTermCaps = 0;
+ if (noediting && Strcmp(cp, STRnetwork) != 0 &&
+ Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
+ editing = 1;
+ noediting = 0;
+ set(STRedit, Strsave(STRNULL), VAR_READWRITE);
+ }
+ ed_Init(); /* reset the editor */
+ }
+ else if (eq(vp, STRhome)) {
+ register Char *cp;
+
+ cp = Strsave(varval(vp)); /* get the old value back */
+
+ /*
+ * convert to cononical pathname (possibly resolving symlinks)
+ */
+ cp = dcanon(cp, cp);
+
+ set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */
+
+ /* and now mirror home with HOME */
+ tsetenv(STRKHOME, cp);
+ /* fix directory stack for new tilde home */
+ dtilde();
+ xfree((ptr_t) cp);
+ }
+ else if (eq(vp, STRedit)) {
+ editing = 1;
+ noediting = 0;
+ /* PWP: add more stuff in here later */
+ }
+ else if (eq(vp, STRshlvl)) {
+ tsetenv(STRKSHLVL, varval(vp));
+ }
+ else if (eq(vp, STRbackslash_quote)) {
+ bslash_quote = 1;
+ }
+ else if (eq(vp, STRdirstack)) {
+ dsetstack();
+ }
+ else if (eq(vp, STRrecognize_only_executables)) {
+ tw_cmd_free();
+ }
+#ifndef HAVENOUTMP
+ else if (eq(vp, STRwatch)) {
+ resetwatch();
+ }
+#endif /* HAVENOUTMP */
+ else if (eq(vp, STRimplicitcd)) {
+ implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
+ }
+#ifdef COLOR_LS_F
+ else if (eq(vp, STRcolor)) {
+ set_color_context();
+ }
+#endif /* COLOR_LS_F */
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+ else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
+ update_dspmbyte_vars();
+ }
+#endif
+}
+
+
+/*ARGSUSED*/
+void
+doset(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *p;
+ Char *vp, op;
+ Char **vecp;
+ bool hadsub;
+ int subscr;
+ int flags = VAR_READWRITE;
+ bool first_match = 0;
+ bool last_match = 0;
+ bool changed = 0;
+
+ USE(c);
+ v++;
+ do {
+ changed = 0;
+ /*
+ * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
+ */
+ if (*v && eq(*v, STRmr)) {
+ flags = VAR_READONLY;
+ v++;
+ changed = 1;
+ }
+ if (*v && eq(*v, STRmf) && !last_match) {
+ first_match = 1;
+ v++;
+ changed = 1;
+ }
+ if (*v && eq(*v, STRml) && !first_match) {
+ last_match = 1;
+ v++;
+ changed = 1;
+ }
+ } while(changed);
+ p = *v++;
+ if (p == 0) {
+ plist(&shvhed, flags);
+ return;
+ }
+ do {
+ hadsub = 0;
+ vp = p;
+ if (letter(*p))
+ for (; alnum(*p); p++)
+ continue;
+ if (vp == p || !letter(*vp))
+ stderror(ERR_NAME | ERR_VARBEGIN);
+ if ((p - vp) > MAXVARLEN) {
+ stderror(ERR_NAME | ERR_VARTOOLONG);
+ return;
+ }
+ if (*p == '[') {
+ hadsub++;
+ p = getinx(p, &subscr);
+ }
+ if ((op = *p) != 0) {
+ *p++ = 0;
+ if (*p == 0 && *v && **v == '(')
+ p = *v++;
+ }
+ else if (*v && eq(*v, STRequal)) {
+ op = '=', v++;
+ if (*v)
+ p = *v++;
+ }
+ if (op && op != '=')
+ stderror(ERR_NAME | ERR_SYNTAX);
+ if (eq(p, STRLparen)) {
+ register Char **e = v;
+
+ if (hadsub)
+ stderror(ERR_NAME | ERR_SYNTAX);
+ for (;;) {
+ if (!*e)
+ stderror(ERR_NAME | ERR_MISSING, ')');
+ if (**e == ')')
+ break;
+ e++;
+ }
+ p = *e;
+ *e = 0;
+ vecp = saveblk(v);
+ if (first_match)
+ flags |= VAR_FIRST;
+ else if (last_match)
+ flags |= VAR_LAST;
+
+ set1(vp, vecp, &shvhed, flags);
+ *e = p;
+ v = e + 1;
+ }
+ else if (hadsub)
+ asx(vp, subscr, Strsave(p));
+ else
+ set(vp, Strsave(p), flags);
+ update_vars(vp);
+ } while ((p = *v++) != NULL);
+}
+
+static Char *
+getinx(cp, ip)
+ register Char *cp;
+ register int *ip;
+{
+ *ip = 0;
+ *cp++ = 0;
+ while (*cp && Isdigit(*cp))
+ *ip = *ip * 10 + *cp++ - '0';
+ if (*cp++ != ']')
+ stderror(ERR_NAME | ERR_SUBSCRIPT);
+ return (cp);
+}
+
+static void
+asx(vp, subscr, p)
+ Char *vp;
+ int subscr;
+ Char *p;
+{
+ register struct varent *v = getvx(vp, subscr);
+
+ if (v->v_flags & VAR_READONLY)
+ stderror(ERR_READONLY|ERR_NAME, v->v_name);
+ xfree((ptr_t) v->vec[subscr - 1]);
+ v->vec[subscr - 1] = globone(p, G_APPEND);
+}
+
+static struct varent *
+getvx(vp, subscr)
+ Char *vp;
+ int subscr;
+{
+ register struct varent *v = adrof(vp);
+
+ if (v == 0)
+ udvar(vp);
+ if (subscr < 1 || subscr > blklen(v->vec))
+ stderror(ERR_NAME | ERR_RANGE);
+ return (v);
+}
+
+/*ARGSUSED*/
+void
+dolet(v, dummy)
+ Char **v;
+ struct command *dummy;
+{
+ register Char *p;
+ Char *vp, c, op;
+ bool hadsub;
+ int subscr;
+
+ USE(dummy);
+ v++;
+ p = *v++;
+ if (p == 0) {
+ prvars();
+ return;
+ }
+ do {
+ hadsub = 0;
+ vp = p;
+ if (letter(*p))
+ for (; alnum(*p); p++)
+ continue;
+ if (vp == p || !letter(*vp))
+ stderror(ERR_NAME | ERR_VARBEGIN);
+ if ((p - vp) > MAXVARLEN)
+ stderror(ERR_NAME | ERR_VARTOOLONG);
+ if (*p == '[') {
+ hadsub++;
+ p = getinx(p, &subscr);
+ }
+ if (*p == 0 && *v)
+ p = *v++;
+ if ((op = *p) != 0)
+ *p++ = 0;
+ else
+ stderror(ERR_NAME | ERR_ASSIGN);
+
+ /*
+ * if there is no expression after the '=' then print a "Syntax Error"
+ * message - strike
+ */
+ if (*p == '\0' && *v == NULL)
+ stderror(ERR_NAME | ERR_ASSIGN);
+
+ vp = Strsave(vp);
+ if (op == '=') {
+ c = '=';
+ p = xset(p, &v);
+ }
+ else {
+ c = *p++;
+ if (any("+-", c)) {
+ if (c != op || *p)
+ stderror(ERR_NAME | ERR_UNKNOWNOP);
+ p = Strsave(STR1);
+ }
+ else {
+ if (any("<>", op)) {
+ if (c != op)
+ stderror(ERR_NAME | ERR_UNKNOWNOP);
+ c = *p++;
+ stderror(ERR_NAME | ERR_SYNTAX);
+ }
+ if (c != '=')
+ stderror(ERR_NAME | ERR_UNKNOWNOP);
+ p = xset(p, &v);
+ }
+ }
+ if (op == '=') {
+ if (hadsub)
+ asx(vp, subscr, p);
+ else
+ set(vp, p, VAR_READWRITE);
+ }
+ else if (hadsub) {
+ struct varent *gv = getvx(vp, subscr);
+
+ asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
+ }
+ else
+ set(vp, operate(op, varval(vp), p), VAR_READWRITE);
+ update_vars(vp);
+ xfree((ptr_t) vp);
+ if (c != '=')
+ xfree((ptr_t) p);
+ } while ((p = *v++) != NULL);
+}
+
+static Char *
+xset(cp, vp)
+ Char *cp, ***vp;
+{
+ register Char *dp;
+
+ if (*cp) {
+ dp = Strsave(cp);
+ --(*vp);
+ xfree((ptr_t) ** vp);
+ **vp = dp;
+ }
+ return (putn(expr(vp)));
+}
+
+static Char *
+operate(op, vp, p)
+ int op;
+ Char *vp, *p;
+{
+ Char opr[2];
+ Char *vec[5];
+ register Char **v = vec;
+ Char **vecp = v;
+ register int i;
+
+ if (op != '=') {
+ if (*vp)
+ *v++ = vp;
+ opr[0] = (Char) op;
+ opr[1] = 0;
+ *v++ = opr;
+ if (op == '<' || op == '>')
+ *v++ = opr;
+ }
+ *v++ = p;
+ *v++ = 0;
+ i = expr(&vecp);
+ if (*vecp)
+ stderror(ERR_NAME | ERR_EXPRESSION);
+ return (putn(i));
+}
+
+static Char *putp, nbuf[50];
+
+Char *
+putn(n)
+ register int n;
+{
+ int num;
+
+ putp = nbuf;
+ if (n < 0) {
+ n = -n;
+ *putp++ = '-';
+ }
+ num = 2; /* confuse lint */
+ if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
+ *putp++ = '3';
+ n = 2768;
+#ifdef pdp11
+ }
+#else /* !pdp11 */
+ }
+ else {
+ num = 4; /* confuse lint */
+ if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
+ *putp++ = '2';
+ n = 147483648;
+ }
+ }
+#endif /* pdp11 */
+ putn1(n);
+ *putp = 0;
+ return (Strsave(nbuf));
+}
+
+static void
+putn1(n)
+ register int n;
+{
+ if (n > 9)
+ putn1(n / 10);
+ *putp++ = n % 10 + '0';
+}
+
+int
+getn(cp)
+ register Char *cp;
+{
+ register int n;
+ int sign;
+
+ if (!cp) /* PWP: extra error checking */
+ stderror(ERR_NAME | ERR_BADNUM);
+
+ sign = 0;
+ if (cp[0] == '+' && cp[1])
+ cp++;
+ if (*cp == '-') {
+ sign++;
+ cp++;
+ if (!Isdigit(*cp))
+ stderror(ERR_NAME | ERR_BADNUM);
+ }
+ n = 0;
+ while (Isdigit(*cp))
+ n = n * 10 + *cp++ - '0';
+ if (*cp)
+ stderror(ERR_NAME | ERR_BADNUM);
+ return (sign ? -n : n);
+}
+
+Char *
+value1(var, head)
+ Char *var;
+ struct varent *head;
+{
+ register struct varent *vp;
+
+ if (!var || !head) /* PWP: extra error checking */
+ return (STRNULL);
+
+ vp = adrof1(var, head);
+ return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
+}
+
+static struct varent *
+madrof(pat, vp)
+ Char *pat;
+ register struct varent *vp;
+{
+ register struct varent *vp1;
+
+ for (vp = vp->v_left; vp; vp = vp->v_right) {
+ if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
+ return vp1;
+ if (Gmatch(vp->v_name, pat))
+ return vp;
+ }
+ return vp;
+}
+
+struct varent *
+adrof1(name, v)
+ register Char *name;
+ register struct varent *v;
+{
+ int cmp;
+
+ v = v->v_left;
+ while (v && ((cmp = *name - *v->v_name) != 0 ||
+ (cmp = Strcmp(name, v->v_name)) != 0))
+ if (cmp < 0)
+ v = v->v_left;
+ else
+ v = v->v_right;
+ return v;
+}
+
+/*
+ * The caller is responsible for putting value in a safe place
+ */
+void
+set(var, val, flags)
+ Char *var, *val;
+ int flags;
+{
+ register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
+
+ vec[0] = val;
+ vec[1] = 0;
+ set1(var, vec, &shvhed, flags);
+}
+
+void
+set1(var, vec, head, flags)
+ Char *var, **vec;
+ struct varent *head;
+ int flags;
+{
+ register Char **oldv = vec;
+
+ if ((flags & VAR_NOGLOB) == 0) {
+ gflag = 0;
+ tglob(oldv);
+ if (gflag) {
+ vec = globall(oldv);
+ if (vec == 0) {
+ blkfree(oldv);
+ stderror(ERR_NAME | ERR_NOMATCH);
+ return;
+ }
+ blkfree(oldv);
+ gargv = 0;
+ }
+ }
+ /*
+ * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
+ */
+ if ( flags & (VAR_FIRST | VAR_LAST) ) {
+ /*
+ * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
+ * Method:
+ * Delete all duplicate words leaving "holes" in the word array (vec).
+ * Then remove the "holes", keeping the order of the words unchanged.
+ */
+ if (vec && vec[0] && vec[1]) { /* more than one word ? */
+ int i, j;
+ int num_items;
+
+ for (num_items = 0; vec[num_items]; num_items++)
+ continue;
+ if (flags & VAR_FIRST) {
+ /* delete duplications, keeping first occurance */
+ for (i = 1; i < num_items; i++)
+ for (j = 0; j < i; j++)
+ /* If have earlier identical item, remove i'th item */
+ if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
+ free(vec[i]);
+ vec[i] = NULL;
+ break;
+ }
+ } else if (flags & VAR_LAST) {
+ /* delete duplications, keeping last occurance */
+ for (i = 0; i < num_items - 1; i++)
+ for (j = i + 1; j < num_items; j++)
+ /* If have later identical item, remove i'th item */
+ if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
+ /* remove identical item (the first) */
+ free(vec[i]);
+ vec[i] = NULL;
+ }
+ }
+ /* Compress items - remove empty items */
+ for (j = i = 0; i < num_items; i++)
+ if (vec[i])
+ vec[j++] = vec[i];
+
+ /* NULL-fy remaining items */
+ for (; j < num_items; j++)
+ vec[j] = NULL;
+ }
+ /* don't let the attribute propagate */
+ flags &= ~(VAR_FIRST|VAR_LAST);
+ }
+ setq(var, vec, head, flags);
+}
+
+
+void
+setq(name, vec, p, flags)
+ Char *name, **vec;
+ register struct varent *p;
+ int flags;
+{
+ register struct varent *c;
+ register int f;
+
+ f = 0; /* tree hangs off the header's left link */
+ while ((c = p->v_link[f]) != 0) {
+ if ((f = *name - *c->v_name) == 0 &&
+ (f = Strcmp(name, c->v_name)) == 0) {
+ if (c->v_flags & VAR_READONLY)
+ stderror(ERR_READONLY|ERR_NAME, c->v_name);
+ blkfree(c->vec);
+ c->v_flags = flags;
+ trim(c->vec = vec);
+ return;
+ }
+ p = c;
+ f = f > 0;
+ }
+ p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
+ c->v_name = Strsave(name);
+ c->v_flags = flags;
+ c->v_bal = 0;
+ c->v_left = c->v_right = 0;
+ c->v_parent = p;
+ balance(p, f, 0);
+ trim(c->vec = vec);
+}
+
+/*ARGSUSED*/
+void
+unset(v, c)
+ Char **v;
+ struct command *c;
+{
+ bool did_roe, did_edit;
+
+ USE(c);
+ did_roe = adrof(STRrecognize_only_executables) != NULL;
+ did_edit = adrof(STRedit) != NULL;
+ unset1(v, &shvhed);
+ if (adrof(STRhistchars) == 0) {
+ HIST = '!';
+ HISTSUB = '^';
+ }
+ if (adrof(STRpromptchars) == 0) {
+ PRCH = '>';
+ PRCHROOT = '#';
+ }
+ if (adrof(STRhistlit) == 0)
+ HistLit = 0;
+ if (adrof(STRloginsh) == 0)
+ loginsh = 0;
+ if (adrof(STRwordchars) == 0)
+ word_chars = STR_WORD_CHARS;
+ if (adrof(STRedit) == 0)
+ editing = 0;
+ if (adrof(STRbackslash_quote) == 0)
+ bslash_quote = 0;
+ if (adrof(STRsymlinks) == 0)
+ symlinks = 0;
+ if (adrof(STRimplicitcd) == 0)
+ implicit_cd = 0;
+ if (did_edit && noediting && adrof(STRedit) == 0)
+ noediting = 0;
+ if (did_roe && adrof(STRrecognize_only_executables) == 0)
+ tw_cmd_free();
+#ifdef COLOR_LS_F
+ if (adrof(STRcolor) == 0)
+ set_color_context();
+#endif /* COLOR_LS_F */
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+ update_dspmbyte_vars();
+#endif
+}
+
+void
+unset1(v, head)
+ register Char *v[];
+ struct varent *head;
+{
+ register struct varent *vp;
+ register int cnt;
+
+ while (*++v) {
+ cnt = 0;
+ while ((vp = madrof(*v, head)) != NULL)
+ if (vp->v_flags & VAR_READONLY)
+ stderror(ERR_READONLY|ERR_NAME, vp->v_name);
+ else
+ unsetv1(vp), cnt++;
+ if (cnt == 0)
+ setname(short2str(*v));
+ }
+}
+
+void
+unsetv(var)
+ Char *var;
+{
+ register struct varent *vp;
+
+ if ((vp = adrof1(var, &shvhed)) == 0)
+ udvar(var);
+ unsetv1(vp);
+}
+
+static void
+unsetv1(p)
+ register struct varent *p;
+{
+ register struct varent *c, *pp;
+ register int f;
+
+ /*
+ * Free associated memory first to avoid complications.
+ */
+ blkfree(p->vec);
+ xfree((ptr_t) p->v_name);
+ /*
+ * If p is missing one child, then we can move the other into where p is.
+ * Otherwise, we find the predecessor of p, which is guaranteed to have no
+ * right child, copy it into p, and move it's left child into it.
+ */
+ if (p->v_right == 0)
+ c = p->v_left;
+ else if (p->v_left == 0)
+ c = p->v_right;
+ else {
+ for (c = p->v_left; c->v_right; c = c->v_right)
+ continue;
+ p->v_name = c->v_name;
+ p->v_flags = c->v_flags;
+ p->vec = c->vec;
+ p = c;
+ c = p->v_left;
+ }
+
+ /*
+ * Move c into where p is.
+ */
+ pp = p->v_parent;
+ f = pp->v_right == p;
+ if ((pp->v_link[f] = c) != 0)
+ c->v_parent = pp;
+ /*
+ * Free the deleted node, and rebalance.
+ */
+ xfree((ptr_t) p);
+ balance(pp, f, 1);
+}
+
+void
+setNS(cp)
+ Char *cp;
+{
+ set(cp, Strsave(STRNULL), VAR_READWRITE);
+}
+
+/*ARGSUSED*/
+void
+shift(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register struct varent *argv;
+ register Char *name;
+
+ USE(c);
+ v++;
+ name = *v;
+ if (name == 0)
+ name = STRargv;
+ else
+ (void) strip(name);
+ argv = adrof(name);
+ if (argv == 0)
+ udvar(name);
+ if (argv->vec[0] == 0)
+ stderror(ERR_NAME | ERR_NOMORE);
+ lshift(argv->vec, 1);
+ update_vars(name);
+}
+
+static Char STRsep[2] = { PATHSEP, '\0' };
+
+static void
+exportpath(val)
+ Char **val;
+{
+ Char *exppath;
+ size_t exppath_size = BUFSIZE;
+ exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
+
+ exppath[0] = 0;
+ if (val)
+ while (*val) {
+ while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
+ if ((exppath
+ = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
+ == NULL) {
+ xprintf(CGETS(18, 1,
+ "Warning: ridiculously long PATH truncated\n"));
+ break;
+ }
+ }
+ (void) Strcat(exppath, *val++);
+ if (*val == 0 || eq(*val, STRRparen))
+ break;
+ (void) Strcat(exppath, STRsep);
+ }
+ tsetenv(STRKPATH, exppath);
+ free(exppath);
+}
+
+#ifndef lint
+ /*
+ * Lint thinks these have null effect
+ */
+ /* macros to do single rotations on node p */
+# define rright(p) (\
+ t = (p)->v_left,\
+ (t)->v_parent = (p)->v_parent,\
+ (((p)->v_left = t->v_right) != NULL) ?\
+ (t->v_right->v_parent = (p)) : 0,\
+ (t->v_right = (p))->v_parent = t,\
+ (p) = t)
+# define rleft(p) (\
+ t = (p)->v_right,\
+ ((t)->v_parent = (p)->v_parent,\
+ ((p)->v_right = t->v_left) != NULL) ? \
+ (t->v_left->v_parent = (p)) : 0,\
+ (t->v_left = (p))->v_parent = t,\
+ (p) = t)
+#else
+static struct varent *
+rleft(p)
+ struct varent *p;
+{
+ return (p);
+}
+static struct varent *
+rright(p)
+ struct varent *p;
+{
+ return (p);
+}
+
+#endif /* ! lint */
+
+
+/*
+ * Rebalance a tree, starting at p and up.
+ * F == 0 means we've come from p's left child.
+ * D == 1 means we've just done a delete, otherwise an insert.
+ */
+static void
+balance(p, f, d)
+ register struct varent *p;
+ register int f, d;
+{
+ register struct varent *pp;
+
+#ifndef lint
+ register struct varent *t; /* used by the rotate macros */
+#endif /* !lint */
+ register int ff;
+#ifdef lint
+ ff = 0; /* Sun's lint is dumb! */
+#endif
+
+ /*
+ * Ok, from here on, p is the node we're operating on; pp is it's parent; f
+ * is the branch of p from which we have come; ff is the branch of pp which
+ * is p.
+ */
+ for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
+ ff = pp->v_right == p;
+ if (f ^ d) { /* right heavy */
+ switch (p->v_bal) {
+ case -1: /* was left heavy */
+ p->v_bal = 0;
+ break;
+ case 0: /* was balanced */
+ p->v_bal = 1;
+ break;
+ case 1: /* was already right heavy */
+ switch (p->v_right->v_bal) {
+ case 1: /* sigle rotate */
+ pp->v_link[ff] = rleft(p);
+ p->v_left->v_bal = 0;
+ p->v_bal = 0;
+ break;
+ case 0: /* single rotate */
+ pp->v_link[ff] = rleft(p);
+ p->v_left->v_bal = 1;
+ p->v_bal = -1;
+ break;
+ case -1: /* double rotate */
+ (void) rright(p->v_right);
+ pp->v_link[ff] = rleft(p);
+ p->v_left->v_bal =
+ p->v_bal < 1 ? 0 : -1;
+ p->v_right->v_bal =
+ p->v_bal > -1 ? 0 : 1;
+ p->v_bal = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else { /* left heavy */
+ switch (p->v_bal) {
+ case 1: /* was right heavy */
+ p->v_bal = 0;
+ break;
+ case 0: /* was balanced */
+ p->v_bal = -1;
+ break;
+ case -1: /* was already left heavy */
+ switch (p->v_left->v_bal) {
+ case -1: /* single rotate */
+ pp->v_link[ff] = rright(p);
+ p->v_right->v_bal = 0;
+ p->v_bal = 0;
+ break;
+ case 0: /* signle rotate */
+ pp->v_link[ff] = rright(p);
+ p->v_right->v_bal = -1;
+ p->v_bal = 1;
+ break;
+ case 1: /* double rotate */
+ (void) rleft(p->v_left);
+ pp->v_link[ff] = rright(p);
+ p->v_left->v_bal =
+ p->v_bal < 1 ? 0 : -1;
+ p->v_right->v_bal =
+ p->v_bal > -1 ? 0 : 1;
+ p->v_bal = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * If from insert, then we terminate when p is balanced. If from
+ * delete, then we terminate when p is unbalanced.
+ */
+ if ((p->v_bal == 0) ^ d)
+ break;
+ }
+}
+
+void
+plist(p, what)
+ register struct varent *p;
+ int what;
+{
+ register struct varent *c;
+ register int len;
+
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+
+ for (;;) {
+ while (p->v_left)
+ p = p->v_left;
+x:
+ if (p->v_parent == 0) /* is it the header? */
+ return;
+ if ((p->v_flags & what) != 0) {
+ len = blklen(p->vec);
+ xprintf("%S\t", p->v_name);
+ if (len != 1)
+ xputchar('(');
+ blkpr(p->vec);
+ if (len != 1)
+ xputchar(')');
+ xputchar('\n');
+ }
+ if (p->v_right) {
+ p = p->v_right;
+ continue;
+ }
+ do {
+ c = p;
+ p = p->v_parent;
+ } while (p->v_right == c);
+ goto x;
+ }
+}
+
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+bool dspmbyte_ls;
+
+void
+update_dspmbyte_vars()
+{
+ int lp, iskcode;
+ Char *dstr1;
+ struct varent *vp;
+
+ /* if variable "nokanji" is set, multi-byte display is disabled */
+ if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
+ _enable_mbdisp = 1;
+ dstr1 = vp->vec[0];
+ if(eq (dstr1, STRKSJIS))
+ iskcode = 1;
+ else if (eq(dstr1, STRKEUC))
+ iskcode = 2;
+ else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
+ iskcode = 0;
+ }
+ else {
+ xprintf(CGETS(18, 2,
+ "Warning: unknown multibyte display; using default(euc(JP))\n"));
+ iskcode = 2;
+ }
+ if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
+ dspmbyte_ls = 1;
+ else
+ dspmbyte_ls = 0;
+ for (lp = 0; lp < 256 && iskcode > 0; lp++) {
+ switch (iskcode) {
+ case 1:
+ /* Shift-JIS */
+ _cmap[lp] = _cmap_mbyte[lp];
+ _mbmap[lp] = _mbmap_sjis[lp];
+ break;
+ case 2:
+ /* 2 ... euc */
+ _cmap[lp] = _cmap_mbyte[lp];
+ _mbmap[lp] = _mbmap_euc[lp];
+ break;
+ default:
+ xprintf(CGETS(18, 3,
+ "Warning: unknown multibyte code %d; multibyte disabled\n"),
+ iskcode);
+ _cmap[lp] = _cmap_c[lp];
+ _mbmap[lp] = 0; /* Default map all 0 */
+ _enable_mbdisp = 0;
+ break;
+ }
+ }
+ if (iskcode == 0) {
+ /* check original table */
+ if (Strlen(dstr1) != 256) {
+ xprintf(CGETS(18, 4,
+ "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
+ Strlen(dstr1));
+ _enable_mbdisp = 0;
+ }
+ for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
+ if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
+ xprintf(CGETS(18, 4,
+ "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
+ lp);
+ _enable_mbdisp = 0;
+ break;
+ }
+ }
+ /* set original table */
+ for (lp = 0; lp < 256; lp++) {
+ if (_enable_mbdisp == 1) {
+ _cmap[lp] = _cmap_mbyte[lp];
+ _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
+ }
+ else {
+ _cmap[lp] = _cmap_c[lp];
+ _mbmap[lp] = 0; /* Default map all 0 */
+ }
+ }
+ }
+ }
+ else {
+ for (lp = 0; lp < 256; lp++) {
+ _cmap[lp] = _cmap_c[lp];
+ _mbmap[lp] = 0; /* Default map all 0 */
+ }
+ _enable_mbdisp = 0;
+ dspmbyte_ls = 0;
+ }
+#ifdef MBYTEDEBUG /* Sorry, use for beta testing */
+ {
+ Char mbmapstr[300];
+ for (lp = 0; lp < 256; lp++) {
+ mbmapstr[lp] = _mbmap[lp] + '0';
+ mbmapstr[lp+1] = 0;
+ }
+ set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
+ }
+#endif /* MBYTEMAP */
+}
+
+/* dspkanji/dspmbyte autosetting */
+/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
+void
+autoset_dspmbyte(pcp)
+ Char *pcp;
+{
+ int i;
+ struct dspm_autoset_Table {
+ Char *n;
+ Char *v;
+ } dspmt[] = {
+ { STRLANGEUC, STRKEUC },
+ { STRLANGEUCB, STRKEUC },
+ { STRLANGSJIS, STRKSJIS },
+ { STRLANGSJISB, STRKSJIS },
+ { NULL, NULL }
+ };
+
+ if (*pcp == '\0')
+ return;
+
+ for (i = 0; dspmt[i].n; i++) {
+ if (eq(pcp, dspmt[i].n)) {
+ set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
+ update_dspmbyte_vars();
+ break;
+ }
+ }
+}
+#endif
diff --git a/contrib/tcsh/sh.time.c b/contrib/tcsh/sh.time.c
new file mode 100644
index 0000000..f670fdc
--- /dev/null
+++ b/contrib/tcsh/sh.time.c
@@ -0,0 +1,711 @@
+/* $Header: /src/pub/tcsh/sh.time.c,v 3.20 1998/11/24 18:17:38 christos Exp $ */
+/*
+ * sh.time.c: Shell time keeping and printing.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: sh.time.c,v 3.20 1998/11/24 18:17:38 christos Exp $")
+
+#ifdef SUNOS4
+# include <machine/param.h>
+#endif /* SUNOS4 */
+
+/*
+ * C Shell - routines handling process timing and niceing
+ */
+#ifdef BSDTIMES
+# ifndef RUSAGE_SELF
+# define RUSAGE_SELF 0
+# define RUSAGE_CHILDREN -1
+# endif /* RUSAGE_SELF */
+#else /* BSDTIMES */
+struct tms times0;
+#endif /* BSDTIMES */
+
+#if !defined(BSDTIMES) && !defined(_SEQUENT_)
+# ifdef POSIX
+static void pdtimet __P((clock_t, clock_t));
+# else /* ! POSIX */
+static void pdtimet __P((time_t, time_t));
+# endif /* ! POSIX */
+#else /* BSDTIMES || _SEQUENT_ */
+static void tvadd __P((timeval_t *, timeval_t *));
+static void pdeltat __P((timeval_t *, timeval_t *));
+#endif /* BSDTIMES || _SEQUENT_ */
+
+void
+settimes()
+{
+#ifdef BSDTIMES
+ struct sysrusage ruch;
+#ifdef convex
+ memset(&ru0, 0, sizeof(ru0));
+ memset(&ruch, 0, sizeof(ruch));
+#endif /* convex */
+
+ (void) gettimeofday(&time0, NULL);
+ (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
+ (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
+ ruadd(&ru0, &ruch);
+#else
+# ifdef _SEQUENT_
+ struct process_stats ruch;
+
+ (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
+ ruadd(&ru0, &ruch);
+# else /* _SEQUENT_ */
+# ifndef COHERENT
+ time0 = times(&times0);
+# else /* !COHERENT */
+ time0 = HZ * time(NULL);
+ times(&times0);
+# endif /* !COHERENT */
+ times0.tms_stime += times0.tms_cstime;
+ times0.tms_utime += times0.tms_cutime;
+ times0.tms_cstime = 0;
+ times0.tms_cutime = 0;
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+}
+
+/*
+ * dotime is only called if it is truly a builtin function and not a
+ * prefix to another command
+ */
+/*ARGSUSED*/
+void
+dotime(v, c)
+ Char **v;
+ struct command *c;
+{
+#ifdef BSDTIMES
+ timeval_t timedol;
+ struct sysrusage ru1, ruch;
+#ifdef convex
+ memset(&ru1, 0, sizeof(ru1));
+ memset(&ruch, 0, sizeof(ruch));
+#endif /* convex */
+
+ (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
+ (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
+ ruadd(&ru1, &ruch);
+ (void) gettimeofday(&timedol, NULL);
+ prusage(&ru0, &ru1, &timedol, &time0);
+#else
+# ifdef _SEQUENT_
+ timeval_t timedol;
+ struct process_stats ru1, ruch;
+
+ (void) get_process_stats(&timedol, PS_SELF, &ru1, &ruch);
+ ruadd(&ru1, &ruch);
+ prusage(&ru0, &ru1, &timedol, &time0);
+# else /* _SEQUENT_ */
+# ifndef POSIX
+ time_t timedol;
+# else /* POSIX */
+ clock_t timedol;
+# endif /* POSIX */
+
+ struct tms times_dol;
+
+#ifndef COHERENT
+ timedol = times(&times_dol);
+#else
+ timedol = HZ * time(NULL);
+ times(&times_dol);
+#endif
+ times_dol.tms_stime += times_dol.tms_cstime;
+ times_dol.tms_utime += times_dol.tms_cutime;
+ times_dol.tms_cstime = 0;
+ times_dol.tms_cutime = 0;
+ prusage(&times0, &times_dol, timedol, time0);
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+ USE(c);
+ USE(v);
+}
+
+/*
+ * donice is only called when it on the line by itself or with a +- value
+ */
+/*ARGSUSED*/
+void
+donice(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp;
+ int nval = 0;
+
+ USE(c);
+ v++, cp = *v++;
+ if (cp == 0)
+ nval = 4;
+ else if (*v == 0 && any("+-", cp[0]))
+ nval = getn(cp);
+#ifdef BSDNICE
+ (void) setpriority(PRIO_PROCESS, 0, nval);
+#else /* BSDNICE */
+ (void) nice(nval);
+#endif /* BSDNICE */
+}
+
+#ifdef BSDTIMES
+void
+ruadd(ru, ru2)
+ register struct sysrusage *ru, *ru2;
+{
+ tvadd(&ru->ru_utime, &ru2->ru_utime);
+ tvadd(&ru->ru_stime, &ru2->ru_stime);
+ if (ru2->ru_maxrss > ru->ru_maxrss)
+ ru->ru_maxrss = ru2->ru_maxrss;
+
+ ru->ru_ixrss += ru2->ru_ixrss;
+ ru->ru_idrss += ru2->ru_idrss;
+ ru->ru_isrss += ru2->ru_isrss;
+ ru->ru_minflt += ru2->ru_minflt;
+ ru->ru_majflt += ru2->ru_majflt;
+ ru->ru_nswap += ru2->ru_nswap;
+ ru->ru_inblock += ru2->ru_inblock;
+ ru->ru_oublock += ru2->ru_oublock;
+ ru->ru_msgsnd += ru2->ru_msgsnd;
+ ru->ru_msgrcv += ru2->ru_msgrcv;
+ ru->ru_nsignals += ru2->ru_nsignals;
+ ru->ru_nvcsw += ru2->ru_nvcsw;
+ ru->ru_nivcsw += ru2->ru_nivcsw;
+
+# ifdef convex
+ tvadd(&ru->ru_exutime, &ru2->ru_exutime);
+ ru->ru_utotal += ru2->ru_utotal;
+ ru->ru_usamples += ru2->ru_usamples;
+ ru->ru_stotal += ru2->ru_stotal;
+ ru->ru_ssamples += ru2->ru_ssamples;
+# endif /* convex */
+}
+
+#else /* BSDTIMES */
+# ifdef _SEQUENT_
+void
+ruadd(ru, ru2)
+ register struct process_stats *ru, *ru2;
+{
+ tvadd(&ru->ps_utime, &ru2->ps_utime);
+ tvadd(&ru->ps_stime, &ru2->ps_stime);
+ if (ru2->ps_maxrss > ru->ps_maxrss)
+ ru->ps_maxrss = ru2->ps_maxrss;
+
+ ru->ps_pagein += ru2->ps_pagein;
+ ru->ps_reclaim += ru2->ps_reclaim;
+ ru->ps_zerofill += ru2->ps_zerofill;
+ ru->ps_pffincr += ru2->ps_pffincr;
+ ru->ps_pffdecr += ru2->ps_pffdecr;
+ ru->ps_swap += ru2->ps_swap;
+ ru->ps_syscall += ru2->ps_syscall;
+ ru->ps_volcsw += ru2->ps_volcsw;
+ ru->ps_involcsw += ru2->ps_involcsw;
+ ru->ps_signal += ru2->ps_signal;
+ ru->ps_lread += ru2->ps_lread;
+ ru->ps_lwrite += ru2->ps_lwrite;
+ ru->ps_bread += ru2->ps_bread;
+ ru->ps_bwrite += ru2->ps_bwrite;
+ ru->ps_phread += ru2->ps_phread;
+ ru->ps_phwrite += ru2->ps_phwrite;
+}
+
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+
+#ifdef BSDTIMES
+
+/*
+ * PWP: the LOG1024 and pagetok stuff taken from the top command,
+ * written by William LeFebvre
+ */
+/* Log base 2 of 1024 is 10 (2^10 == 1024) */
+#define LOG1024 10
+
+/* Convert clicks (kernel pages) to kbytes ... */
+/* If there is no PGSHIFT defined, assume it is 11 */
+/* Is this needed for compatability with some old flavor of 4.2 or 4.1? */
+#ifdef SUNOS4
+# ifndef PGSHIFT
+# define pagetok(size) ((size) << 1)
+# else
+# if PGSHIFT>10
+# define pagetok(size) ((size) << (PGSHIFT - LOG1024))
+# else
+# define pagetok(size) ((size) >> (LOG1024 - PGSHIFT))
+# endif
+# endif
+#endif
+
+/*
+ * if any other machines return wierd values in the ru_i* stuff, put
+ * the adjusting macro here:
+ */
+#ifdef SUNOS4
+# define IADJUST(i) (pagetok(i)/2)
+#else /* SUNOS4 */
+# ifdef convex
+ /*
+ * convex has megabytes * CLK_TCK
+ * multiply by 100 since we use time in 100ths of a second in prusage
+ */
+# define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
+# else /* convex */
+# define IADJUST(i) (i)
+# endif /* convex */
+#endif /* SUNOS4 */
+
+void
+prusage(r0, r1, e, b)
+ register struct sysrusage *r0, *r1;
+ timeval_t *e, *b;
+
+#else /* BSDTIMES */
+# ifdef _SEQUENT_
+void
+prusage(r0, r1, e, b)
+ register struct process_stats *r0, *r1;
+ timeval_t *e, *b;
+
+# else /* _SEQUENT_ */
+void
+prusage(bs, es, e, b)
+ struct tms *bs, *es;
+
+# ifndef POSIX
+ time_t e, b;
+
+# else /* POSIX */
+ clock_t e, b;
+
+# endif /* POSIX */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+{
+#ifdef BSDTIMES
+ register time_t t =
+ (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
+ (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
+ (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
+ (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
+
+#else
+# ifdef _SEQUENT_
+ register time_t t =
+ (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec) * 100 +
+ (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
+ (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec) * 100 +
+ (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
+
+# else /* _SEQUENT_ */
+# ifndef POSIX
+ register time_t t = (es->tms_utime - bs->tms_utime +
+ es->tms_stime - bs->tms_stime) * 100 / HZ;
+
+# else /* POSIX */
+ register clock_t t = (es->tms_utime - bs->tms_utime +
+ es->tms_stime - bs->tms_stime) * 100 / clk_tck;
+
+# endif /* POSIX */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+
+ register char *cp;
+ register long i;
+ register struct varent *vp = adrof(STRtime);
+
+#ifdef BSDTIMES
+# ifdef convex
+ static struct system_information sysinfo;
+ long long memtmp; /* let memory calculations exceede 2Gb */
+# endif /* convex */
+ int ms = (int)
+ ((e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
+
+ cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
+#else /* !BSDTIMES */
+# ifdef _SEQUENT_
+ int ms = (int)
+ ((e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
+
+ cp = "%Uu %Ss %E %P %I+%Oio %Fpf+%Ww";
+# else /* !_SEQUENT_ */
+# ifndef POSIX
+ time_t ms = ((time_t)((e - b) / HZ) * 100) +
+ (time_t)(((e - b) % HZ) * 100) / HZ;
+# else /* POSIX */
+ clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
+ (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
+# endif /* POSIX */
+
+ cp = "%Uu %Ss %E %P";
+
+ /*
+ * the tms stuff is not very precise, so we fudge it.
+ * granularity fix: can't be more than 100%
+ * this breaks in multi-processor systems...
+ * maybe I should take it out and let people see more then 100%
+ * utilizations.
+ */
+# if 0
+ if (ms < t && ms != 0)
+ ms = t;
+# endif
+# endif /*! _SEQUENT_ */
+#endif /* !BSDTIMES */
+#ifdef TDEBUG
+ xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
+ es->tms_utime, bs->tms_utime);
+ xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
+ es->tms_stime, bs->tms_stime);
+ xprintf("ms %lu e %lu b %lu\n", ms, e, b);
+ xprintf("t %lu\n", t);
+#endif /* TDEBUG */
+
+ if (vp && vp->vec[0] && vp->vec[1])
+ cp = short2str(vp->vec[1]);
+ for (; *cp; cp++)
+ if (*cp != '%')
+ xputchar(*cp);
+ else if (cp[1])
+ switch (*++cp) {
+
+ case 'U': /* user CPU time used */
+#ifdef BSDTIMES
+ pdeltat(&r1->ru_utime, &r0->ru_utime);
+#else
+# ifdef _SEQUENT_
+ pdeltat(&r1->ps_utime, &r0->ps_utime);
+# else /* _SEQUENT_ */
+# ifndef POSIX
+ pdtimet(es->tms_utime, bs->tms_utime);
+# else /* POSIX */
+ pdtimet(es->tms_utime, bs->tms_utime);
+# endif /* POSIX */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+ break;
+
+ case 'S': /* system CPU time used */
+#ifdef BSDTIMES
+ pdeltat(&r1->ru_stime, &r0->ru_stime);
+#else
+# ifdef _SEQUENT_
+ pdeltat(&r1->ps_stime, &r0->ps_stime);
+# else /* _SEQUENT_ */
+# ifndef POSIX
+ pdtimet(es->tms_stime, bs->tms_stime);
+# else /* POSIX */
+ pdtimet(es->tms_stime, bs->tms_stime);
+# endif /* POSIX */
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+ break;
+
+ case 'E': /* elapsed (wall-clock) time */
+#ifdef BSDTIMES
+ pcsecs((long) ms);
+#else /* BSDTIMES */
+ pcsecs(ms);
+#endif /* BSDTIMES */
+ break;
+
+ case 'P': /* percent time spent running */
+ /* check if the process did not run */
+#ifdef convex
+ /*
+ * scale the cpu %- ages by the number of processors
+ * available on this machine
+ */
+ if ((sysinfo.cpu_count == 0) &&
+ (getsysinfo(SYSINFO_SIZE, &sysinfo) < 0))
+ sysinfo.cpu_count = 1;
+ i = (ms == 0) ? 0 : (t * 1000 / (ms * sysinfo.cpu_count));
+#else /* convex */
+ i = (ms == 0) ? 0 : (t * 1000 / ms);
+#endif /* convex */
+ xprintf("%ld.%01ld%%", i / 10, i % 10); /* nn.n% */
+ break;
+
+#ifdef BSDTIMES
+ case 'W': /* number of swaps */
+ i = r1->ru_nswap - r0->ru_nswap;
+ xprintf("%ld", i);
+ break;
+
+#ifdef convex
+ case 'X': /* (average) shared text size */
+ memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
+ (long long)r0->ru_ixrss) /
+ (long long)t);
+ xprintf("%lu", (unsigned long)memtmp);
+
+ break;
+
+ case 'D': /* (average) unshared data size */
+ memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
+ (long long)r1->ru_isrss -
+ ((long long)r0->ru_idrss +
+ (long long)r0->ru_isrss)) /
+ (long long)t);
+ xprintf("%lu", (unsigned long)memtmp);
+ break;
+
+ case 'K': /* (average) total data memory used */
+ memtmp = (t == 0 ? 0LL : IADJUST(((long long)r1->ru_ixrss +
+ (long long)r1->ru_isrss +
+ (long long)r1->ru_idrss) -
+ ((long long)r0->ru_ixrss +
+ (long long)r0->ru_idrss +
+ (long long)r0->ru_isrss)) /
+ (long long)t);
+ xprintf("%lu", (unsigned long)memtmp);
+ break;
+#else /* !convex */
+ case 'X': /* (average) shared text size */
+ xprintf("%ld", t == 0 ? 0L :
+ IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
+ break;
+
+ case 'D': /* (average) unshared data size */
+ xprintf("%ld", t == 0 ? 0L :
+ IADJUST(r1->ru_idrss + r1->ru_isrss -
+ (r0->ru_idrss + r0->ru_isrss)) / t);
+ break;
+
+ case 'K': /* (average) total data memory used */
+ xprintf("%ld", t == 0 ? 0L :
+ IADJUST((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
+ (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
+ break;
+#endif /* convex */
+ case 'M': /* max. Resident Set Size */
+#ifdef SUNOS4
+ xprintf("%ld", pagetok(r1->ru_maxrss));
+#else
+# ifdef convex
+ xprintf("%ld", r1->ru_maxrss * 4L);
+# else /* !convex */
+ xprintf("%ld", r1->ru_maxrss / 2L);
+# endif /* convex */
+#endif /* SUNOS4 */
+ break;
+
+ case 'F': /* page faults */
+ xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
+ break;
+
+ case 'R': /* page reclaims */
+ xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
+ break;
+
+ case 'I': /* FS blocks in */
+ xprintf("%ld", r1->ru_inblock - r0->ru_inblock);
+ break;
+
+ case 'O': /* FS blocks out */
+ xprintf("%ld", r1->ru_oublock - r0->ru_oublock);
+ break;
+
+# ifdef convex
+ case 'C': /* CPU parallelization factor */
+ if (r1->ru_usamples != 0LL) {
+ long long parr = ((r1->ru_utotal * 100LL) /
+ r1->ru_usamples);
+ xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
+ } else
+ xprintf("?");
+ break;
+# endif /* convex */
+ case 'r': /* PWP: socket messages recieved */
+ xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
+ break;
+
+ case 's': /* PWP: socket messages sent */
+ xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
+ break;
+
+ case 'k': /* PWP: signals received */
+ xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
+ break;
+
+ case 'w': /* PWP: voluntary context switches (waits) */
+ xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
+ break;
+
+ case 'c': /* PWP: involuntary context switches */
+ xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
+ break;
+#else /* BSDTIMES */
+# ifdef _SEQUENT_
+ case 'W': /* number of swaps */
+ i = r1->ps_swap - r0->ps_swap;
+ xprintf("%ld", i);
+ break;
+
+ case 'M':
+ xprintf("%ld", r1->ps_maxrss / 2);
+ break;
+
+ case 'F':
+ xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
+ break;
+
+ case 'R':
+ xprintf("%ld", r1->ps_reclaim - r0->ps_reclaim);
+ break;
+
+ case 'I':
+ xprintf("%ld", r1->ps_bread - r0->ps_bread);
+ break;
+
+ case 'O':
+ xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
+ break;
+
+ case 'k':
+ xprintf("%ld", r1->ps_signal - r0->ps_signal);
+ break;
+
+ case 'w':
+ xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
+ break;
+
+ case 'c':
+ xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
+ break;
+
+ case 'Z':
+ xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
+ break;
+
+ case 'i':
+ xprintf("%ld", r1->ps_pffincr - r0->ps_pffincr);
+ break;
+
+ case 'd':
+ xprintf("%ld", r1->ps_pffdecr - r0->ps_pffdecr);
+ break;
+
+ case 'Y':
+ xprintf("%ld", r1->ps_syscall - r0->ps_syscall);
+ break;
+
+ case 'l':
+ xprintf("%ld", r1->ps_lread - r0->ps_lread);
+ break;
+
+ case 'm':
+ xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
+ break;
+
+ case 'p':
+ xprintf("%ld", r1->ps_phread - r0->ps_phread);
+ break;
+
+ case 'q':
+ xprintf("%ld", r1->ps_phwrite - r0->ps_phwrite);
+ break;
+# endif /* _SEQUENT_ */
+#endif /* BSDTIMES */
+ default:
+ break;
+ }
+ xputchar('\n');
+}
+
+#if defined(BSDTIMES) || defined(_SEQUENT_)
+static void
+pdeltat(t1, t0)
+ timeval_t *t1, *t0;
+{
+ timeval_t td;
+
+ tvsub(&td, t1, t0);
+ xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
+}
+
+static void
+tvadd(tsum, t0)
+ timeval_t *tsum, *t0;
+{
+
+ tsum->tv_sec += t0->tv_sec;
+ tsum->tv_usec += t0->tv_usec;
+ if (tsum->tv_usec >= 1000000)
+ tsum->tv_sec++, tsum->tv_usec -= 1000000;
+}
+
+void
+tvsub(tdiff, t1, t0)
+ timeval_t *tdiff, *t1, *t0;
+{
+
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0)
+ tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+#else /* !BSDTIMES && !_SEQUENT_ */
+static void
+pdtimet(eval, bval)
+#ifndef POSIX
+ time_t eval, bval;
+
+#else /* POSIX */
+ clock_t eval, bval;
+
+#endif /* POSIX */
+{
+#ifndef POSIX
+ time_t val;
+
+#else /* POSIX */
+ clock_t val;
+
+#endif /* POSIX */
+
+#ifndef POSIX
+ val = (eval - bval) * 100 / HZ;
+#else /* POSIX */
+ val = (eval - bval) * 100 / clk_tck;
+#endif /* POSIX */
+
+ xprintf("%ld.%02ld", val / 100, val - (val / 100 * 100));
+}
+#endif /* BSDTIMES || _SEQUENT_ */
diff --git a/contrib/tcsh/sh.types.h b/contrib/tcsh/sh.types.h
new file mode 100644
index 0000000..2a9d8bf
--- /dev/null
+++ b/contrib/tcsh/sh.types.h
@@ -0,0 +1,608 @@
+/* $Header: /src/pub/tcsh/sh.types.h,v 3.36 1998/04/21 16:08:51 christos Exp $ */
+/* sh.types.h: Do the necessary typedefs for each system.
+ * Up till now I avoided making this into a separate file
+ * But I just wanted to eliminate the whole mess from sh.h
+ * In reality this should not be here! It is OS and MACHINE
+ * dependent, even between different revisions of OS's...
+ * Ideally there should be a way in c, to find out if something
+ * was typedef'ed, but unfortunately we rely in cpp kludges.
+ * Someday, this file will be removed...
+ *
+ * christos
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_sh_types
+#define _h_sh_types
+
+
+/***
+ *** LynxOS 2.1
+ ***/
+#ifdef Lynx
+# ifndef _SIGMASK_T
+# define _SIGMASK_T
+ typedef long sigmask_t;
+# endif /* _SIGMASK_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif
+
+/***
+ *** MachTen
+ ***/
+#ifdef __MACHTEN__
+# ifndef _PID_T
+# define _PID_T
+# endif
+#endif
+
+
+/***
+ *** Suns running sunos3.x - sunos4.1.x
+ ***/
+#if (defined(sun) || defined(__sun__)) && SYSVREL == 0
+/* This used to be long, but lint dissagrees... */
+# ifndef _SIGMASK_T
+# define _SIGMASK_T
+ typedef int sigmask_t;
+# endif /* _SIGMASK_T */
+# ifndef _PTR_T
+# define _PTR_T
+# ifdef __GNUC__
+ typedef void * ptr_t;
+# else
+ typedef char * ptr_t;
+# endif /* __GNUC__ */
+# endif /* _PTR_T */
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef __sys_stdtypes_h
+# define __sys_stdtypes_h
+# ifndef __lucid
+ typedef int pid_t;
+ typedef unsigned int speed_t;
+# endif
+# endif /* __sys_stdtypes.h */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+# ifndef _SPEED_T
+# define _SPEED_T
+# endif /* _SPEED_T */
+# ifndef SUNOS4
+# ifndef MACH
+# ifndef _UID_T
+# define _UID_T
+ typedef int uid_t;
+# endif /* _UID_T */
+# ifndef _GID_T
+# define _GID_T
+ typedef int gid_t;
+# endif /* _GID_T */
+# endif /* !MACH */
+# endif /* !SUNOS4 */
+#endif /* (sun || __sun__) && SYSVREL == 0 */
+
+
+/***
+ *** Hp's running hpux 7.0 or 8.0
+ ***/
+#ifdef __hpux
+# ifndef _SIZE_T
+# define _SIZE_T
+ typedef unsigned int size_t;
+# endif /* _SIZE_T */
+
+# ifndef _PTR_T
+# define _PTR_T
+ typedef void * ptr_t;
+# endif /* _PTR_T */
+
+# ifndef _PID_T
+# define _PID_T
+ typedef long pid_t;
+# endif /* _PID_T */
+
+# ifndef _SIGMASK_T
+# define _SIGMASK_T
+ typedef long sigmask_t;
+# endif /* _SIGMASK_T */
+
+# ifndef _SPEED_T
+ /* I thought POSIX was supposed to protect all typedefs! */
+# define _SPEED_T
+# endif /* _SPEED_T */
+
+extern uid_t getuid(), geteuid();
+extern gid_t getgid(), getegid();
+extern sigmask_t sigblock();
+extern sigmask_t sigsetmask();
+extern pid_t getpid();
+extern pid_t fork();
+extern void perror();
+extern void _exit();
+extern void abort();
+extern void qsort();
+extern void free();
+extern unsigned int alarm();
+extern unsigned int sleep();
+# if HPUXVERSION < 800 /* XXX: Not true for 8.0 */
+extern void sigpause();
+extern sigmask_t sigspace();
+extern int lstat();
+extern int readlink();
+extern int sigvector();
+extern int gethostname();
+extern int ioctl();
+extern int nice();
+extern char *sbrk();
+# endif /* HPUXVERSION < 800 */
+#endif /* __hpux */
+
+#if defined(_MINIX) || defined(__EMX__) || defined(COHERENT)
+typedef char * caddr_t;
+#endif /* _MINIX || __EMX__ || COHERENT */
+
+/***
+ *** hp9000s500 running hpux-5.2
+ ***/
+#ifdef hp9000s500
+# ifndef _PTR_T
+# define _PTR_T
+ typedef char * ptr_t;
+# endif /* _PTR_T */
+#endif /* hp9000s500 */
+
+/***
+ *** Data General AViiON 88000 or Pentium, running dgux 5.4R3 or R4.11
+ ***/
+#ifdef DGUX
+# ifndef _SIZE_T
+# define _SIZE_T size_t
+ typedef unsigned int size_t;
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* DGUX */
+
+
+/***
+ *** Intel 386, ISC 386/ix v2.0.2
+ ***/
+#ifdef ISC202
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* ISC202 */
+
+/***
+ *** a PFU/Fujitsu A-xx computer SX/A Edition 60 or later
+ ***/
+#ifdef SXA
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* SXA */
+
+/***
+ *** a stellar 2600, running stellix 2.3
+ ***/
+#ifdef stellar
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* stellar */
+
+/***
+ *** BSD systems, pre and post 4.3
+ ***/
+#ifdef BSD
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* BSD */
+
+
+/***
+ *** BSD RENO advertises itself as POSIX, but
+ *** it is missing speed_t
+ ***/
+#ifdef RENO
+# ifndef _SPEED_T
+# define _SPEED_T
+ typedef unsigned int speed_t;
+# endif /* _SPEED_T */
+#endif /* RENO */
+
+
+/***
+ *** NeXT OS 3.x
+ ***/
+#ifdef NeXT
+# ifndef _SPEED_T
+# define _SPEED_T
+ typedef unsigned int speed_t;
+# endif /* _SPEED_T */
+#endif /* NeXT */
+
+/***
+ *** Utah's HPBSD
+ *** some posix & 4.4 BSD changes (pid_t is a short)
+ ***/
+#ifdef HPBSD
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* HPBSD */
+
+
+/***
+ *** Pyramid, BSD universe
+ *** In addition to the size_t
+ ***/
+#ifdef pyr
+# ifndef _PID_T
+# define _PID_T
+ typedef short pid_t;
+# endif /* _PID_T */
+#endif /* pyr */
+
+
+/***
+ *** rs6000, ibm370, ps2, rt: running flavors of aix.
+ ***/
+#ifdef IBMAIX
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef aiws
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+# endif /* !aiws */
+# ifdef _IBMR2
+# ifndef _SPEED_T
+# define _SPEED_T
+# endif /* _SPEED_T */
+# endif /* _IBMR2 */
+#endif /* IBMAIX */
+
+
+/***
+ *** Ultrix...
+ ***/
+#if defined(ultrix) || defined(__ultrix)
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* ultrix || __ultrix */
+
+
+/***
+ *** Silicon graphics IRIS4D running IRIX3_3
+ ***/
+#if defined(IRIS4D) && defined(IRIX3_3)
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* IRIS4D && IRIX3_3 */
+
+
+/***
+ *** Sequent
+ ***/
+#ifdef sequent
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* sequent */
+
+/***
+ *** Apple AUX.
+ ***/
+#ifdef OREO
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* OREO */
+
+/***
+ *** Intel 386, Hypercube
+ ***/
+#ifdef INTEL
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* INTEL */
+
+/***
+ *** Concurrent (Masscomp) running RTU 4.1A & RTU 5.0.
+ **** [RTU 6.0 from mike connor]
+ *** Added, DAS DEC-90.
+ ***/
+#ifdef masscomp
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifdef RTU6
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+# ifndef _SPEED_T
+# define _SPEED_T
+# endif /* _SPEED_T */
+#endif /* RTU6 */
+#endif /* masscomp */
+
+/***
+ *** Encore multimax running umax 4.2
+ ***/
+#ifdef ns32000
+# ifdef __TYPES_DOT_H__
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# endif /* __TYPES_DOT_H__ */
+#endif /* ns32000 */
+
+/***
+ *** Silicon Graphics IRIS 3000
+ ***
+ ***/
+#ifdef IRIS3D
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* IRIS3D */
+
+/*
+ * Motorola MPC running R32V2 (sysV88)
+ */
+#ifdef sysV88
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* sysV88 */
+
+/*
+ * Amdahl running UTS (Sys V3)
+ */
+#ifdef uts
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* uts */
+
+/*
+ * Tektronix 4300 running UTek 4.0 (BSD 4.2)
+ */
+#ifdef UTek
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _UID_T
+# define _UID_T
+ typedef int uid_t;
+# endif /* _UID_T */
+# ifndef _GID_T
+# define _GID_T
+ typedef int gid_t;
+# endif /* _GID_T */
+#endif /* UTek */
+
+/*
+ * Tektronix XD88/10 running UTekV (Sys V3)
+ */
+#ifdef UTekV
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* UTekV*/
+
+/*
+ * UnixPC aka u3b1
+ */
+#ifdef UNIXPC
+# ifdef types_h
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+# endif /* types_h */
+#endif /* UNIXPC */
+
+/*
+ * NS32000 OPUS
+ */
+#ifdef OPUS
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* OPUS */
+
+/*
+ * BBN Butterfly gp1000
+ */
+#ifdef butterfly
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* butterfly */
+
+/*
+ * Convex
+ */
+#ifdef convex
+# if defined(__SIZE_T) && !defined(_SIZE_T)
+# define _SIZE_T
+# endif /* __SIZE_T && !_SIZE_T */
+#endif /* convex */
+
+/*
+ * Alliant FX-2800/FX-80
+ */
+#ifdef alliant
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+# ifdef mc68000
+ typedef int pid_t; /* FX-80 */
+# else
+ typedef short pid_t; /* FX-2800 */
+# endif
+#endif /* alliant */
+
+/*
+ * DNIX
+ */
+#ifdef DNIX
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* DNIX */
+
+/*
+ * Apollo running Domain/OS SR10.3 or greater
+ */
+#ifdef apollo
+# ifndef _PID_T
+# define _PID_T
+ typedef int pid_t; /* Older versions might not like that */
+# endif /* _PID_T */
+#endif /* apollo */
+
+/*
+ * Vax running VMS_POSIX
+ */
+#ifdef _VMS_POSIX
+# ifndef _SIZE_T
+# define _SIZE_T
+# endif /* _SIZE_T */
+#endif /* _VMS_POSIX */
+
+/***
+ *** a pdp/11, running 2BSD
+ ***/
+#ifdef pdp11
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* pdp11 */
+
+/***
+ *** a Harris, running CX/UX
+ ***/
+#ifdef _CX_UX
+# ifndef _PID_T
+# define _PID_T
+# endif /* _PID_T */
+#endif /* _CX_UX */
+
+/***
+ *** Catch all for non POSIX and/or non ANSI systems.
+ *** Systems up to spec *should* define these automatically
+ *** I am open to suggestions on how to do this correctly!
+ ***/
+
+#ifndef __STDC__
+
+# ifndef _SIZE_T
+# define _SIZE_T
+ typedef int size_t; /* As sun comments ??? : meaning I take it */
+# endif /* _SIZE_T */ /* Until we make the world ANSI... */
+
+#endif /* ! __STDC__ */
+
+#ifndef POSIX
+
+# ifndef _PID_T
+# define _PID_T
+ typedef int pid_t;
+# endif /* _PID_T */
+
+# ifndef _SPEED_T
+# define _SPEED_T
+ typedef unsigned int speed_t;
+# endif /* _SPEED_T */
+
+# ifndef _PTR_T
+# define _PTR_T
+ typedef char * ptr_t;
+#endif /* _PTR_T */
+
+# ifndef _IOCTL_T
+# define _IOCTL_T
+ typedef char * ioctl_t; /* Third arg of ioctl */
+# endif /* _IOCTL_T */
+
+#endif /* ! POSIX */
+
+
+
+/***
+ *** This is our own junk types.
+ ***/
+#ifndef _PTR_T
+# define _PTR_T
+ typedef void * ptr_t;
+#endif /* _PTR_T */
+
+#ifndef _SIGMASK_T
+# define _SIGMASK_T
+ typedef int sigmask_t;
+#endif /* _SIGMASK_T */
+
+#ifndef _IOCTL_T
+# define _IOCTL_T
+ typedef void * ioctl_t; /* Third arg of ioctl */
+#endif /* _IOCTL_T */
+
+#endif /* _h_sh_types */
diff --git a/contrib/tcsh/snames.h b/contrib/tcsh/snames.h
new file mode 100644
index 0000000..0eefa25
--- /dev/null
+++ b/contrib/tcsh/snames.h
@@ -0,0 +1,88 @@
+/* $Header: /src/pub/tcsh/snames.h,v 1.3 1996/04/26 19:20:31 christos Exp $ */
+/*
+ * snames.h: Short names for old compilers
+ */
+#ifndef _snames_h
+#define _snames_h
+
+#define tw_cmd_add twcmdadd
+#define tw_cmd_alias twcmdalias
+#define tw_cmd_sort twcmdsort
+#define tw_cmd_start twcmdstart
+#define tw_logname_end twnameend
+#define tw_logname_next twnamenext
+#define tw_logname_start twnamestart
+#define tw_file_next twfilenext
+#define tw_file_start twfilestart
+#define tw_item_add twitemadd
+#define tw_item_find twitemfind
+#define tw_item_get twitemget
+#define tw_bind_next twbindnext
+#define tw_bind_start twbindstart
+#define tw_limit_next twlimitnext
+#define tw_limit_start twlimitstart
+#define tw_collect twcllct
+#define tw_collect_items twcllcti
+#define e_complete ecomp
+#define e_complete_all ecompall
+#define e_complete_back ecompback
+#define e_complete_fwd ecompfwd
+#define e_correct ecrrct
+#define e_correctl ecrrctl
+#define e_expand_glob eexpandglob
+#define e_expand_vars eexpandvars
+#define e_delnext edelnxt
+#define e_delnext_eof edelnxteof
+#define e_delnext_list edelnxtlst
+#define e_delnext_list_eof edellsteof
+#define e_delwordnext edelwrdnext
+#define e_delwordprev edelwrdprev
+#define e_expand eexp
+#define e_expand_history eexphistory
+#define e_expand_vars eexpvars
+#define e_tty_starto ettystarto
+#define e_tty_stopo ettystopo
+#define v_csearch_back vcsrchback
+#define v_csearch_fwd vcsrchfwd
+#define v_charto_back vchartovack
+#define v_charto_fwd vchartofwd
+#define v_rchar_back vrcharback
+#define v_rchar_fwd vrcharfwd
+#define v_rsrch_back vrsrchback
+#define v_rsrch_fwd vrsrchfwd
+#define ed_InitMaps edInitMaps
+#define ed_InitMetaBindings edInitMetaBindings
+#define QuoteModeOff QuoteOff
+#define QuoteModeOn QuoteOn
+#define GetNextChar GetNxtChar
+#define GetNextCommand GetNxtCommand
+#define tty_gettabs ttygettabs
+#define tty_getty ttygetty
+#define printkey prntkey
+#define printkeys prntkeys
+#define STRprompt STRpmpt
+#define STRprompt2 STRpmpt2
+#define STRprompt3 STRpmpt3
+#define STRtildotdirs STRtdotdirs
+#define STRtildothist STRtdothist
+#define STRpushdsilent STRpushsilent
+#define STRpushdtohome STRpushtohome
+#define STRdefault STRdef
+#define STRdefautologout STRdefautologout
+#define STRfakecom STRfake
+#define STRfakecom1 STRfake1
+#define STRLparen STRLpar
+#define STRLparensp STRLparsp
+#define STRspLarrowsp STRspLarrowsp
+#define STRspLarrow2sp STRspL2arrowsp
+#define STRspRarrow STRspRarrow
+#define STRspRarrow2 STRspR2arrow
+#define STRcontinue STRcont
+#define STRcontinue_args STRcont_args
+#define STRsldotcshrc STRsdotcshrc
+#define STRsldottcshrc STRsdottcshrc
+#define STRsldotlogin STRsdotlogin
+#define STRlistmax STRlmax
+#define STRlistmaxrows STRlmaxrows
+
+#endif /* _snames_h */
diff --git a/contrib/tcsh/src.desc b/contrib/tcsh/src.desc
new file mode 100644
index 0000000..7262cc7
--- /dev/null
+++ b/contrib/tcsh/src.desc
@@ -0,0 +1,72 @@
+Editor functions (ed.*c)
+ed.chared.c: Editor basic function implementation. (Motion/Search etc.)
+ed.defns.c: Editor command tables.
+ed.init.c: Editor initialization. Tty/signal setup.
+ed.term.c: Tty driver dependent initialization portion.
+ed.inputl.c: Editor input, editor command parser, and dispatcher.
+ed.refresh.c: Editor refreshing. How to change the old line to the current.
+ed.screen.c: Termcap related functions.
+ed.xmap.c: Key macro handling.
+
+glob.c: The 4.4BSD globbing library function.
+
+Shell functions (sh*.c). All these files are from csh.
+sh.c: Initialization, command loop and script handling.
+sh.char.c: Character classification tables.
+sh.dir.c: Directory handling (cd, pushd, popd, dirs). Initialization
+ and symbolic link resolution.
+sh.dol.c: Input line processor. Dollar/History expansion.
+sh.err.c: Error handling routines and table.
+sh.exec.c: Command execution (searching and executing commands)
+ also which builtin.
+sh.exp.c: Expression evaluation.
+sh.file.c: Old csh file completion. Not used in tcsh.
+sh.func.c: Csh builtin functions.
+sh.glob.c: Wildcard matching. Also backquote, brace and tilde evaluation.
+sh.hist.c: History book-keeping.
+sh.init.c: Signal and builtin tables.
+sh.lex.c: Lexical analyzer.
+sh.misc.c: General purpose utilities.
+sh.parse.c: Parser. Not really a parser. Recognizes sequences of tokens
+ as builtins.
+sh.print.c: Primitive output (basic character output).
+sh.proc.c: Job handling. Adds new children to the job list.
+ Catches dead children and removes them from the job list.
+ Builtins for stopping/killing/ and moving jobs to the background
+ foreground.
+sh.sem.c: Job spawning (nice and time are handled here too) and I/O
+ redirection.
+sh.set.c: Variable setting.
+sh.time.c: Time keeping and reporting.
+
+Tcsh additions (tc*.c)
+tc.alloc.c: Malloc/Free
+tc.bind.c: Key binding user access functions.
+tc.const.c: Short String constants.
+tc.disc.c: Line discipline set/clear.
+tc.func.c: Tcsh additional builtins.
+tc.os.c: OS dependencies/system call emulations.
+tc.printf.c: Stdio like printf using the routines in sh.print.c
+tc.prompt.c: Prompt expansion.
+tc.sched.c: Scheduling commands handling.
+tc.sig.c: Signal emulation for SVR2, SVR1 and V5.
+tc.str.c: <string.h> for short strings.
+tc.vers.c: HOSTTYPE and $version
+tc.who.c: Watch variable handling.
+
+Spelling, listing, and completion (tw*.c)
+tw.help.c: Display help for a command by catting a file.
+tw.init.c: Initialization and some utilities.
+tw.parse.c: All the listing and completion. Tries to tokenize the line
+ and figure out where the word(s) started and if they were
+ commands or not. Then it applies the requested function to
+ the word fragment.
+tw.spell.c: String spelling correction.
+tw.comp.c: File completion builtin
+
+OS/Dependent files
+mi.termios.c: Minix termios emulation
+mi.varargs.h: Minix varargs
+mi.wait.h: Minix wait.
+ma.setp.c: MACH's setpath() library function
+atp.termcap.c: Termcap routines for vmsposix
diff --git a/contrib/tcsh/tc.alloc.c b/contrib/tcsh/tc.alloc.c
new file mode 100644
index 0000000..b2771db
--- /dev/null
+++ b/contrib/tcsh/tc.alloc.c
@@ -0,0 +1,637 @@
+/* $Header: /src/pub/tcsh/tc.alloc.c,v 3.34 1999/04/20 07:48:49 christos Exp $ */
+/*
+ * tc.alloc.c (Caltech) 2/21/82
+ * Chris Kingsley, kingsley@cit-20.
+ *
+ * This is a very fast storage allocator. It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size. Blocks that
+ * don't exactly fit are passed up to the next larger size. In this
+ * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
+ * This is designed for use in a program that uses vast quantities of memory,
+ * but bombs when it runs out.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.alloc.c,v 3.34 1999/04/20 07:48:49 christos Exp $")
+
+static char *memtop = NULL; /* PWP: top of current memory */
+static char *membot = NULL; /* PWP: bottom of allocatable memory */
+
+int dont_free = 0;
+
+#if defined(_VMS_POSIX) || defined(_AMIGA_MEMORY)
+# define NO_SBRK
+#endif
+
+#ifdef WINNT
+# define malloc fmalloc
+# define free ffree
+# define calloc fcalloc
+# define realloc frealloc
+#endif /* WINNT */
+
+#ifndef SYSMALLOC
+
+#undef RCHECK
+#undef DEBUG
+
+#ifdef SX
+extern void* sbrk();
+#endif
+/*
+ * Lots of os routines are busted and try to free invalid pointers.
+ * Although our free routine is smart enough and it will pick bad
+ * pointers most of the time, in cases where we know we are going to get
+ * a bad pointer, we'd rather leak.
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef unsigned char U_char; /* we don't really have signed chars */
+typedef unsigned int U_int;
+typedef unsigned short U_short;
+typedef unsigned long U_long;
+
+
+/*
+ * The overhead on a block is at least 4 bytes. When free, this space
+ * contains a pointer to the next free block, and the bottom two bits must
+ * be zero. When in use, the first byte is set to MAGIC, and the second
+ * byte is the size index. The remaining bytes are for alignment.
+ * If range checking is enabled and the size of the block fits
+ * in two bytes, then the top two bytes hold the size of the requested block
+ * plus the range checking words, and the header word MINUS ONE.
+ */
+
+
+#define MEMALIGN(a) (((a) + ROUNDUP) & ~ROUNDUP)
+
+union overhead {
+ union overhead *ov_next; /* when free */
+ struct {
+ U_char ovu_magic; /* magic number */
+ U_char ovu_index; /* bucket # */
+#ifdef RCHECK
+ U_short ovu_size; /* actual block size */
+ U_int ovu_rmagic; /* range magic number */
+#endif
+ } ovu;
+#define ov_magic ovu.ovu_magic
+#define ov_index ovu.ovu_index
+#define ov_size ovu.ovu_size
+#define ov_rmagic ovu.ovu_rmagic
+};
+
+#define MAGIC 0xfd /* magic # on accounting info */
+#define RMAGIC 0x55555555 /* magic # on range info */
+#ifdef RCHECK
+#define RSLOP sizeof (U_int)
+#else
+#define RSLOP 0
+#endif
+
+
+#define ROUNDUP 7
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3). The
+ * smallest allocatable block is 8 bytes. The overhead information
+ * precedes the data area returned to the user.
+ */
+#define NBUCKETS ((sizeof(long) << 3) - 3)
+static union overhead *nextf[NBUCKETS] IZERO_STRUCT;
+
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+static U_int nmalloc[NBUCKETS] IZERO_STRUCT;
+
+#ifndef lint
+static int findbucket __P((union overhead *, int));
+static void morecore __P((int));
+#endif
+
+
+#ifdef DEBUG
+# define CHECK(a, str, p) \
+ if (a) { \
+ xprintf(str, p); \
+ xprintf(" (memtop = %lx membot = %lx)\n", memtop, membot); \
+ abort(); \
+ }
+#else
+# define CHECK(a, str, p) \
+ if (a) { \
+ xprintf(str, p); \
+ xprintf(" (memtop = %lx membot = %lx)\n", memtop, membot); \
+ return; \
+ }
+#endif
+
+memalign_t
+malloc(nbytes)
+ register size_t nbytes;
+{
+#ifndef lint
+ register union overhead *p;
+ register int bucket = 0;
+ register unsigned shiftr;
+
+ /*
+ * Convert amount of memory requested into closest block size stored in
+ * hash buckets which satisfies request. Account for space used per block
+ * for accounting.
+ */
+#ifdef SUNOS4
+ /*
+ * SunOS localtime() overwrites the 9th byte on an 8 byte malloc()....
+ * so we get one more...
+ * From Michael Schroeder: This is not true. It depends on the
+ * timezone string. In Europe it can overwrite the 13th byte on a
+ * 12 byte malloc.
+ * So we punt and we always allocate an extra byte.
+ */
+ nbytes++;
+#endif
+
+ nbytes = MEMALIGN(MEMALIGN(sizeof(union overhead)) + nbytes + RSLOP);
+ shiftr = (nbytes - 1) >> 2;
+
+ /* apart from this loop, this is O(1) */
+ while ((shiftr >>= 1) != 0)
+ bucket++;
+ /*
+ * If nothing in hash bucket right now, request more memory from the
+ * system.
+ */
+ if (nextf[bucket] == NULL)
+ morecore(bucket);
+ if ((p = (union overhead *) nextf[bucket]) == NULL) {
+ child++;
+#ifndef DEBUG
+ stderror(ERR_NOMEM);
+#else
+ showall(NULL, NULL);
+ xprintf(CGETS(19, 1, "nbytes=%d: Out of memory\n"), nbytes);
+ abort();
+#endif
+ /* fool lint */
+ return ((memalign_t) 0);
+ }
+ /* remove from linked list */
+ nextf[bucket] = nextf[bucket]->ov_next;
+ p->ov_magic = MAGIC;
+ p->ov_index = bucket;
+ nmalloc[bucket]++;
+#ifdef RCHECK
+ /*
+ * Record allocated size of block and bound space with magic numbers.
+ */
+ p->ov_size = (p->ov_index <= 13) ? nbytes - 1 : 0;
+ p->ov_rmagic = RMAGIC;
+ *((U_int *) (((caddr_t) p) + nbytes - RSLOP)) = RMAGIC;
+#endif
+ return ((memalign_t) (((caddr_t) p) + MEMALIGN(sizeof(union overhead))));
+#else
+ if (nbytes)
+ return ((memalign_t) 0);
+ else
+ return ((memalign_t) 0);
+#endif /* !lint */
+}
+
+#ifndef lint
+/*
+ * Allocate more memory to the indicated bucket.
+ */
+static void
+morecore(bucket)
+ register int bucket;
+{
+ register union overhead *op;
+ register int rnu; /* 2^rnu bytes will be requested */
+ register int nblks; /* become nblks blocks of the desired size */
+ register int siz;
+
+ if (nextf[bucket])
+ return;
+ /*
+ * Insure memory is allocated on a page boundary. Should make getpageize
+ * call?
+ */
+ op = (union overhead *) sbrk(0);
+ memtop = (char *) op;
+ if (membot == NULL)
+ membot = memtop;
+ if ((long) op & 0x3ff) {
+ memtop = (char *) sbrk((int) (1024 - ((long) op & 0x3ff)));
+ memtop += (long) (1024 - ((long) op & 0x3ff));
+ }
+
+ /* take 2k unless the block is bigger than that */
+ rnu = (bucket <= 8) ? 11 : bucket + 3;
+ nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
+ memtop = (char *) sbrk(1 << rnu); /* PWP */
+ op = (union overhead *) memtop;
+ /* no more room! */
+ if ((long) op == -1)
+ return;
+ memtop += (long) (1 << rnu);
+ /*
+ * Round up to minimum allocation size boundary and deduct from block count
+ * to reflect.
+ */
+ if (((U_long) op) & ROUNDUP) {
+ op = (union overhead *) (((U_long) op + (ROUNDUP + 1)) & ~ROUNDUP);
+ nblks--;
+ }
+ /*
+ * Add new memory allocated to that on free list for this hash bucket.
+ */
+ nextf[bucket] = op;
+ siz = 1 << (bucket + 3);
+ while (--nblks > 0) {
+ op->ov_next = (union overhead *) (((caddr_t) op) + siz);
+ op = (union overhead *) (((caddr_t) op) + siz);
+ }
+ op->ov_next = NULL;
+}
+
+#endif
+
+void
+free(cp)
+ ptr_t cp;
+{
+#ifndef lint
+ register int size;
+ register union overhead *op;
+
+ /*
+ * the don't free flag is there so that we avoid os bugs in routines
+ * that free invalid pointers!
+ */
+ if (cp == NULL || dont_free)
+ return;
+ CHECK(!memtop || !membot,
+ CGETS(19, 2, "free(%lx) called before any allocations."), cp);
+ CHECK(cp > (ptr_t) memtop,
+ CGETS(19, 3, "free(%lx) above top of memory."), cp);
+ CHECK(cp < (ptr_t) membot,
+ CGETS(19, 4, "free(%lx) below bottom of memory."), cp);
+ op = (union overhead *) (((caddr_t) cp) - MEMALIGN(sizeof(union overhead)));
+ CHECK(op->ov_magic != MAGIC,
+ CGETS(19, 5, "free(%lx) bad block."), cp);
+
+#ifdef RCHECK
+ if (op->ov_index <= 13)
+ CHECK(*(U_int *) ((caddr_t) op + op->ov_size + 1 - RSLOP) != RMAGIC,
+ CGETS(19, 6, "free(%lx) bad range check."), cp);
+#endif
+ CHECK(op->ov_index >= NBUCKETS,
+ CGETS(19, 7, "free(%lx) bad block index."), cp);
+ size = op->ov_index;
+ op->ov_next = nextf[size];
+ nextf[size] = op;
+
+ nmalloc[size]--;
+
+#else
+ if (cp == NULL)
+ return;
+#endif
+}
+
+memalign_t
+calloc(i, j)
+ size_t i, j;
+{
+#ifndef lint
+ register char *cp, *scp;
+
+ i *= j;
+ scp = cp = (char *) xmalloc((size_t) i);
+ if (i != 0)
+ do
+ *cp++ = 0;
+ while (--i);
+
+ return ((memalign_t) scp);
+#else
+ if (i && j)
+ return ((memalign_t) 0);
+ else
+ return ((memalign_t) 0);
+#endif
+}
+
+/*
+ * When a program attempts "storage compaction" as mentioned in the
+ * old malloc man page, it realloc's an already freed block. Usually
+ * this is the last block it freed; occasionally it might be farther
+ * back. We have to search all the free lists for the block in order
+ * to determine its bucket: 1st we make one pass thru the lists
+ * checking only the first block in each; if that fails we search
+ * ``realloc_srchlen'' blocks in each list for a match (the variable
+ * is extern so the caller can modify it). If that fails we just copy
+ * however many bytes was given to realloc() and hope it's not huge.
+ */
+#ifndef lint
+/* 4 should be plenty, -1 =>'s whole list */
+static int realloc_srchlen = 4;
+#endif /* lint */
+
+memalign_t
+realloc(cp, nbytes)
+ ptr_t cp;
+ size_t nbytes;
+{
+#ifndef lint
+ register U_int onb;
+ union overhead *op;
+ ptr_t res;
+ register int i;
+ int was_alloced = 0;
+
+ if (cp == NULL)
+ return (malloc(nbytes));
+ op = (union overhead *) (((caddr_t) cp) - MEMALIGN(sizeof(union overhead)));
+ if (op->ov_magic == MAGIC) {
+ was_alloced++;
+ i = op->ov_index;
+ }
+ else
+ /*
+ * Already free, doing "compaction".
+ *
+ * Search for the old block of memory on the free list. First, check the
+ * most common case (last element free'd), then (this failing) the last
+ * ``realloc_srchlen'' items free'd. If all lookups fail, then assume
+ * the size of the memory block being realloc'd is the smallest
+ * possible.
+ */
+ if ((i = findbucket(op, 1)) < 0 &&
+ (i = findbucket(op, realloc_srchlen)) < 0)
+ i = 0;
+
+ onb = MEMALIGN(nbytes + MEMALIGN(sizeof(union overhead)) + RSLOP);
+
+ /* avoid the copy if same size block */
+ if (was_alloced && (onb <= (U_int) (1 << (i + 3))) &&
+ (onb > (U_int) (1 << (i + 2)))) {
+#ifdef RCHECK
+ /* JMR: formerly this wasn't updated ! */
+ nbytes = MEMALIGN(MEMALIGN(sizeof(union overhead))+nbytes+RSLOP);
+ *((U_int *) (((caddr_t) op) + nbytes - RSLOP)) = RMAGIC;
+ op->ov_rmagic = RMAGIC;
+ op->ov_size = (op->ov_index <= 13) ? nbytes - 1 : 0;
+#endif
+ return ((memalign_t) cp);
+ }
+ if ((res = malloc(nbytes)) == NULL)
+ return ((memalign_t) NULL);
+ if (cp != res) { /* common optimization */
+ /*
+ * christos: this used to copy nbytes! It should copy the
+ * smaller of the old and new size
+ */
+ onb = (1 << (i + 3)) - MEMALIGN(sizeof(union overhead)) - RSLOP;
+ (void) memmove((ptr_t) res, (ptr_t) cp,
+ (size_t) (onb < nbytes ? onb : nbytes));
+ }
+ if (was_alloced)
+ free(cp);
+ return ((memalign_t) res);
+#else
+ if (cp && nbytes)
+ return ((memalign_t) 0);
+ else
+ return ((memalign_t) 0);
+#endif /* !lint */
+}
+
+
+
+#ifndef lint
+/*
+ * Search ``srchlen'' elements of each free list for a block whose
+ * header starts at ``freep''. If srchlen is -1 search the whole list.
+ * Return bucket number, or -1 if not found.
+ */
+static int
+findbucket(freep, srchlen)
+ union overhead *freep;
+ int srchlen;
+{
+ register union overhead *p;
+ register int i, j;
+
+ for (i = 0; i < NBUCKETS; i++) {
+ j = 0;
+ for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
+ if (p == freep)
+ return (i);
+ j++;
+ }
+ }
+ return (-1);
+}
+
+#endif
+
+
+#else /* SYSMALLOC */
+
+/**
+ ** ``Protected versions'' of malloc, realloc, calloc, and free
+ **
+ ** On many systems:
+ **
+ ** 1. malloc(0) is bad
+ ** 2. free(0) is bad
+ ** 3. realloc(0, n) is bad
+ ** 4. realloc(n, 0) is bad
+ **
+ ** Also we call our error routine if we run out of memory.
+ **/
+memalign_t
+smalloc(n)
+ size_t n;
+{
+ ptr_t ptr;
+
+ n = n ? n : 1;
+
+#ifndef NO_SBRK
+ if (membot == NULL)
+ membot = (char*) sbrk(0);
+#endif /* !NO_SBRK */
+
+ if ((ptr = malloc(n)) == (ptr_t) 0) {
+ child++;
+ stderror(ERR_NOMEM);
+ }
+#ifdef NO_SBRK
+ if (memtop < ((char *) ptr) + n)
+ memtop = ((char *) ptr) + n;
+ if (membot == NULL)
+ membot = (char*) ptr;
+#endif /* NO_SBRK */
+ return ((memalign_t) ptr);
+}
+
+memalign_t
+srealloc(p, n)
+ ptr_t p;
+ size_t n;
+{
+ ptr_t ptr;
+
+ n = n ? n : 1;
+
+#ifndef NO_SBRK
+ if (membot == NULL)
+ membot = (char*) sbrk(0);
+#endif /* NO_SBRK */
+
+ if ((ptr = (p ? realloc(p, n) : malloc(n))) == (ptr_t) 0) {
+ child++;
+ stderror(ERR_NOMEM);
+ }
+#ifdef NO_SBRK
+ if (memtop < ((char *) ptr) + n)
+ memtop = ((char *) ptr) + n;
+ if (membot == NULL)
+ membot = (char*) ptr;
+#endif /* NO_SBRK */
+ return ((memalign_t) ptr);
+}
+
+memalign_t
+scalloc(s, n)
+ size_t s, n;
+{
+ char *sptr;
+ ptr_t ptr;
+
+ n *= s;
+ n = n ? n : 1;
+
+#ifndef NO_SBRK
+ if (membot == NULL)
+ membot = (char*) sbrk(0);
+#endif /* NO_SBRK */
+
+ if ((ptr = malloc(n)) == (ptr_t) 0) {
+ child++;
+ stderror(ERR_NOMEM);
+ }
+
+ sptr = (char *) ptr;
+ if (n != 0)
+ do
+ *sptr++ = 0;
+ while (--n);
+
+#ifdef NO_SBRK
+ if (memtop < ((char *) ptr) + n)
+ memtop = ((char *) ptr) + n;
+ if (membot == NULL)
+ membot = (char*) ptr;
+#endif /* NO_SBRK */
+
+ return ((memalign_t) ptr);
+}
+
+void
+sfree(p)
+ ptr_t p;
+{
+ if (p && !dont_free)
+ free(p);
+}
+
+#endif /* SYSMALLOC */
+
+/*
+ * mstats - print out statistics about malloc
+ *
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
+ */
+/*ARGSUSED*/
+void
+showall(v, c)
+ Char **v;
+ struct command *c;
+{
+#ifndef SYSMALLOC
+ register int i, j;
+ register union overhead *p;
+ int totfree = 0, totused = 0;
+
+ xprintf(CGETS(19, 8, "%s current memory allocation:\nfree:\t"), progname);
+ for (i = 0; i < NBUCKETS; i++) {
+ for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+ continue;
+ xprintf(" %4d", j);
+ totfree += j * (1 << (i + 3));
+ }
+ xprintf(CGETS(19, 9, "\nused:\t"));
+ for (i = 0; i < NBUCKETS; i++) {
+ xprintf(" %4u", nmalloc[i]);
+ totused += nmalloc[i] * (1 << (i + 3));
+ }
+ xprintf(CGETS(19, 10, "\n\tTotal in use: %d, total free: %d\n"),
+ totused, totfree);
+ xprintf(CGETS(19, 11,
+ "\tAllocated memory from 0x%lx to 0x%lx. Real top at 0x%lx\n"),
+ (unsigned long) membot, (unsigned long) memtop,
+ (unsigned long) sbrk(0));
+#else
+#ifndef NO_SBRK
+ memtop = (char *) sbrk(0);
+#endif /* !NO_SBRK */
+ xprintf(CGETS(19, 12, "Allocated memory from 0x%lx to 0x%lx (%ld).\n"),
+ (unsigned long) membot, (unsigned long) memtop,
+ (unsigned long) (memtop - membot));
+#endif /* SYSMALLOC */
+ USE(c);
+ USE(v);
+}
diff --git a/contrib/tcsh/tc.bind.c b/contrib/tcsh/tc.bind.c
new file mode 100644
index 0000000..3ff3839
--- /dev/null
+++ b/contrib/tcsh/tc.bind.c
@@ -0,0 +1,1079 @@
+/* $Header: /src/pub/tcsh/tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $ */
+/*
+ * tc.bind.c: Key binding functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.bind.c,v 3.33 1998/11/24 18:17:40 christos Exp $")
+
+#include "ed.h"
+#include "ed.defns.h"
+
+#ifdef OBSOLETE
+static int tocontrol __P((int));
+static char *unparsekey __P((int));
+static KEYCMD getkeycmd __P((Char **));
+static int parsekey __P((Char **));
+static void pkeys __P((int, int));
+#endif /* OBSOLETE */
+
+static void printkey __P((KEYCMD *, CStr *));
+static KEYCMD parsecmd __P((Char *));
+static void bad_spec __P((Char *));
+static CStr *parsestring __P((Char *, CStr *));
+static CStr *parsebind __P((Char *, CStr *));
+static void print_all_keys __P((void));
+static void printkeys __P((KEYCMD *, int, int));
+static void bindkey_usage __P((void));
+static void list_functions __P((void));
+
+extern int MapsAreInited;
+
+
+
+
+/*ARGSUSED*/
+void
+dobindkey(v, c)
+ Char **v;
+ struct command *c;
+{
+ KEYCMD *map;
+ int ntype, no, remove, key, bind;
+ Char *par;
+ Char p;
+ KEYCMD cmd;
+ CStr in;
+ CStr out;
+ Char inbuf[200];
+ Char outbuf[200];
+ uChar ch;
+ in.buf = inbuf;
+ out.buf = outbuf;
+ in.len = 0;
+ out.len = 0;
+
+ USE(c);
+ if (!MapsAreInited)
+ ed_InitMaps();
+
+ map = CcKeyMap;
+ ntype = XK_CMD;
+ key = remove = bind = 0;
+ for (no = 1, par = v[no];
+ par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
+ if ((p = (*par & CHAR)) == '-') {
+ no++;
+ break;
+ }
+ else
+ switch (p) {
+ case 'b':
+ bind = 1;
+ break;
+ case 'k':
+ key = 1;
+ break;
+ case 'a':
+ map = CcAltMap;
+ break;
+ case 's':
+ ntype = XK_STR;
+ break;
+ case 'c':
+ ntype = XK_EXE;
+ break;
+ case 'r':
+ remove = 1;
+ break;
+ case 'v':
+ ed_InitVIMaps();
+ return;
+ case 'e':
+ ed_InitEmacsMaps();
+ return;
+ case 'd':
+#ifdef VIDEFAULT
+ ed_InitVIMaps();
+#else /* EMACSDEFAULT */
+ ed_InitEmacsMaps();
+#endif /* VIDEFAULT */
+ return;
+ case 'l':
+ list_functions();
+ return;
+ default:
+ bindkey_usage();
+ return;
+ }
+ }
+
+ if (!v[no]) {
+ print_all_keys();
+ return;
+ }
+
+ if (key) {
+ if (!IsArrowKey(v[no]))
+ xprintf(CGETS(20, 1, "Invalid key name `%S'\n"), v[no]);
+ in.buf = v[no++];
+ in.len = Strlen(in.buf);
+ }
+ else {
+ if (bind) {
+ if (parsebind(v[no++], &in) == NULL)
+ return;
+ }
+ else {
+ if (parsestring(v[no++], &in) == NULL)
+ return;
+ }
+ }
+
+ ch = (uChar) in.buf[0];
+
+ if (remove) {
+ if (key) {
+ (void) ClearArrowKeys(&in);
+ return;
+ }
+ if (in.len > 1) {
+ (void) DeleteXkey(&in);
+ }
+ else if (map[ch] == F_XKEY) {
+ (void) DeleteXkey(&in);
+ map[ch] = F_UNASSIGNED;
+ }
+ else {
+ map[ch] = F_UNASSIGNED;
+ }
+ return;
+ }
+ if (!v[no]) {
+ if (key)
+ PrintArrowKeys(&in);
+ else
+ printkey(map, &in);
+ return;
+ }
+ if (v[no + 1]) {
+ bindkey_usage();
+ return;
+ }
+ switch (ntype) {
+ case XK_STR:
+ case XK_EXE:
+ if (parsestring(v[no], &out) == NULL)
+ return;
+ if (key) {
+ if (SetArrowKeys(&in, XmapStr(&out), ntype) == -1)
+ xprintf(CGETS(20, 2, "Bad key name: %S\n"), in);
+ }
+ else
+ AddXkey(&in, XmapStr(&out), ntype);
+ map[ch] = F_XKEY;
+ break;
+ case XK_CMD:
+ if ((cmd = parsecmd(v[no])) == 0)
+ return;
+ if (key)
+ (void) SetArrowKeys(&in, XmapCmd((int) cmd), ntype);
+ else {
+ if (in.len > 1) {
+ AddXkey(&in, XmapCmd((int) cmd), ntype);
+ map[ch] = F_XKEY;
+ }
+ else {
+ ClearXkey(map, &in);
+ map[ch] = cmd;
+ }
+ }
+ break;
+ default:
+ abort();
+ break;
+ }
+ if (key)
+ BindArrowKeys();
+}
+
+static void
+printkey(map, in)
+ KEYCMD *map;
+ CStr *in;
+{
+ unsigned char outbuf[100];
+ register struct KeyFuncs *fp;
+
+ if (in->len < 2) {
+ (void) unparsestring(in, outbuf, STRQQ);
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[(uChar) *(in->buf)]) {
+ xprintf("%s\t->\t%s\n", outbuf, fp->name);
+ }
+ }
+ }
+ else
+ PrintXkey(in);
+}
+
+static KEYCMD
+parsecmd(str)
+ Char *str;
+{
+ register struct KeyFuncs *fp;
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (strcmp(short2str(str), fp->name) == 0) {
+ return (KEYCMD) fp->func;
+ }
+ }
+ xprintf(CGETS(20, 3, "Bad command name: %S\n"), str);
+ return 0;
+}
+
+
+static void
+bad_spec(str)
+ Char *str;
+{
+ xprintf(CGETS(20, 4, "Bad key spec %S\n"), str);
+}
+
+static CStr *
+parsebind(s, str)
+ Char *s;
+ CStr *str;
+{
+#ifdef DSPMBYTE
+ extern bool NoNLSRebind;
+#endif /* DSPMBYTE */
+ Char *b = str->buf;
+
+ if (Iscntrl(*s)) {
+ *b++ = *s;
+ *b = '\0';
+ str->len = (int) (b - str->buf);
+ return str;
+ }
+
+ switch (*s) {
+ case '^':
+ s++;
+#ifndef _OSD_POSIX
+ *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
+#else /*_OSD_POSIX*/
+ *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
+#endif /*_OSD_POSIX*/
+ *b = '\0';
+ break;
+
+ case 'F':
+ case 'M':
+ case 'X':
+ case 'C':
+#ifdef WINNT
+ case 'N':
+#endif /* WINNT */
+ if (s[1] != '-' || s[2] == '\0') {
+ bad_spec(s);
+ return NULL;
+ }
+ s += 2;
+ switch (s[-2]) {
+ case 'F': case 'f': /* Turn into ^[str */
+ *b++ = CTL_ESC('\033');
+ while ((*b++ = *s++) != '\0')
+ continue;
+ b--;
+ break;
+
+ case 'C': case 'c': /* Turn into ^c */
+#ifndef _OSD_POSIX
+ *b++ = (*s == '?') ? '\177' : ((*s & CHAR) & 0237);
+#else /*_OSD_POSIX*/
+ *b++ = (*s == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*s & CHAR] & 0237];
+#endif /*_OSD_POSIX*/
+ *b = '\0';
+ break;
+
+ case 'X' : case 'x': /* Turn into ^Xc */
+#ifndef _OSD_POSIX
+ *b++ = 'X' & 0237;
+#else /*_OSD_POSIX*/
+ *b++ = _toebcdic[_toascii['X'] & 0237];
+#endif /*_OSD_POSIX*/
+ *b++ = *s;
+ *b = '\0';
+ break;
+
+ case 'M' : case 'm': /* Turn into 0x80|c */
+#ifdef DSPMBYTE
+ if (!NoNLSRebind) {
+ *b++ = CTL_ESC('\033');
+ *b++ = *s;
+ } else {
+#endif /* DSPMBYTE */
+#ifndef _OSD_POSIX
+ *b++ = *s | 0x80;
+#else /*_OSD_POSIX*/
+ *b++ = _toebcdic[_toascii[*s] | 0x80];
+#endif /*_OSD_POSIX*/
+#ifdef DSPMBYTE
+ }
+#endif /* DSPMBYTE */
+ *b = '\0';
+ break;
+#ifdef WINNT
+ case 'N' : case 'n': /* NT */
+ {
+ Char bnt;
+
+ bnt = nt_translate_bindkey(s);
+ if (bnt != 0)
+ *b++ = bnt;
+ else
+ bad_spec(s);
+ }
+ break;
+#endif /* WINNT */
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ return NULL;
+ }
+ break;
+
+ default:
+ bad_spec(s);
+ return NULL;
+ }
+
+ str->len = (int) (b - str->buf);
+ return str;
+}
+
+
+static CStr *
+parsestring(str, buf)
+ Char *str;
+ CStr *buf;
+{
+ Char *b;
+ const Char *p;
+ int es;
+
+ b = buf->buf;
+ if (*str == 0) {
+ xprintf(CGETS(20, 5, "Null string specification\n"));
+ return NULL;
+ }
+
+ for (p = str; *p != 0; p++) {
+ if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
+ if ((es = parseescape(&p)) == -1)
+ return 0;
+ else
+ *b++ = (Char) es;
+ }
+ else
+ *b++ = *p & CHAR;
+ }
+ *b = 0;
+ buf->len = (int) (b - buf->buf);
+ return buf;
+}
+
+static void
+print_all_keys()
+{
+ int prev, i;
+ CStr nilstr;
+ nilstr.buf = NULL;
+ nilstr.len = 0;
+
+
+ xprintf(CGETS(20, 6, "Standard key bindings\n"));
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcKeyMap[prev] == CcKeyMap[i])
+ continue;
+ printkeys(CcKeyMap, prev, i - 1);
+ prev = i;
+ }
+ printkeys(CcKeyMap, prev, i - 1);
+
+ xprintf(CGETS(20, 7, "Alternative key bindings\n"));
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcAltMap[prev] == CcAltMap[i])
+ continue;
+ printkeys(CcAltMap, prev, i - 1);
+ prev = i;
+ }
+ printkeys(CcAltMap, prev, i - 1);
+ xprintf(CGETS(20, 8, "Multi-character bindings\n"));
+ PrintXkey(NULL); /* print all Xkey bindings */
+ xprintf(CGETS(20, 9, "Arrow key bindings\n"));
+ PrintArrowKeys(&nilstr);
+}
+
+static void
+printkeys(map, first, last)
+ KEYCMD *map;
+ int first, last;
+{
+ register struct KeyFuncs *fp;
+ Char firstbuf[2], lastbuf[2];
+ CStr fb, lb;
+ unsigned char unparsbuf[10], extrabuf[10];
+ fb.buf = firstbuf;
+ lb.buf = lastbuf;
+
+ firstbuf[0] = (Char) first;
+ firstbuf[1] = 0;
+ lastbuf[0] = (Char) last;
+ lastbuf[1] = 0;
+ fb.len = 1;
+ lb.len = 1;
+
+ if (map[first] == F_UNASSIGNED) {
+ if (first == last)
+ xprintf(CGETS(20, 10, "%-15s-> is undefined\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ return;
+ }
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[first]) {
+ if (first == last) {
+ xprintf("%-15s-> %s\n",
+ unparsestring(&fb, unparsbuf, STRQQ), fp->name);
+ }
+ else {
+ xprintf("%-4s to %-7s-> %s\n",
+ unparsestring(&fb, unparsbuf, STRQQ),
+ unparsestring(&lb, extrabuf, STRQQ), fp->name);
+ }
+ return;
+ }
+ }
+ if (map == CcKeyMap) {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
+ }
+ else {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsestring(&fb, unparsbuf, STRQQ));
+ xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
+ }
+}
+
+static void
+bindkey_usage()
+{
+ xprintf(CGETS(20, 12,
+ "Usage: bindkey [options] [--] [KEY [COMMAND]]\n"));
+ xprintf(CGETS(20, 13,
+ " -a list or bind KEY in alternative key map\n"));
+ xprintf(CGETS(20, 14,
+ " -b interpret KEY as a C-, M-, F- or X- key name\n"));
+ xprintf(CGETS(20, 15,
+ " -s interpret COMMAND as a literal string to be output\n"));
+ xprintf(CGETS(20, 16,
+ " -c interpret COMMAND as a builtin or external command\n"));
+ xprintf(CGETS(20, 17,
+ " -v bind all keys to vi bindings\n"));
+ xprintf(CGETS(20, 18,
+ " -e bind all keys to emacs bindings\n"));
+ xprintf(CGETS(20, 19,
+ " -d bind all keys to default editor's bindings\n"));
+ xprintf(CGETS(20, 20,
+ " -l list editor commands with descriptions\n"));
+ xprintf(CGETS(20, 21,
+ " -r remove KEY's binding\n"));
+ xprintf(CGETS(20, 22,
+ " -k interpret KEY as a symbolic arrow-key name\n"));
+ xprintf(CGETS(20, 23,
+ " -- force a break from option processing\n"));
+ xprintf(CGETS(20, 24,
+ " -u (or any invalid option) this message\n"));
+ xprintf("\n");
+ xprintf(CGETS(20, 25,
+ "Without KEY or COMMAND, prints all bindings\n"));
+ xprintf(CGETS(20, 26,
+ "Without COMMAND, prints the binding for KEY.\n"));
+}
+
+static void
+list_functions()
+{
+ register struct KeyFuncs *fp;
+
+ for (fp = FuncNames; fp->name; fp++) {
+ xprintf("%s\n %s\n", fp->name, fp->desc);
+ }
+}
+
+#ifdef OBSOLETE
+
+/*
+ * Unfortunately the apollo optimizer does not like & operations
+ * with 0377, and produces illegal instructions. So we make it
+ * an unsigned char, and hope for the best.
+ * Of-course the compiler is smart enough to produce bad assembly
+ * language instructions, but dumb when it comes to fold the constant :-)
+ */
+#ifdef apollo
+static unsigned char APOLLO_0377 = 0377;
+#else /* sane */
+# define APOLLO_0377 0377
+#endif /* apollo */
+
+static int
+tocontrol(c)
+ int c;
+{
+ c &= CHAR;
+ if (Islower(c))
+ c = Toupper(c);
+ else if (c == ' ')
+ c = '@';
+ if (c == '?')
+ c = CTL_ESC('\177');
+ else
+#ifndef _OSD_POSIX
+ c &= 037;
+#else /* EBCDIC: simulate ASCII-behavior by transforming to ASCII and back */
+ c = _toebcdic[_toascii[c] & 037];
+#endif
+ return (c);
+}
+
+static char *
+unparsekey(c) /* 'c' -> "c", '^C' -> "^" + "C" */
+ register int c;
+{
+ register char *cp;
+ static char tmp[10];
+
+ cp = tmp;
+
+ if (c & 0400) {
+ *cp++ = 'A';
+ *cp++ = '-';
+ c &= APOLLO_0377;
+ }
+ if ((c & META) && !(Isprint(c) || (Iscntrl(c) && Isprint(c | 0100)))) {
+ *cp++ = 'M';
+ *cp++ = '-';
+ c &= ASCII;
+ }
+ if (Isprint(c)) {
+ *cp++ = (char) c;
+ *cp = '\0';
+ return (tmp);
+ }
+ switch (c) {
+ case ' ':
+ (void) strcpy(cp, "Spc");
+ return (tmp);
+ case '\n':
+ (void) strcpy(cp, "Lfd");
+ return (tmp);
+ case '\r':
+ (void) strcpy(cp, "Ret");
+ return (tmp);
+ case '\t':
+ (void) strcpy(cp, "Tab");
+ return (tmp);
+#ifndef _OSD_POSIX
+ case '\033':
+ (void) strcpy(cp, "Esc");
+ return (tmp);
+ case '\177':
+ (void) strcpy(cp, "Del");
+ return (tmp);
+ default:
+ *cp++ = '^';
+ if (c == '\177') {
+ *cp++ = '?';
+ }
+ else {
+ *cp++ = c | 0100;
+ }
+ *cp = '\0';
+ return (tmp);
+#else /*_OSD_POSIX*/
+ default:
+ if (*cp == CTL_ESC('\033')) {
+ (void) strcpy(cp, "Esc");
+ return (tmp);
+ }
+ else if (*cp == CTL_ESC('\177')) {
+ (void) strcpy(cp, "Del");
+ return (tmp);
+ }
+ else if (Isupper(_toebcdic[_toascii[c]|0100])
+ || strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]) != NULL) {
+ *cp++ = '^';
+ *cp++ = _toebcdic[_toascii[c]|0100]
+ }
+ else {
+ xsnprintf(cp, 3, "\\%3.3o", c);
+ cp += 4;
+ }
+#endif /*_OSD_POSIX*/
+ }
+}
+
+static KEYCMD
+getkeycmd(sp)
+ Char **sp;
+{
+ register Char *s = *sp;
+ register char c;
+ register KEYCMD keycmd = F_UNASSIGNED;
+ KEYCMD *map;
+ int meta = 0;
+ Char *ret_sp = s;
+
+ map = CcKeyMap;
+
+ while (*s) {
+ if (*s == '^' && s[1]) {
+ s++;
+ c = tocontrol(*s++);
+ }
+ else
+ c = *s++;
+
+ if (*s == '\0')
+ break;
+
+ switch (map[c | meta]) {
+ case F_METANEXT:
+ meta = META;
+ keycmd = F_METANEXT;
+ ret_sp = s;
+ break;
+
+ case F_XKEY:
+ keycmd = F_XKEY;
+ ret_sp = s;
+ /* FALLTHROUGH */
+
+ default:
+ *sp = ret_sp;
+ return (keycmd);
+
+ }
+ }
+ *sp = ret_sp;
+ return (keycmd);
+}
+
+static int
+parsekey(sp)
+ Char **sp; /* Return position of first unparsed character
+ * for return value -2 (xkeynext) */
+{
+ register int c, meta = 0, control = 0, ctrlx = 0;
+ Char *s = *sp;
+ KEYCMD keycmd;
+
+ if (s == NULL) {
+ xprintf(CGETS(20, 27, "bad key specification -- null string\n"));
+ return -1;
+ }
+ if (*s == 0) {
+ xprintf(CGETS(20, 28, "bad key specification -- empty string\n"));
+ return -1;
+ }
+
+ (void) strip(s); /* trim to 7 bits. */
+
+ if (s[1] == 0) /* single char */
+ return (s[0] & APOLLO_0377);
+
+ if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') {
+ if (s[2] == 0) {
+ xprintf(CGETS(20, 29,
+ "Bad function-key specification. Null key not allowed\n"));
+ return (-1);
+ }
+ *sp = s + 2;
+ return (-2);
+ }
+
+ if (s[0] == '0' && s[1] == 'x') { /* if 0xn, then assume number */
+ c = 0;
+ for (s += 2; *s; s++) { /* convert to hex; skip the first 0 */
+ c *= 16;
+ if (!Isxdigit(*s)) {
+ xprintf(CGETS(20, 30,
+ "bad key specification -- malformed hex number\n"));
+ return -1; /* error */
+ }
+ if (Isdigit(*s))
+ c += *s - '0';
+ else if (*s >= 'a' && *s <= 'f')
+ c += *s - 'a' + 0xA;
+ else if (*s >= 'F' && *s <= 'F')
+ c += *s - 'A' + 0xA;
+ }
+ }
+ else if (s[0] == '0' && Isdigit(s[1])) { /* if 0n, then assume number */
+ c = 0;
+ for (s++; *s; s++) { /* convert to octal; skip the first 0 */
+ if (!Isdigit(*s) || *s == '8' || *s == '9') {
+ xprintf(CGETS(20, 31,
+ "bad key specification -- malformed octal number\n"));
+ return -1; /* error */
+ }
+ c = (c * 8) + *s - '0';
+ }
+ }
+ else if (Isdigit(s[0]) && Isdigit(s[1])) { /* decimal number */
+ c = 0;
+ for (; *s; s++) { /* convert to octal; skip the first 0 */
+ if (!Isdigit(*s)) {
+ xprintf(CGETS(20, 32,
+ "bad key specification -- malformed decimal number\n"));
+ return -1; /* error */
+ }
+ c = (c * 10) + *s - '0';
+ }
+ }
+ else {
+ keycmd = getkeycmd(&s);
+
+ if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') { /* X- */
+ ctrlx++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+ if ((*s == 'm' || *s == 'M') && s[1] == '-') { /* meta */
+ meta++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+ else if (keycmd == F_METANEXT && *s) { /* meta */
+ meta++;
+ keycmd = getkeycmd(&s);
+ }
+ if (*s == '^' && s[1]) {
+ control++;
+ s++;
+ keycmd = getkeycmd(&s);
+ }
+ else if ((*s == 'c' || *s == 'C') && s[1] == '-') { /* control */
+ control++;
+ s += 2;
+ keycmd = getkeycmd(&s);
+ }
+
+ if (keycmd == F_XKEY) {
+ if (*s == 0) {
+ xprintf(CGETS(20, 33,
+ "Bad function-key specification.\n"));
+ xprintf(CGETS(20, 34, "Null key not allowed\n"));
+ return (-1);
+ }
+ *sp = s;
+ return (-2);
+ }
+
+ if (s[1] != 0) { /* if symbolic name */
+ char *ts;
+
+ ts = short2str(s);
+ if (!strcmp(ts, "space") || !strcmp(ts, "Spc"))
+ c = ' ';
+ else if (!strcmp(ts, "return") || !strcmp(ts, "Ret"))
+ c = '\r';
+ else if (!strcmp(ts, "newline") || !strcmp(ts, "Lfd"))
+ c = '\n';
+ else if (!strcmp(ts, "linefeed"))
+ c = '\n';
+ else if (!strcmp(ts, "tab"))
+ c = '\t';
+ else if (!strcmp(ts, "escape") || !strcmp(ts, "Esc"))
+ c = CTL_ESC('\033');
+ else if (!strcmp(ts, "backspace"))
+ c = '\b';
+ else if (!strcmp(ts, "delete"))
+ c = CTL_ESC('\177');
+ else {
+ xprintf(CGETS(20, 35,
+ "bad key specification -- unknown name \"%S\"\n"), s);
+ return -1; /* error */
+ }
+ }
+ else
+ c = *s; /* just a single char */
+
+ if (control)
+ c = tocontrol(c);
+ if (meta)
+ c |= META;
+ if (ctrlx)
+ c |= 0400;
+ }
+ return (c & 0777);
+}
+
+
+/*ARGSUSED*/
+void
+dobind(v, dummy)
+ register Char **v;
+ struct command *dummy;
+{
+ register int c;
+ register struct KeyFuncs *fp;
+ register int i, prev;
+ Char *p, *l;
+ CStr cstr;
+ Char buf[1000];
+
+ USE(dummy);
+ /*
+ * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
+ * and the key; or 'bind' key to print the func for that key.
+ */
+
+ if (!MapsAreInited)
+ ed_InitMaps();
+
+ if (v[1] && v[2] && v[3]) {
+ xprintf(CGETS(20, 36,
+ "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n"));
+ return;
+ }
+
+ if (v[1] && v[2]) { /* if bind FUNCTION KEY */
+ for (fp = FuncNames; fp->name; fp++) {
+ if (strcmp(short2str(v[1]), fp->name) == 0) {
+ Char *s = v[2];
+
+ if ((c = parsekey(&s)) == -1)
+ return;
+ if (c == -2) { /* extended key */
+ for (i = 0; i < 256; i++) {
+ if (i != CTL_ESC('\033') && (CcKeyMap[i] == F_XKEY ||
+ CcAltMap[i] == F_XKEY)) {
+ p = buf;
+#ifndef _OSD_POSIX /* this is only for ASCII, not for EBCDIC */
+ if (i > 0177) {
+ *p++ = 033;
+ *p++ = i & ASCII;
+ }
+ else {
+ *p++ = (Char) i;
+ }
+#else /*_OSD_POSIX*/
+ *p++ = (Char) i;
+#endif /*_OSD_POSIX*/
+ for (l = s; *l != 0; l++) {
+ *p++ = *l;
+ }
+ *p = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ return;
+ }
+ if (c & 0400) {
+ if (VImode) {
+ CcAltMap[c & APOLLO_0377] = fp->func;
+ /* bind the vi cmd mode key */
+ if (c & META) {
+ buf[0] = CTL_ESC('\033');
+ buf[1] = c & ASCII;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ else {
+ buf[0] = CTL_ESC('\030'); /* ^X */
+ buf[1] = c & APOLLO_0377;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ CcKeyMap[CTL_ESC('\030')] = F_XKEY;
+ }
+ }
+ else {
+ CcKeyMap[c] = fp->func; /* bind the key */
+ if (c & META) {
+ buf[0] = CTL_ESC('\033');
+ buf[1] = c & ASCII;
+ buf[2] = 0;
+ cstr.buf = buf;
+ cstr.len = Strlen(buf);
+ AddXkey(&cstr, XmapCmd(fp->func), XK_CMD);
+ }
+ }
+ return;
+ }
+ }
+ stderror(ERR_NAME | ERR_STRING, CGETS(20, 37, "Invalid function"));
+ }
+ else if (v[1]) {
+ char *cv = short2str(v[1]);
+
+ if (strcmp(cv, "list") == 0) {
+ for (fp = FuncNames; fp->name; fp++) {
+ xprintf("%s\n", fp->name);
+ }
+ return;
+ }
+ if ((strcmp(cv, "emacs") == 0) ||
+#ifndef VIDEFAULT
+ (strcmp(cv, "defaults") == 0) ||
+ (strcmp(cv, "default") == 0) ||
+#endif
+ (strcmp(cv, "mg") == 0) ||
+ (strcmp(cv, "gnumacs") == 0)) {
+ /* reset keys to default */
+ ed_InitEmacsMaps();
+#ifdef VIDEFAULT
+ }
+ else if ((strcmp(cv, "vi") == 0)
+ || (strcmp(cv, "default") == 0)
+ || (strcmp(cv, "defaults") == 0)) {
+#else
+ }
+ else if (strcmp(cv, "vi") == 0) {
+#endif
+ ed_InitVIMaps();
+ }
+ else { /* want to know what this key does */
+ Char *s = v[1];
+
+ if ((c = parsekey(&s)) == -1)
+ return;
+ if (c == -2) { /* extended key */
+ cstr.buf = s;
+ cstr.len = Strlen(s);
+ PrintXkey(&cstr);
+ return;
+ }
+ pkeys(c, c); /* must be regular key */
+ }
+ }
+ else { /* list all the bindings */
+ prev = 0;
+ for (i = 0; i < 256; i++) {
+ if (CcKeyMap[prev] == CcKeyMap[i])
+ continue;
+ pkeys(prev, i - 1);
+ prev = i;
+ }
+ pkeys(prev, i - 1);
+ prev = 0;
+ for (i = 256; i < 512; i++) {
+ if (CcAltMap[prev & APOLLO_0377] == CcAltMap[i & APOLLO_0377])
+ continue;
+ pkeys(prev, i - 1);
+ prev = i;
+ }
+ pkeys(prev, i - 1);
+ cstr.buf = NULL;
+ cstr.len = 0;
+ PrintXkey(&cstr); /* print all Xkey bindings */
+ }
+ return;
+}
+
+static void
+pkeys(first, last)
+ register int first, last;
+{
+ register struct KeyFuncs *fp;
+ register KEYCMD *map;
+ int mask;
+ char buf[8];
+
+ if (last & 0400) {
+ map = CcAltMap;
+ first &= APOLLO_0377;
+ last &= APOLLO_0377;
+ mask = 0400;
+ }
+ else {
+ map = CcKeyMap;
+ mask = 0;
+ }
+ if (map[first] == F_UNASSIGNED) {
+ if (first == last)
+ xprintf(CGETS(20, 38, " %s\t\tis undefined\n"),
+ unparsekey(first | mask));
+ return;
+ }
+
+ for (fp = FuncNames; fp->name; fp++) {
+ if (fp->func == map[first]) {
+ if (first == last)
+ xprintf(" %s\t\t%s\n",
+ unparsekey((first & APOLLO_0377) | mask), fp->name);
+ else {
+ (void) strcpy(buf, unparsekey((first & APOLLO_0377) | mask));
+ xprintf(" %s..%s\t\t%s\n", buf,
+ unparsekey((last & APOLLO_0377) | mask), fp->name);
+ }
+ return;
+ }
+ }
+ if (map == CcKeyMap) {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsekey(first));
+ xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
+ }
+ else {
+ xprintf(CGETS(20, 11, "BUG!!! %s isn't bound to anything.\n"),
+ unparsekey(first & 0400));
+ xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
+ }
+}
+#endif /* OBSOLETE */
diff --git a/contrib/tcsh/tc.const.c b/contrib/tcsh/tc.const.c
new file mode 100644
index 0000000..3fa5bbd
--- /dev/null
+++ b/contrib/tcsh/tc.const.c
@@ -0,0 +1,406 @@
+/* $Header: /src/pub/tcsh/tc.const.c,v 3.52 1999/05/11 13:07:52 christos Exp $ */
+/*
+ * sh.const.c: String constants for tcsh.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.const.c,v 3.52 1999/05/11 13:07:52 christos Exp $")
+
+Char STRlogout[] = { 'l', 'o', 'g', 'o', 'u', 't', '\0' };
+Char STRautologout[] = { 'a', 'u', 't', 'o', 'l', 'o', 'g', 'o', 'u', 't',
+ '\0' };
+Char STRdefautologout[] = { '6', '0', '\0' };
+#ifdef convex
+Char STRrootdefautologout[] = { '1', '5', '\0' };
+#endif
+Char STRautomatic[] = { 'a', 'u', 't', 'o', 'm', 'a', 't', 'i', 'c',
+ '\0' };
+Char STRhangup[] = { 'h', 'a', 'n', 'g', 'u', 'p', '\0' };
+Char STRaout[] = { 'a', '.', 'o', 'u', 't', '\0' };
+Char STRtty[] = { 't', 't', 'y', '\0' };
+Char STRpts[] = { 'p', 't', 's', '\0' };
+Char STRany[] = { 'a', 'n', 'y', '\0' };
+Char STRstatus[] = { 's', 't', 'a', 't', 'u', 's', '\0' };
+Char STR0[] = { '0', '\0' };
+Char STR1[] = { '1', '\0' };
+/* STRm1 would look too much like STRml IMHO */
+Char STRminus1[] = { '-', '1', '\0' };
+Char STRmaxint[] = { '0', 'x', '7', 'f', 'f', 'f', 'f', 'f', 'f', 'f',
+ '\0' };
+Char STRcolon[] = { ':', '\0' };
+Char STR_[] = { '_', '\0' };
+Char STRNULL[] = { '\0' };
+Char STRtcsh[] = { 't', 'c', 's', 'h', '\0' };
+Char STRhome[] = { 'h', 'o', 'm', 'e', '\0' };
+Char STRuser[] = { 'u', 's', 'e', 'r', '\0' };
+Char STRgroup[] = { 'g', 'r', 'o', 'u', 'p', '\0' };
+#ifdef AFS
+Char STRafsuser[] = { 'a', 'f', 's', 'u', 's', 'e', 'r', '\0' };
+#endif /* AFS */
+Char STRterm[] = { 't', 'e', 'r', 'm', '\0' };
+Char STRversion[] = { 'v', 'e', 'r', 's', 'i', 'o', 'n', '\0' };
+Char STRuid[] = { 'u', 'i', 'd', '\0' };
+Char STRgid[] = { 'g', 'i', 'd', '\0' };
+Char STRunknown[] = { 'u', 'n', 'k', 'n', 'o', 'w', 'n', '\0' };
+Char STRnetwork[] = { 'n', 'e', 't', 'w', 'o', 'r', 'k', '\0' };
+Char STRdumb[] = { 'd', 'u', 'm', 'b', '\0' };
+Char STRHOST[] = { 'H', 'O', 'S', 'T', '\0' };
+#ifdef REMOTEHOST
+Char STRREMOTEHOST[] = { 'R', 'E', 'M', 'O', 'T', 'E', 'H',
+ 'O', 'S', 'T', '\0' };
+#endif /* REMOTEHOST */
+Char STRHOSTTYPE[] = { 'H', 'O', 'S', 'T', 'T', 'Y', 'P', 'E', '\0' };
+Char STRVENDOR[] = { 'V', 'E', 'N', 'D', 'O', 'R', '\0' };
+Char STRMACHTYPE[] = { 'M', 'A', 'C', 'H', 'T', 'Y', 'P', 'E', '\0' };
+Char STROSTYPE[] = { 'O', 'S', 'T', 'Y', 'P', 'E', '\0' };
+Char STRedit[] = { 'e', 'd', 'i', 't', '\0' };
+Char STRaddsuffix[] = { 'a', 'd', 'd', 's', 'u', 'f', 'f', 'i', 'x',
+ '\0' };
+Char STRnostat[] = { 'n', 'o', 's', 't', 'a', 't', '\0' };
+Char STRshell[] = { 's', 'h', 'e', 'l', 'l', '\0' };
+Char STRtmpsh[] = { '/', 't', 'm', 'p', '/', 's', 'h', '\0' };
+Char STRverbose[] = { 'v', 'e', 'r', 'b', 'o', 's', 'e', '\0' };
+Char STRecho[] = { 'e', 'c', 'h', 'o', '\0' };
+Char STRpath[] = { 'p', 'a', 't', 'h', '\0' };
+Char STRprompt[] = { 'p', 'r', 'o', 'm', 'p', 't', '\0' };
+Char STRprompt2[] = { 'p', 'r', 'o', 'm', 'p', 't', '2', '\0' };
+Char STRprompt3[] = { 'p', 'r', 'o', 'm', 'p', 't', '3', '\0' };
+Char STRrprompt[] = { 'r', 'p', 'r', 'o', 'm', 'p', 't', '\0' };
+Char STRellipsis[] = { 'e', 'l', 'l', 'i', 'p', 's', 'i', 's', '\0' };
+Char STRcwd[] = { 'c', 'w', 'd', '\0' };
+Char STRowd[] = { 'o', 'w', 'd', '\0' };
+Char STRstar[] = { '*', '\0' };
+Char STRdot[] = { '.', '\0' };
+Char STRhistory[] = { 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' };
+Char STRhistdup[] = { 'h', 'i', 's', 't', 'd', 'u', 'p', '\0' };
+Char STRhistfile[] = { 'h', 'i', 's', 't', 'f', 'i', 'l', 'e', '\0' };
+Char STRsource[] = { 's', 'o', 'u', 'r', 'c', 'e', '\0' };
+Char STRmh[] = { '-', 'h', '\0' };
+Char STRmhT[] = { '-', 'h', 'T', '\0' };
+Char STRmm[] = { '-', 'm', '\0' };
+Char STRmr[] = { '-', 'r', '\0' };
+Char STRmerge[] = { 'm', 'e', 'r', 'g', 'e', '\0' };
+Char STRtildothist[] = { '~', '/', '.', 'h', 'i', 's', 't', 'o', 'r',
+ 'y', '\0' };
+
+#ifdef KANJI
+Char STRnokanji[] = { 'n', 'o', 'k', 'a', 'n', 'j', 'i', '\0' };
+# ifdef DSPMBYTE
+Char STRdspmbyte[] = { 'd', 's', 'p', 'm', 'b', 'y', 't', 'e', '\0' };
+Char STRmmliteral[] = { '-', '-', 'l', 'i', 't', 'e', 'r', 'a', 'l', '\0' };
+Char STRKEUC[] = { 'e', 'u', 'c', '\0' };
+Char STRKSJIS[] = { 's', 'j', 'i', 's', '\0' };
+# ifdef MBYTEDEBUG /* Sorry, use for beta testing */
+Char STRmbytemap[] = { 'm', 'b', 'y', 't', 'e', 'm', 'a', 'p', '\0' };
+# endif /* MBYTEMAP */
+/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
+/* dspmbyte autoset trap */
+/* STRLANGEUC,STRLANGEUCB = EUC Trap */
+/* STRLANGSJIS,STRLANGSJISB = SJIS Trap */
+# if defined(__FreeBSD__) || defined(__uxps__) || defined(linux) || defined(sgi) || defined(aix) /* linux? */
+Char STRLANGEUC[] = { 'j', 'a', '_', 'J', 'P', '.', 'E', 'U', 'C', '\0' };
+# if defined(__uxps__)
+Char STRLANGEUCB[] = { 'j', 'a', 'p', 'a', 'n', '\0' };
+# elif defined(linux)
+Char STRLANGEUCB[] = { 'j', 'a', '_', 'J', 'P', '.', 'u', 'j', 'i', 's',
+ '\0' };
+# elif defined(aix)
+Char STRLANGEUCB[] = { 'j', 'a', '_', 'J', 'P', '\0' };
+# else
+Char STRLANGEUCB[] = { '\0' };
+# endif
+Char STRLANGSJIS[] = { 'j', 'a', '_', 'J', 'P', '.', 'S', 'J', 'I', 'S',
+ '\0' };
+Char STRLANGSJISB[] = { '\0' };
+# elif defined(__uxpm__)
+Char STRLANGEUC[] = { 'j', 'a', 'p', 'a', 'n', '\0' };
+Char STRLANGEUCB[] = { '\0' };
+Char STRLANGSJIS[] = { '\0' };
+Char STRLANGSJISB[] = { '\0' };
+# elif defined(SOLARIS2)
+Char STRLANGEUC[] = { 'j', 'a', '\0' };
+Char STRLANGEUCB[] = { 'j', 'a', 'p', 'a', 'n', 'e', 's', 'e', '\0' };
+Char STRLANGSJIS[] = { '\0' };
+Char STRLANGSJISB[] = { '\0' };
+# elif defined(hpux)
+Char STRLANGEUC[] = { 'j', 'a', '_', 'J', 'P', '.', 'e', 'u', 'c', 'J', 'P' };
+Char STRLANGEUCB[] = { '\0' };
+Char STRLANGSJIS[] = { '\0' };
+Char STRLANGSJISB[] = { '\0' };
+# else
+Char STRLANGEUC[] = { '\0' };
+Char STRLANGEUCB[] = { '\0' };
+Char STRLANGSJIS[] = { '\0' };
+Char STRLANGSJISB[] = { '\0' };
+# endif
+# endif /* defined(DSPMBYTE) */
+#endif
+
+Char STRtildotdirs[] = { '~', '/', '.', 'c', 's', 'h', 'd', 'i', 'r',
+ 's', '\0' };
+Char STRdirsfile[] = { 'd', 'i', 'r', 's', 'f', 'i', 'l', 'e', '\0' };
+Char STRsavedirs[] = { 's', 'a', 'v', 'e', 'd', 'i', 'r', 's', '\0' };
+Char STRloginsh[] = { 'l', 'o', 'g', 'i', 'n', 's', 'h', '\0' };
+Char STRdirstack[] = { 'd', 'i', 'r', 's', 't', 'a', 'c', 'k', '\0' };
+Char STRargv[] = { 'a', 'r', 'g', 'v', '\0' };
+Char STRcommand[] = { 'c', 'o', 'm', 'm', 'a', 'n', 'd', '\0' };
+Char STRsavehist[] = { 's', 'a', 'v', 'e', 'h', 'i', 's', 't', '\0' };
+Char STRnormal[] = { 'n', 'o', 'r', 'm', 'a', 'l', '\0' };
+Char STRsldtlogout[] = { '/', '.', 'l', 'o', 'g', 'o', 'u', 't', '\0' };
+Char STRjobs[] = { 'j', 'o', 'b', 's', '\0' };
+Char STRdeftcshprompt[] = { '%', '#', ' ', '\0' };
+Char STRdefcshprompt[] = { '%', '\0' };
+Char STRmquestion[] = { '%', 'R', '?' | QUOTE, ' ', '\0' };
+Char STRKCORRECT[] = { 'C', 'O', 'R', 'R', 'E', 'C', 'T', '>', '%', 'R',
+ ' ', '(', 'y', '|', 'n', '|', 'e', '|', 'a', ')',
+ '?' | QUOTE, ' ', '\0' };
+Char STRunalias[] = { 'u', 'n', 'a', 'l', 'i', 'a', 's', '\0' };
+Char STRalias[] = { 'a', 'l', 'i', 'a', 's', '\0' };
+Char STRprecmd[] = { 'p', 'r', 'e', 'c', 'm', 'd', '\0' };
+Char STRpostcmd[] = { 'p', 'o', 's', 't', 'c', 'm', 'd', '\0' };
+Char STRcwdcmd[] = { 'c', 'w', 'd', 'c', 'm', 'd', '\0' };
+Char STRperiodic[] = { 'p', 'e', 'r', 'i', 'o', 'd', 'i', 'c', '\0' };
+Char STRtperiod[] = { 't', 'p', 'e', 'r', 'i', 'o', 'd', '\0' };
+Char STRmf[] = { '-', 'f', '\0' };
+Char STRml[] = { '-', 'l', '\0' };
+Char STRslash[] = { '/', '\0' };
+Char STRdotsl[] = { '.', '/', '\0' };
+Char STRdotdotsl[] = { '.', '.', '/', '\0' };
+Char STRcdpath[] = { 'c', 'd', 'p', 'a', 't', 'h', '\0' };
+Char STRcd[] = { 'c', 'd', '\0' };
+Char STRpushdtohome[] = { 'p', 'u', 's', 'h', 'd', 't', 'o', 'h', 'o', 'm',
+ 'e', '\0' };
+Char STRpushdsilent[] = { 'p', 'u', 's', 'h', 'd', 's', 'i', 'l', 'e', 'n',
+ 't', '\0' };
+Char STRdextract[] = { 'd', 'e', 'x', 't', 'r', 'a', 'c', 't', '\0' };
+Char STRdunique[] = { 'd', 'u', 'n', 'i', 'q', 'u', 'e', '\0' };
+Char STRsymlinks[] = { 's', 'y', 'm', 'l', 'i', 'n', 'k', 's', '\0' };
+Char STRignore[] = { 'i', 'g', 'n', 'o', 'r', 'e', '\0' };
+Char STRchase[] = { 'c', 'h', 'a', 's', 'e', '\0' };
+Char STRexpand[] = { 'e', 'x', 'p', 'a', 'n', 'd', '\0' };
+Char STRecho_style[] = { 'e', 'c', 'h', 'o', '_', 's', 't', 'y', 'l', 'e',
+ '\0' };
+Char STRbsd[] = { 'b', 's', 'd', '\0' };
+Char STRsysv[] = { 's', 'y', 's', 'v', '\0' };
+Char STRboth[] = { 'b', 'o', 't', 'h', '\0' };
+Char STRnone[] = { 'n', 'o', 'n', 'e', '\0' };
+Char STRPWD[] = { 'P', 'W', 'D', '\0' };
+Char STRor2[] = { '|', '|', '\0' };
+Char STRand2[] = { '&', '&', '\0' };
+Char STRor[] = { '|', '\0' };
+Char STRcaret[] = { '^', '\0' };
+Char STRand[] = { '&', '\0' };
+Char STRequal[] = { '=', '\0' };
+Char STRbang[] = { '!', '\0' };
+Char STRtilde[] = { '~', '\0' };
+Char STRLparen[] = { '(', '\0' };
+Char STRLbrace[] = { '{', '\0' };
+Char STRfakecom[] = { '{', ' ', '.', '.', '.', ' ', '}', '\0' };
+Char STRRbrace[] = { '}', '\0' };
+Char STRKPATH[] = { 'P', 'A', 'T', 'H', '\0' };
+Char STRdefault[] = { 'd', 'e', 'f', 'a', 'u', 'l', 't', '\0' };
+Char STRmn[] = { '-', 'n', '\0' };
+Char STRminus[] = { '-', '\0' };
+Char STRnoglob[] = { 'n', 'o', 'g', 'l', 'o', 'b', '\0' };
+Char STRnonomatch[] = { 'n', 'o', 'n', 'o', 'm', 'a', 't', 'c', 'h', '\0' };
+Char STRfakecom1[] = { '`', ' ', '.', '.', '.', ' ', '`', '\0' };
+Char STRampm[] = { 'a', 'm', 'p', 'm', '\0' };
+Char STRtime[] = { 't', 'i', 'm', 'e', '\0' };
+Char STRnotify[] = { 'n', 'o', 't', 'i', 'f', 'y', '\0' };
+Char STRprintexitvalue[] = { 'p', 'r', 'i', 'n', 't', 'e', 'x', 'i', 't', 'v',
+ 'a', 'l', 'u', 'e', '\0' };
+Char STRLparensp[] = { '(', ' ', '\0' };
+Char STRspRparen[] = { ' ', ')', '\0' };
+Char STRspace[] = { ' ', '\0' };
+Char STRspor2sp[] = { ' ', '|', '|', ' ', '\0' };
+Char STRspand2sp[] = { ' ', '&', '&', ' ', '\0' };
+Char STRsporsp[] = { ' ', '|', ' ', '\0' };
+Char STRsemisp[] = { ';', ' ', '\0' };
+Char STRsemi[] = { ';', '\0' };
+Char STRQQ[] = { '"', '"', '\0' };
+Char STRBB[] = { '[', ']', '\0' };
+Char STRspLarrow2sp[] = { ' ', '<', '<', ' ', '\0' };
+Char STRspLarrowsp[] = { ' ', '<', ' ', '\0' };
+Char STRspRarrow2[] = { ' ', '>', '>', '\0' };
+Char STRspRarrow[] = { ' ', '>', '\0' };
+Char STRgt[] = { '>', '\0' };
+Char STRsp3dots[] = { ' ', '.', '.', '.', '\0' };
+Char STRcent2[] = { '%', '%', '\0' };
+Char STRcentplus[] = { '%', '+', '\0' };
+Char STRcentminus[] = { '%', '-', '\0' };
+Char STRcenthash[] = { '%', '#', '\0' };
+#ifdef BSDJOBS
+Char STRcontinue[] = { 'c', 'o', 'n', 't', 'i', 'n', 'u', 'e', '\0' };
+Char STRcontinue_args[] = { 'c', 'o', 'n', 't', 'i', 'n', 'u', 'e', '_', 'a',
+ 'r', 'g', 's', '\0' };
+Char STRunderpause[] = { '_', 'p', 'a', 'u', 's', 'e', '\0' };
+#endif
+Char STRbackqpwd[] = { '`', 'p', 'w', 'd', '`', '\0' };
+Char STRhistchars[] = { 'h', 'i', 's', 't', 'c', 'h', 'a', 'r', 's', '\0' };
+Char STRpromptchars[] = { 'p', 'r', 'o', 'm', 'p', 't', 'c', 'h', 'a', 'r',
+ 's', '\0' };
+Char STRhistlit[] = { 'h', 'i', 's', 't', 'l', 'i', 't', '\0' };
+Char STRKUSER[] = { 'U', 'S', 'E', 'R', '\0' };
+Char STRLOGNAME[] = { 'L', 'O', 'G', 'N', 'A', 'M', 'E', '\0' };
+Char STRKGROUP[] = { 'G', 'R', 'O', 'U', 'P', '\0' };
+Char STRwordchars[] = { 'w', 'o', 'r', 'd', 'c', 'h', 'a', 'r', 's', '\0' };
+Char STRKTERM[] = { 'T', 'E', 'R', 'M', '\0' };
+Char STRKHOME[] = { 'H', 'O', 'M', 'E', '\0' };
+Char STRbackslash_quote[] = { 'b', 'a', 'c', 'k', 's', 'l', 'a', 's', 'h', '_',
+ 'q', 'u', 'o', 't', 'e', '\0' };
+Char STRRparen[] = { ')', '\0' };
+Char STRmail[] = { 'm', 'a', 'i', 'l', '\0' };
+#ifndef HAVENOUTMP
+Char STRwatch[] = { 'w', 'a', 't', 'c', 'h', '\0' };
+#endif /* HAVENOUTMP */
+
+Char STRsldottcshrc[] = { '/', '.', 't', 'c', 's', 'h', 'r', 'c', '\0' };
+Char STRsldotcshrc[] = { '/', '.', 'c', 's', 'h', 'r', 'c', '\0' };
+Char STRsldotlogin[] = { '/', '.', 'l', 'o', 'g', 'i', 'n', '\0' };
+Char STRignoreeof[] = { 'i', 'g', 'n', 'o', 'r', 'e', 'e', 'o', 'f', '\0' };
+Char STRnoclobber[] = { 'n', 'o', 'c', 'l', 'o', 'b', 'b', 'e', 'r', '\0' };
+Char STRhelpcommand[] = { 'h', 'e', 'l', 'p', 'c', 'o', 'm', 'm', 'a', 'n',
+ 'd', '\0' };
+Char STRfignore[] = { 'f', 'i', 'g', 'n', 'o', 'r', 'e', '\0' };
+Char STRrecexact[] = { 'r', 'e', 'c', 'e', 'x', 'a', 'c', 't', '\0' };
+Char STRlistmaxrows[] = { 'l', 'i', 's', 't', 'm', 'a', 'x', 'r', 'o', 'w',
+ 's', '\0' };
+Char STRlistmax[] = { 'l', 'i', 's', 't', 'm', 'a', 'x', '\0' };
+Char STRlistlinks[] = { 'l', 'i', 's', 't', 'l', 'i', 'n', 'k', 's', '\0' };
+Char STRDING[] = { 'D', 'I', 'N', 'G', '!', '\0' };
+Char STRQNULL[] = { '\0' | QUOTE, '\0' };
+Char STRcorrect[] = { 'c', 'o', 'r', 'r', 'e', 'c', 't', '\0' };
+Char STRcmd[] = { 'c', 'm', 'd', '\0' };
+Char STRall[] = { 'a', 'l', 'l', '\0' };
+Char STRerase[] = { 'e', 'r', 'a', 's', 'e', '\0' };
+Char STRprev[] = { 'p', 'r', 'e', 'v', '\0' };
+Char STRcomplete[] = { 'c', 'o', 'm', 'p', 'l', 'e', 't', 'e', '\0' };
+Char STRenhance[] = { 'e', 'n', 'h', 'a', 'n', 'c', 'e', '\0' };
+Char STRautoexpand[] = { 'a', 'u', 't', 'o', 'e', 'x', 'p', 'a', 'n', 'd',
+ '\0' };
+Char STRautocorrect[] = { 'a', 'u', 't', 'o', 'c', 'o', 'r', 'r', 'e', 'c',
+ 't', '\0' };
+Char STRautolist[] = { 'a', 'u', 't', 'o', 'l', 'i', 's', 't', '\0' };
+Char STRbeepcmd[] = { 'b', 'e', 'e', 'p', 'c', 'm', 'd', '\0' };
+Char STRmatchbeep[] = { 'm', 'a', 't', 'c', 'h', 'b', 'e', 'e', 'p', '\0' };
+Char STRnomatch[] = { 'n', 'o', 'm', 'a', 't', 'c', 'h', '\0' };
+Char STRambiguous[] = { 'a', 'm', 'b', 'i', 'g', 'u', 'o', 'u', 's', '\0' };
+Char STRnotunique[] = { 'n', 'o', 't', 'u', 'n', 'i', 'q', 'u', 'e', '\0' };
+Char STRret[] = { '\n', '\0' };
+Char STRnobeep[] = { 'n', 'o', 'b', 'e', 'e', 'p', '\0' };
+Char STRnoding[] = { 'n', 'o', 'd', 'i', 'n', 'g', '\0' };
+Char STRnoambiguous[] = { 'n', 'o', 'a', 'm', 'b', 'i', 'g', 'u', 'o', 'u',
+ 's', '\0' };
+Char STRvisiblebell[] = { 'v', 'i', 's', 'i', 'b', 'l', 'e', 'b', 'e', 'l',
+ 'l', '\0' };
+Char STRrecognize_only_executables[] = { 'r', 'e', 'c', 'o', 'g', 'n', 'i',
+ 'z', 'e', '_', 'o', 'n', 'l', 'y',
+ '_', 'e', 'x', 'e', 'c', 'u', 't',
+ 'a', 'b', 'l', 'e', 's', '\0' };
+Char STRinputmode[] = { 'i', 'n', 'p', 'u', 't', 'm', 'o', 'd', 'e',
+ '\0' };
+Char STRoverwrite[] = { 'o', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e',
+ '\0' };
+Char STRinsert[] = { 'i', 'n', 's', 'e', 'r', 't', '\0' };
+Char STRnohup[] = { 'n', 'o', 'h', 'u', 'p', '\0' };
+Char STRhup[] = { 'h', 'u', 'p', '\0' };
+Char STRnice[] = { 'n', 'i', 'c', 'e', '\0' };
+Char STRthen[] = { 't', 'h', 'e', 'n', '\0' };
+Char STReof[] = { '^', 'D', '\b', '\b', '\0' };
+Char STRlistjobs[] = { 'l', 'i', 's', 't', 'j', 'o', 'b', 's', '\0' };
+Char STRlistflags[] = { 'l', 'i', 's', 't', 'f', 'l', 'a', 'g', 's', '\0' };
+Char STRlong[] = { 'l', 'o', 'n', 'g', '\0' };
+Char STRwho[] = { 'w', 'h', 'o', '\0' };
+Char STRsched[] = { 's', 'c', 'h', 'e', 'd', '\0' };
+Char STRrmstar[] = { 'r', 'm', 's', 't', 'a', 'r', '\0' };
+Char STRrm[] = { 'r', 'm', '\0' };
+
+Char STRimplicitcd[] = { 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't',
+ 'c', 'd', '\0' };
+Char STRshlvl[] = { 's', 'h', 'l', 'v', 'l', '\0' };
+Char STRKSHLVL[] = { 'S', 'H', 'L', 'V', 'L', '\0' };
+Char STRLANG[] = { 'L', 'A', 'N', 'G', '\0' };
+Char STRLC_CTYPE[] = { 'L', 'C', '_', 'C', 'T', 'Y', 'P', 'E' ,'\0' };
+Char STRLC_NUMERIC[] = { 'L', 'C', '_', 'N', 'U', 'M', 'E', 'R', 'I',
+ 'C', '\0' };
+Char STRLC_TIME[] = { 'L', 'C', '_', 'T', 'I', 'M', 'E', '\0' };
+Char STRLC_COLLATE[] = { 'L', 'C', '_', 'C', 'O', 'L', 'L', 'A', 'T',
+ 'E', '\0' };
+Char STRLC_MESSAGES[] = { 'L', 'C', '_', 'M', 'E', 'S', 'S', 'A', 'G',
+ 'E', 'S', '\0' };
+Char STRLC_MONETARY[] = { 'L', 'C', '_', 'M', 'O', 'N', 'E', 'T', 'A',
+ 'R', 'Y', '\0' };
+Char STRNOREBIND[] = { 'N', 'O', 'R', 'E', 'B', 'I', 'N', 'D', '\0' };
+
+#if defined(SIG_WINDOW) || defined (_VMS_POSIX)
+/* atp - problem with declaration of str{lines,columns} in sh.func.c (1277) */
+Char STRLINES[] = { 'L', 'I', 'N', 'E', 'S', '\0'};
+Char STRCOLUMNS[] = { 'C', 'O', 'L', 'U', 'M', 'N', 'S', '\0'};
+Char STRTERMCAP[] = { 'T', 'E', 'R', 'M', 'C', 'A', 'P', '\0'};
+#endif /* SIG_WINDOW || _VMS_POSIX */
+
+#ifdef WARP
+Char STRwarp[] = { 'w', 'a', 'r', 'p', '\0' };
+#endif /* WARP */
+
+#ifdef apollo
+Char STRSYSTYPE[] = { 'S', 'Y', 'S', 'T', 'Y', 'P', 'E', '\0' };
+Char STRoid[] = { 'o', 'i', 'd', '\0' };
+Char STRbsd43[] = { 'b', 's', 'd', '4', '.', '3', '\0' };
+Char STRsys53[] = { 's', 'y', 's', '5', '.', '3', '\0' };
+Char STRver[] = { 'v', 'e', 'r', '\0' };
+#endif /* apollo */
+
+#ifdef _OSD_POSIX
+Char STRwarnebcdic[] = { 'w', 'a', 'r', 'n', 'e', 'b', 'c', 'd', 'i', 'c', '\0' };
+#endif
+
+#ifdef COLOR_LS_F
+Char STRlsmF[] = { 'l', 's', '-', 'F', '\0' };
+Char STRcolor[] = { 'c', 'o', 'l', 'o', 'r', '\0' };
+Char STRmmcolormauto[] = {'-', '-', 'c', 'o', 'l', 'o', 'r', '=', 'a', 'u', 't', 'o', '\0' };
+Char STRLS_COLORS[] = { 'L', 'S', '_', 'C', 'O', 'L', 'O', 'R', 'S', '\0' };
+#endif /* COLOR_LS_F */
+
+Char STRls[] = { 'l', 's', '\0' };
+
+Char STRup[] = { 'u', 'p', '\0' };
+Char STRdown[] = { 'd', 'o', 'w', 'n', '\0' };
+Char STRleft[] = { 'l', 'e', 'f', 't', '\0' };
+Char STRright[] = { 'r', 'i', 'g', 'h', 't', '\0' };
+
+#ifdef COLORCAT
+Char STRcolorcat[] = { 'c', 'o', 'l', 'o', 'r', 'c', 'a', 't', '\0' };
+#endif
diff --git a/contrib/tcsh/tc.decls.h b/contrib/tcsh/tc.decls.h
new file mode 100644
index 0000000..3498c14
--- /dev/null
+++ b/contrib/tcsh/tc.decls.h
@@ -0,0 +1,335 @@
+/* $Header: /src/pub/tcsh/tc.decls.h,v 3.44 1999/02/06 15:19:00 christos Exp $ */
+/*
+ * tc.decls.h: Function declarations from all the tcsh modules
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tc_decls
+#define _h_tc_decls
+
+/*
+ * tc.alloc.c
+ */
+#ifndef SYSMALLOC
+#ifndef WINNT
+extern void free __P((ptr_t));
+extern memalign_t malloc __P((size_t));
+extern memalign_t realloc __P((ptr_t, size_t));
+extern memalign_t calloc __P((size_t, size_t));
+#endif /* !WINNT */
+#else /* SYSMALLOC */
+extern void sfree __P((ptr_t));
+extern memalign_t smalloc __P((size_t));
+extern memalign_t srealloc __P((ptr_t, size_t));
+extern memalign_t scalloc __P((size_t, size_t));
+#endif /* SYSMALLOC */
+extern void showall __P((Char **, struct command *));
+
+/*
+ * tc.bind.c
+ */
+extern void dobindkey __P((Char **, struct command *));
+#ifdef OBSOLETE
+extern void dobind __P((Char **, struct command *));
+#endif /* OBSOLETE */
+
+/*
+ * tc.defs.c:
+ */
+extern void getmachine __P((void));
+
+
+/*
+ * tc.disc.c
+ */
+extern int setdisc __P((int));
+extern int resetdisc __P((int));
+
+/*
+ * tc.func.c
+ */
+extern Char *expand_lex __P((Char *, size_t, struct wordent *,
+ int, int));
+extern Char *sprlex __P((Char *, size_t, struct wordent *));
+extern Char *Itoa __P((int, Char *, int, int));
+extern void dolist __P((Char **, struct command *));
+extern void dotelltc __P((Char **, struct command *));
+extern void doechotc __P((Char **, struct command *));
+extern void dosettc __P((Char **, struct command *));
+extern int cmd_expand __P((Char *, Char *));
+extern void dowhich __P((Char **, struct command *));
+extern struct process *find_stop_ed __P((void));
+extern void fg_proc_entry __P((struct process *));
+extern sigret_t alrmcatch __P((int));
+extern void precmd __P((void));
+extern void postcmd __P((void));
+extern void cwd_cmd __P((void));
+extern void beep_cmd __P((void));
+extern void period_cmd __P((void));
+extern void aliasrun __P((int, Char *, Char *));
+extern void setalarm __P((int));
+extern void rmstar __P((struct wordent *));
+extern void continue_jobs __P((struct wordent *));
+extern Char *gettilde __P((Char *));
+extern Char *getusername __P((Char **));
+#ifdef OBSOLETE
+extern void doaliases __P((Char **, struct command *));
+#endif /* OBSOLETE */
+extern void shlvl __P((int));
+extern int fixio __P((int, int));
+extern int collate __P((const Char *, const Char *));
+#ifdef HASHBANG
+extern int hashbang __P((int, Char ***));
+#endif /* HASHBANG */
+#ifdef REMOTEHOST
+extern void remotehost __P((void));
+#endif /* REMOTEHOST */
+
+
+/*
+ * tc.os.c
+ */
+#ifdef MACH
+extern void dosetpath __P((Char **, struct command *));
+#endif /* MACH */
+
+#ifdef TCF
+extern void dogetxvers __P((Char **, struct command *));
+extern void dosetxvers __P((Char **, struct command *));
+extern void dogetspath __P((Char **, struct command *));
+extern void dosetspath __P((Char **, struct command *));
+extern char *sitename __P((pid_t));
+extern void domigrate __P((Char **, struct command *));
+#endif /* TCF */
+
+#ifdef WARP
+extern void dowarp __P((Char **, struct command *));
+#endif /* WARP */
+
+#if defined(_CRAY) && !defined(_CRAYMPP)
+extern void dodmmode __P((Char **, struct command *));
+#endif /* _CRAY && !_CRAYMPP */
+
+#if defined(masscomp) || defined(hcx)
+extern void douniverse __P((Char **, struct command *));
+#endif /* masscomp */
+
+#if defined(hcx)
+extern void doatt __P((Char **, struct command *));
+extern void doucb __P((Char **, struct command *));
+#endif /* hcx */
+
+#ifdef _SEQUENT_
+extern void pr_stat_sub __P((struct process_stats *,
+ struct process_stats *,
+ struct process_stats *));
+#endif /* _SEQUENT_ */
+
+#ifdef NEEDtcgetpgrp
+extern int xtcgetpgrp __P((int));
+extern int xtcsetpgrp __P((int, int));
+# undef tcgetpgrp
+# define tcgetpgrp(a) xtcgetpgrp(a)
+# undef tcsetpgrp
+# define tcsetpgrp(a, b) xtcsetpgrp((a), (b))
+#endif /* NEEDtcgetpgrp */
+
+#ifdef YPBUGS
+extern void fix_yp_bugs __P((void));
+#endif /* YPBUGS */
+#ifdef STRCOLLBUG
+extern void fix_strcoll_bug __P((void));
+#endif /* STRCOLLBUG */
+
+extern void osinit __P((void));
+
+#ifdef NEEDmemmove
+extern ptr_t xmemmove __P((ptr_t, const ptr_t, size_t));
+# define memmove(a, b, c) xmemmove((a), (b), (c))
+#endif /* NEEDmemmove */
+
+#ifdef NEEDmemset
+extern ptr_t xmemset __P((ptr_t, int, size_t));
+# define memset(a, b, c) xmemset((a), (b), (c))
+#endif /* NEEDmemset */
+
+
+#ifdef NEEDgetcwd
+extern char *xgetcwd __P((char *, size_t));
+# undef getcwd
+# define getcwd(a, b) xgetcwd((a), (b))
+#endif /* NEEDgetcwd */
+
+#ifdef NEEDgethostname
+extern int xgethostname __P((char *, int));
+# undef gethostname
+# define gethostname(a, b) xgethostname((a), (b))
+#endif /* NEEDgethostname */
+
+#ifdef NEEDnice
+extern int xnice __P((int));
+# undef nice
+# define nice(a) xnice(a)
+#endif /* NEEDnice */
+
+#ifdef NEEDstrerror
+extern char *xstrerror __P((int));
+# undef strerror
+# define strerror(a) xstrerror(a)
+#endif /* NEEDstrerror */
+
+#ifdef apollo
+extern void doinlib __P((Char **, struct command *));
+extern void dover __P((Char **, struct command *));
+extern void dorootnode __P((Char **, struct command *));
+extern int getv __P((Char *));
+#endif /* apollo */
+
+
+/*
+ * tc.printf.h
+ */
+extern pret_t xprintf __P((const char *, ...));
+extern pret_t xsnprintf __P((char *, size_t, const char *, ...));
+extern pret_t xvprintf __P((const char *, va_list));
+extern pret_t xvsnprintf __P((char *, size_t, const char *,
+ va_list));
+
+/*
+ * tc.prompt.c
+ */
+extern void dateinit __P((void));
+extern void printprompt __P((int, char *));
+extern Char *expdollar __P((Char **, const Char **, size_t *,
+ int));
+extern void tprintf __P((int, Char *, const Char *, size_t,
+ char *, time_t, ptr_t));
+
+/*
+ * tc.sched.c
+ */
+extern time_t sched_next __P((void));
+extern void dosched __P((Char **, struct command *));
+extern void sched_run __P((int));
+
+/*
+ * tc.sig.c
+ */
+#ifndef BSDSIGS
+# ifdef UNRELSIGS
+# ifdef COHERENT
+extern sigret_t (*xsignal __P((int, sigret_t (*)(int)))) ();
+# define signal(x,y) xsignal(x,y)
+# endif /* COHERENT */
+extern sigret_t (*xsigset __P((int, sigret_t (*)(int)))) ();
+# define sigset(x,y) xsigset(x,y)
+extern void xsigrelse __P((int));
+# define sigrelse(x) xsigrelse(x)
+extern void xsighold __P((int));
+# define sighold(x) xsighold(x)
+extern void xsigignore __P((int));
+# define sigignore(x) xsigignore(x)
+extern void xsigpause __P((int));
+# define sigpause(x) xsigpause(x)
+extern pid_t ourwait __P((int *));
+# endif /* UNRELSIGS */
+# ifdef SXA
+extern void sigpause __P((int));
+# endif /* SXA */
+#endif /* !BSDSIGS */
+
+#ifdef NEEDsignal
+extern sigret_t (*xsignal __P((int, sigret_t (*)(int)))) ();
+# define signal(a, b) xsignal(a, b)
+#endif /* NEEDsignal */
+#if defined(_SEQUENT_) || ((SYSVREL > 3 || defined(_DGUX_SOURCE)) && defined(POSIXSIGS)) || (defined(_AIX) && defined(POSIXSIGS)) || defined(WINNT)
+extern sigmask_t sigsetmask __P((sigmask_t));
+# if !defined(DGUX) || (defined(DGUX) && defined(__ix86))
+extern sigmask_t sigblock __P((sigmask_t));
+# endif /* !DGUX */
+extern void bsd_sigpause __P((sigmask_t));
+extern sigret_t (*bsd_signal __P((int, sigret_t (*)(int)))) __P((int));
+#endif /* _SEQUENT_ */
+#ifdef SIGSYNCH
+extern sigret_t synch_handler __P((int));
+#endif /* SIGSYNCH */
+
+
+/*
+ * tc.str.c:
+ */
+#ifdef SHORT_STRINGS
+extern Char *s_strchr __P((const Char *, int));
+extern Char *s_strrchr __P((const Char *, int));
+extern Char *s_strcat __P((Char *, const Char *));
+# ifdef NOTUSED
+extern Char *s_strncat __P((Char *, const Char *, size_t));
+# endif /* NOTUSED */
+extern Char *s_strcpy __P((Char *, const Char *));
+extern Char *s_strncpy __P((Char *, const Char *, size_t));
+extern Char *s_strspl __P((const Char *, const Char *));
+extern size_t s_strlen __P((const Char *));
+extern int s_strcmp __P((const Char *, const Char *));
+extern int s_strncmp __P((const Char *, const Char *,
+ size_t));
+extern Char *s_strsave __P((const Char *));
+extern Char *s_strend __P((const Char *));
+extern Char *s_strstr __P((const Char *, const Char *));
+extern Char *str2short __P((const char *));
+extern Char **blk2short __P((char **));
+extern char *short2str __P((const Char *));
+extern char **short2blk __P((Char **));
+#endif /* SHORT_STRINGS */
+extern char *short2qstr __P((const Char *));
+
+
+/*
+ * tc.vers.c:
+ */
+extern void fix_version __P((void));
+
+/*
+ * tc.who.c
+ */
+#ifndef HAVENOUTMP
+extern void initwatch __P((void));
+extern void resetwatch __P((void));
+extern void watch_login __P((int));
+extern const char *who_info __P((ptr_t, int, char *, size_t));
+extern void dolog __P((Char **, struct command *));
+# ifdef UTHOST
+extern char *utmphost __P((void));
+# endif /* UTHOST */
+#endif /* HAVENOUTMP */
+
+#endif /* _h_tc_decls */
diff --git a/contrib/tcsh/tc.disc.c b/contrib/tcsh/tc.disc.c
new file mode 100644
index 0000000..7c68103
--- /dev/null
+++ b/contrib/tcsh/tc.disc.c
@@ -0,0 +1,200 @@
+/* $Header: /src/pub/tcsh/tc.disc.c,v 3.11 1997/10/02 16:36:31 christos Exp $ */
+/*
+ * tc.disc.c: Functions to set/clear line disciplines
+ *
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.disc.c,v 3.11 1997/10/02 16:36:31 christos Exp $")
+
+#ifdef OREO
+#include <compat.h>
+#endif /* OREO */
+
+#include "ed.term.h"
+
+static bool add_discipline = 0; /* Did we add a line discipline */
+
+#if defined(IRIS4D) || defined(OREO) || defined(sonyrisc)
+# define HAVE_DISC
+# ifndef POSIX
+static struct termio otermiob;
+# else
+static struct termios otermiob;
+# endif /* POSIX */
+#endif /* IRIS4D || OREO */
+
+#ifdef _IBMR2
+# define HAVE_DISC
+char strPOSIX[] = "posix";
+#endif /* _IBMR2 */
+
+#if !defined(HAVE_DISC) && defined(TIOCGETD) && defined(NTTYDISC)
+static int oldisc;
+#endif /* !HAVE_DISC && TIOCGETD && NTTYDISC */
+
+int
+/*ARGSUSED*/
+setdisc(f)
+int f;
+{
+#ifdef IRIS4D
+# ifndef POSIX
+ struct termio termiob;
+# else
+ struct termios termiob;
+# endif
+
+ if (ioctl(f, TCGETA, (ioctl_t) & termiob) == 0) {
+ otermiob = termiob;
+#if (SYSVREL < 4) || !defined(IRIS4D)
+ if (termiob.c_line != NTTYDISC || termiob.c_cc[VSWTCH] == 0) { /*}*/
+ termiob.c_line = NTTYDISC;
+#else
+ if (termiob.c_cc[VSWTCH] == 0) {
+#endif
+ termiob.c_cc[VSWTCH] = CSWTCH;
+ if (ioctl(f, TCSETA, (ioctl_t) & termiob) != 0)
+ return (-1);
+ }
+ }
+ else
+ return (-1);
+ add_discipline = 1;
+ return (0);
+#endif /* IRIS4D */
+
+
+#ifdef OREO
+# ifndef POSIX
+ struct termio termiob;
+# else
+ struct termios termiob;
+# endif
+
+ struct ltchars ltcbuf;
+
+ if (ioctl(f, TCGETA, (ioctl_t) & termiob) == 0) {
+ int comp = getcompat(COMPAT_BSDTTY);
+ otermiob = termiob;
+ if ((comp & COMPAT_BSDTTY) != COMPAT_BSDTTY) {
+ (void) setcompat(comp | COMPAT_BSDTTY);
+ if (ioctl(f, TIOCGLTC, (ioctl_t) & ltcbuf) != 0)
+ xprintf(CGETS(21, 1, "Couldn't get local chars.\n"));
+ else {
+ ltcbuf.t_suspc = CTL_ESC('\032'); /* ^Z */
+ ltcbuf.t_dsuspc = CTL_ESC('\031'); /* ^Y */
+ ltcbuf.t_rprntc = CTL_ESC('\022'); /* ^R */
+ ltcbuf.t_flushc = CTL_ESC('\017'); /* ^O */
+ ltcbuf.t_werasc = CTL_ESC('\027'); /* ^W */
+ ltcbuf.t_lnextc = CTL_ESC('\026'); /* ^V */
+ if (ioctl(f, TIOCSLTC, (ioctl_t) & ltcbuf) != 0)
+ xprintf(CGETS(21, 2, "Couldn't set local chars.\n"));
+ }
+ termiob.c_cc[VSWTCH] = '\0';
+ if (ioctl(f, TCSETAF, (ioctl_t) & termiob) != 0)
+ return (-1);
+ }
+ }
+ else
+ return (-1);
+ add_discipline = 1;
+ return (0);
+#endif /* OREO */
+
+
+#ifdef _IBMR2
+ union txname tx;
+
+ tx.tx_which = 0;
+
+ if (ioctl(f, TXGETLD, (ioctl_t) & tx) == 0) {
+ if (strcmp(tx.tx_name, strPOSIX) != 0)
+ if (ioctl(f, TXADDCD, (ioctl_t) strPOSIX) == 0) {
+ add_discipline = 1;
+ return (0);
+ }
+ return (0);
+ }
+ else
+ return (-1);
+#endif /* _IBMR2 */
+
+#ifndef HAVE_DISC
+# if defined(TIOCGETD) && defined(NTTYDISC)
+ if (ioctl(f, TIOCGETD, (ioctl_t) & oldisc) == 0) {
+ if (oldisc != NTTYDISC) {
+ int ldisc = NTTYDISC;
+
+ if (ioctl(f, TIOCSETD, (ioctl_t) & ldisc) != 0)
+ return (-1);
+ add_discipline = 1;
+ }
+ else
+ oldisc = -1;
+ return (0);
+ }
+ else
+ return (-1);
+# else
+ return (0);
+# endif /* TIOCGETD && NTTYDISC */
+#endif /* !HAVE_DISC */
+} /* end setdisc */
+
+
+int
+/*ARGSUSED*/
+resetdisc(f)
+int f;
+{
+ if (add_discipline) {
+ add_discipline = 0;
+#if defined(OREO) || defined(IRIS4D)
+ return (ioctl(f, TCSETAF, (ioctl_t) & otermiob));
+#endif /* OREO || IRIS4D */
+
+#ifdef _IBMR2
+ return (ioctl(f, TXDELCD, (ioctl_t) strPOSIX));
+#endif /* _IBMR2 */
+
+#ifndef HAVE_DISC
+# if defined(TIOCSETD) && defined(NTTYDISC)
+ return (ioctl(f, TIOCSETD, (ioctl_t) & oldisc));
+# endif /* TIOCSETD && NTTYDISC */
+#endif /* !HAVE_DISC */
+ }
+ return (0);
+} /* end resetdisc */
diff --git a/contrib/tcsh/tc.func.c b/contrib/tcsh/tc.func.c
new file mode 100644
index 0000000..2dcb03f
--- /dev/null
+++ b/contrib/tcsh/tc.func.c
@@ -0,0 +1,2125 @@
+/* $Header: /src/pub/tcsh/tc.func.c,v 3.87 1999/08/14 21:24:13 christos Exp $ */
+/*
+ * tc.func.c: New tcsh builtins.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.func.c,v 3.87 1999/08/14 21:24:13 christos Exp $")
+
+#include "ed.h"
+#include "ed.defns.h" /* for the function names */
+#include "tw.h"
+#include "tc.h"
+#ifdef WINNT
+#include "nt.const.h"
+#endif /* WINNT */
+
+#ifdef AFS
+#define PASSMAX 16
+#include <afs/stds.h>
+#include <afs/kautils.h>
+long ka_UserAuthenticateGeneral();
+#else
+#ifndef PASSMAX
+#define PASSMAX 8
+#endif
+#endif /* AFS */
+
+#ifdef TESLA
+extern int do_logout;
+#endif /* TESLA */
+extern time_t t_period;
+extern int just_signaled;
+static bool precmd_active = 0;
+static bool postcmd_active = 0;
+static bool periodic_active = 0;
+static bool cwdcmd_active = 0; /* PWP: for cwd_cmd */
+static bool beepcmd_active = 0;
+static signalfun_t alm_fun = NULL;
+
+static void auto_logout __P((int));
+static char *xgetpass __P((char *));
+static void auto_lock __P((int));
+#ifdef BSDJOBS
+static void insert __P((struct wordent *, bool));
+static void insert_we __P((struct wordent *, struct wordent *));
+static int inlist __P((Char *, Char *));
+#endif /* BSDJOBS */
+struct tildecache;
+static int tildecompare __P((struct tildecache *, struct tildecache *));
+static Char *gethomedir __P((Char *));
+#ifdef REMOTEHOST
+static sigret_t palarm __P((int));
+static void getremotehost __P((void));
+#endif /* REMOTEHOST */
+
+/*
+ * Tops-C shell
+ */
+
+/*
+ * expand_lex: Take the given lex and put an expanded version of it in the
+ * string buf. First guy in lex list is ignored; last guy is ^J which we
+ * ignore Only take lex'es from position from to position to inclusive Note:
+ * csh sometimes sets bit 8 in characters which causes all kinds of problems
+ * if we don't mask it here. Note: excl's in lexes have been un-back-slashed
+ * and must be re-back-slashed
+ * (PWP: NOTE: this returns a pointer to the END of the string expanded
+ * (in other words, where the NUL is).)
+ */
+/* PWP: this is a combination of the old sprlex() and the expand_lex from
+ the magic-space stuff */
+
+Char *
+expand_lex(buf, bufsiz, sp0, from, to)
+ Char *buf;
+ size_t bufsiz;
+ struct wordent *sp0;
+ int from, to;
+{
+ register struct wordent *sp;
+ register Char *s, *d, *e;
+ register Char prev_c;
+ register int i;
+
+ buf[0] = '\0';
+ prev_c = '\0';
+ d = buf;
+ e = &buf[bufsiz]; /* for bounds checking */
+
+ if (!sp0)
+ return (buf); /* null lex */
+ if ((sp = sp0->next) == sp0)
+ return (buf); /* nada */
+ if (sp == (sp0 = sp0->prev))
+ return (buf); /* nada */
+
+ for (i = 0; i < NCARGS; i++) {
+ if ((i >= from) && (i <= to)) { /* if in range */
+ for (s = sp->word; *s && d < e; s++) {
+ /*
+ * bugfix by Michael Bloom: anything but the current history
+ * character {(PWP) and backslash} seem to be dealt with
+ * elsewhere.
+ */
+ if ((*s & QUOTE)
+ && (((*s & TRIM) == HIST) ||
+ (((*s & TRIM) == '\'') && (prev_c != '\\')) ||
+ (((*s & TRIM) == '\"') && (prev_c != '\\')) ||
+ (((*s & TRIM) == '\\') && (prev_c != '\\')))) {
+ *d++ = '\\';
+ }
+ if (d < e)
+ *d++ = (*s & TRIM);
+ prev_c = *s;
+ }
+ if (d < e)
+ *d++ = ' ';
+ }
+ sp = sp->next;
+ if (sp == sp0)
+ break;
+ }
+ if (d > buf)
+ d--; /* get rid of trailing space */
+
+ return (d);
+}
+
+Char *
+sprlex(buf, bufsiz, sp0)
+ Char *buf;
+ size_t bufsiz;
+ struct wordent *sp0;
+{
+ Char *cp;
+
+ cp = expand_lex(buf, bufsiz, sp0, 0, NCARGS);
+ *cp = '\0';
+ return (buf);
+}
+
+
+Char *
+Itoa(n, s, min_digits, attributes)
+ int n;
+ Char *s;
+ int min_digits, attributes;
+{
+ /*
+ * The array size here is derived from
+ * log8(UINT_MAX)
+ * which is guaranteed to be enough for a decimal
+ * representation. We add 1 because integer divide
+ * rounds down.
+ */
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+ Char buf[CHAR_BIT * sizeof(int) / 3 + 1];
+ Char *p;
+ unsigned int un; /* handle most negative # too */
+ int pad = (min_digits != 0);
+
+ if (sizeof(buf) - 1 < min_digits)
+ min_digits = sizeof(buf) - 1;
+
+ un = n;
+ if (n < 0) {
+ un = -n;
+ *s++ = '-';
+ }
+
+ p = buf;
+ do {
+ *p++ = un % 10 + '0';
+ un /= 10;
+ } while ((pad && --min_digits > 0) || un != 0);
+
+ while (p > buf)
+ *s++ = *--p | attributes;
+
+ *s = '\0';
+ return s;
+}
+
+
+/*ARGSUSED*/
+void
+dolist(v, c)
+ register Char **v;
+ struct command *c;
+{
+ int i, k;
+ struct stat st;
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+ extern bool dspmbyte_ls;
+#endif
+#ifdef COLOR_LS_F
+ extern bool color_context_ls;
+#endif /* COLOR_LS_F */
+
+ USE(c);
+ if (*++v == NULL) {
+ (void) t_search(STRNULL, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0);
+ return;
+ }
+ gflag = 0;
+ tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else
+ v = gargv = saveblk(v);
+ trim(v);
+ for (k = 0; v[k] != NULL && v[k][0] != '-'; k++)
+ continue;
+ if (v[k]) {
+ /*
+ * We cannot process a flag therefore we let ls do it right.
+ */
+ static Char STRls[] = {'l', 's', '\0'};
+ static Char STRmCF[] = {'-', 'C', 'F', '\0', '\0' };
+ Char *lspath;
+ struct command *t;
+ struct wordent cmd, *nextword, *lastword;
+ Char *cp;
+ struct varent *vp;
+
+#ifdef BSDSIGS
+ sigmask_t omask = 0;
+
+ if (setintr)
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (seterr) {
+ xfree((ptr_t) seterr);
+ seterr = NULL;
+ }
+
+ lspath = STRls;
+ STRmCF[1] = 'C';
+ STRmCF[3] = '\0';
+ /* Look at listflags, to add -A to the flags, to get a path
+ of ls if necessary */
+ if ((vp = adrof(STRlistflags)) != NULL && vp->vec[0] != STRNULL) {
+ if (vp->vec[1] != NULL && vp->vec[1][0] != '\0')
+ lspath = vp->vec[1];
+ for (cp = vp->vec[0]; *cp; cp++)
+ switch (*cp) {
+ case 'x':
+ STRmCF[1] = 'x';
+ break;
+ case 'a':
+ STRmCF[3] = 'a';
+ break;
+ case 'A':
+ STRmCF[3] = 'A';
+ break;
+ default:
+ break;
+ }
+ }
+
+ cmd.word = STRNULL;
+ lastword = &cmd;
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(lspath);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+ lastword = nextword;
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(STRmCF);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
+ if (dspmbyte_ls) {
+ lastword = nextword;
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(STRmmliteral);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+ }
+#endif
+#ifdef COLOR_LS_F
+ if (color_context_ls) {
+ lastword = nextword;
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(STRmmcolormauto);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+ }
+#endif /* COLOR_LS_F */
+ lastword = nextword;
+ for (cp = *v; cp; cp = *++v) {
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(cp);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+ lastword = nextword;
+ }
+ lastword->next = &cmd;
+ cmd.prev = lastword;
+
+ /* build a syntax tree for the command. */
+ t = syntax(cmd.next, &cmd, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+ /* expand aliases like process() does */
+ /* alias(&cmd); */
+ /* execute the parse tree. */
+ execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL);
+ /* done. free the lex list and parse tree. */
+ freelex(&cmd), freesyn(t);
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+ }
+ else {
+ Char *dp, *tmp, buf[MAXPATHLEN];
+
+ for (k = 0, i = 0; v[k] != NULL; k++) {
+ tmp = dnormalize(v[k], symlinks == SYM_IGNORE);
+ dp = &tmp[Strlen(tmp) - 1];
+ if (*dp == '/' && dp != tmp)
+#ifdef apollo
+ if (dp != &tmp[1])
+#endif /* apollo */
+ *dp = '\0';
+ if (stat(short2str(tmp), &st) == -1) {
+ if (k != i) {
+ if (i != 0)
+ xputchar('\n');
+ print_by_column(STRNULL, &v[i], k - i, FALSE);
+ }
+ xprintf("%S: %s.\n", tmp, strerror(errno));
+ i = k + 1;
+ }
+ else if (S_ISDIR(st.st_mode)) {
+ Char *cp;
+
+ if (k != i) {
+ if (i != 0)
+ xputchar('\n');
+ print_by_column(STRNULL, &v[i], k - i, FALSE);
+ }
+ if (k != 0 && v[1] != NULL)
+ xputchar('\n');
+ xprintf("%S:\n", tmp);
+ for (cp = tmp, dp = buf; *cp; *dp++ = (*cp++ | QUOTE))
+ continue;
+ if (
+#ifdef WINNT
+ (dp[-1] != (Char) (':' | QUOTE)) &&
+#endif /* WINNT */
+ (dp[-1] != (Char) ('/' | QUOTE)))
+ *dp++ = '/';
+ else
+ dp[-1] &= TRIM;
+ *dp = '\0';
+ (void) t_search(buf, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0);
+ i = k + 1;
+ }
+ xfree((ptr_t) tmp);
+ }
+ if (k != i) {
+ if (i != 0)
+ xputchar('\n');
+ print_by_column(STRNULL, &v[i], k - i, FALSE);
+ }
+ }
+
+ if (gargv) {
+ blkfree(gargv);
+ gargv = 0;
+ }
+}
+
+static char *defaulttell = "ALL";
+extern bool GotTermCaps;
+
+/*ARGSUSED*/
+void
+dotelltc(v, c)
+ register Char **v;
+ struct command *c;
+{
+ USE(c);
+ if (!GotTermCaps)
+ GetTermCaps();
+
+ /*
+ * Avoid a compiler bug on hpux 9.05
+ * Writing the following as func(a ? b : c) breaks
+ */
+ if (v[1])
+ TellTC(short2str(v[1]));
+ else
+ TellTC(defaulttell);
+}
+
+/*ARGSUSED*/
+void
+doechotc(v, c)
+ register Char **v;
+ struct command *c;
+{
+ if (!GotTermCaps)
+ GetTermCaps();
+ EchoTC(++v);
+}
+
+/*ARGSUSED*/
+void
+dosettc(v, c)
+ Char **v;
+ struct command *c;
+{
+ char tv[2][BUFSIZE];
+
+ if (!GotTermCaps)
+ GetTermCaps();
+
+ (void) strcpy(tv[0], short2str(v[1]));
+ (void) strcpy(tv[1], short2str(v[2]));
+ SetTC(tv[0], tv[1]);
+}
+
+/* The dowhich() is by:
+ * Andreas Luik <luik@isaak.isa.de>
+ * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
+ * Azenberstr. 35
+ * D-7000 Stuttgart 1
+ * West-Germany
+ * Thanks!!
+ */
+int
+cmd_expand(cmd, str)
+ Char *cmd;
+ Char *str;
+{
+ struct wordent lexp[3];
+ struct varent *vp;
+ int rv = TRUE;
+
+ lexp[0].next = &lexp[1];
+ lexp[1].next = &lexp[2];
+ lexp[2].next = &lexp[0];
+
+ lexp[0].prev = &lexp[2];
+ lexp[1].prev = &lexp[0];
+ lexp[2].prev = &lexp[1];
+
+ lexp[0].word = STRNULL;
+ lexp[2].word = STRret;
+
+ if ((vp = adrof1(cmd, &aliases)) != NULL) {
+ if (str == NULL) {
+ xprintf(CGETS(22, 1, "%S: \t aliased to "), cmd);
+ blkpr(vp->vec);
+ xputchar('\n');
+ }
+ else
+ blkexpand(vp->vec, str);
+ }
+ else {
+ lexp[1].word = cmd;
+ rv = tellmewhat(lexp, str);
+ }
+ return rv;
+}
+
+
+/*ARGSUSED*/
+void
+dowhich(v, c)
+ register Char **v;
+ struct command *c;
+{
+ int rv = TRUE;
+ USE(c);
+
+#ifdef notdef
+ /*
+ * We don't want to glob dowhich args because we lose quoteing
+ * E.g. which \ls if ls is aliased will not work correctly if
+ * we glob here.
+ */
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+#endif
+
+ while (*++v)
+ rv &= cmd_expand(*v, NULL);
+
+ if (!rv)
+ set(STRstatus, Strsave(STR1), VAR_READWRITE);
+
+#ifdef notdef
+ /* Again look at the comment above; since we don't glob, we don't free */
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+#endif
+}
+
+/* PWP: a hack to start up your stopped editor on a single keystroke */
+/* jbs - fixed hack so it worked :-) 3/28/89 */
+
+struct process *
+find_stop_ed()
+{
+ register struct process *pp, *retp;
+ register char *ep, *vp, *cp, *p;
+ int epl, vpl, pstatus;
+
+ if ((ep = getenv("EDITOR")) != NULL) { /* if we have a value */
+ if ((p = strrchr(ep, '/')) != NULL) /* if it has a path */
+ ep = p + 1; /* then we want only the last part */
+ }
+ else
+ ep = "ed";
+
+ if ((vp = getenv("VISUAL")) != NULL) { /* if we have a value */
+ if ((p = strrchr(vp, '/')) != NULL) /* and it has a path */
+ vp = p + 1; /* then we want only the last part */
+ }
+ else
+ vp = "vi";
+
+ for (vpl = 0; vp[vpl] && !Isspace(vp[vpl]); vpl++)
+ continue;
+ for (epl = 0; ep[epl] && !Isspace(ep[epl]); epl++)
+ continue;
+
+ if (pcurrent == NULL) /* see if we have any jobs */
+ return NULL; /* nope */
+
+ retp = NULL;
+ for (pp = proclist.p_next; pp; pp = pp->p_next)
+ if (pp->p_procid == pp->p_jobid) {
+
+ /*
+ * Only foreground an edit session if it is suspended. Some GUI
+ * editors have may be happily running in a separate window, no
+ * point in foregrounding these if they're already running - webb
+ */
+ pstatus = (int) (pp->p_flags & PALLSTATES);
+ if (pstatus != PINTERRUPTED && pstatus != PSTOPPED &&
+ pstatus != PSIGNALED)
+ continue;
+
+ p = short2str(pp->p_command);
+ /* get the first word */
+ for (cp = p; *cp && !isspace((unsigned char) *cp); cp++)
+ continue;
+ *cp = '\0';
+
+ if ((cp = strrchr(p, '/')) != NULL) /* and it has a path */
+ cp = cp + 1; /* then we want only the last part */
+ else
+ cp = p; /* else we get all of it */
+
+ /* if we find either in the current name, fg it */
+ if (strncmp(ep, cp, (size_t) epl) == 0 ||
+ strncmp(vp, cp, (size_t) vpl) == 0) {
+
+ /*
+ * If there is a choice, then choose the current process if
+ * available, or the previous process otherwise, or else
+ * anything will do - Robert Webb (robertw@mulga.cs.mu.oz.au).
+ */
+ if (pp == pcurrent)
+ return pp;
+ else if (retp == NULL || pp == pprevious)
+ retp = pp;
+ }
+ }
+
+ return retp; /* Will be NULL if we didn't find a job */
+}
+
+void
+fg_proc_entry(pp)
+ register struct process *pp;
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif
+ jmp_buf_t osetexit;
+ bool ohaderr;
+ Char oGettingInput;
+
+ getexit(osetexit);
+
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+ oGettingInput = GettingInput;
+ GettingInput = 0;
+
+ ohaderr = haderr; /* we need to ignore setting of haderr due to
+ * process getting stopped by a signal */
+ if (setexit() == 0) { /* come back here after pjwait */
+ pendjob();
+ (void) alarm(0); /* No autologout */
+ if (!pstart(pp, 1)) {
+ pp->p_procid = 0;
+ stderror(ERR_BADJOB, pp->p_command, strerror(errno));
+ }
+ pjwait(pp);
+ }
+ setalarm(1); /* Autologout back on */
+ resexit(osetexit);
+ haderr = ohaderr;
+ GettingInput = oGettingInput;
+
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+
+}
+
+static char *
+xgetpass(prm)
+ char *prm;
+{
+ static char pass[PASSMAX + 1];
+ int fd, i;
+ signalfun_t sigint;
+
+ sigint = (signalfun_t) sigset(SIGINT, SIG_IGN);
+ (void) Rawmode(); /* Make sure, cause we want echo off */
+ if ((fd = open("/dev/tty", O_RDWR)) == -1)
+ fd = SHIN;
+
+ xprintf("%s", prm); flush();
+ for (i = 0;;) {
+ if (read(fd, &pass[i], 1) < 1 || pass[i] == '\n')
+ break;
+ if (i < PASSMAX)
+ i++;
+ }
+
+ pass[i] = '\0';
+
+ if (fd != SHIN)
+ (void) close(fd);
+ (void) sigset(SIGINT, sigint);
+
+ return(pass);
+}
+
+/*
+ * Ask the user for his login password to continue working
+ * On systems that have a shadow password, this will only
+ * work for root, but what can we do?
+ *
+ * If we fail to get the password, then we log the user out
+ * immediately
+ */
+/*ARGSUSED*/
+static void
+auto_lock(n)
+ int n;
+{
+#ifndef NO_CRYPT
+
+ int i;
+ char *srpp = NULL;
+ struct passwd *pw;
+#ifdef POSIX
+ extern char *crypt __P((const char *, const char *));
+#else
+ extern char *crypt __P(());
+#endif
+
+#undef XCRYPT
+
+#if defined(PW_AUTH) && !defined(XCRYPT)
+
+ struct authorization *apw;
+ extern char *crypt16 __P((const char *, const char *));
+
+# define XCRYPT(a, b) crypt16(a, b)
+
+ if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */
+ (apw = getauthuid(euid)) != NULL) /* enhanced ultrix passwd */
+ srpp = apw->a_password;
+
+#endif /* PW_AUTH && !XCRYPT */
+
+#if defined(PW_SHADOW) && !defined(XCRYPT)
+
+ struct spwd *spw;
+
+# define XCRYPT(a, b) crypt(a, b)
+
+ if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */
+ (spw = getspnam(pw->pw_name)) != NULL) /* shadowed passwd */
+ srpp = spw->sp_pwdp;
+
+#endif /* PW_SHADOW && !XCRYPT */
+
+#ifndef XCRYPT
+
+#define XCRYPT(a, b) crypt(a, b)
+
+ if ((pw = getpwuid(euid)) != NULL) /* effective user passwd */
+ srpp = pw->pw_passwd;
+
+#endif /* !XCRYPT */
+
+ if (srpp == NULL) {
+ auto_logout(0);
+ /*NOTREACHED*/
+ return;
+ }
+
+ setalarm(0); /* Not for locking any more */
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM)));
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGALRM);
+#endif /* BSDSIGS */
+ xputchar('\n');
+ for (i = 0; i < 5; i++) {
+ const char *crpp;
+ char *pp;
+#ifdef AFS
+ char *afsname;
+ Char *safs;
+
+ if ((safs = varval(STRafsuser)) != STRNULL)
+ afsname = short2str(safs);
+ else
+ if ((afsname = getenv("AFSUSER")) == NULL)
+ afsname = pw->pw_name;
+#endif
+ pp = xgetpass("Password:");
+
+ crpp = XCRYPT(pp, srpp);
+ if ((strcmp(crpp, srpp) == 0)
+#ifdef AFS
+ || (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION,
+ afsname, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ pp, /* password */
+ 0, /* lifetime */
+ 0, 0, /* spare */
+ NULL) /* reason */
+ == 0)
+#endif /* AFS */
+ ) {
+ (void) memset(pp, 0, PASSMAX);
+ if (GettingInput && !just_signaled) {
+ (void) Rawmode();
+ ClearLines();
+ ClearDisp();
+ Refresh();
+ }
+ just_signaled = 0;
+ return;
+ }
+ xprintf(CGETS(22, 2, "\nIncorrect passwd for %s\n"), pw->pw_name);
+ }
+#endif /* NO_CRYPT */
+ auto_logout(0);
+ USE(n);
+}
+
+
+static void
+auto_logout(n)
+ int n;
+{
+ USE(n);
+ xprintf("auto-logout\n");
+ /* Don't leave the tty in raw mode */
+ if (editing)
+ (void) Cookedmode();
+ (void) close(SHIN);
+ set(STRlogout, Strsave(STRautomatic), VAR_READWRITE);
+ child = 1;
+#ifdef TESLA
+ do_logout = 1;
+#endif /* TESLA */
+ GettingInput = FALSE; /* make flush() work to write hist files. Huber*/
+ goodbye(NULL, NULL);
+}
+
+sigret_t
+/*ARGSUSED*/
+alrmcatch(snum)
+int snum;
+{
+#ifdef UNRELSIGS
+ if (snum)
+ (void) sigset(SIGALRM, alrmcatch);
+#endif /* UNRELSIGS */
+
+ (*alm_fun)(0);
+
+ setalarm(1);
+#ifndef SIGVOID
+ return (snum);
+#endif /* !SIGVOID */
+}
+
+/*
+ * Karl Kleinpaste, 21oct1983.
+ * Added precmd(), which checks for the alias
+ * precmd in aliases. If it's there, the alias
+ * is executed as a command. This is done
+ * after mailchk() and just before print-
+ * ing the prompt. Useful for things like printing
+ * one's current directory just before each command.
+ */
+void
+precmd()
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (precmd_active) { /* an error must have been caught */
+ aliasrun(2, STRunalias, STRprecmd);
+ xprintf(CGETS(22, 3, "Faulty alias 'precmd' removed.\n"));
+ goto leave;
+ }
+ precmd_active = 1;
+ if (!whyles && adrof1(STRprecmd, &aliases))
+ aliasrun(1, STRprecmd, NULL);
+leave:
+ precmd_active = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+}
+
+void
+postcmd()
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (postcmd_active) { /* an error must have been caught */
+ aliasrun(2, STRunalias, STRpostcmd);
+ xprintf(CGETS(22, 3, "Faulty alias 'postcmd' removed.\n"));
+ goto leave;
+ }
+ postcmd_active = 1;
+ if (!whyles && adrof1(STRpostcmd, &aliases))
+ aliasrun(1, STRpostcmd, NULL);
+leave:
+ postcmd_active = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+}
+
+/*
+ * Paul Placeway 11/24/87 Added cwd_cmd by hacking precmd() into
+ * submission... Run every time $cwd is set (after it is set). Useful
+ * for putting your machine and cwd (or anything else) in an xterm title
+ * space.
+ */
+void
+cwd_cmd()
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (cwdcmd_active) { /* an error must have been caught */
+ aliasrun(2, STRunalias, STRcwdcmd);
+ xprintf(CGETS(22, 4, "Faulty alias 'cwdcmd' removed.\n"));
+ goto leave;
+ }
+ cwdcmd_active = 1;
+ if (!whyles && adrof1(STRcwdcmd, &aliases))
+ aliasrun(1, STRcwdcmd, NULL);
+leave:
+ cwdcmd_active = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+}
+
+/*
+ * Joachim Hoenig 07/16/91 Added beep_cmd, run every time tcsh wishes
+ * to beep the terminal bell. Useful for playing nice sounds instead.
+ */
+void
+beep_cmd()
+{
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (beepcmd_active) { /* an error must have been caught */
+ aliasrun(2, STRunalias, STRbeepcmd);
+ xprintf(CGETS(22, 5, "Faulty alias 'beepcmd' removed.\n"));
+ }
+ else {
+ beepcmd_active = 1;
+ if (!whyles && adrof1(STRbeepcmd, &aliases))
+ aliasrun(1, STRbeepcmd, NULL);
+ }
+ beepcmd_active = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+}
+
+
+/*
+ * Karl Kleinpaste, 18 Jan 1984.
+ * Added period_cmd(), which executes the alias "periodic" every
+ * $tperiod minutes. Useful for occasional checking of msgs and such.
+ */
+void
+period_cmd()
+{
+ register Char *vp;
+ time_t t, interval;
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT));
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ if (periodic_active) { /* an error must have been caught */
+ aliasrun(2, STRunalias, STRperiodic);
+ xprintf(CGETS(22, 6, "Faulty alias 'periodic' removed.\n"));
+ goto leave;
+ }
+ periodic_active = 1;
+ if (!whyles && adrof1(STRperiodic, &aliases)) {
+ vp = varval(STRtperiod);
+ if (vp == STRNULL) {
+ aliasrun(1, STRperiodic, NULL);
+ goto leave;
+ }
+ interval = getn(vp);
+ (void) time(&t);
+ if (t - t_period >= interval * 60) {
+ t_period = t;
+ aliasrun(1, STRperiodic, NULL);
+ }
+ }
+leave:
+ periodic_active = 0;
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+}
+
+/*
+ * Karl Kleinpaste, 21oct1983.
+ * Set up a one-word alias command, for use for special things.
+ * This code is based on the mainline of process().
+ */
+void
+aliasrun(cnt, s1, s2)
+ int cnt;
+ Char *s1, *s2;
+{
+ struct wordent w, *new1, *new2; /* for holding alias name */
+ struct command *t = NULL;
+ jmp_buf_t osetexit;
+ int status;
+
+ getexit(osetexit);
+ if (seterr) {
+ xfree((ptr_t) seterr);
+ seterr = NULL; /* don't repeatedly print err msg. */
+ }
+ w.word = STRNULL;
+ new1 = (struct wordent *) xcalloc(1, sizeof w);
+ new1->word = Strsave(s1);
+ if (cnt == 1) {
+ /* build a lex list with one word. */
+ w.next = w.prev = new1;
+ new1->next = new1->prev = &w;
+ }
+ else {
+ /* build a lex list with two words. */
+ new2 = (struct wordent *) xcalloc(1, sizeof w);
+ new2->word = Strsave(s2);
+ w.next = new2->prev = new1;
+ new1->next = w.prev = new2;
+ new1->prev = new2->next = &w;
+ }
+
+ /* Save the old status */
+ status = getn(varval(STRstatus));
+
+ /* expand aliases like process() does. */
+ alias(&w);
+ /* build a syntax tree for the command. */
+ t = syntax(w.next, &w, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+
+ psavejob();
+
+
+ /* catch any errors here */
+ if (setexit() == 0)
+ /* execute the parse tree. */
+ /*
+ * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ * was execute(t, tpgrp);
+ */
+ execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL);
+ /* done. free the lex list and parse tree. */
+ freelex(&w), freesyn(t);
+ if (haderr) {
+ haderr = 0;
+ /*
+ * Either precmd, or cwdcmd, or periodic had an error. Call it again so
+ * that it is removed
+ */
+ if (precmd_active)
+ precmd();
+ if (postcmd_active)
+ postcmd();
+#ifdef notdef
+ /*
+ * XXX: On the other hand, just interrupting them causes an error too.
+ * So if we hit ^C in the middle of cwdcmd or periodic the alias gets
+ * removed. We don't want that. Note that we want to remove precmd
+ * though, cause that could lead into an infinite loop. This should be
+ * fixed correctly, but then haderr should give us the whole exit
+ * status not just true or false.
+ */
+ else if (cwdcmd_active)
+ cwd_cmd();
+ else if (beepcmd_active)
+ beep_cmd();
+ else if (periodic_active)
+ period_cmd();
+#endif /* notdef */
+ }
+ /* reset the error catcher to the old place */
+ resexit(osetexit);
+ prestjob();
+ pendjob();
+ /* Restore status */
+ set(STRstatus, putn(status), VAR_READWRITE);
+}
+
+void
+setalarm(lck)
+ int lck;
+{
+ struct varent *vp;
+ Char *cp;
+ unsigned alrm_time = 0, logout_time, lock_time;
+ time_t cl, nl, sched_dif;
+
+ if ((vp = adrof(STRautologout)) != NULL) {
+ if ((cp = vp->vec[0]) != 0) {
+ if ((logout_time = (unsigned) atoi(short2str(cp)) * 60) > 0) {
+ alrm_time = logout_time;
+ alm_fun = auto_logout;
+ }
+ }
+ if ((cp = vp->vec[1]) != 0) {
+ if ((lock_time = (unsigned) atoi(short2str(cp)) * 60) > 0) {
+ if (lck) {
+ if (alrm_time == 0 || lock_time < alrm_time) {
+ alrm_time = lock_time;
+ alm_fun = auto_lock;
+ }
+ }
+ else /* lock_time always < alrm_time */
+ if (alrm_time)
+ alrm_time -= lock_time;
+ }
+ }
+ }
+ if ((nl = sched_next()) != -1) {
+ (void) time(&cl);
+ sched_dif = nl > cl ? nl - cl : 0;
+ if ((alrm_time == 0) || ((unsigned) sched_dif < alrm_time)) {
+ alrm_time = ((unsigned) sched_dif) + 1;
+ alm_fun = sched_run;
+ }
+ }
+ (void) alarm(alrm_time); /* Autologout ON */
+}
+
+#undef RMDEBUG /* For now... */
+
+void
+rmstar(cp)
+ struct wordent *cp;
+{
+ struct wordent *we, *args;
+ register struct wordent *tmp, *del;
+
+#ifdef RMDEBUG
+ static Char STRrmdebug[] = {'r', 'm', 'd', 'e', 'b', 'u', 'g', '\0'};
+ Char *tag;
+#endif /* RMDEBUG */
+ Char *charac;
+ char c;
+ int ask, doit, star = 0, silent = 0;
+
+ if (!adrof(STRrmstar))
+ return;
+#ifdef RMDEBUG
+ tag = varval(STRrmdebug);
+#endif /* RMDEBUG */
+ we = cp->next;
+ while (*we->word == ';' && we != cp)
+ we = we->next;
+ while (we != cp) {
+#ifdef RMDEBUG
+ if (*tag)
+ xprintf(CGETS(22, 7, "parsing command line\n"));
+#endif /* RMDEBUG */
+ if (!Strcmp(we->word, STRrm)) {
+ args = we->next;
+ ask = (*args->word != '-');
+ while (*args->word == '-' && !silent) { /* check options */
+ for (charac = (args->word + 1); *charac && !silent; charac++)
+ silent = (*charac == 'i' || *charac == 'f');
+ args = args->next;
+ }
+ ask = (ask || (!ask && !silent));
+ if (ask) {
+ for (; !star && *args->word != ';'
+ && args != cp; args = args->next)
+ if (!Strcmp(args->word, STRstar))
+ star = 1;
+ if (ask && star) {
+ xprintf(CGETS(22, 8,
+ "Do you really want to delete all files? [n/y] "));
+ flush();
+ (void) force_read(SHIN, &c, 1);
+ /*
+ * Perhaps we should use the yesexpr from the
+ * actual locale
+ */
+ doit = (strchr(CGETS(22, 14, "Yy"), c) != NULL);
+ while (c != '\n' && force_read(SHIN, &c, 1) == 1)
+ continue;
+ if (!doit) {
+ /* remove the command instead */
+#ifdef RMDEBUG
+ if (*tag)
+ xprintf(CGETS(22, 9,
+ "skipping deletion of files!\n"));
+#endif /* RMDEBUG */
+ for (tmp = we;
+ *tmp->word != '\n' &&
+ *tmp->word != ';' && tmp != cp;) {
+ tmp->prev->next = tmp->next;
+ tmp->next->prev = tmp->prev;
+ xfree((ptr_t) tmp->word);
+ del = tmp;
+ tmp = tmp->next;
+ xfree((ptr_t) del);
+ }
+ if (*tmp->word == ';') {
+ tmp->prev->next = tmp->next;
+ tmp->next->prev = tmp->prev;
+ xfree((ptr_t) tmp->word);
+ del = tmp;
+ xfree((ptr_t) del);
+ }
+ }
+ }
+ }
+ }
+ for (we = we->next;
+ *we->word != ';' && we != cp;
+ we = we->next)
+ continue;
+ if (*we->word == ';')
+ we = we->next;
+ }
+#ifdef RMDEBUG
+ if (*tag) {
+ xprintf(CGETS(22, 10, "command line now is:\n"));
+ for (we = cp->next; we != cp; we = we->next)
+ xprintf("%S ", we->word);
+ }
+#endif /* RMDEBUG */
+ return;
+}
+
+#ifdef BSDJOBS
+/* Check if command is in continue list
+ and do a "aliasing" if it exists as a job in background */
+
+#undef CNDEBUG /* For now */
+void
+continue_jobs(cp)
+ struct wordent *cp;
+{
+ struct wordent *we;
+ register struct process *pp, *np;
+ Char *cmd, *continue_list, *continue_args_list;
+
+#ifdef CNDEBUG
+ Char *tag;
+ static Char STRcndebug[] =
+ {'c', 'n', 'd', 'e', 'b', 'u', 'g', '\0'};
+#endif /* CNDEBUG */
+ bool in_cont_list, in_cont_arg_list;
+
+
+#ifdef CNDEBUG
+ tag = varval(STRcndebug);
+#endif /* CNDEBUG */
+ continue_list = varval(STRcontinue);
+ continue_args_list = varval(STRcontinue_args);
+ if (*continue_list == '\0' && *continue_args_list == '\0')
+ return;
+
+ we = cp->next;
+ while (*we->word == ';' && we != cp)
+ we = we->next;
+ while (we != cp) {
+#ifdef CNDEBUG
+ if (*tag)
+ xprintf(CGETS(22, 11, "parsing command line\n"));
+#endif /* CNDEBUG */
+ cmd = we->word;
+ in_cont_list = inlist(continue_list, cmd);
+ in_cont_arg_list = inlist(continue_args_list, cmd);
+ if (in_cont_list || in_cont_arg_list) {
+#ifdef CNDEBUG
+ if (*tag)
+ xprintf(CGETS(22, 12, "in one of the lists\n"));
+#endif /* CNDEBUG */
+ np = NULL;
+ for (pp = proclist.p_next; pp; pp = pp->p_next) {
+ if (prefix(cmd, pp->p_command)) {
+ if (pp->p_index) {
+ np = pp;
+ break;
+ }
+ }
+ }
+ if (np) {
+ insert(we, in_cont_arg_list);
+ }
+ }
+ for (we = we->next;
+ *we->word != ';' && we != cp;
+ we = we->next)
+ continue;
+ if (*we->word == ';')
+ we = we->next;
+ }
+#ifdef CNDEBUG
+ if (*tag) {
+ xprintf(CGETS(22, 13, "command line now is:\n"));
+ for (we = cp->next; we != cp; we = we->next)
+ xprintf("%S ", we->word);
+ }
+#endif /* CNDEBUG */
+ return;
+}
+
+/* The actual "aliasing" of for backgrounds() is done here
+ with the aid of insert_we(). */
+static void
+insert(pl, file_args)
+ struct wordent *pl;
+ bool file_args;
+{
+ struct wordent *now, *last;
+ Char *cmd, *bcmd, *cp1, *cp2;
+ int cmd_len;
+ Char *pause = STRunderpause;
+ int p_len = (int) Strlen(pause);
+
+ cmd_len = (int) Strlen(pl->word);
+ cmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 1) * sizeof(Char)));
+ (void) Strcpy(cmd, pl->word);
+/* Do insertions at beginning, first replace command word */
+
+ if (file_args) {
+ now = pl;
+ xfree((ptr_t) now->word);
+ now->word = (Char *) xcalloc(1, (size_t) (5 * sizeof(Char)));
+ (void) Strcpy(now->word, STRecho);
+
+ now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
+ now->word = (Char *) xcalloc(1, (size_t) (6 * sizeof(Char)));
+ (void) Strcpy(now->word, STRbackqpwd);
+ insert_we(now, pl);
+
+ for (last = now; *last->word != '\n' && *last->word != ';';
+ last = last->next)
+ continue;
+
+ now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
+ now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
+ (void) Strcpy(now->word, STRgt);
+ insert_we(now, last->prev);
+
+ now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
+ now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
+ (void) Strcpy(now->word, STRbang);
+ insert_we(now, last->prev);
+
+ now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
+ now->word = (Char *) xcalloc(1, (size_t) cmd_len + p_len + 4);
+ cp1 = now->word;
+ cp2 = cmd;
+ *cp1++ = '~';
+ *cp1++ = '/';
+ *cp1++ = '.';
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ cp1--;
+ cp2 = pause;
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ insert_we(now, last->prev);
+
+ now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
+ now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
+ (void) Strcpy(now->word, STRsemi);
+ insert_we(now, last->prev);
+ bcmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 2) * sizeof(Char)));
+ cp1 = bcmd;
+ cp2 = cmd;
+ *cp1++ = '%';
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ now = (struct wordent *) xcalloc(1, (size_t) (sizeof(struct wordent)));
+ now->word = bcmd;
+ insert_we(now, last->prev);
+ }
+ else {
+ struct wordent *del;
+
+ now = pl;
+ xfree((ptr_t) now->word);
+ now->word = (Char *) xcalloc(1,
+ (size_t) ((cmd_len + 2) * sizeof(Char)));
+ cp1 = now->word;
+ cp2 = cmd;
+ *cp1++ = '%';
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ for (now = now->next;
+ *now->word != '\n' && *now->word != ';' && now != pl;) {
+ now->prev->next = now->next;
+ now->next->prev = now->prev;
+ xfree((ptr_t) now->word);
+ del = now;
+ now = now->next;
+ xfree((ptr_t) del);
+ }
+ }
+}
+
+static void
+insert_we(new, where)
+ struct wordent *new, *where;
+{
+
+ new->prev = where;
+ new->next = where->next;
+ where->next = new;
+ new->next->prev = new;
+}
+
+static int
+inlist(list, name)
+ Char *list, *name;
+{
+ register Char *l, *n;
+
+ l = list;
+ n = name;
+
+ while (*l && *n) {
+ if (*l == *n) {
+ l++;
+ n++;
+ if (*n == '\0' && (*l == ' ' || *l == '\0'))
+ return (1);
+ else
+ continue;
+ }
+ else {
+ while (*l && *l != ' ')
+ l++; /* skip to blank */
+ while (*l && *l == ' ')
+ l++; /* and find first nonblank character */
+ n = name;
+ }
+ }
+ return (0);
+}
+
+#endif /* BSDJOBS */
+
+
+/*
+ * Implement a small cache for tilde names. This is used primarily
+ * to expand tilde names to directories, but also
+ * we can find users from their home directories for the tilde
+ * prompt, on machines where yp lookup is slow this can be a big win...
+ * As with any cache this can run out of sync, rehash can sync it again.
+ */
+static struct tildecache {
+ Char *user;
+ Char *home;
+ int hlen;
+} *tcache = NULL;
+
+#define TILINCR 10
+int tlength = 0;
+static int tsize = TILINCR;
+
+static int
+tildecompare(p1, p2)
+ struct tildecache *p1, *p2;
+{
+ return Strcmp(p1->user, p2->user);
+}
+
+static Char *
+gethomedir(us)
+ Char *us;
+{
+ register struct passwd *pp;
+#ifdef HESIOD
+ char **res, **res1, *cp;
+ Char *rp;
+#endif /* HESIOD */
+
+ pp = getpwnam(short2str(us));
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif /* YPBUGS */
+ if (pp != NULL)
+ return Strsave(str2short(pp->pw_dir));
+#ifdef HESIOD
+ res = hes_resolve(short2str(us), "filsys");
+ rp = 0;
+ if (res != 0) {
+ extern char *strtok();
+ if ((*res) != 0) {
+ /*
+ * Look at the first token to determine how to interpret
+ * the rest of it.
+ * Yes, strtok is evil (it's not thread-safe), but it's also
+ * easy to use.
+ */
+ cp = strtok(*res, " ");
+ if (strcmp(cp, "AFS") == 0) {
+ /* next token is AFS pathname.. */
+ cp = strtok(NULL, " ");
+ if (cp != NULL)
+ rp = Strsave(str2short(cp));
+ } else if (strcmp(cp, "NFS") == 0) {
+ cp = NULL;
+ if ((strtok(NULL, " ")) && /* skip remote pathname */
+ (strtok(NULL, " ")) && /* skip host */
+ (strtok(NULL, " ")) && /* skip mode */
+ (cp = strtok(NULL, " "))) {
+ rp = Strsave(str2short(cp));
+ }
+ }
+ }
+ for (res1 = res; *res1; res1++)
+ free(*res1);
+ return rp;
+ }
+#endif /* HESIOD */
+ return NULL;
+}
+
+Char *
+gettilde(us)
+ Char *us;
+{
+ struct tildecache *bp1, *bp2, *bp;
+ Char *hd;
+
+ /* Ignore NIS special names */
+ if (*us == '+' || *us == '-')
+ return NULL;
+
+ if (tcache == NULL)
+ tcache = (struct tildecache *) xmalloc((size_t) (TILINCR *
+ sizeof(struct tildecache)));
+ /*
+ * Binary search
+ */
+ for (bp1 = tcache, bp2 = tcache + tlength; bp1 < bp2;) {
+ register int i;
+
+ bp = bp1 + ((bp2 - bp1) >> 1);
+ if ((i = *us - *bp->user) == 0 && (i = Strcmp(us, bp->user)) == 0)
+ return (bp->home);
+ if (i < 0)
+ bp2 = bp;
+ else
+ bp1 = bp + 1;
+ }
+ /*
+ * Not in the cache, try to get it from the passwd file
+ */
+ hd = gethomedir(us);
+ if (hd == NULL)
+ return NULL;
+
+ /*
+ * Update the cache
+ */
+ tcache[tlength].user = Strsave(us);
+ tcache[tlength].home = hd;
+ tcache[tlength++].hlen = (int) Strlen(hd);
+
+ qsort((ptr_t) tcache, (size_t) tlength, sizeof(struct tildecache),
+ (int (*) __P((const void *, const void *))) tildecompare);
+
+ if (tlength == tsize) {
+ tsize += TILINCR;
+ tcache = (struct tildecache *) xrealloc((ptr_t) tcache,
+ (size_t) (tsize *
+ sizeof(struct tildecache)));
+ }
+ return (hd);
+}
+
+/*
+ * Return the username if the directory path passed contains a
+ * user's home directory in the tilde cache, otherwise return NULL
+ * hm points to the place where the path became different.
+ * Special case: Our own home directory.
+ * If we are passed a null pointer, then we flush the cache.
+ */
+Char *
+getusername(hm)
+ Char **hm;
+{
+ Char *h, *p;
+ int i, j;
+
+ if (hm == NULL) {
+ for (i = 0; i < tlength; i++) {
+ xfree((ptr_t) tcache[i].home);
+ xfree((ptr_t) tcache[i].user);
+ }
+ xfree((ptr_t) tcache);
+ tlength = 0;
+ tsize = TILINCR;
+ tcache = NULL;
+ return NULL;
+ }
+ if (((h = varval(STRhome)) != STRNULL) &&
+ (Strncmp(p = *hm, h, (size_t) (j = (int) Strlen(h))) == 0) &&
+ (p[j] == '/' || p[j] == '\0')) {
+ *hm = &p[j];
+ return STRNULL;
+ }
+ for (i = 0; i < tlength; i++)
+ if ((Strncmp(p = *hm, tcache[i].home, (size_t)
+ (j = tcache[i].hlen)) == 0) && (p[j] == '/' || p[j] == '\0')) {
+ *hm = &p[j];
+ return tcache[i].user;
+ }
+ return NULL;
+}
+
+#ifdef OBSOLETE
+/*
+ * PWP: read a bunch of aliases out of a file QUICKLY. The format
+ * is almost the same as the result of saying "alias > FILE", except
+ * that saying "aliases > FILE" does not expand non-letters to printable
+ * sequences.
+ */
+/*ARGSUSED*/
+void
+doaliases(v, c)
+ Char **v;
+ struct command *c;
+{
+ jmp_buf_t oldexit;
+ Char **vec, *lp;
+ int fd;
+ Char buf[BUFSIZE], line[BUFSIZE];
+ char tbuf[BUFSIZE + 1], *tmp;
+ extern bool output_raw; /* PWP: in sh.print.c */
+
+ USE(c);
+ v++;
+ if (*v == 0) {
+ output_raw = 1;
+ plist(&aliases, VAR_ALL);
+ output_raw = 0;
+ return;
+ }
+
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+
+ if ((fd = open(tmp = short2str(*v), O_RDONLY)) < 0)
+ stderror(ERR_NAME | ERR_SYSTEM, tmp, strerror(errno));
+
+ getexit(oldexit);
+ if (setexit() == 0) {
+ for (;;) {
+ Char *p = NULL;
+ int n = 0;
+ lp = line;
+ for (;;) {
+ if (n <= 0) {
+ int i;
+
+ if ((n = read(fd, tbuf, BUFSIZE)) <= 0) {
+#ifdef convex
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#endif /* convex */
+ goto eof;
+ }
+ for (i = 0; i < n; i++)
+ buf[i] = (Char) tbuf[i];
+ p = buf;
+ }
+ n--;
+ if ((*lp++ = *p++) == '\n') {
+ lp[-1] = '\0';
+ break;
+ }
+ }
+ for (lp = line; *lp; lp++) {
+ if (isspc(*lp)) {
+ *lp++ = '\0';
+ while (isspc(*lp))
+ lp++;
+ vec = (Char **) xmalloc((size_t)
+ (2 * sizeof(Char **)));
+ vec[0] = Strsave(lp);
+ vec[1] = NULL;
+ setq(strip(line), vec, &aliases, VAR_READWRITE);
+ break;
+ }
+ }
+ }
+ }
+
+eof:
+ (void) close(fd);
+ tw_cmd_free();
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+ resexit(oldexit);
+}
+#endif /* OBSOLETE */
+
+
+/*
+ * set the shell-level var to 1 or apply change to it.
+ */
+void
+shlvl(val)
+ int val;
+{
+ char *cp;
+
+ if ((cp = getenv("SHLVL")) != NULL) {
+
+ if (loginsh)
+ val = 1;
+ else
+ val += atoi(cp);
+
+ if (val <= 0) {
+ if (adrof(STRshlvl) != NULL)
+ unsetv(STRshlvl);
+ Unsetenv(STRKSHLVL);
+ }
+ else {
+ Char buff[BUFSIZE];
+
+ (void) Itoa(val, buff, 0, 0);
+ set(STRshlvl, Strsave(buff), VAR_READWRITE);
+ tsetenv(STRKSHLVL, buff);
+ }
+ }
+ else {
+ set(STRshlvl, SAVE("1"), VAR_READWRITE);
+ tsetenv(STRKSHLVL, str2short("1"));
+ }
+}
+
+
+/* fixio():
+ * Try to recover from a read error
+ */
+int
+fixio(fd, e)
+ int fd, e;
+{
+ switch (e) {
+ case -1: /* Make sure that the code is reachable */
+
+#ifdef EWOULDBLOCK
+ case EWOULDBLOCK:
+# define FDRETRY
+#endif /* EWOULDBLOCK */
+
+#if defined(POSIX) && defined(EAGAIN)
+# if !defined(EWOULDBLOCK) || EWOULDBLOCK != EAGAIN
+ case EAGAIN:
+# define FDRETRY
+# endif /* !EWOULDBLOCK || EWOULDBLOCK != EAGAIN */
+#endif /* POSIX && EAGAIN */
+
+ e = 0;
+#ifdef FDRETRY
+# ifdef F_SETFL
+/*
+ * Great! we have on suns 3 flavors and 5 names...
+ * I hope that will cover everything.
+ * I added some more defines... many systems have different defines.
+ * Rather than dealing with getting the right includes, we'll just
+ * cover all the known possibilities here. -- sterling@netcom.com
+ */
+# ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+# endif /* O_NONBLOCK */
+# ifndef O_NDELAY
+# define O_NDELAY 0
+# endif /* O_NDELAY */
+# ifndef FNBIO
+# define FNBIO 0
+# endif /* FNBIO */
+# ifndef _FNBIO
+# define _FNBIO 0
+# endif /* _FNBIO */
+# ifndef FNONBIO
+# define FNONBIO 0
+# endif /* FNONBIO */
+# ifndef FNONBLOCK
+# define FNONBLOCK 0
+# endif /* FNONBLOCK */
+# ifndef _FNONBLOCK
+# define _FNONBLOCK 0
+# endif /* _FNONBLOCK */
+# ifndef FNDELAY
+# define FNDELAY 0
+# endif /* FNDELAY */
+# ifndef _FNDELAY
+# define _FNDELAY 0
+# endif /* _FNDELAY */
+# ifndef FNDLEAY /* Some linux versions have this typo */
+# define FNDLEAY 0
+# endif /* FNDLEAY */
+ if ((e = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ e &= ~(O_NDELAY|O_NONBLOCK|FNBIO|_FNBIO|FNONBIO|FNONBLOCK|_FNONBLOCK|
+ FNDELAY|_FNDELAY|FNDLEAY); /* whew! */
+ if (fcntl(fd, F_SETFL, e) == -1)
+ return -1;
+ else
+ e = 1;
+# endif /* F_SETFL */
+
+# ifdef FIONBIO
+ e = 0;
+ if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1)
+ return -1;
+ else
+ e = 1;
+# endif /* FIONBIO */
+
+#endif /* FDRETRY */
+ return e ? 0 : -1;
+
+ case EINTR:
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+/* collate():
+ * String collation
+ */
+int
+collate(a, b)
+ const Char *a;
+ const Char *b;
+{
+ int rv;
+#ifdef SHORT_STRINGS
+ /* This strips the quote bit as a side effect */
+ char *sa = strsave(short2str(a));
+ char *sb = strsave(short2str(b));
+#else
+ char *sa = strip(strsave(a));
+ char *sb = strip(strsave(b));
+#endif /* SHORT_STRINGS */
+
+#if defined(NLS) && !defined(NOSTRCOLL)
+ errno = 0; /* strcoll sets errno, another brain-damage */
+
+ rv = strcoll(sa, sb);
+
+ /*
+ * We should be checking for errno != 0, but some systems
+ * forget to reset errno to 0. So we only check for the
+ * only documented valid errno value for strcoll [EINVAL]
+ */
+ if (errno == EINVAL) {
+ xfree((ptr_t) sa);
+ xfree((ptr_t) sb);
+ stderror(ERR_SYSTEM, "strcoll", strerror(errno));
+ }
+#else
+ rv = strcmp(sa, sb);
+#endif /* NLS && !NOSTRCOLL */
+
+ xfree((ptr_t) sa);
+ xfree((ptr_t) sb);
+
+ return rv;
+}
+
+#ifdef HASHBANG
+/*
+ * From: peter@zeus.dialix.oz.au (Peter Wemm)
+ * If exec() fails look first for a #! [word] [word] ....
+ * If it is, splice the header into the argument list and retry.
+ */
+#define HACKBUFSZ 1024 /* Max chars in #! vector */
+#define HACKVECSZ 128 /* Max words in #! vector */
+int
+hashbang(fd, vp)
+ int fd;
+ Char ***vp;
+{
+ unsigned char lbuf[HACKBUFSZ];
+ char *sargv[HACKVECSZ];
+ unsigned char *p, *ws;
+ int sargc = 0;
+#ifdef WINNT
+ int fw = 0; /* found at least one word */
+ int first_word = 0;
+#endif /* WINNT */
+
+ if (read(fd, (char *) lbuf, HACKBUFSZ) <= 0)
+ return -1;
+
+ ws = 0; /* word started = 0 */
+
+ for (p = lbuf; p < &lbuf[HACKBUFSZ]; )
+ switch (*p) {
+ case ' ':
+ case '\t':
+#ifdef WINNT
+ case '\r':
+#endif /* WINNT */
+ if (ws) { /* a blank after a word.. save it */
+ *p = '\0';
+#ifndef WINNT
+ if (sargc < HACKVECSZ - 1)
+ sargv[sargc++] = ws;
+ ws = NULL;
+#else /* WINNT */
+ if (sargc < HACKVECSZ - 1) {
+ sargv[sargc] = first_word ? NULL: hb_subst(ws);
+ if (sargv[sargc] == NULL)
+ sargv[sargc] = ws;
+ sargc++;
+ }
+ ws = NULL;
+ fw = 1;
+ first_word = 1;
+#endif /* WINNT */
+ }
+ p++;
+ continue;
+
+ case '\0': /* Whoa!! what the hell happened */
+ return -1;
+
+ case '\n': /* The end of the line. */
+ if (
+#ifdef WINNT
+ fw ||
+#endif /* WINNT */
+ ws) { /* terminate the last word */
+ *p = '\0';
+#ifndef WINNT
+ if (sargc < HACKVECSZ - 1)
+ sargv[sargc++] = ws;
+#else /* WINNT */
+ if (sargc < HACKVECSZ - 1) { /* deal with the 1-word case */
+ sargv[sargc] = first_word? NULL : hb_subst(ws);
+ if (sargv[sargc] == NULL)
+ sargv[sargc] = ws;
+ sargc++;
+ }
+#endif /* !WINNT */
+ }
+ sargv[sargc] = NULL;
+ ws = NULL;
+ if (sargc > 0) {
+ *vp = blk2short(sargv);
+ return 0;
+ }
+ else
+ return -1;
+
+ default:
+ if (!ws) /* Start a new word? */
+ ws = p;
+ p++;
+ break;
+ }
+ return -1;
+}
+#endif /* HASHBANG */
+
+#ifdef REMOTEHOST
+
+static sigret_t
+palarm(snum)
+ int snum;
+{
+ USE(snum);
+#ifdef UNRELSIGS
+ if (snum)
+ (void) sigset(snum, SIG_IGN);
+#endif /* UNRELSIGS */
+ (void) alarm(0);
+ reset();
+
+#ifndef SIGVOID
+ return (snum);
+#endif
+}
+
+
+static void
+getremotehost()
+{
+ const char *host = NULL;
+ struct hostent* hp;
+ struct sockaddr_in saddr;
+ int len = sizeof(struct sockaddr_in);
+#if defined(UTHOST) && !defined(HAVENOUTMP)
+ char *sptr = NULL;
+#endif
+
+ if (getpeername(SHIN, (struct sockaddr *) &saddr, &len) != -1) {
+#if 0
+ if ((hp = gethostbyaddr((char *)&saddr.sin_addr, sizeof(struct in_addr),
+ AF_INET)) != NULL)
+ host = hp->h_name;
+ else
+#endif
+ host = inet_ntoa(saddr.sin_addr);
+ }
+#if defined(UTHOST) && !defined(HAVENOUTMP)
+ else {
+ char *ptr;
+ char *name = utmphost();
+ /* Avoid empty names and local X displays */
+ if (name != NULL && *name != '\0' && *name != ':') {
+ /* Look for host:display.screen */
+ if ((sptr = strchr(name, ':')) != NULL)
+ *sptr = '\0';
+ /* Leave IP address as is */
+ if (isdigit(*name))
+ host = name;
+ else {
+ if (sptr != name) {
+ if ((hp = gethostbyname(name)) == NULL) {
+ /* Try again eliminating the trailing domain */
+ if ((ptr = strchr(name, '.')) != NULL) {
+ *ptr = '\0';
+ if ((hp = gethostbyname(name)) != NULL)
+ host = hp->h_name;
+ *ptr = '.';
+ }
+ }
+ else
+ host = hp->h_name;
+ }
+ }
+ }
+ }
+#endif
+
+ if (host)
+ tsetenv(STRREMOTEHOST, str2short(host));
+
+#if defined(UTHOST) && !defined(HAVENOUTMP)
+ if (sptr)
+ *sptr = ':';
+#endif
+}
+
+
+/*
+ * From: <lesv@ppvku.ericsson.se> (Lennart Svensson)
+ */
+void
+remotehost()
+{
+ /* Don't get stuck if the resolver does not work! */
+ signalfun_t osig = sigset(SIGALRM, palarm);
+
+ jmp_buf_t osetexit;
+ getexit(osetexit);
+
+ (void) alarm(2);
+
+ if (setexit() == 0)
+ getremotehost();
+
+ resexit(osetexit);
+
+ (void) alarm(0);
+ (void) sigset(SIGALRM, osig);
+
+#ifdef YPBUGS
+ /* From: casper@fwi.uva.nl (Casper H.S. Dik), for Solaris 2.3 */
+ fix_yp_bugs();
+#endif /* YPBUGS */
+
+}
+#endif /* REMOTEHOST */
diff --git a/contrib/tcsh/tc.h b/contrib/tcsh/tc.h
new file mode 100644
index 0000000..f39d746
--- /dev/null
+++ b/contrib/tcsh/tc.h
@@ -0,0 +1,53 @@
+/* $Header: /src/pub/tcsh/tc.h,v 3.4 1996/04/26 19:21:03 christos Exp $ */
+/*
+ * tc.h: Tcsh includes
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tc
+#define _h_tc
+
+#ifndef _h_tc_const
+/* Don't include it while we are making it. */
+# include "tc.const.h"
+#endif /* _h_tc_const */
+#include "tc.os.h"
+#include "tc.sig.h"
+#include "tc.decls.h"
+
+#define FMT_PROMPT 0
+#define FMT_WHO 1
+#define FMT_HISTORY 2
+#define FMT_SCHED 3
+
+#endif /* _h_tc */
diff --git a/contrib/tcsh/tc.os.c b/contrib/tcsh/tc.os.c
new file mode 100644
index 0000000..b2af5f6
--- /dev/null
+++ b/contrib/tcsh/tc.os.c
@@ -0,0 +1,1474 @@
+/* $Header: /src/pub/tcsh/tc.os.c,v 3.50 1998/10/25 15:10:35 christos Exp $ */
+/*
+ * tc.os.c: OS Dependent builtin functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.os.c,v 3.50 1998/10/25 15:10:35 christos Exp $")
+
+#include "tw.h"
+#include "ed.h"
+#include "ed.defns.h" /* for the function names */
+#include "sh.decls.h"
+
+#ifdef _UWIN
+#define TIOCGPGRP TIOCGETPGRP
+#define TIOCSPGRP TIOCSETPGRP
+#endif
+
+/***
+ *** MACH
+ ***/
+
+#ifdef MACH
+/* dosetpath -- setpath built-in command
+ *
+ **********************************************************************
+ * HISTORY
+ * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University
+ * Major changes to remove artificial limits on sizes and numbers
+ * of paths.
+ *
+ **********************************************************************
+ */
+
+#ifdef MACH
+static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
+static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
+static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
+# if EPATH
+static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
+# endif
+#endif /* MACH */
+static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH,
+
+#if EPATH
+ STREPATH,
+#endif
+ 0};
+#define LOCALSYSPATH "/usr/local"
+
+/*ARGSUSED*/
+void
+dosetpath(arglist, c)
+ Char **arglist;
+ struct command *c;
+{
+ extern char *getenv();
+ sigmask_t omask;
+ Char **pathvars, **cmdargs;
+ char **spaths, **cpaths, **cmds;
+ char *tcp;
+ unsigned int npaths, ncmds;
+ int i, sysflag;
+
+ omask = sigsetmask(sigmask(SIGINT));
+
+ /*
+ * setpath(3) uses stdio and we want 0, 1, 2 to work...
+ */
+ if (!didfds) {
+ (void) dcopy(SHIN, 0);
+ (void) dcopy(SHOUT, 1);
+ (void) dcopy(SHDIAG, 2);
+ didfds = 1;
+ }
+
+ for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
+ npaths = i - 1;
+
+ cmdargs = &arglist[i];
+ for (; arglist[i]; i++);
+ ncmds = i - npaths - 1;
+
+ if (npaths) {
+ sysflag = 0;
+ pathvars = &arglist[1];
+ }
+ else {
+ sysflag = 1;
+ npaths = (sizeof syspaths / sizeof *syspaths) - 1;
+ pathvars = syspaths;
+ }
+
+ /* note that npaths != 0 */
+
+ spaths = (char **) xmalloc((size_t) npaths * sizeof *spaths);
+ setzero((char *) spaths, npaths * sizeof *spaths);
+ cpaths = (char **) xmalloc((size_t) (npaths + 1) * sizeof *cpaths);
+ setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths);
+ cmds = (char **) xmalloc((size_t) (ncmds + 1) * sizeof *cmds);
+ setzero((char *) cmds, (ncmds + 1) * sizeof *cmds);
+ for (i = 0; i < npaths; i++) {
+ char *val = getenv(short2str(pathvars[i]));
+
+ if (val == NULL)
+ val = "";
+
+ spaths[i] = (char *) xmalloc((size_t) (Strlen(pathvars[i]) +
+ strlen(val) + 2) * sizeof **spaths);
+ (void) strcpy(spaths[i], short2str(pathvars[i]));
+ (void) strcat(spaths[i], "=");
+ (void) strcat(spaths[i], val);
+ cpaths[i] = spaths[i];
+ }
+
+ for (i = 0; i < ncmds; i++) {
+ Char *val = globone(cmdargs[i], G_ERROR);
+
+ if (val == NULL)
+ goto abortpath;
+ cmds[i] = (char *) xmalloc((size_t) Strlen(val) + 1);
+ (void) strcpy(cmds[i], short2str(val));
+ }
+
+
+ if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
+abortpath:
+ if (spaths) {
+ for (i = 0; i < npaths; i++)
+ if (spaths[i])
+ xfree((ptr_t) spaths[i]);
+ xfree((ptr_t) spaths);
+ }
+ if (cpaths)
+ xfree((ptr_t) cpaths);
+ if (cmds) {
+ for (i = 0; i < ncmds; i++)
+ if (cmds[i])
+ xfree((ptr_t) cmds[i]);
+ xfree((ptr_t) cmds);
+ }
+
+ (void) sigsetmask(omask);
+ donefds();
+ return;
+ }
+
+ for (i = 0; i < npaths; i++) {
+ Char *val, *name;
+
+ name = str2short(cpaths[i]);
+ for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
+ if (val && *val == '=') {
+ *val++ = '\0';
+
+ tsetenv(name, val);
+ if (Strcmp(name, STRKPATH) == 0) {
+ importpath(val);
+ if (havhash)
+ dohash(NULL, NULL);
+ }
+ *--val = '=';
+ }
+ }
+ (void) sigsetmask(omask);
+ donefds();
+}
+#endif /* MACH */
+
+/***
+ *** AIX
+ ***/
+#ifdef TCF
+/* ARGSUSED */
+void
+dogetxvers(v, c)
+ Char **v;
+ struct command *c;
+{
+ char xvers[MAXPATHLEN];
+
+ if (getxvers(xvers, MAXPATHLEN) == -1)
+ stderror(ERR_SYSTEM, "getxvers", strerror(errno));
+ xprintf("%s\n", xvers);
+ flush();
+}
+
+/*ARGSUSED*/
+void
+dosetxvers(v, c)
+ Char **v;
+ struct command *c;
+{
+ char *xvers;
+
+ ++v;
+ if (!*v || *v[0] == '\0')
+ xvers = "";
+ else
+ xvers = short2str(*v);
+ if (setxvers(xvers) == -1)
+ stderror(ERR_SYSTEM, "setxvers", strerror(errno));
+}
+
+#include <sf.h>
+#ifdef _AIXPS2
+# define XC_PDP11 0x01
+# define XC_23 0x02
+# define XC_Z8K 0x03
+# define XC_8086 0x04
+# define XC_68K 0x05
+# define XC_Z80 0x06
+# define XC_VAX 0x07
+# define XC_16032 0x08
+# define XC_286 0x09
+# define XC_386 0x0a
+# define XC_S370 0x0b
+#else
+# include <sys/x.out.h>
+#endif /* _AIXPS2 */
+
+static struct xc_cpu_t {
+ short xc_id;
+ char *xc_name;
+} xcpu[] =
+{
+ { XC_PDP11, "pdp11" },
+ { XC_23, "i370" },
+ { XC_Z8K, "z8000" },
+ { XC_8086, "i86" },
+ { XC_68K, "mc68000" },
+ { XC_Z80, "x80" },
+ { XC_VAX, "vax" },
+ { XC_16032, "ns16032" },
+ { XC_286, "i286" },
+ { XC_386, "i386" },
+ { XC_S370, "xa370" },
+ { 0, NULL }
+};
+
+/*
+ * our local hack table, stolen from x.out.h
+ */
+static char *
+getxcode(xcid)
+ short xcid;
+{
+ int i;
+
+ for (i = 0; xcpu[i].xc_name != NULL; i++)
+ if (xcpu[i].xc_id == xcid)
+ return (xcpu[i].xc_name);
+ return (NULL);
+}
+
+static short
+getxid(xcname)
+ char *xcname;
+{
+ int i;
+
+ for (i = 0; xcpu[i].xc_name != NULL; i++)
+ if (strcmp(xcpu[i].xc_name, xcname) == 0)
+ return (xcpu[i].xc_id);
+ return ((short) -1);
+}
+
+
+/*ARGSUSED*/
+void
+dogetspath(v, c)
+ Char **v;
+ struct command *c;
+{
+ int i, j;
+ sitepath_t p[MAXSITE];
+ struct sf *st;
+ static char *local = "LOCAL ";
+
+ if ((j = getspath(p, MAXSITE)) == -1)
+ stderror(ERR_SYSTEM, "getspath", strerror(errno));
+ for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
+ if (p[i] & SPATH_CPU) {
+ if ((p[i] & SPATH_MASK) == NULLSITE)
+ xprintf(local);
+ else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
+ xprintf("%s ", st->sf_ctype);
+ else {
+ char *xc = getxcode(p[i] & SPATH_MASK);
+
+ if (xc != NULL)
+ xprintf("%s ", xc);
+ else
+ xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
+ /*
+ * BUG in the aix code... needs that cause if
+ * sfxcode fails once it fails for ever
+ */
+ endsf();
+ }
+ }
+ else {
+ if (p[i] == NULLSITE)
+ xprintf(local);
+ else if ((st = sfnum(p[i])) != NULL)
+ xprintf("%s ", st->sf_sname);
+ else
+ xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
+ }
+ }
+ xputchar('\n');
+ flush();
+}
+
+/*ARGSUSED*/
+void
+dosetspath(v, c)
+ Char **v;
+ struct command *c;
+{
+ int i;
+ short j;
+ char *s;
+ sitepath_t p[MAXSITE];
+ struct sf *st;
+
+ /*
+ * sfname() on AIX G9.9 at least, mallocs too pointers p, q
+ * then does the equivalent of while (*p++ == *q++) continue;
+ * and then tries to free(p,q) them! Congrats to the wizard who
+ * wrote that one. I bet he tested it really well too.
+ * Sooo, we set dont_free :-)
+ */
+ dont_free = 1;
+ for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
+ s = short2str(*v);
+ if (Isdigit(*s))
+ p[i] = atoi(s);
+ else if (strcmp(s, "LOCAL") == 0)
+ p[i] = NULLSITE;
+ else if ((st = sfctype(s)) != NULL)
+ p[i] = SPATH_CPU | st->sf_ccode;
+ else if ((j = getxid(s)) != -1)
+ p[i] = SPATH_CPU | j;
+ else if ((st = sfname(s)) != NULL)
+ p[i] = st->sf_id;
+ else {
+ setname(s);
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name"));
+ }
+ if (i == MAXSITE - 1)
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long"));
+ }
+ if (setspath(p, i) == -1)
+ stderror(ERR_SYSTEM, "setspath", strerror(errno));
+ dont_free = 0;
+}
+
+/* sitename():
+ * Return the site name where the process is running
+ */
+char *
+sitename(pid)
+ pid_t pid;
+{
+ siteno_t ss;
+ struct sf *st;
+
+ if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
+ return CGETS(23, 3, "unknown");
+ else
+ return st->sf_sname;
+}
+
+static int
+migratepid(pid, new_site)
+ pid_t pid;
+ siteno_t new_site;
+{
+ struct sf *st;
+ int need_local;
+
+ need_local = (pid == 0) || (pid == getpid());
+
+ if (kill3((pid_t) pid, SIGMIGRATE, new_site) < 0) {
+ xprintf("%d: %s\n", pid, strerror(errno));
+ return (-1);
+ }
+
+ if (need_local) {
+ if ((new_site = site(0)) == -1) {
+ xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno));
+ return (-1);
+ }
+ if ((st = sfnum(new_site)) == NULL) {
+ xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site);
+ return (-1);
+ }
+ if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
+ xprintf(CGETS(23, 6, "setlocal: %s: %s\n"),
+ st->sf_local, strerror(errno));
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+void
+domigrate(v, c)
+ Char **v;
+ struct command *c;
+{
+ struct sf *st;
+ char *s;
+ Char *cp;
+ struct process *pp;
+ int err1 = 0;
+ int pid = 0;
+ siteno_t new_site = 0;
+ sigmask_t omask;
+
+#ifdef BSDSIGS
+ omask = sigmask(SIGCHLD);
+ if (setintr)
+ omask |= sigmask(SIGINT);
+ omask = sigblock(omask) & ~omask;
+#else
+ if (setintr)
+ (void) sighold(SIGINT);
+ (void) sighold(SIGCHLD);
+#endif /* BSDSIGS */
+
+ ++v;
+ if (*v[0] == '-') {
+ /*
+ * Do the -site.
+ */
+ s = short2str(&v[0][1]);
+ /*
+ * see comment in setspath()
+ */
+ dont_free = 1;
+ if ((st = sfname(s)) == NULL) {
+ setname(s);
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found"));
+ }
+ dont_free = 0;
+ new_site = st->sf_id;
+ ++v;
+ }
+
+ if (!*v || *v[0] == '\0') {
+ if (migratepid(0, new_site) == -1)
+ err1++;
+ }
+ else {
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+
+ while (v && (cp = *v)) {
+ if (*cp == '%') {
+ pp = pfind(cp);
+ if (kill3((pid_t) - pp->p_jobid, SIGMIGRATE, new_site) < 0) {
+ xprintf("%S: %s\n", cp, strerror(errno));
+ err1++;
+ }
+ }
+ else if (!(Isdigit(*cp) || *cp == '-'))
+ stderror(ERR_NAME | ERR_JOBARGS);
+ else {
+ pid = atoi(short2str(cp));
+ if (migratepid(pid, new_site) == -1)
+ err1++;
+ }
+ v++;
+ }
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+ }
+
+done:
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGCHLD);
+ if (setintr)
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+ if (err1)
+ stderror(ERR_SILENT);
+}
+
+#endif /* TCF */
+
+/***
+ *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
+ ***/
+#if defined(_CRAY) && !defined(_CRAYMPP)
+void
+dodmmode(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char *cp = v[1];
+
+ USE(c);
+
+ if ( !cp ) {
+ int mode;
+
+ mode = dmmode(0);
+ dmmode(mode);
+ xprintf("%d\n",mode);
+ }
+ else {
+ if (cp[1] != '\0')
+ stderror(ERR_NAME | ERR_STRING,
+ CGETS(23, 30, "Too many arguments"));
+ else
+ switch(*cp) {
+ case '0':
+ dmmode(0);
+ break;
+ case '1':
+ dmmode(1);
+ break;
+ default:
+ stderror(ERR_NAME | ERR_STRING,
+ CGETS(23, 31, "Invalid argument"));
+ }
+ }
+}
+#endif /* _CRAY && !_CRAYMPP */
+
+
+/***
+ *** CONVEX Warps.
+ ***/
+
+#ifdef WARP
+/*
+ * handle the funky warping of symlinks
+ */
+#include <warpdb.h>
+#include <sys/warp.h>
+
+static jmp_buf sigsys_buf;
+
+static sigret_t
+catch_sigsys()
+{
+ longjmp(sigsys_buf, 1);
+}
+
+
+/*ARGSUSED*/
+void
+dowarp(v, c)
+ Char **v;
+ struct command *c;
+{
+ int warp, oldwarp;
+ struct warpent *we;
+ void (*old_sigsys_handler) () = 0;
+ char *newwarp;
+
+ if (setjmp(sigsys_buf)) {
+ signal(SIGSYS, old_sigsys_handler);
+ stderror(ERR_NAME | ERR_STRING,
+ CGETS(23, 8, "You're trapped in a universe you never made"));
+ return;
+ }
+ old_sigsys_handler = signal(SIGSYS, catch_sigsys);
+
+ warp = getwarp();
+
+ v++;
+ if (*v == 0) { /* display warp value */
+ if (warp < 0)
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed"));
+ we = getwarpbyvalue(warp);
+ if (we)
+ printf("%s\n", we->w_name);
+ else
+ printf("%d\n", warp);
+ }
+ else { /* set warp value */
+ oldwarp = warp;
+ newwarp = short2str(*v);
+ if (Isdigit(*v[0]))
+ warp = atoi(newwarp);
+ else {
+ we = getwarpbyname(newwarp);
+ if (we)
+ warp = we->w_value;
+ else
+ warp = -1;
+ }
+ if ((warp < 0) || (warp >= WARP_MAXLINK))
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp"));
+ if ((setwarp(warp) < 0) || (getwarp() != warp)) {
+ (void) setwarp(oldwarp);
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed"));
+ }
+ }
+ signal(SIGSYS, old_sigsys_handler);
+ return;
+}
+#endif /* WARP */
+
+/***
+ *** Masscomp or HCX
+ ***/
+/* Added, DAS DEC-90. */
+#if defined(masscomp) || defined(_CX_UX)
+/*ARGSUSED*/
+void
+douniverse(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp = v[1];
+ register Char *cp2; /* dunno how many elements v comes in with */
+ char ubuf[100];
+#ifdef BSDSIGS
+ register sigmask_t omask = 0;
+#endif /* BSDSIGS */
+
+ if (cp == 0) {
+ (void) getuniverse(ubuf);
+ xprintf("%s\n", ubuf);
+ }
+ else {
+ cp2 = v[2];
+ if (cp2 == 0) {
+ if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
+ }
+ else {
+ (void) getuniverse(ubuf);
+ if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
+ stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
+ if (setintr)
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ lshift(v, 2);
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ reexecute(c);
+ (void) setuniverse(ubuf);
+ }
+ }
+}
+#endif /* masscomp || _CX_UX */
+
+#if defined(_CX_UX)
+/*ARGSUSED*/
+void
+doatt(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp = v[1];
+ char ubuf[100];
+#ifdef BSDSIGS
+ register sigmask_t omask = 0;
+#endif /* BSDSIGS */
+
+ if (cp == 0)
+ (void) setuniverse("att");
+ else {
+ (void) getuniverse(ubuf);
+ (void) setuniverse("att");
+ if (setintr)
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ lshift(v, 1);
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ reexecute(c);
+ (void) setuniverse(ubuf);
+ }
+}
+
+/*ARGSUSED*/
+void
+doucb(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register Char *cp = v[1];
+ char ubuf[100];
+#ifdef BSDSIGS
+ register sigmask_t omask = 0;
+#endif /* BSDSIGS */
+
+ if (cp == 0)
+ (void) setuniverse("ucb");
+ else {
+ (void) getuniverse(ubuf);
+ (void) setuniverse("ucb");
+ if (setintr)
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else /* !BSDSIGS */
+ (void) sighold(SIGINT);
+#endif /* BSDSIGS */
+ lshift(v, 1);
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else /* !BSDSIGS */
+ (void) sigrelse (SIGINT);
+#endif /* BSDSIGS */
+ reexecute(c);
+ (void) setuniverse(ubuf);
+ }
+}
+#endif /* _CX_UX */
+
+#ifdef _SEQUENT_
+/*
+ * Compute the difference in process stats.
+ */
+void
+pr_stat_sub(p2, p1, pr)
+ struct process_stats *p2, *p1, *pr;
+{
+ pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
+ pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
+ if (pr->ps_utime.tv_usec < 0) {
+ pr->ps_utime.tv_sec -= 1;
+ pr->ps_utime.tv_usec += 1000000;
+ }
+ pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
+ pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
+ if (pr->ps_stime.tv_usec < 0) {
+ pr->ps_stime.tv_sec -= 1;
+ pr->ps_stime.tv_usec += 1000000;
+ }
+
+ pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
+ pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
+ pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
+ pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
+ pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
+ pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
+ pr->ps_swap = p2->ps_swap - p1->ps_swap;
+ pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
+ pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
+ pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
+ pr->ps_signal = p2->ps_signal - p1->ps_signal;
+ pr->ps_lread = p2->ps_lread - p1->ps_lread;
+ pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
+ pr->ps_bread = p2->ps_bread - p1->ps_bread;
+ pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
+ pr->ps_phread = p2->ps_phread - p1->ps_phread;
+ pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
+}
+
+#endif /* _SEQUENT_ */
+
+
+#ifdef NEEDmemset
+/* This is a replacement for a missing memset function */
+ptr_t xmemset(loc, value, len)
+ ptr_t loc;
+ int len;
+ size_t value;
+{
+ char *ptr = (char *) loc;
+
+ while (len--)
+ *ptr++ = value;
+ return loc;
+}
+#endif /* NEEDmemset */
+
+
+#ifdef NEEDmemmove
+/* memmove():
+ * This is the ANSI form of bcopy() with the arguments backwards...
+ * Unlike memcpy(), it handles overlaps between source and
+ * destination memory
+ */
+ptr_t
+xmemmove(vdst, vsrc, len)
+ ptr_t vdst;
+ const ptr_t vsrc;
+ size_t len;
+{
+ const char *src = (const char *) vsrc;
+ char *dst = (char *) vdst;
+
+ if (src == dst)
+ return vdst;
+
+ if (src > dst) {
+ while (len--)
+ *dst++ = *src++;
+ }
+ else {
+ src += len;
+ dst += len;
+ while (len--)
+ *--dst = *--src;
+ }
+ return vdst;
+}
+#endif /* NEEDmemmove */
+
+
+#ifndef WINNT
+#ifdef tcgetpgrp
+int
+xtcgetpgrp(fd)
+ int fd;
+{
+ int pgrp;
+
+ /* ioctl will handle setting errno correctly. */
+ if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
+ return (-1);
+ return (pgrp);
+}
+
+/*
+ * XXX: tcsetpgrp is not a macro any more cause on some systems,
+ * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
+ * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
+ * this out.
+ */
+int
+xtcsetpgrp(fd, pgrp)
+ int fd, pgrp;
+{
+ return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
+}
+
+#endif /* tcgetpgrp */
+#endif /* WINNT */
+
+
+#ifdef YPBUGS
+void
+fix_yp_bugs()
+{
+ char *mydomain;
+
+ extern int yp_get_default_domain __P((char **));
+ /*
+ * PWP: The previous version assumed that yp domain was the same as the
+ * internet name domain. This isn't allways true. (Thanks to Mat Landau
+ * <mlandau@bbn.com> for the original version of this.)
+ */
+ if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */
+ extern void yp_unbind __P((const char *));
+
+ yp_unbind(mydomain);
+ }
+}
+
+#endif /* YPBUGS */
+
+#ifdef STRCOLLBUG
+void
+fix_strcoll_bug()
+{
+#if defined(NLS) && !defined(NOSTRCOLL)
+ /*
+ * SunOS4 checks the file descriptor from openlocale() for <= 0
+ * instead of == -1. Someone should tell sun that file descriptor 0
+ * is valid! Our portable hack: open one so we call it with 0 used...
+ * We have to call this routine every time the locale changes...
+ *
+ * Of course it also tries to free the constant locale "C" it initially
+ * had allocated, with the sequence
+ * > setenv LANG "fr"
+ * > ls^D
+ * > unsetenv LANG
+ * But we are smarter than that and just print a warning message.
+ */
+ int fd = -1;
+ static char *root = "/";
+
+ if (!didfds)
+ fd = open(root, O_RDONLY);
+
+ (void) strcoll(root, root);
+
+ if (fd != -1)
+ (void) close(fd);
+#endif
+}
+#endif /* STRCOLLBUG */
+
+
+#ifdef OREO
+#include <compat.h>
+#endif /* OREO */
+
+void
+osinit()
+{
+#ifdef OREO
+ set42sig();
+ setcompat(getcompat() & ~COMPAT_EXEC);
+ sigignore(SIGIO); /* ignore SIGIO */
+#endif /* OREO */
+
+#ifdef aiws
+ {
+ struct sigstack inst;
+ inst.ss_sp = (char *) xmalloc((size_t) 4192) + 4192;
+ inst.ss_onstack = 0;
+ sigstack(&inst, NULL);
+ }
+#endif /* aiws */
+
+#ifdef apollo
+ (void) isapad();
+#endif
+
+#ifdef _SX
+ /*
+ * kill(SIGCONT) problems, don't know what this syscall does
+ * [schott@rzg.mpg.de]
+ */
+ syscall(151, getpid(), getpid());
+#endif /* _SX */
+}
+
+#ifdef strerror
+char *
+xstrerror(i)
+ int i;
+{
+ static char errbuf[128];
+
+ if (i >= 0 && i < sys_nerr) {
+ return sys_errlist[i];
+ } else {
+ (void) xsnprintf(errbuf, sizeof(errbuf),
+ CGETS(23, 13, "Unknown Error: %d"), i);
+ return errbuf;
+ }
+}
+#endif /* strerror */
+
+#ifdef gethostname
+# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT)
+# include <sys/utsname.h>
+# endif /* !_MINIX && !__EMX__ && !WINNT */
+
+int
+xgethostname(name, namlen)
+ char *name;
+ int namlen;
+{
+# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT)
+ int i, retval;
+ struct utsname uts;
+
+ retval = uname(&uts);
+
+# ifdef DEBUG
+ xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname);
+ xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename);
+ xprintf(CGETS(23, 16, "release: %s\n"), uts.release);
+ xprintf(CGETS(23, 17, "version: %s\n"), uts.version);
+ xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine);
+# endif /* DEBUG */
+ i = strlen(uts.nodename) + 1;
+ (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
+
+ return retval;
+# else /* !_MINIX && !__EMX__ */
+ if (namlen > 0) {
+# ifdef __EMX__
+ (void) strncpy(name, "OS/2", namlen);
+# else /* _MINIX */
+ (void) strncpy(name, "minix", namlen);
+# endif /* __EMX__ */
+ name[namlen-1] = '\0';
+ }
+ return(0);
+#endif /* _MINIX && !__EMX__ */
+} /* end xgethostname */
+#endif /* gethostname */
+
+#ifdef nice
+# if defined(_MINIX) && defined(NICE)
+# undef _POSIX_SOURCE /* redefined in <lib.h> */
+# undef _MINIX /* redefined in <lib.h> */
+# undef HZ /* redefined in <minix/const.h> */
+# include <lib.h>
+# endif /* _MINIX && NICE */
+int
+xnice(incr)
+ int incr;
+{
+#if defined(_MINIX) && defined(NICE)
+ return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
+#else
+ return /* incr ? 0 : */ 0;
+#endif /* _MINIX && NICE */
+} /* end xnice */
+#endif /* nice */
+
+#ifdef NEEDgetcwd
+static char *strnrcpy __P((char *, char *, size_t));
+
+/* xgetcwd():
+ * Return the pathname of the current directory, or return
+ * an error message in pathname.
+ */
+
+# ifdef hp9000s500
+/*
+ * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
+ * I also ported the tcsh to the HP9000 Series 500. This computer
+ * is a little bit different than the other HP 9000 computer. It has
+ * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
+ * HP-UX which is emulated in top of a HP operating system. So, the last
+ * supported version of HP-UX is 5.2 on the HP9000s500. This has two
+ * consequences: it supports no job control and it has a filesystem
+ * without "." and ".." !!!
+ */
+char *
+xgetcwd(pathname, pathlen)
+ char *pathname;
+ size_t pathlen;
+{
+ char pathbuf[MAXNAMLEN]; /* temporary pathname buffer */
+ char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
+ dev_t rdev; /* root device number */
+ DIR *dirp = NULL; /* directory stream */
+ ino_t rino; /* root inode number */
+ off_t rsize; /* root size */
+ struct direct *dir; /* directory entry struct */
+ struct stat d, dd; /* file status struct */
+ int serrno;
+
+ *pnptr = '\0';
+ (void) stat("/.", &d);
+ rdev = d.st_dev;
+ rino = d.st_ino;
+ rsize = d.st_size;
+ for (;;) {
+ if (stat(".", &d) == -1) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
+ "getcwd: Cannot stat \".\" (%s)"), strerror(errno));
+ goto fail;
+ }
+ if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
+ break; /* reached root directory */
+ if ((dirp = opendir("..")) == NULL) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 19,
+ "getcwd: Cannot open \"..\" (%s)"), strerror(errno));
+ goto fail;
+ }
+ if (chdir("..") == -1) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 20,
+ "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno));
+ goto fail;
+ }
+ do {
+ if ((dir = readdir(dirp)) == NULL) {
+ (void) xsnprintf(pathname, pathlen,
+ CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
+ strerror(errno));
+ goto fail;
+ }
+ if (stat(dir->d_name, &dd) == -1) {
+ (void) xsnprintf(pathname, pathlen,
+ CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"),
+ dir->d_name, strerror(errno));
+ goto fail;
+ }
+ } while (dd.st_ino != d.st_ino ||
+ dd.st_dev != d.st_dev ||
+ dd.st_size != d.st_size);
+ (void) closedir(dirp);
+ dirp = NULL;
+ pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf);
+ pnptr = strnrcpy("/", pnptr, pnptr - pathbuf);
+ }
+
+ if (*pnptr == '\0') /* current dir == root dir */
+ (void) strncpy(pathname, "/", pathlen);
+ else {
+ (void) strncpy(pathname, pnptr, pathlen);
+ pathname[pathlen - 1] = '\0';
+ if (chdir(pnptr) == -1) {
+ (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22,
+ "getcwd: Cannot change back to \".\" (%s)"),
+ strerror(errno));
+ return NULL;
+ }
+ }
+ return pathname;
+
+fail:
+ serrno = errno;
+ (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf));
+ errno = serrno;
+ return NULL;
+}
+
+# else /* ! hp9000s500 */
+
+# if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX) || defined(WINNT)
+# define d_fileno d_ino
+# endif
+
+char *
+xgetcwd(pathname, pathlen)
+ char *pathname;
+ size_t pathlen;
+{
+ DIR *dp;
+ struct dirent *d;
+
+ struct stat st_root, st_cur, st_next, st_dotdot;
+ char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
+ char *pathptr, *nextpathptr, *cur_name_add;
+ int save_errno = 0;
+
+ /* find the inode of root */
+ if (stat("/", &st_root) == -1) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 23,
+ "getcwd: Cannot stat \"/\" (%s)"),
+ strerror(errno));
+ return NULL;
+ }
+ pathbuf[MAXPATHLEN - 1] = '\0';
+ pathptr = &pathbuf[MAXPATHLEN - 1];
+ nextpathbuf[MAXPATHLEN - 1] = '\0';
+ cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
+
+ /* find the inode of the current directory */
+ if (lstat(".", &st_cur) == -1) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
+ "getcwd: Cannot stat \".\" (%s)"),
+ strerror(errno));
+ return NULL;
+ }
+ nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
+
+ /* Descend to root */
+ for (;;) {
+
+ /* look if we found root yet */
+ if (st_cur.st_ino == st_root.st_ino &&
+ DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
+ (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen);
+ pathname[pathlen - 1] = '\0';
+ return pathname;
+ }
+
+ /* open the parent directory */
+ if (stat(nextpathptr, &st_dotdot) == -1) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 25,
+ "getcwd: Cannot stat directory \"%s\" (%s)"),
+ nextpathptr, strerror(errno));
+ return NULL;
+ }
+ if ((dp = opendir(nextpathptr)) == NULL) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 26,
+ "getcwd: Cannot open directory \"%s\" (%s)"),
+ nextpathptr, strerror(errno));
+ return NULL;
+ }
+
+ /* look in the parent for the entry with the same inode */
+ if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
+ /* Parent has same device. No need to stat every member */
+ for (d = readdir(dp); d != NULL; d = readdir(dp)) {
+#ifdef __clipper__
+ if (((unsigned long)d->d_fileno & 0xffff) == st_cur.st_ino)
+ break;
+#else
+ if (d->d_fileno == st_cur.st_ino)
+ break;
+#endif
+ }
+ }
+ else {
+ /*
+ * Parent has a different device. This is a mount point so we
+ * need to stat every member
+ */
+ for (d = readdir(dp); d != NULL; d = readdir(dp)) {
+ if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
+ continue;
+ (void)strncpy(cur_name_add, d->d_name,
+ (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add));
+ if (lstat(nextpathptr, &st_next) == -1) {
+ /*
+ * We might not be able to stat() some path components
+ * if we are using afs, but this is not an error as
+ * long as we find the one we need; we also save the
+ * first error to report it if we don't finally succeed.
+ */
+ if (save_errno == 0)
+ save_errno = errno;
+ continue;
+ }
+ /* check if we found it yet */
+ if (st_next.st_ino == st_cur.st_ino &&
+ DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
+ break;
+ }
+ }
+ if (d == NULL) {
+ (void) xsnprintf(pathname, pathlen, CGETS(23, 27,
+ "getcwd: Cannot find \".\" in \"..\" (%s)"),
+ strerror(save_errno ? save_errno : ENOENT));
+ (void) closedir(dp);
+ return NULL;
+ }
+ else
+ save_errno = 0;
+ st_cur = st_dotdot;
+ pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf);
+ pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf);
+ nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
+ *cur_name_add = '\0';
+ (void) closedir(dp);
+ }
+} /* end getcwd */
+# endif /* hp9000s500 */
+
+/* strnrcpy():
+ * Like strncpy, going backwards and returning the new pointer
+ */
+static char *
+strnrcpy(ptr, str, siz)
+ register char *ptr, *str;
+ size_t siz;
+{
+ register int len = strlen(str);
+ if (siz == 0)
+ return ptr;
+
+ while (len && siz--)
+ *--ptr = str[--len];
+
+ return (ptr);
+} /* end strnrcpy */
+#endif /* getcwd */
+
+#ifdef apollo
+/***
+ *** Domain/OS
+ ***/
+#include <apollo/base.h>
+#include <apollo/loader.h>
+#include <apollo/error.h>
+
+
+static char *
+apperr(st)
+ status_$t *st;
+{
+ static char buf[BUFSIZE];
+ short e_subl, e_modl, e_codel;
+ error_$string_t e_sub, e_mod, e_code;
+
+ error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
+ e_sub[e_subl] = '\0';
+ e_code[e_codel] = '\0';
+ e_mod[e_modl] = '\0';
+ (void) xsnprintf(buf, sizeof(buf), "%s (%s/%s)", e_code, e_sub, e_mod);
+
+ return(buf);
+}
+
+static int
+llib(s)
+ Char *s;
+{
+ short len = Strlen(s);
+ status_$t st;
+ char *t;
+
+ loader_$inlib(t = short2str(s), len, &st);
+ if (st.all != status_$ok)
+ stderror(ERR_SYSTEM, t, apperr(&st));
+}
+
+/*ARGSUSED*/
+void
+doinlib(v, c)
+ Char **v;
+ struct command *c;
+{
+ setname(short2str(*v++));
+ gflag = 0, tglob(v);
+ if (gflag) {
+ v = globall(v);
+ if (v == 0)
+ stderror(ERR_NAME | ERR_NOMATCH);
+ }
+ else {
+ v = gargv = saveblk(v);
+ trim(v);
+ }
+
+ while (v && *v)
+ llib(*v++);
+ if (gargv)
+ blkfree(gargv), gargv = 0;
+}
+
+int
+getv(v)
+ Char *v;
+{
+ if (eq(v, STRbsd43))
+ return(1);
+ else if (eq(v, STRsys53))
+ return(0);
+ else
+ stderror(ERR_NAME | ERR_SYSTEM, short2str(v),
+ CGETS(23, 28, "Invalid system type"));
+ /*NOTREACHED*/
+ return(0);
+}
+
+/*ARGSUSED*/
+void
+dover(v, c)
+ Char **v;
+ struct command *c;
+{
+ Char *p;
+
+ setname(short2str(*v++));
+ if (!*v) {
+ if (!(p = tgetenv(STRSYSTYPE)))
+ stderror(ERR_NAME | ERR_STRING,
+ CGETS(23, 29, "System type is not set"));
+ xprintf("%S\n", p);
+ }
+ else {
+ tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
+ dohash(NULL, NULL);
+ }
+}
+
+/*
+ * Many thanks to rees@citi.umich.edu (Jim Rees) and
+ * mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
+ * For figuring out how to do this... I could have never done
+ * it without their help.
+ */
+typedef short enum {
+ name_$wdir_type,
+ name_$ndir_type,
+ name_$node_dir_type,
+} name_$dir_type_t;
+
+/*ARGSUSED*/
+void
+dorootnode(v, c)
+ Char **v;
+ struct command *c;
+{
+ name_$dir_type_t dirtype = name_$node_dir_type;
+ uid_$t uid;
+ status_$t st;
+ char *name;
+ short namelen;
+
+ setname(short2str(*v++));
+
+ name = short2str(*v);
+ namelen = strlen(name);
+
+ name_$resolve(name, &namelen, &uid, &st);
+ if (st.all != status_$ok)
+ stderror(ERR_SYSTEM, name, apperr(&st));
+ namelen = 0;
+ name_$set_diru(&uid, "", &namelen, &dirtype, &st);
+ if (st.all != status_$ok)
+ stderror(ERR_SYSTEM, name, apperr(&st));
+ dohash(NULL, NULL);
+}
+
+int
+isapad()
+{
+ static int res = -1;
+ static status_$t st;
+
+ if (res == -1) {
+ int strm;
+ if (isatty(0))
+ strm = 0;
+ if (isatty(1))
+ strm = 1;
+ if (isatty(2))
+ strm = 2;
+ else {
+ res = 0;
+ st.all = status_$ok;
+ return(res);
+ }
+ res = stream_$isavt(&strm, &st);
+ res = res ? 1 : 0;
+ }
+ else {
+ if (st.all != status_$ok)
+ stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));
+ }
+ return(res);
+}
+#endif
diff --git a/contrib/tcsh/tc.os.h b/contrib/tcsh/tc.os.h
new file mode 100644
index 0000000..fcd4ade
--- /dev/null
+++ b/contrib/tcsh/tc.os.h
@@ -0,0 +1,754 @@
+/* $Header: /src/pub/tcsh/tc.os.h,v 3.82 1999/02/06 15:19:03 christos Exp $ */
+/*
+ * tc.os.h: Shell os dependent defines
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tc_os
+#define _h_tc_os
+
+#ifndef WINNT
+#define NEEDstrerror /* Too hard to find which systems have it */
+#endif /* WINNT */
+
+
+#ifdef notdef
+/*
+ * for SVR4 and linux we used to fork pipelines backwards.
+ * This should not be needed any more.
+ * more info in sh.sem.c
+ */
+# define BACKPIPE
+#endif /* notdef */
+
+#ifdef _VMS_POSIX
+# ifndef NOFILE
+# define NOFILE 64
+# endif /* NOFILE */
+# define nice(a) setprio((getpid()),a)
+# undef NEEDstrerror /* won't get sensible error messages otherwise */
+# define NEEDgethostname
+# include <sys/time.h> /* for time stuff in tc.prompt.c */
+# include <limits.h>
+#endif /* atp vmsposix */
+
+#if defined(DECOSF1) || defined(HPUXVERSION)
+# include <sys/signal.h>
+#endif /* DECOSF1 || HPUXVERSION */
+
+#ifdef DECOSF1
+# include <sys/ioctl.h>
+#endif /* DECOSF1 */
+
+#if defined(OPEN_MAX) && !defined(NOFILE)
+# define NOFILE OPEN_MAX
+#endif /* OPEN_MAX && !NOFILE */
+
+#if defined(USR_NFDS) && !defined(NOFILE)
+# define NOFILE USR_NFDS
+#endif /* USR_NFDS && !NOFILE */
+
+#ifndef NOFILE
+# define NOFILE 256
+#endif /* NOFILE */
+
+#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || SYSVREL >= 4
+# undef NEEDstrerror
+#endif /* linux || __NetBSD__ || __FreeBSD__ || SYSVREL >= 4 */
+
+#if !defined(pyr) && !defined(sinix)
+/* Pyramid's cpp complains about the next line */
+# if defined(BSD) && BSD >= 199306
+# undef NEEDstrerror
+# endif /* BSD && BSD >= 199306 */
+#endif /* pyr */
+
+#ifdef OREO
+# include <sys/time.h>
+# ifdef notdef
+ /* Don't include it, because it defines things we don't really have */
+# include <sys/resource.h>
+# endif /* notdef */
+# ifdef POSIX
+# include <sys/tty.h>
+# include <termios.h>
+# endif /* POSIX */
+#endif /* OREO */
+
+#ifndef NCARGS
+# ifdef _SC_ARG_MAX
+# define NCARGS sysconf(_SC_ARG_MAX)
+# else /* !_SC_ARG_MAX */
+# ifdef ARG_MAX
+# define NCARGS ARG_MAX
+# else /* !ARG_MAX */
+# ifdef _MINIX
+# define NCARGS 80
+# else /* !_MINIX */
+# define NCARGS 1024
+# endif /* _MINIX */
+# endif /* ARG_MAX */
+# endif /* _SC_ARG_MAX */
+#endif /* NCARGS */
+
+#ifdef convex
+# include <sys/dmon.h>
+#endif /* convex */
+
+#ifdef titan
+extern int end;
+#endif /* titan */
+
+#ifdef hpux
+# ifdef lint
+/*
+ * Hpux defines struct ucred, in <sys/user.h>, but if I include that
+ * then I need to include the *world*
+ * [all this to pass lint cleanly!!!]
+ * so I define struct ucred here...
+ */
+struct ucred {
+ int foo;
+};
+# endif /* lint */
+
+/*
+ * hpux 7.0 does not define it
+ */
+# ifndef CSUSP
+# define CSUSP 032
+# endif /* CSUSP */
+
+# include <signal.h>
+# if !defined(hp9000s500) && !(defined(SIGRTMAX) || defined(SIGRTMIN))
+/*
+ * hpux < 7
+ */
+# include <sys/bsdtty.h>
+# endif /* !hp9000s500 && !(SIGRTMAX || SIGRTMIN) */
+
+# ifndef POSIX
+# ifdef BSDJOBS
+# define getpgrp(a) getpgrp2(a)
+# define setpgrp(a, b) setpgrp2(a, b)
+# endif /* BSDJOBS */
+# endif /* POSIX */
+#endif /* hpux */
+
+/*
+ * ISC does not define CSUSP
+ */
+#ifdef ISC
+# ifndef CSUSP
+# define CSUSP 032
+# endif /* CSUSP */
+# if defined(POSIX) && !defined(TIOCGWINSZ)
+/*
+ * ISC defines this only in termio.h. If we are using POSIX and include
+ * termios.h, then we define it ourselves so that window resizing works.
+ */
+# define TIOCGWINSZ (('T'<<8)|104)
+# endif /* POSIX && !TIOCGWINSZ */
+#endif /* ISC */
+
+#ifdef ISC202
+# undef TIOCGWINSZ
+#endif /* ISC202 */
+
+/*
+ * XXX: This will be changed soon to
+ * #if (SYSVREL > 0) && defined(TIOCGWINSZ)
+ * If that breaks on your machine, let me know.
+ *
+ * It would break on linux, where all this is
+ * defined in <termios.h>. Wrapper added.
+ */
+#if !defined(linux) && !defined(_VMS_POSIX)
+# if defined(INTEL) || defined(u3b2) || defined (u3b5) || defined(ub15) || defined(u3b20d) || defined(ISC) || defined(SCO) || defined(tower32)
+# ifdef TIOCGWINSZ
+/*
+ * for struct winsiz
+ */
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# endif /* TIOCGWINSZ */
+# ifndef ODT
+# define NEEDgethostname
+# endif /* ODT */
+# endif /* INTEL || u3b2 || u3b5 || ub15 || u3b20d || ISC || SCO || tower32 */
+#endif /* !linux && !_VMS_POSIX */
+
+#if defined(UNIXPC) || defined(COHERENT)
+# define NEEDgethostname
+#endif /* UNIXPC || COHERENT */
+
+#ifdef IRIS4D
+# include <sys/time.h>
+# include <sys/resource.h>
+# ifndef POSIX
+/*
+ * BSDsetpgrp() and BSDgetpgrp() are BSD versions of setpgrp, etc.
+ */
+# define setpgrp BSDsetpgrp
+# define getpgrp BSDgetpgrp
+# endif /* POSIX */
+#endif /* IRIS4D */
+
+/*
+ * For some versions of system V software, specially ones that use the
+ * Wollongong Software TCP/IP, the FIOCLEX, FIONCLEX, FIONBIO calls
+ * might not work correctly for file descriptors [they work only for
+ * sockets]. So we try to use first the fcntl() and we only use the
+ * ioctl() form, only if we don't have the fcntl() one.
+ *
+ * From: scott@craycos.com (Scott Bolte)
+ */
+#ifndef WINNT
+# ifdef F_SETFD
+# define close_on_exec(fd, v) fcntl((fd), F_SETFD, v)
+# else /* !F_SETFD */
+# ifdef FIOCLEX
+# define close_on_exec(fd, v) ioctl((fd), ((v) ? FIOCLEX : FIONCLEX), NULL)
+# else /* !FIOCLEX */
+# define close_on_exec(fd, v) /* Nothing */
+# endif /* FIOCLEX */
+# endif /* F_SETFD */
+#else /* WINNT */
+# define close_on_exec(fd, v) nt_close_on_exec((fd),(v))
+#endif /* !WINNT */
+
+/*
+ * Stat
+ */
+#ifdef ISC
+/* these are not defined for _POSIX_SOURCE under ISC 2.2 */
+# ifndef S_IFMT
+# define S_IFMT 0170000 /* type of file */
+# define S_IFDIR 0040000 /* directory */
+# define S_IFCHR 0020000 /* character special */
+# define S_IFBLK 0060000 /* block special */
+# define S_IFREG 0100000 /* regular */
+# define S_IFIFO 0010000 /* fifo */
+# define S_IFNAM 0050000 /* special named file */
+# ifndef ISC202
+# define S_IFLNK 0120000 /* symbolic link */
+# endif /* ISC202 */
+# endif /* S_IFMT */
+#endif /* ISC */
+
+#if defined(uts) || defined(UTekV) || defined(sysV88)
+/*
+ * The uts 2.1.2 macros (Amdahl) are busted!
+ * You should fix <sys/stat.h>, cause other programs will break too!
+ *
+ * From: creiman@ncsa.uiuc.edu (Charlie Reiman)
+ */
+
+/*
+ * The same applies to Motorola MPC (System V/88 R32V2, UTekV 3.2e)
+ * workstations, the stat macros are broken.
+ * Kaveh Ghazi (ghazi@caip.rutgers.edu)
+ */
+# undef S_ISDIR
+# undef S_ISCHR
+# undef S_ISBLK
+# undef S_ISREG
+# undef S_ISFIFO
+# undef S_ISNAM
+# undef S_ISLNK
+# undef S_ISSOCK
+#endif /* uts || UTekV || sysV88 */
+
+#ifdef S_IFMT
+# if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+# endif /* ! S_ISDIR && S_IFDIR */
+# if !defined(S_ISCHR) && defined(S_IFCHR)
+# define S_ISCHR(a) (((a) & S_IFMT) == S_IFCHR)
+# endif /* ! S_ISCHR && S_IFCHR */
+# if !defined(S_ISBLK) && defined(S_IFBLK)
+# define S_ISBLK(a) (((a) & S_IFMT) == S_IFBLK)
+# endif /* ! S_ISBLK && S_IFBLK */
+# if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(a) (((a) & S_IFMT) == S_IFREG)
+# endif /* ! S_ISREG && S_IFREG */
+# if !defined(S_ISFIFO) && defined(S_IFIFO)
+# define S_ISFIFO(a) (((a) & S_IFMT) == S_IFIFO)
+# endif /* ! S_ISFIFO && S_IFIFO */
+# if !defined(S_ISNAM) && defined(S_IFNAM)
+# define S_ISNAM(a) (((a) & S_IFMT) == S_IFNAM)
+# endif /* ! S_ISNAM && S_IFNAM */
+# if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+# endif /* ! S_ISLNK && S_IFLNK */
+# if !defined(S_ISSOCK) && defined(S_IFSOCK)
+# define S_ISSOCK(a) (((a) & S_IFMT) == S_IFSOCK)
+# endif /* ! S_ISSOCK && S_IFSOCK */
+#endif /* S_IFMT */
+
+#ifdef tower32
+/* The header files lie; we really don't have symlinks */
+# undef S_ISLNK
+# undef S_IFLNK
+#endif /* tower32 */
+
+#ifndef S_IREAD
+# define S_IREAD 0000400
+#endif /* S_IREAD */
+#ifndef S_IROTH
+# define S_IROTH (S_IREAD >> 6)
+#endif /* S_IROTH */
+#ifndef S_IRGRP
+# define S_IRGRP (S_IREAD >> 3)
+#endif /* S_IRGRP */
+#ifndef S_IRUSR
+# define S_IRUSR S_IREAD
+#endif /* S_IRUSR */
+
+#ifndef S_IWRITE
+# define S_IWRITE 0000200
+#endif /* S_IWRITE */
+#ifndef S_IWOTH
+# define S_IWOTH (S_IWRITE >> 6)
+#endif /* S_IWOTH */
+#ifndef S_IWGRP
+# define S_IWGRP (S_IWRITE >> 3)
+#endif /* S_IWGRP */
+#ifndef S_IWUSR
+# define S_IWUSR S_IWRITE
+#endif /* S_IWUSR */
+
+#ifndef S_IEXEC
+# define S_IEXEC 0000100
+#endif /* S_IEXEC */
+#ifndef S_IXOTH
+# define S_IXOTH (S_IEXEC >> 6)
+#endif /* S_IXOTH */
+#ifndef S_IXGRP
+# define S_IXGRP (S_IEXEC >> 3)
+#endif /* S_IXGRP */
+#ifndef S_IXUSR
+# define S_IXUSR S_IEXEC
+#endif /* S_IXUSR */
+
+#ifndef S_ISUID
+# define S_ISUID 0004000 /* setuid */
+#endif /* S_ISUID */
+#ifndef S_ISGID
+# define S_ISGID 0002000 /* setgid */
+#endif /* S_ISGID */
+#ifndef S_ISVTX
+# define S_ISVTX 0001000 /* sticky */
+#endif /* S_ISVTX */
+#ifndef S_ENFMT
+# define S_ENFMT S_ISGID /* record locking enforcement flag */
+#endif /* S_ENFMT */
+
+/* the following macros are for POSIX conformance */
+#ifndef S_IRWXU
+# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+#endif /* S_IRWXU */
+#ifndef S_IRWXG
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#endif /* S_IRWXG */
+#ifndef S_IRWXO
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif /* S_IRWXO */
+
+/*
+ * Access()
+ */
+#ifndef F_OK
+# define F_OK 0
+#endif /* F_OK */
+#ifndef X_OK
+# define X_OK 1
+#endif /* X_OK */
+#ifndef W_OK
+# define W_OK 2
+#endif /* W_OK */
+#ifndef R_OK
+# define R_OK 4
+#endif /* R_OK */
+
+/*
+ * Open()
+ */
+#ifndef O_RDONLY
+# define O_RDONLY 0
+#endif /* O_RDONLY */
+#ifndef O_WRONLY
+# define O_WRONLY 1
+#endif /* O_WRONLY */
+#ifndef O_RDWR
+# define O_RDWR 2
+#endif /* O_RDWR */
+
+/*
+ * Lseek()
+ */
+#ifndef L_SET
+# ifdef SEEK_SET
+# define L_SET SEEK_SET
+# else /* !SEEK_SET */
+# define L_SET 0
+# endif /* SEEK_SET */
+#endif /* L_SET */
+#ifndef L_INCR
+# ifdef SEEK_CUR
+# define L_INCR SEEK_CUR
+# else /* !SEEK_CUR */
+# define L_INCR 1
+# endif /* SEEK_CUR */
+#endif /* L_INCR */
+#ifndef L_XTND
+# ifdef SEEK_END
+# define L_XTND SEEK_END
+# else /* !SEEK_END */
+# define L_XTND 2
+# endif /* SEEK_END */
+#endif /* L_XTND */
+
+#ifdef _SEQUENT_
+# define NEEDgethostname
+#endif /* _SEQUENT_ */
+
+#if defined(BSD) && defined(POSIXJOBS) && !defined(BSD4_4) && !defined(__hp_osf)
+# define setpgid(pid, pgrp) setpgrp(pid, pgrp)
+#endif /* BSD && POSIXJOBS && && !BSD4_4 && !__hp_osf */
+
+#if defined(BSDJOBS) && !(defined(POSIX) && defined(POSIXJOBS))
+# if !defined(_AIX370) && !defined(_AIXPS2)
+# define setpgid(pid, pgrp) setpgrp(pid, pgrp)
+# endif /* !_AIX370 && !_AIXPS2 */
+# define NEEDtcgetpgrp
+#endif /* BSDJOBS && !(POSIX && POSIXJOBS) */
+
+#ifdef RENO
+/*
+ * RENO has this broken. It is fixed on 4.4BSD
+ */
+# define NEEDtcgetpgrp
+#endif /* RENO */
+
+#ifdef DGUX
+# define setpgrp(a, b) setpgrp2(a, b)
+# define getpgrp(a) getpgrp2(a)
+#endif /* DGUX */
+
+#ifdef SXA
+# ifndef _BSDX_
+/*
+ * Only needed in the system V environment.
+ */
+# define setrlimit bsd_setrlimit
+# define getrlimit bsd_getrlimit
+# endif /* _BSDX_ */
+#endif /* SXA */
+
+#if defined(_MINIX) || defined(__EMX__)
+# define NEEDgethostname
+# define NEEDnice
+# define HAVENOLIMIT
+/*
+ * Minix does not have these, so...
+ */
+# define getpgrp getpid
+#endif /* _MINIX || __EMX__ */
+
+#ifdef __EMX__
+/* XXX: How can we get the tty name in emx? */
+# define ttyname(fd) (isatty(fd) ? "/dev/tty" : NULL)
+#endif /* __EMX__ */
+
+#ifndef POSIX
+# define mygetpgrp() getpgrp(0)
+#else /* POSIX */
+# if (defined(BSD) && !defined(BSD4_4)) || defined(SUNOS4) || defined(IRIS4D) || defined(DGUX) || defined(HPRT)
+# define mygetpgrp() getpgrp(0)
+# else /* !((BSD && !BSD4_4) || SUNOS4 || IRIS4D || DGUX || HPRT) */
+# define mygetpgrp() getpgrp()
+# endif /* (BSD && BSD4_4) || SUNOS4 || IRISD || DGUX || HPRT */
+#endif /* POSIX */
+
+
+#if !defined(SOLARIS2) && !defined(sinix) && !defined(BSD4_4) && !defined(WINNT)
+# if (SYSVREL > 0 && !defined(OREO) && !defined(sgi) && !defined(linux) && !defined(sinix) && !defined(_AIX) &&!defined(_UWIN)) || defined(NeXT)
+# define NEEDgetcwd
+# endif /* (SYSVREL > 0 && !OREO && !sgi && !linux && !sinix && !_AIX && !_UWIN) || NeXT */
+#endif
+
+#ifndef S_IFLNK
+# define lstat stat
+#endif /* S_IFLNK */
+
+
+#if defined(BSDTIMES) && !defined(_SEQUENT_)
+typedef struct timeval timeval_t;
+#endif /* BSDTIMES && ! _SEQUENT_ */
+
+#ifdef NeXT
+/*
+ * From Tony_Mason@transarc.com, override NeXT's malloc stuff.
+ */
+# define malloc tcsh_malloc
+# define calloc tcsh_calloc
+# define realloc tcsh_realloc
+# define free tcsh_free
+#endif /* NeXT */
+
+#if !defined(BSD4_4) && !defined(__linux__) && !defined(__hpux) && !defined(sgi)
+#ifndef NEEDgethostname
+extern int gethostname __P((char *, int));
+#endif /* NEEDgethostname */
+#endif /* !BDS4_4 && !__linux__ && !__hpux && !sgi */
+
+#if !defined(POSIX) || defined(SUNOS4) || defined(UTekV) || defined(sysV88)
+extern time_t time();
+extern char *getenv();
+extern int atoi();
+# ifndef __EMX__
+extern char *ttyname();
+# endif /* __EMX__ */
+
+# if defined(SUNOS4)
+# ifndef toupper
+extern int toupper __P((int));
+# endif /* toupper */
+# ifndef tolower
+extern int tolower __P((int));
+# endif /* tolower */
+extern caddr_t sbrk __P((int));
+# if SYSVREL == 0 && !defined(__lucid)
+extern int qsort();
+# endif /* SYSVREL == 0 && !__lucid */
+# else /* !SUNOS4 */
+# ifndef WINNT
+# ifndef hpux
+# if __GNUC__ != 2
+extern int abort();
+# endif /* __GNUC__ != 2 */
+# ifndef fps500
+extern int qsort();
+# endif /* !fps500 */
+# else /* !hpux */
+extern void abort();
+extern void qsort();
+# endif /* hpux */
+# endif /* !WINNT */
+# endif /* SUNOS4 */
+#ifndef _CX_UX
+extern void perror();
+#endif
+
+# ifdef BSDSIGS
+# if defined(_AIX370) || defined(MACH) || defined(NeXT) || defined(_AIXPS2) || defined(ardent) || defined(SUNOS4) || defined(HPBSD) || defined(__MACHTEN__)
+extern int sigvec();
+extern int sigpause();
+# else /* !(_AIX370 || MACH || NeXT || _AIXPS2 || ardent || SUNOS4 || HPBSD) */
+# if (!defined(apollo) || !defined(__STDC__)) && !defined(__DGUX__) && !defined(fps500)
+extern sigret_t sigvec();
+#ifndef _CX_UX
+extern void sigpause();
+#endif /* _CX_UX */
+# endif /* (!apollo || !__STDC__) && !__DGUX__ && !fps500 */
+# endif /* _AIX370 || MACH || NeXT || _AIXPS2 || ardent || SUNOS4 || HPBSD */
+extern sigmask_t sigblock();
+extern sigmask_t sigsetmask();
+# endif /* BSDSIGS */
+
+# ifndef killpg
+extern int killpg();
+# endif /* killpg */
+
+# ifndef lstat
+extern int lstat();
+# endif /* lstat */
+
+# ifdef BSD
+extern uid_t getuid(), geteuid();
+extern gid_t getgid(), getegid();
+# endif /* BSD */
+
+# ifdef SYSMALLOC
+extern memalign_t malloc();
+extern memalign_t realloc();
+extern memalign_t calloc();
+extern void free();
+# endif /* SYSMALLOC */
+
+# ifdef BSDTIMES
+extern int getrlimit();
+extern int setrlimit();
+extern int getrusage();
+extern int gettimeofday();
+# endif /* BSDTIMES */
+
+# if defined(NLS) && !defined(NOSTRCOLL) && !defined(NeXT)
+extern int strcoll();
+# endif /* NLS && !NOSTRCOLL && !NeXT */
+
+# ifdef BSDJOBS
+# ifdef BSDTIMES
+# ifdef __MACHTEN__
+extern pid_t wait3();
+# else
+# ifndef HPBSD
+extern int wait3();
+# endif /* HPBSD */
+# endif /* __MACHTEN__ */
+# else /* !BSDTIMES */
+# if !defined(POSIXJOBS) && !defined(_SEQUENT_)
+extern int wait3();
+# else /* POSIXJOBS || _SEQUENT_ */
+extern int waitpid();
+# endif /* POSIXJOBS || _SEQUENT_ */
+# endif /* BSDTIMES */
+# else /* !BSDJOBS */
+# if SYSVREL < 3
+extern int ourwait();
+# else /* SYSVREL >= 3 */
+extern int wait();
+# endif /* SYSVREL < 3 */
+# endif /* BSDJOBS */
+
+# ifdef BSDNICE
+extern int setpriority();
+# else /* !BSDNICE */
+extern int nice();
+# endif /* BSDNICE */
+
+# if (!defined(fps500) && !defined(apollo) && !defined(__lucid) && !defined(HPBSD) && !defined(DECOSF1))
+extern void setpwent();
+extern void endpwent();
+# endif /* !fps500 && !apollo && !__lucid && !HPBSD && !DECOSF1 */
+
+# ifndef __STDC__
+extern struct passwd *getpwuid(), *getpwnam(), *getpwent();
+# ifdef PW_SHADOW
+extern struct spwd *getspnam(), *getspent();
+# endif /* PW_SHADOW */
+# ifdef PW_AUTH
+extern struct authorization *getauthuid();
+# endif /* PW_AUTH */
+# endif /* __STDC__ */
+
+# ifndef getcwd
+extern char *getcwd();
+# endif /* getcwd */
+
+#else /* POSIX || !SUNOS4 || !UTekV || !sysV88 */
+
+# if (defined(SUNOS4) && !defined(__GNUC__)) || defined(_IBMR2) || defined(_IBMESA)
+extern char *getvwd();
+# endif /* (SUNOS4 && ! __GNUC__) || _IBMR2 || _IBMESA */
+
+# ifdef SCO
+extern char *ttyname();
+# endif /* SCO */
+
+# ifdef __clipper__
+extern char *ttyname();
+# endif /* __clipper__ */
+
+#endif /* !POSIX || SUNOS4 || UTekV || sysV88 */
+
+#if defined(SUNOS4) && __GNUC__ == 2
+/*
+ * Somehow these are missing
+ */
+extern int ioctl __P((int, int, ...));
+extern int readlink __P((const char *, char *, size_t));
+extern void setgrent __P((void));
+extern void endgrent __P((void));
+# ifdef REMOTEHOST
+# ifndef _SOCKLEN_T /* Avoid Solaris 2.7 bogosity. */
+struct sockaddr;
+extern int getpeername __P((int, struct sockaddr *, int *));
+# endif /* _SOCKLEN_T */
+# endif /* REMOTEHOST */
+#endif /* SUNOS4 && __GNUC__ == 2 */
+
+#if (defined(BSD) && !defined(BSD4_4)) || defined(SUNOS4)
+# if defined(__alpha) && defined(__osf__) && DECOSF1 < 200
+extern void bcopy __P((const void *, void *, size_t));
+# define memmove(a, b, c) (bcopy((char *) (b), (char *) (a), (int) (c)), a)
+# endif /* __alpha && __osf__ && DECOSF1 < 200 */
+#endif /* (BSD && !BSD4_4) || SUNOS4 */
+
+#if !defined(hpux) && !defined(COHERENT) && ((SYSVREL < 4) || defined(_SEQUENT_)) && !defined(BSD4_4) && !defined(memmove)
+# define NEEDmemmove
+#endif /* !hpux && !COHERENT && (SYSVREL < 4 || _SEQUENT_) && !BSD4_4 && !memmove */
+
+#if defined(UTek) || defined(pyr)
+# define NEEDmemset
+#else /* !UTek && !pyr */
+# ifdef SUNOS4
+# include <memory.h> /* memset should be declared in <string.h> but isn't */
+# endif /* SUNOS4 */
+#endif /* UTek || pyr */
+
+#if SYSVREL == 4
+# ifdef REMOTEHOST
+/* Irix6 defines getpeername(int, void *, int *) which conflicts with
+ the definition below. */
+# if !defined(__sgi) && !defined(_OSD_POSIX)
+# ifndef _SOCKLEN_T /* Avoid Solaris 2.7 bogosity. */
+struct sockaddr;
+extern int getpeername __P((int, struct sockaddr *, int *));
+# endif /* _SOCKLEN_T */
+# endif /* !__sgi && !_OSD_POSIX */
+# endif /* REMOTEHOST */
+# ifndef BSDTIMES
+extern int getrlimit __P((int, struct rlimit *));
+extern int setrlimit __P((int, const struct rlimit *));
+# endif /* !BSDTIMES */
+# if !defined(IRIS4D) && !defined(SOLARIS2)
+extern int wait3(); /* I think some bizarre systems still need this */
+# endif /* !IRIS4D && !SOLARIS2 */
+# if defined(SOLARIS2)
+# undef NEEDstrerror
+extern char *strerror __P((int));
+# endif /* SOLARIS2 */
+#endif /* SYSVREL == 4 */
+
+#if defined(__alpha) && defined(__osf__) && DECOSF1 < 200
+/* These are ok for 1.3, but conflict with the header files for 2.0 */
+extern int gethostname __P((char *, int));
+extern char *sbrk __P((ssize_t));
+extern int ioctl __P((int, unsigned long, char *));
+extern pid_t vfork __P((void));
+extern int killpg __P((pid_t, int));
+#endif /* __osf__ && __alpha && DECOSF1 < 200 */
+
+#endif /* _h_tc_os */
diff --git a/contrib/tcsh/tc.printf.c b/contrib/tcsh/tc.printf.c
new file mode 100644
index 0000000..d2b044e
--- /dev/null
+++ b/contrib/tcsh/tc.printf.c
@@ -0,0 +1,415 @@
+/* $Header: /src/pub/tcsh/tc.printf.c,v 3.19 1998/10/25 15:10:37 christos Exp $ */
+/*
+ * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
+ * through the putchar() routine. Feel free to use for
+ * anything... -- 7/17/87 Paul Placeway
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.printf.c,v 3.19 1998/10/25 15:10:37 christos Exp $")
+
+#ifdef lint
+#undef va_arg
+#define va_arg(a, b) (a ? (b) 0 : (b) 0)
+#endif
+
+#define INF 32766 /* should be bigger than any field to print */
+
+static char buf[128];
+
+static void xaddchar __P((int));
+static void doprnt __P((void (*) __P((int)), const char *, va_list));
+
+static void
+doprnt(addchar, sfmt, ap)
+ void (*addchar) __P((int));
+ const char *sfmt;
+ va_list ap;
+{
+ register char *bp;
+ register const char *f;
+#ifdef SHORT_STRINGS
+ register Char *Bp;
+#endif /* SHORT_STRINGS */
+ register long l;
+ register unsigned long u;
+ register int i;
+ register int fmt;
+ register unsigned char pad = ' ';
+ int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
+ int sign = 0;
+ int attributes = 0;
+
+
+ f = sfmt;
+ for (; *f; f++) {
+ if (*f != '%') { /* then just out the char */
+ (*addchar) ((int) (((unsigned char)*f) | attributes));
+ }
+ else {
+ f++; /* skip the % */
+
+ if (*f == '-') { /* minus: flush left */
+ flush_left = 1;
+ f++;
+ }
+
+ if (*f == '0' || *f == '.') {
+ /* padding with 0 rather than blank */
+ pad = '0';
+ f++;
+ }
+ if (*f == '*') { /* field width */
+ f_width = va_arg(ap, int);
+ f++;
+ }
+ else if (Isdigit((unsigned char) *f)) {
+ f_width = atoi(f);
+ while (Isdigit((unsigned char) *f))
+ f++; /* skip the digits */
+ }
+
+ if (*f == '.') { /* precision */
+ f++;
+ if (*f == '*') {
+ prec = va_arg(ap, int);
+ f++;
+ }
+ else if (Isdigit((unsigned char) *f)) {
+ prec = atoi((char *) f);
+ while (Isdigit((unsigned char) *f))
+ f++; /* skip the digits */
+ }
+ }
+
+ if (*f == '#') { /* alternate form */
+ hash = 1;
+ f++;
+ }
+
+ if (*f == 'l') { /* long format */
+ do_long = 1;
+ f++;
+ }
+
+ fmt = (unsigned char) *f;
+ if (fmt != 'S' && fmt != 'Q' && Isupper(fmt)) {
+ do_long = 1;
+ fmt = Tolower(fmt);
+ }
+ bp = buf;
+ switch (fmt) { /* do the format */
+ case 'd':
+ if (do_long)
+ l = va_arg(ap, long);
+ else
+ l = (long) (va_arg(ap, int));
+ if (l < 0) {
+ sign = 1;
+ l = -l;
+ }
+ do {
+ *bp++ = (char) (l % 10) + '0';
+ } while ((l /= 10) > 0);
+ if (sign)
+ *bp++ = '-';
+ f_width = f_width - (int) (bp - buf);
+ if (!flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (pad | attributes));
+ for (bp--; bp >= buf; bp--)
+ (*addchar) ((int) (((unsigned char) *bp) | attributes));
+ if (flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (' ' | attributes));
+ break;
+
+ case 'o':
+ case 'x':
+ case 'u':
+ if (do_long)
+ u = va_arg(ap, unsigned long);
+ else
+ u = (unsigned long) (va_arg(ap, unsigned int));
+ if (fmt == 'u') { /* unsigned decimal */
+ do {
+ *bp++ = (char) (u % 10) + '0';
+ } while ((u /= 10) > 0);
+ }
+ else if (fmt == 'o') { /* octal */
+ do {
+ *bp++ = (char) (u % 8) + '0';
+ } while ((u /= 8) > 0);
+ if (hash)
+ *bp++ = '0';
+ }
+ else if (fmt == 'x') { /* hex */
+ do {
+ i = (int) (u % 16);
+ if (i < 10)
+ *bp++ = i + '0';
+ else
+ *bp++ = i - 10 + 'a';
+ } while ((u /= 16) > 0);
+ if (hash) {
+ *bp++ = 'x';
+ *bp++ = '0';
+ }
+ }
+ i = f_width - (int) (bp - buf);
+ if (!flush_left)
+ while (i-- > 0)
+ (*addchar) ((int) (pad | attributes));
+ for (bp--; bp >= buf; bp--)
+ (*addchar) ((int) (((unsigned char) *bp) | attributes));
+ if (flush_left)
+ while (i-- > 0)
+ (*addchar) ((int) (' ' | attributes));
+ break;
+
+
+ case 'c':
+ i = va_arg(ap, int);
+ (*addchar) ((int) (i | attributes));
+ break;
+
+ case 'S':
+ case 'Q':
+ Bp = va_arg(ap, Char *);
+ if (!Bp) {
+ bp = NULL;
+ goto lcase_s;
+ }
+ f_width = f_width - Strlen(Bp);
+ if (!flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (pad | attributes));
+ for (i = 0; *Bp && i < prec; i++) {
+ if (fmt == 'Q' && *Bp & QUOTE)
+ (*addchar) ((int) ('\\' | attributes));
+ (*addchar) ((int) ((*Bp & TRIM) | attributes));
+ Bp++;
+ }
+ if (flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (' ' | attributes));
+ break;
+
+ case 's':
+ case 'q':
+ bp = va_arg(ap, char *);
+lcase_s:
+ if (!bp)
+ bp = "(nil)";
+ f_width = f_width - strlen((char *) bp);
+ if (!flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (pad | attributes));
+ for (i = 0; *bp && i < prec; i++) {
+ if (fmt == 'q' && *bp & QUOTE)
+ (*addchar) ((int) ('\\' | attributes));
+ (*addchar) ((int) (((unsigned char) *bp & TRIM) |
+ attributes));
+ bp++;
+ }
+ if (flush_left)
+ while (f_width-- > 0)
+ (*addchar) ((int) (' ' | attributes));
+ break;
+
+ case 'a':
+ attributes = va_arg(ap, int);
+ break;
+
+ case '%':
+ (*addchar) ((int) ('%' | attributes));
+ break;
+
+ default:
+ break;
+ }
+ flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
+ sign = 0;
+ pad = ' ';
+ }
+ }
+}
+
+
+static char *xstring, *xestring;
+static void
+xaddchar(c)
+ int c;
+{
+ if (xestring == xstring)
+ *xstring = '\0';
+ else
+ *xstring++ = (char) c;
+}
+
+
+pret_t
+/*VARARGS*/
+#ifdef FUNCPROTO
+xsnprintf(char *str, size_t size, const char *fmt, ...)
+#else
+xsnprintf(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+#ifdef FUNCPROTO
+ va_start(va, fmt);
+#else
+ char *str, *fmt;
+ size_t size;
+
+ va_start(va);
+ str = va_arg(va, char *);
+ size = va_arg(va, size_t);
+ fmt = va_arg(va, char *);
+#endif
+
+ xstring = str;
+ xestring = str + size - 1;
+ doprnt(xaddchar, fmt, va);
+ va_end(va);
+ *xstring++ = '\0';
+#ifdef PURIFY
+ return 1;
+#endif
+}
+
+pret_t
+/*VARARGS*/
+#ifdef FUNCPROTO
+xprintf(const char *fmt, ...)
+#else
+xprintf(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+#ifdef FUNCPROTO
+ va_start(va, fmt);
+#else
+ char *fmt;
+
+ va_start(va);
+ fmt = va_arg(va, char *);
+#endif
+ doprnt(xputchar, fmt, va);
+ va_end(va);
+#ifdef PURIFY
+ return 1;
+#endif
+}
+
+
+pret_t
+xvprintf(fmt, va)
+ const char *fmt;
+ va_list va;
+{
+ doprnt(xputchar, fmt, va);
+#ifdef PURIFY
+ return 1;
+#endif
+}
+
+pret_t
+xvsnprintf(str, size, fmt, va)
+ char *str;
+ size_t size;
+ const char *fmt;
+ va_list va;
+{
+ xstring = str;
+ xestring = str + size - 1;
+ doprnt(xaddchar, fmt, va);
+ *xstring++ = '\0';
+#ifdef PURIFY
+ return 1;
+#endif
+}
+
+
+
+#ifdef PURIFY
+/* Purify uses (some of..) the following functions to output memory-use
+ * debugging info. Given all the messing with file descriptors that
+ * tcsh does, the easiest way I could think of to get it (Purify) to
+ * print anything was by replacing some standard functions with
+ * ones that do tcsh output directly - see dumb hook in doreaddirs()
+ * (sh.dir.c) -sg
+ */
+#ifndef FILE
+#define FILE int
+#endif
+int
+#ifdef FUNCPROTO
+fprintf(FILE *fp, const char* fmt, ...)
+#else
+fprintf(va_alist)
+ va_dcl
+#endif
+{
+ va_list va;
+#ifdef FUNCPROTO
+ va_start(va, fmt);
+#else
+ FILE *fp;
+ const char *fmt;
+
+ va_start(va);
+ fp = va_arg(va, FILE *);
+ fmt = va_arg(va, const char *);
+#endif
+ doprnt(xputchar, fmt, va);
+ va_end(va);
+ return 1;
+}
+
+int
+vfprintf(fp, fmt, va)
+ FILE *fp;
+ const char *fmt;
+ va_list va;
+{
+ doprnt(xputchar, fmt, va);
+ return 1;
+}
+
+#endif /* PURIFY */
diff --git a/contrib/tcsh/tc.prompt.c b/contrib/tcsh/tc.prompt.c
new file mode 100644
index 0000000..204630e
--- /dev/null
+++ b/contrib/tcsh/tc.prompt.c
@@ -0,0 +1,614 @@
+/* $Header: /src/pub/tcsh/tc.prompt.c,v 3.36 1999/02/06 15:19:04 christos Exp $ */
+/*
+ * tc.prompt.c: Prompt printing stuff
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.prompt.c,v 3.36 1999/02/06 15:19:04 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+
+/*
+ * kfk 21oct1983 -- add @ (time) and / ($cwd) in prompt.
+ * PWP 4/27/87 -- rearange for tcsh.
+ * mrdch@com.tau.edu.il 6/26/89 - added ~, T and .# - rearanged to switch()
+ * instead of if/elseif
+ * Luke Mewburn, <lukem@cs.rmit.edu.au>
+ * 6-Sep-91 changed date format
+ * 16-Feb-94 rewrote directory prompt code, added $ellipsis
+ * 29-Dec-96 added rprompt support
+ */
+
+static char *month_list[12];
+static char *day_list[7];
+
+void
+dateinit()
+{
+#ifdef notyet
+ int i;
+
+ setlocale(LC_TIME, "");
+
+ for (i = 0; i < 12; i++)
+ xfree((ptr_t) month_list[i]);
+ month_list[0] = strsave(_time_info->abbrev_month[0]);
+ month_list[1] = strsave(_time_info->abbrev_month[1]);
+ month_list[2] = strsave(_time_info->abbrev_month[2]);
+ month_list[3] = strsave(_time_info->abbrev_month[3]);
+ month_list[4] = strsave(_time_info->abbrev_month[4]);
+ month_list[5] = strsave(_time_info->abbrev_month[5]);
+ month_list[6] = strsave(_time_info->abbrev_month[6]);
+ month_list[7] = strsave(_time_info->abbrev_month[7]);
+ month_list[8] = strsave(_time_info->abbrev_month[8]);
+ month_list[9] = strsave(_time_info->abbrev_month[9]);
+ month_list[10] = strsave(_time_info->abbrev_month[10]);
+ month_list[11] = strsave(_time_info->abbrev_month[11]);
+
+ for (i = 0; i < 7; i++)
+ xfree((ptr_t) day_list[i]);
+ day_list[0] = strsave(_time_info->abbrev_wkday[0]);
+ day_list[1] = strsave(_time_info->abbrev_wkday[1]);
+ day_list[2] = strsave(_time_info->abbrev_wkday[2]);
+ day_list[3] = strsave(_time_info->abbrev_wkday[3]);
+ day_list[4] = strsave(_time_info->abbrev_wkday[4]);
+ day_list[5] = strsave(_time_info->abbrev_wkday[5]);
+ day_list[6] = strsave(_time_info->abbrev_wkday[6]);
+#else
+ month_list[0] = "Jan";
+ month_list[1] = "Feb";
+ month_list[2] = "Mar";
+ month_list[3] = "Apr";
+ month_list[4] = "May";
+ month_list[5] = "Jun";
+ month_list[6] = "Jul";
+ month_list[7] = "Aug";
+ month_list[8] = "Sep";
+ month_list[9] = "Oct";
+ month_list[10] = "Nov";
+ month_list[11] = "Dec";
+
+ day_list[0] = "Sun";
+ day_list[1] = "Mon";
+ day_list[2] = "Tue";
+ day_list[3] = "Wed";
+ day_list[4] = "Thu";
+ day_list[5] = "Fri";
+ day_list[6] = "Sat";
+#endif
+}
+
+void
+printprompt(promptno, str)
+ int promptno;
+ char *str;
+{
+ static Char *ocp = NULL;
+ static char *ostr = NULL;
+ time_t lclock = time(NULL);
+ Char *cp;
+
+ switch (promptno) {
+ default:
+ case 0:
+ cp = varval(STRprompt);
+ break;
+ case 1:
+ cp = varval(STRprompt2);
+ break;
+ case 2:
+ cp = varval(STRprompt3);
+ break;
+ case 3:
+ if (ocp != NULL) {
+ cp = ocp;
+ str = ostr;
+ }
+ else
+ cp = varval(STRprompt);
+ break;
+ }
+
+ if (promptno < 2) {
+ ocp = cp;
+ ostr = str;
+ }
+
+ PromptBuf[0] = '\0';
+ tprintf(FMT_PROMPT, PromptBuf, cp, 2 * INBUFSIZE - 2, str, lclock, NULL);
+
+ if (!editing) {
+ for (cp = PromptBuf; *cp ; )
+ (void) putraw(*cp++);
+ SetAttributes(0);
+ flush();
+ }
+
+ RPromptBuf[0] = '\0';
+ if (promptno == 0) { /* determine rprompt if using main prompt */
+ cp = varval(STRrprompt);
+ tprintf(FMT_PROMPT, RPromptBuf, cp, INBUFSIZE - 2, NULL, lclock, NULL);
+
+ /* if not editing, put rprompt after prompt */
+ if (!editing && RPromptBuf[0] != '\0') {
+ for (cp = RPromptBuf; *cp ; )
+ (void) putraw(*cp++);
+ SetAttributes(0);
+ putraw(' ');
+ flush();
+ }
+ }
+}
+
+void
+tprintf(what, buf, fmt, siz, str, tim, info)
+ int what;
+ Char *buf;
+ const Char *fmt;
+ size_t siz;
+ char *str;
+ time_t tim;
+ ptr_t info;
+{
+ Char *z, *q;
+ Char attributes = 0;
+ static int print_prompt_did_ding = 0;
+ const char *cz;
+ Char buff[BUFSIZE];
+ char cbuff[BUFSIZE];
+
+ Char *p = buf;
+ Char *ep = &p[siz];
+ const Char *cp = fmt;
+ Char Scp;
+ struct tm *t = localtime(&tim);
+
+ /* prompt stuff */
+ static Char *olddir = NULL, *olduser = NULL;
+ extern int tlength; /* cache cleared */
+ int updirs, sz;
+ size_t pdirs;
+
+ for (; *cp; cp++) {
+ if (p >= ep)
+ break;
+ if ((*cp == '%') && ! (cp[1] == '\0')) {
+ cp++;
+ switch (*cp) {
+ case 'R':
+ if (what == FMT_HISTORY)
+ fmthist('R', info, str = cbuff, sizeof(cbuff));
+ if (str != NULL)
+ for (; *str; *p++ = attributes | *str++)
+ if (p >= ep) break;
+ break;
+ case '#':
+ *p++ = attributes | ((uid == 0) ? PRCHROOT : PRCH);
+ break;
+ case '!':
+ case 'h':
+ switch (what) {
+ case FMT_HISTORY:
+ fmthist('h', info, (char *) cbuff, sizeof(cbuff));
+ break;
+ case FMT_SCHED:
+ (void) xsnprintf((char *) cbuff, sizeof(cbuff), "%d", *(int *)info);
+ break;
+ default:
+ (void) xsnprintf((char *) cbuff, sizeof(cbuff), "%d", eventno + 1);
+ break;
+ }
+ for (cz = cbuff; *cz; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ break;
+ case 'T': /* 24 hour format */
+ case '@':
+ case 't': /* 12 hour am/pm format */
+ case 'p': /* With seconds */
+ case 'P':
+ {
+ char ampm = 'a';
+ int hr = t->tm_hour;
+
+ if (p >= ep - 10) break;
+
+ /* addition by Hans J. Albertsson */
+ /* and another adapted from Justin Bur */
+ if (adrof(STRampm) || (*cp != 'T' && *cp != 'P')) {
+ if (hr >= 12) {
+ if (hr > 12)
+ hr -= 12;
+ ampm = 'p';
+ }
+ else if (hr == 0)
+ hr = 12;
+ } /* else do a 24 hour clock */
+
+ /* "DING!" stuff by Hans also */
+ if (t->tm_min || print_prompt_did_ding ||
+ what != FMT_PROMPT || adrof(STRnoding)) {
+ if (t->tm_min)
+ print_prompt_did_ding = 0;
+ p = Itoa(hr, p, 0, attributes);
+ *p++ = attributes | ':';
+ p = Itoa(t->tm_min, p, 2, attributes);
+ if (*cp == 'p' || *cp == 'P') {
+ *p++ = attributes | ':';
+ p = Itoa(t->tm_sec, p, 2, attributes);
+ }
+ if (adrof(STRampm) || (*cp != 'T' && *cp != 'P')) {
+ *p++ = attributes | ampm;
+ *p++ = attributes | 'm';
+ }
+ }
+ else { /* we need to ding */
+ int i = 0;
+
+ (void) Strcpy(buff, STRDING);
+ while (buff[i]) {
+ *p++ = attributes | buff[i++];
+ }
+ print_prompt_did_ding = 1;
+ }
+ }
+ break;
+
+ case 'M':
+#ifndef HAVENOUTMP
+ if (what == FMT_WHO)
+ cz = who_info(info, 'M', (char *) cbuff, sizeof(cbuff));
+ else
+#endif /* HAVENOUTMP */
+ cz = getenv("HOST");
+ /*
+ * Bug pointed out by Laurent Dami <dami@cui.unige.ch>: don't
+ * derefrence that NULL (if HOST is not set)...
+ */
+ if (cz != NULL)
+ for (; *cz ; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ break;
+
+ case 'm':
+#ifndef HAVENOUTMP
+ if (what == FMT_WHO)
+ cz = who_info(info, 'm', (char *) cbuff, sizeof(cbuff));
+ else
+#endif /* HAVENOUTMP */
+ cz = getenv("HOST");
+
+ if (cz != NULL)
+ for ( ; *cz && (what == FMT_WHO || *cz != '.')
+ ; *p++ = attributes | *cz++ )
+ if (p >= ep) break;
+ break;
+
+ /* lukem: new directory prompt code */
+ case '~':
+ case '/':
+ case '.':
+ case 'c':
+ case 'C':
+ Scp = *cp;
+ if (Scp == 'c') /* store format type (c == .) */
+ Scp = '.';
+ if ((z = varval(STRcwd)) == STRNULL)
+ break; /* no cwd, so don't do anything */
+
+ /* show ~ whenever possible - a la dirs */
+ if (Scp == '~' || Scp == '.' ) {
+ if (tlength == 0 || olddir != z) {
+ olddir = z; /* have we changed dir? */
+ olduser = getusername(&olddir);
+ }
+ if (olduser)
+ z = olddir;
+ }
+ updirs = pdirs = 0;
+
+ /* option to determine fixed # of dirs from path */
+ if (Scp == '.' || Scp == 'C') {
+ int skip;
+#ifdef WINNT
+ if (z[1] == ':') {
+ *p++ = attributes | *z++;
+ *p++ = attributes | *z++;
+ }
+ if (*z == '/' && z[1] == '/') {
+ *p++ = attributes | *z++;
+ *p++ = attributes | *z++;
+ do {
+ *p++ = attributes | *z++;
+ }while(*z != '/');
+ }
+#endif /* WINNT */
+ q = z;
+ while (*z) /* calc # of /'s */
+ if (*z++ == '/')
+ updirs++;
+ if ((Scp == 'C' && *q != '/'))
+ updirs++;
+
+ if (cp[1] == '0') { /* print <x> or ... */
+ pdirs = 1;
+ cp++;
+ }
+ if (cp[1] >= '1' && cp[1] <= '9') { /* calc # to skip */
+ skip = cp[1] - '0';
+ cp++;
+ }
+ else
+ skip = 1;
+
+ updirs -= skip;
+ while (skip-- > 0) {
+ while ((z > q) && (*z != '/'))
+ z--; /* back up */
+ if (skip && z > q)
+ z--;
+ }
+ if (*z == '/' && z != q)
+ z++;
+ } /* . || C */
+
+ /* print ~[user] */
+ if ((olduser) && ((Scp == '~') ||
+ (Scp == '.' && (pdirs || (!pdirs && updirs <= 0))) )) {
+ *p++ = attributes | '~';
+ if (p >= ep) break;
+ for (q = olduser; *q; *p++ = attributes | *q++)
+ if (p >= ep) break;
+ }
+
+ /* RWM - tell you how many dirs we've ignored */
+ /* and add '/' at front of this */
+ if (updirs > 0 && pdirs) {
+ if (p >= ep - 5) break;
+ if (adrof(STRellipsis)) {
+ *p++ = attributes | '.';
+ *p++ = attributes | '.';
+ *p++ = attributes | '.';
+ } else {
+ *p++ = attributes | '/';
+ *p++ = attributes | '<';
+ if (updirs > 9) {
+ *p++ = attributes | '9';
+ *p++ = attributes | '+';
+ } else
+ *p++ = attributes | ('0' + updirs);
+ *p++ = attributes | tcsh ? '>' : '%';
+ }
+ }
+
+ for (; *z ; *p++ = attributes | *z++)
+ if (p >= ep) break;
+ break;
+ /* lukem: end of new directory prompt code */
+
+ case 'n':
+#ifndef HAVENOUTMP
+ if (what == FMT_WHO) {
+ cz = who_info(info, 'n', (char *) cbuff, sizeof(cbuff));
+ for (; cz && *cz ; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ }
+ else
+#endif /* HAVENOUTMP */
+ {
+ if ((z = varval(STRuser)) != STRNULL)
+ for (; *z; *p++ = attributes | *z++)
+ if (p >= ep) break;
+ }
+ break;
+ case 'l':
+#ifndef HAVENOUTMP
+ if (what == FMT_WHO) {
+ cz = who_info(info, 'l', (char *) cbuff, sizeof(cbuff));
+ for (; cz && *cz ; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ }
+ else
+#endif /* HAVENOUTMP */
+ {
+ if ((z = varval(STRtty)) != STRNULL)
+ for (; *z; *p++ = attributes | *z++)
+ if (p >= ep) break;
+ }
+ break;
+ case 'd':
+ for (cz = day_list[t->tm_wday]; *cz; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ break;
+ case 'D':
+ if (p >= ep - 3) break;
+ p = Itoa(t->tm_mday, p, 2, attributes);
+ break;
+ case 'w':
+ if (p >= ep - 5) break;
+ for (cz = month_list[t->tm_mon]; *cz;)
+ *p++ = attributes | *cz++;
+ break;
+ case 'W':
+ if (p >= ep - 3) break;
+ p = Itoa(t->tm_mon + 1, p, 2, attributes);
+ break;
+ case 'y':
+ if (p >= ep - 3) break;
+ p = Itoa(t->tm_year % 100, p, 2, attributes);
+ break;
+ case 'Y':
+ if (p >= ep - 5) break;
+ p = Itoa(t->tm_year + 1900, p, 4, attributes);
+ break;
+ case 'S': /* start standout */
+ attributes |= STANDOUT;
+ break;
+ case 'B': /* start bold */
+ attributes |= BOLD;
+ break;
+ case 'U': /* start underline */
+ attributes |= UNDER;
+ break;
+ case 's': /* end standout */
+ attributes &= ~STANDOUT;
+ break;
+ case 'b': /* end bold */
+ attributes &= ~BOLD;
+ break;
+ case 'u': /* end underline */
+ attributes &= ~UNDER;
+ break;
+ case 'L':
+ ClearToBottom();
+ break;
+ case '?':
+ if ((z = varval(STRstatus)) != STRNULL)
+ for (; *z; *p++ = attributes | *z++)
+ if (p >= ep) break;
+ break;
+ case '$':
+ sz = (int) (ep - p);
+ (void) expdollar(&p, &cp, &pdirs, attributes);
+ break;
+ case '%':
+ *p++ = attributes | '%';
+ break;
+ case '{': /* literal characters start */
+#if LITERAL == 0
+ /*
+ * No literal capability, so skip all chars in the literal
+ * string
+ */
+ while (*cp != '\0' && (*cp != '%' || cp[1] != '}'))
+ cp++;
+#endif /* LITERAL == 0 */
+ attributes |= LITERAL;
+ break;
+ case '}': /* literal characters end */
+ attributes &= ~LITERAL;
+ break;
+ default:
+#ifndef HAVENOUTMP
+ if (*cp == 'a' && what == FMT_WHO) {
+ cz = who_info(info, 'a', (char *) cbuff, sizeof(cbuff));
+ for (; cz && *cz; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ }
+ else
+#endif /* HAVENOUTMP */
+ {
+ if (p >= ep - 3) break;
+ *p++ = attributes | '%';
+ *p++ = attributes | *cp;
+ }
+ break;
+ }
+ }
+ else if (*cp == '\\' || *cp == '^')
+ *p++ = attributes | parseescape(&cp);
+ else if (*cp == HIST) { /* EGS: handle '!'s in prompts */
+ if (what == FMT_HISTORY)
+ fmthist('h', info, (char *) cbuff, sizeof(cbuff));
+ else
+ (void) xsnprintf((char *) cbuff, sizeof(cbuff), "%d", eventno + 1);
+ for (cz = cbuff; *cz; *p++ = attributes | *cz++)
+ if (p >= ep) break;
+ }
+ else
+ *p++ = attributes | *cp; /* normal character */
+ }
+ *p = '\0';
+}
+
+Char *
+expdollar(dstp, srcp, spp, attr)
+ Char **dstp;
+ const Char **srcp;
+ size_t *spp;
+ int attr;
+{
+ struct varent *vp;
+ Char var[MAXVARLEN];
+ const Char *src = *srcp;
+ Char *val;
+ Char *dst = *dstp;
+ int i, curly = 0;
+
+ /* found a variable, expand it */
+ for (i = 0; i < MAXVARLEN; i++) {
+ var[i] = *++src & TRIM;
+ if (i == 0 && var[i] == '{') {
+ curly = 1;
+ var[i] = *++src & TRIM;
+ }
+ if (!alnum(var[i])) {
+
+ var[i] = '\0';
+ break;
+ }
+ }
+ if (curly && (*src & TRIM) == '}')
+ src++;
+
+ vp = adrof(var);
+ val = (!vp) ? tgetenv(var) : NULL;
+ if (vp) {
+ for (i = 0; vp->vec[i] != NULL; i++) {
+ for (val = vp->vec[i]; *spp > 0 && *val; (*spp)--)
+ *dst++ = *val++ | attr;
+ if (vp->vec[i+1] && *spp > 0) {
+ *dst++ = ' ' | attr;
+ (*spp)--;
+ }
+ }
+ }
+ else if (val) {
+ for (; *spp > 0 && *val; (*spp)--)
+ *dst++ = *val++ | attr;
+ }
+ else {
+ **dstp = '\0';
+ *srcp = src;
+ return NULL;
+ }
+ *dst = '\0';
+
+ val = *dstp;
+ *srcp = src;
+ *dstp = dst;
+
+ return val;
+}
diff --git a/contrib/tcsh/tc.sched.c b/contrib/tcsh/tc.sched.c
new file mode 100644
index 0000000..787a206
--- /dev/null
+++ b/contrib/tcsh/tc.sched.c
@@ -0,0 +1,288 @@
+/* $Header: /src/pub/tcsh/tc.sched.c,v 3.16 1998/10/25 15:10:40 christos Exp $ */
+/*
+ * tc.sched.c: Scheduled command execution
+ *
+ * Karl Kleinpaste: Computer Consoles Inc. 1984
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.sched.c,v 3.16 1998/10/25 15:10:40 christos Exp $")
+
+#include "ed.h"
+#include "tc.h"
+
+extern int just_signaled;
+
+struct sched_event {
+ struct sched_event *t_next;
+ time_t t_when;
+ Char **t_lex;
+};
+static struct sched_event *sched_ptr = NULL;
+
+
+time_t
+sched_next()
+{
+ if (sched_ptr)
+ return (sched_ptr->t_when);
+ return ((time_t) - 1);
+}
+
+/*ARGSUSED*/
+void
+dosched(v, c)
+ register Char **v;
+ struct command *c;
+{
+ register struct sched_event *tp, *tp1, *tp2;
+ time_t cur_time;
+ int count, hours, minutes, dif_hour, dif_min;
+ Char *cp;
+ bool relative; /* time specified as +hh:mm */
+ struct tm *ltp;
+
+ USE(c);
+/* This is a major kludge because of a gcc linker */
+/* Problem. It may or may not be needed for you */
+#ifdef _MINIX
+ char kludge[10];
+ extern char *sprintf();
+ sprintf(kludge, CGETS(24, 1, "kludge"));
+#endif /* _MINIX */
+
+ v++;
+ cp = *v++;
+ if (cp == NULL) {
+ Char *fmt;
+ if ((fmt = varval(STRsched)) == STRNULL)
+ fmt = str2short("%h\t%T\t%R\n");
+ /* print list of scheduled events */
+ for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) {
+ Char buf[BUFSIZE], sbuf[BUFSIZE];
+ blkexpand(tp->t_lex, buf);
+ tprintf(FMT_SCHED, sbuf, fmt, sizeof(sbuf),
+ short2str(buf), tp->t_when, (ptr_t) &count);
+ for (cp = sbuf; *cp;)
+ xputchar(*cp++);
+ }
+ return;
+ }
+
+ if (*cp == '-') {
+ /* remove item from list */
+ if (!sched_ptr)
+ stderror(ERR_NOSCHED);
+ if (*v)
+ stderror(ERR_SCHEDUSAGE);
+ count = atoi(short2str(++cp));
+ if (count <= 0)
+ stderror(ERR_SCHEDUSAGE);
+ tp = sched_ptr;
+ tp1 = 0;
+ while (--count) {
+ if (tp->t_next == 0)
+ break;
+ else {
+ tp1 = tp;
+ tp = tp->t_next;
+ }
+ }
+ if (count)
+ stderror(ERR_SCHEDEV);
+ if (tp1 == 0)
+ sched_ptr = tp->t_next;
+ else
+ tp1->t_next = tp->t_next;
+ blkfree(tp->t_lex);
+ xfree((ptr_t) tp);
+ return;
+ }
+
+ /* else, add an item to the list */
+ if (!*v)
+ stderror(ERR_SCHEDCOM);
+ relative = 0;
+ if (!Isdigit(*cp)) { /* not abs. time */
+ if (*cp != '+')
+ stderror(ERR_SCHEDUSAGE);
+ cp++, relative++;
+ }
+ minutes = 0;
+ hours = atoi(short2str(cp));
+ while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p')
+ cp++;
+ if (*cp && *cp == ':')
+ minutes = atoi(short2str(++cp));
+ if ((hours < 0) || (minutes < 0) ||
+ (hours > 23) || (minutes > 59))
+ stderror(ERR_SCHEDTIME);
+ while (*cp && *cp != 'p' && *cp != 'a')
+ cp++;
+ if (*cp && relative)
+ stderror(ERR_SCHEDREL);
+ if (*cp == 'p')
+ hours += 12;
+ (void) time(&cur_time);
+ ltp = localtime(&cur_time);
+ if (relative) {
+ dif_hour = hours;
+ dif_min = minutes;
+ }
+ else {
+ if ((dif_hour = hours - ltp->tm_hour) < 0)
+ dif_hour += 24;
+ if ((dif_min = minutes - ltp->tm_min) < 0) {
+ dif_min += 60;
+ if ((--dif_hour) < 0)
+ dif_hour = 23;
+ }
+ }
+ tp = (struct sched_event *) xcalloc(1, sizeof *tp);
+#ifdef _SX
+ tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60;
+#else /* _SX */
+ tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L;
+#endif /* _SX */
+ /* use of tm_sec: get to beginning of minute. */
+ if (!sched_ptr || tp->t_when < sched_ptr->t_when) {
+ tp->t_next = sched_ptr;
+ sched_ptr = tp;
+ }
+ else {
+ tp1 = sched_ptr->t_next;
+ tp2 = sched_ptr;
+ while (tp1 && tp->t_when >= tp1->t_when) {
+ tp2 = tp1;
+ tp1 = tp1->t_next;
+ }
+ tp->t_next = tp1;
+ tp2->t_next = tp;
+ }
+ tp->t_lex = saveblk(v);
+}
+
+/*
+ * Execute scheduled events
+ */
+/*ARGSUSED*/
+void
+sched_run(n)
+ int n;
+{
+ time_t cur_time;
+ register struct sched_event *tp, *tp1;
+ struct wordent cmd, *nextword, *lastword;
+ struct command *t;
+ Char **v, *cp;
+ extern Char GettingInput;
+#ifdef BSDSIGS
+ sigmask_t omask;
+
+ omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
+#else
+ (void) sighold(SIGINT);
+#endif
+
+ USE(n);
+
+ (void) time(&cur_time);
+ tp = sched_ptr;
+
+ /* bugfix by: Justin Bur at Universite de Montreal */
+ /*
+ * this test wouldn't be necessary if this routine were not called before
+ * each prompt (in sh.c). But it is, to catch missed alarms. Someone
+ * ought to fix it all up. -jbb
+ */
+ if (!(tp && tp->t_when < cur_time)) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ return;
+ }
+
+ if (GettingInput)
+ (void) Cookedmode();
+
+ while (tp && tp->t_when < cur_time) {
+ if (seterr) {
+ xfree((ptr_t) seterr);
+ seterr = NULL;
+ }
+ cmd.word = STRNULL;
+ lastword = &cmd;
+ v = tp->t_lex;
+ for (cp = *v; cp; cp = *++v) {
+ nextword = (struct wordent *) xcalloc(1, sizeof cmd);
+ nextword->word = Strsave(cp);
+ lastword->next = nextword;
+ nextword->prev = lastword;
+ lastword = nextword;
+ }
+ lastword->next = &cmd;
+ cmd.prev = lastword;
+ tp1 = tp;
+ sched_ptr = tp = tp1->t_next; /* looping termination cond: */
+ blkfree(tp1->t_lex); /* straighten out in case of */
+ xfree((ptr_t) tp1); /* command blow-up. */
+
+ /* expand aliases like process() does. */
+ alias(&cmd);
+ /* build a syntax tree for the command. */
+ t = syntax(cmd.next, &cmd, 0);
+ if (seterr)
+ stderror(ERR_OLD);
+ /* execute the parse tree. */
+ execute(t, -1, NULL, NULL);
+ /* done. free the lex list and parse tree. */
+ freelex(&cmd), freesyn(t);
+ }
+ if (GettingInput && !just_signaled) { /* PWP */
+ (void) Rawmode();
+ ClearLines(); /* do a real refresh since something may */
+ ClearDisp(); /* have printed to the screen */
+ Refresh();
+ }
+ just_signaled = 0;
+
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+}
diff --git a/contrib/tcsh/tc.sig.c b/contrib/tcsh/tc.sig.c
new file mode 100644
index 0000000..f7feae8
--- /dev/null
+++ b/contrib/tcsh/tc.sig.c
@@ -0,0 +1,418 @@
+/* $Header: /src/pub/tcsh/tc.sig.c,v 3.24 1998/04/08 17:57:36 christos Exp $ */
+/*
+ * tc.sig.c: Signal routine emulations
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.sig.c,v 3.24 1998/04/08 17:57:36 christos Exp $")
+
+#include "tc.wait.h"
+
+#ifndef BSDSIGS
+
+/* this stack is used to queue signals
+ * we can handle up to MAX_CHLD outstanding children now;
+ */
+#define MAX_CHLD 50
+
+# ifdef UNRELSIGS
+static struct mysigstack {
+ int s_w; /* wait report */
+ int s_errno; /* errno returned; */
+ pid_t s_pid; /* pid returned */
+} stk[MAX_CHLD];
+static int stk_ptr = -1;
+
+
+/* queue child signals
+ */
+static sigret_t
+sig_ch_queue()
+{
+# ifdef JOBDEBUG
+ xprintf("queue SIGCHLD\n");
+ flush();
+# endif /* JOBDEBUG */
+ stk_ptr++;
+ stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w);
+ stk[stk_ptr].s_errno = errno;
+ (void) signal(SIGCHLD, sig_ch_queue);
+# ifndef SIGVOID
+ return(0);
+# endif /* SIGVOID */
+}
+
+/* process all awaiting child signals
+ */
+static sigret_t
+sig_ch_rel()
+{
+ while (stk_ptr > -1)
+ pchild(SIGCHLD);
+# ifdef JOBDEBUG
+ xprintf("signal(SIGCHLD, pchild);\n");
+# endif /* JOBDEBUG */
+ (void) signal(SIGCHLD, pchild);
+# ifndef SIGVOID
+ return(0);
+# endif /* SIGVOID */
+}
+
+
+/* libc.a contains these functions in SYSVREL >= 3. */
+sigret_t
+(*xsigset(a, b)) ()
+ int a;
+ signalfun_t b;
+{
+ return (signal(a, b));
+}
+
+/* release signal
+ * release all queued signals and
+ * set the default signal handler
+ */
+void
+sigrelse(what)
+ int what;
+{
+ if (what == SIGCHLD)
+ sig_ch_rel();
+
+# ifdef COHERENT
+ (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
+# endif /* COHERENT */
+}
+
+/* hold signal
+ * only works with child and interrupt
+ */
+void
+xsighold(what)
+ int what;
+{
+ if (what == SIGCHLD)
+ (void) signal(SIGCHLD, sig_ch_queue);
+
+# ifdef COHERENT
+ (void) signal(what, SIG_IGN);
+# endif /* COHERENT */
+}
+
+/* ignore signal
+ */
+void
+xsigignore(a)
+ int a;
+{
+ (void) signal(a, SIG_IGN);
+}
+
+/* atomically release one signal
+ */
+void
+xsigpause(what)
+ int what;
+{
+ /* From: Jim Mattson <mattson%cs@ucsd.edu> */
+ if (what == SIGCHLD)
+ pchild(SIGCHLD);
+}
+
+
+/* return either awaiting processes or do a wait now
+ */
+pid_t
+ourwait(w)
+ int *w;
+{
+ pid_t pid;
+
+# ifdef JOBDEBUG
+ xprintf(CGETS(25, 1, "our wait %d\n", stk_ptr));
+ flush();
+# endif /* JOBDEBUG */
+
+ if (stk_ptr == -1) {
+ /* stack empty return signal from stack */
+ pid = (pid_t) wait(w);
+# ifdef JOBDEBUG
+ xprintf("signal(SIGCHLD, pchild);\n");
+# endif /* JOBDEBUG */
+ (void) signal(SIGCHLD, pchild);
+ return (pid);
+ }
+ else {
+ /* return signal from stack */
+ errno = stk[stk_ptr].s_errno;
+ *w = stk[stk_ptr].s_w;
+ stk_ptr--;
+ return (stk[stk_ptr + 1].s_pid);
+ }
+} /* end ourwait */
+
+# ifdef COHERENT
+# undef signal
+sigret_t
+(*xsignal(a, b)) ()
+ int a;
+ signalfun_t b;
+{
+ if (a == SIGCHLD)
+ return SIG_DFL;
+ else
+ return (signal(a, b));
+}
+# endif /* COHERENT */
+
+# endif /* UNRELSIGS */
+
+# ifdef SXA
+/*
+ * SX/A is SYSVREL3 but does not have sys5-sigpause().
+ * I've heard that sigpause() is not defined in SYSVREL3.
+ */
+/* This is not need if you make tcsh by BSD option's cc. */
+void
+sigpause(what)
+{
+ if (what == SIGCHLD) {
+ (void) bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
+ }
+ else if (what == 0) {
+ pause();
+ }
+ else {
+ xprintf("sigpause(%d)\n", what);
+ pause();
+ }
+}
+# endif /* SXA */
+
+#endif /* !BSDSIGS */
+
+#ifdef NEEDsignal
+/* turn into bsd signals */
+sigret_t
+(*xsignal(s, a)) ()
+ int s;
+ signalfun_t a;
+{
+ sigvec_t osv, sv;
+
+ (void) mysigvec(s, NULL, &osv);
+ sv = osv;
+ sv.sv_handler = a;
+#ifdef SIG_STK
+ sv.sv_onstack = SIG_STK;
+#endif /* SIG_STK */
+#ifdef SV_BSDSIG
+ sv.sv_flags = SV_BSDSIG;
+#endif /* SV_BSDSIG */
+
+ if (mysigvec(s, &sv, NULL) < 0)
+ return (BADSIG);
+ return (osv.sv_handler);
+}
+
+#endif /* NEEDsignal */
+
+#ifdef POSIXSIGS
+/*
+ * Support for signals.
+ */
+
+extern int errno;
+
+/* Set and test a bit. Bits numbered 1 to 32 */
+
+#define SETBIT(x, y) x |= sigmask(y)
+#define ISSET(x, y) ((x & sigmask(y)) != 0)
+
+#ifdef DEBUG
+# define SHOW_SIGNALS 1 /* to assist in debugging signals */
+#endif /* DEBUG */
+
+#ifdef SHOW_SIGNALS
+char *show_sig_mask();
+#endif /* SHOW_SIGNALS */
+
+#ifndef __PARAGON__
+/*
+ * sigsetmask(mask)
+ *
+ * Set a new signal mask. Return old mask.
+ */
+sigmask_t
+sigsetmask(mask)
+ sigmask_t mask;
+{
+ sigset_t set, oset;
+ int m;
+ register int i;
+
+ (void) sigemptyset(&set);
+ (void) sigemptyset(&oset);
+
+ for (i = 1; i <= MAXSIG; i++)
+ if (ISSET(mask, i))
+ (void) sigaddset(&set, i);
+
+ if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1) {
+ xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
+ mask, errno);
+ }
+
+ m = 0;
+ for (i = 1; i <= MAXSIG; i++)
+ if (sigismember(&oset, i))
+ SETBIT(m, i);
+
+ return (m);
+}
+#endif /* __PARAGON__ */
+
+#ifndef __DGUX__
+/*
+ * sigblock(mask)
+ *
+ * Add "mask" set of signals to the present signal mask.
+ * Return old mask.
+ */
+sigmask_t
+sigblock(mask)
+ sigmask_t mask;
+{
+ sigset_t set, oset;
+ int m;
+ register int i;
+
+ (void) sigemptyset(&set);
+ (void) sigemptyset(&oset);
+
+ /* Get present set of signals. */
+ if ((sigprocmask(SIG_SETMASK, NULL, &set)) == -1)
+ stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
+
+ /* Add in signals from mask. */
+ for (i = 1; i <= MAXSIG; i++)
+ if (ISSET(mask, i))
+ (void) sigaddset(&set, i);
+
+ if ((sigprocmask(SIG_SETMASK, &set, &oset)) == -1)
+ stderror(ERR_SYSTEM, "sigprocmask", strerror(errno));
+
+ /* Return old mask to user. */
+ m = 0;
+ for (i = 1; i <= MAXSIG; i++)
+ if (sigismember(&oset, i))
+ SETBIT(m, i);
+
+ return (m);
+}
+#endif /* __DGUX__ */
+
+
+/*
+ * bsd_sigpause(mask)
+ *
+ * Set new signal mask and wait for signal;
+ * Old mask is restored on signal.
+ */
+void
+bsd_sigpause(mask)
+ sigmask_t mask;
+{
+ sigset_t set;
+ register int i;
+
+ (void) sigemptyset(&set);
+
+ for (i = 1; i <= MAXSIG; i++)
+ if (ISSET(mask, i))
+ (void) sigaddset(&set, i);
+ (void) sigsuspend(&set);
+}
+
+/*
+ * bsd_signal(sig, func)
+ *
+ * Emulate bsd style signal()
+ */
+sigret_t (*bsd_signal(sig, func)) ()
+ int sig;
+ signalfun_t func;
+{
+ struct sigaction act, oact;
+ sigset_t set;
+ signalfun_t r_func;
+
+ if (sig < 0 || sig > MAXSIG) {
+ xprintf(CGETS(25, 2,
+ "error: bsd_signal(%d) signal out of range\n"), sig);
+ return((signalfun_t) SIG_IGN);
+ }
+
+ (void) sigemptyset(&set);
+
+ act.sa_handler = (signalfun_t) func; /* user function */
+ act.sa_mask = set; /* signal mask */
+ act.sa_flags = 0; /* no special actions */
+
+ if (sigaction(sig, &act, &oact)) {
+ xprintf(CGETS(25, 3,
+ "error: bsd_signal(%d) - sigaction failed, errno %d\n"),
+ sig, errno);
+ return((signalfun_t) SIG_IGN);
+ }
+
+ r_func = (signalfun_t) oact.sa_handler;
+ return(r_func);
+}
+#endif /* POSIXSIG */
+
+
+#ifdef SIGSYNCH
+static long Synch_Cnt = 0;
+
+sigret_t
+synch_handler(sno)
+int sno;
+{
+ if (sno != SIGSYNCH)
+ abort();
+ Synch_Cnt++;
+}
+#endif /* SIGSYNCH */
diff --git a/contrib/tcsh/tc.sig.h b/contrib/tcsh/tc.sig.h
new file mode 100644
index 0000000..b413850
--- /dev/null
+++ b/contrib/tcsh/tc.sig.h
@@ -0,0 +1,226 @@
+/* $Header: /src/pub/tcsh/tc.sig.h,v 3.20 1998/04/08 17:57:37 christos Exp $ */
+/*
+ * tc.sig.h: Signal handling
+ *
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tc_sig
+#define _h_tc_sig
+
+#if (SYSVREL > 0) || defined(BSD4_4) || defined(_MINIX) || defined(DGUX) || defined(WINNT)
+# include <signal.h>
+# ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+# endif /* SIGCHLD */
+#else /* SYSVREL == 0 */
+# include <sys/signal.h>
+#endif /* SYSVREL > 0 */
+
+#if defined(SUNOS4) || defined(DGUX) || defined(hp800) || (SYSVREL > 3 && defined(POSIXSIGS) && defined(VFORK))
+# define SAVESIGVEC
+#endif /* SUNOS4 || DGUX || hp800 || SVR4 & POSIXSIGS & VFORK */
+
+#if (SYSVREL > 0 && SYSVREL < 3 && !defined(BSDSIGS)) || defined(_MINIX) || defined(COHERENT)
+/*
+ * If we have unreliable signals...
+ */
+# define UNRELSIGS
+#endif /* SYSVREL > 0 && SYSVREL < 3 && !BSDSIGS || _MINIX || COHERENT */
+
+#ifdef BSDSIGS
+/*
+ * sigvec is not the same everywhere
+ */
+# if defined(_SEQUENT_) || (defined(_POSIX_SOURCE) && !defined(hpux))
+# define HAVE_SIGVEC
+# define mysigvec(a, b, c) sigaction(a, b, c)
+typedef struct sigaction sigvec_t;
+# if defined(convex) || defined(__convex__)
+ /* eliminate compiler warnings since these are defined in signal.h */
+# undef sv_handler
+# undef sv_flags
+# endif
+# define sv_handler sa_handler
+# define sv_flags sa_flags
+# endif /* _SEQUENT || (_POSIX_SOURCE && !hpux) */
+
+# ifdef hpux
+# define HAVE_SIGVEC
+# define mysigvec(a, b, c) sigvector(a, b, c)
+typedef struct sigvec sigvec_t;
+# define NEEDsignal
+# endif /* hpux */
+
+# ifndef HAVE_SIGVEC
+# ifdef POSIXSIGS
+# define mysigvec(a, b, c) sigaction(a, b, c)
+typedef struct sigaction sigvec_t;
+# define sv_handler sa_handler
+# define sv_flags sa_flags
+# else /* BSDSIGS */
+# define mysigvec(a, b, c) sigvec(a, b, c)
+typedef struct sigvec sigvec_t;
+# endif /* POSIXSIGS */
+# endif /* HAVE_SIGVEC */
+
+# undef HAVE_SIGVEC
+#endif /* BSDSIGS */
+
+#if SYSVREL > 0
+# ifdef BSDJOBS
+/* here I assume that systems that have bsdjobs implement the
+ * the setpgrp call correctly. Otherwise defining this would
+ * work, but it would kill the world, because all the setpgrp
+ * code is the the part defined when BSDJOBS are defined
+ * NOTE: we don't want killpg(a, b) == kill(-getpgrp(a), b)
+ * cause process a might be already dead and getpgrp would fail
+ */
+# define killpg(a, b) kill(-(a), (b))
+# else
+/* this is the poor man's version of killpg()! Just kill the
+ * current process and don't worry about the rest. Someday
+ * I hope I get to fix that.
+ */
+# define killpg(a, b) kill((a), (b))
+# endif /* BSDJOBS */
+#endif /* SYSVREL > 0 */
+
+#ifdef _MINIX
+# include <signal.h>
+# define killpg(a, b) kill((a), (b))
+#endif /* _MINIX */
+
+#ifdef _VMS_POSIX
+# define killpg(a, b) kill(-(a), (b))
+#endif /* atp _VMS_POSIX */
+
+#if !defined(NSIG) && defined(SIGMAX)
+# define NSIG (SIGMAX+1)
+#endif /* !NSIG && SIGMAX */
+#if !defined(NSIG) && defined(_SIG_MAX)
+# define NSIG (_SIG_MAX+1)
+#endif /* !NSIG && _SIG_MAX */
+#if !defined(NSIG) && defined(_NSIG)
+# define NSIG _NSIG
+#endif /* !NSIG && _NSIG */
+#if !defined(MAXSIG) && defined(NSIG)
+# define MAXSIG NSIG
+#endif /* !MAXSIG && NSIG */
+
+#ifdef BSDSIGS
+/*
+ * For 4.2bsd signals.
+ */
+# ifdef sigmask
+# undef sigmask
+# endif /* sigmask */
+# define sigmask(s) (1 << ((s)-1))
+# ifdef POSIXSIGS
+# define sigpause(a) (void) bsd_sigpause(a)
+# ifdef WINNT
+# undef signal
+# endif /* WINNT */
+# define signal(a, b) bsd_signal(a, b)
+# endif /* POSIXSIGS */
+# ifndef _SEQUENT_
+# define sighold(s) sigblock(sigmask(s))
+# define sigignore(s) signal(s, SIG_IGN)
+# define sigset(s, a) signal(s, a)
+# endif /* !_SEQUENT_ */
+# ifdef aiws
+# define sigrelse(a) sigsetmask(sigblock(0) & ~sigmask(a))
+# undef killpg
+# define killpg(a, b) kill(-getpgrp(a), b)
+# define NEEDsignal
+# endif /* aiws */
+#endif /* BSDSIGS */
+
+
+/*
+ * We choose a define for the window signal if it exists..
+ */
+#ifdef SIGWINCH
+# define SIG_WINDOW SIGWINCH
+#else
+# ifdef SIGWINDOW
+# define SIG_WINDOW SIGWINDOW
+# endif /* SIGWINDOW */
+#endif /* SIGWINCH */
+
+#ifdef convex
+# ifdef notdef
+/* Does not seem to work right... Christos */
+# define SIGSYNCH 0
+# endif
+# ifdef SIGSYNCH
+# define SYNCHMASK (sigmask(SIGCHLD)|sigmask(SIGSYNCH))
+# else
+# define SYNCHMASK (sigmask(SIGCHLD))
+# endif
+extern sigret_t synch_handler();
+#endif /* convex */
+
+#ifdef SAVESIGVEC
+# define NSIGSAVED 7
+ /*
+ * These are not inline for speed. gcc -traditional -O on the sparc ignores
+ * the fact that vfork() corrupts the registers. Calling a routine is not
+ * nice, since it can make the compiler put some things that we want saved
+ * into registers - christos
+ */
+# define savesigvec(sv) \
+ ((void) mysigvec(SIGINT, (sigvec_t *) 0, &(sv)[0]), \
+ (void) mysigvec(SIGQUIT, (sigvec_t *) 0, &(sv)[1]), \
+ (void) mysigvec(SIGTSTP, (sigvec_t *) 0, &(sv)[2]), \
+ (void) mysigvec(SIGTTIN, (sigvec_t *) 0, &(sv)[3]), \
+ (void) mysigvec(SIGTTOU, (sigvec_t *) 0, &(sv)[4]), \
+ (void) mysigvec(SIGTERM, (sigvec_t *) 0, &(sv)[5]), \
+ (void) mysigvec(SIGHUP, (sigvec_t *) 0, &(sv)[6]), \
+ sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | \
+ sigmask(SIGTSTP) | sigmask(SIGTTIN) | \
+ sigmask(SIGTTOU) | sigmask(SIGTERM) | \
+ sigmask(SIGHUP)))
+
+# define restoresigvec(sv, sm) \
+ (void) ((void) mysigvec(SIGINT, &(sv)[0], (sigvec_t *) 0), \
+ (void) mysigvec(SIGQUIT, &(sv)[1], (sigvec_t *) 0), \
+ (void) mysigvec(SIGTSTP, &(sv)[2], (sigvec_t *) 0), \
+ (void) mysigvec(SIGTTIN, &(sv)[3], (sigvec_t *) 0), \
+ (void) mysigvec(SIGTTOU, &(sv)[4], (sigvec_t *) 0), \
+ (void) mysigvec(SIGTERM, &(sv)[5], (sigvec_t *) 0), \
+ (void) mysigvec(SIGHUP, &(sv)[6], (sigvec_t *) 0), \
+ (void) sigsetmask(sm))
+# endif /* SAVESIGVEC */
+
+#endif /* _h_tc_sig */
diff --git a/contrib/tcsh/tc.str.c b/contrib/tcsh/tc.str.c
new file mode 100644
index 0000000..5f58ef9
--- /dev/null
+++ b/contrib/tcsh/tc.str.c
@@ -0,0 +1,427 @@
+/* $Header: /src/pub/tcsh/tc.str.c,v 3.9 1996/04/26 19:21:42 christos Exp $ */
+/*
+ * tc.str.c: Short string package
+ * This has been a lesson of how to write buggy code!
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.str.c,v 3.9 1996/04/26 19:21:42 christos Exp $")
+
+#define MALLOC_INCR 128
+
+#ifdef SHORT_STRINGS
+Char **
+blk2short(src)
+ register char **src;
+{
+ size_t n;
+ register Char **sdst, **dst;
+
+ /*
+ * Count
+ */
+ for (n = 0; src[n] != NULL; n++)
+ continue;
+ sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *)));
+
+ for (; *src != NULL; src++)
+ *dst++ = SAVE(*src);
+ *dst = NULL;
+ return (sdst);
+}
+
+char **
+short2blk(src)
+ register Char **src;
+{
+ size_t n;
+ register char **sdst, **dst;
+
+ /*
+ * Count
+ */
+ for (n = 0; src[n] != NULL; n++)
+ continue;
+ sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *)));
+
+ for (; *src != NULL; src++)
+ *dst++ = strsave(short2str(*src));
+ *dst = NULL;
+ return (sdst);
+}
+
+Char *
+str2short(src)
+ register const char *src;
+{
+ static Char *sdst;
+ static size_t dstsize = 0;
+ register Char *dst, *edst;
+
+ if (src == NULL)
+ return (NULL);
+
+ if (sdst == (NULL)) {
+ dstsize = MALLOC_INCR;
+ sdst = (Char *) xmalloc((size_t) (dstsize * sizeof(Char)));
+ }
+
+ dst = sdst;
+ edst = &dst[dstsize];
+ while ((unsigned char) *src) {
+ *dst++ = (Char) ((unsigned char) *src++);
+ if (dst == edst) {
+ dstsize += MALLOC_INCR;
+ sdst = (Char *) xrealloc((ptr_t) sdst,
+ (size_t) (dstsize * sizeof(Char)));
+ edst = &sdst[dstsize];
+ dst = &edst[-MALLOC_INCR];
+ }
+ }
+ *dst = 0;
+ return (sdst);
+}
+
+char *
+short2str(src)
+ register const Char *src;
+{
+ static char *sdst = NULL;
+ static size_t dstsize = 0;
+ register char *dst, *edst;
+
+ if (src == NULL)
+ return (NULL);
+
+ if (sdst == NULL) {
+ dstsize = MALLOC_INCR;
+ sdst = (char *) xmalloc((size_t) (dstsize * sizeof(char)));
+ }
+ dst = sdst;
+ edst = &dst[dstsize];
+ while (*src) {
+ *dst++ = (char) *src++;
+ if (dst == edst) {
+ dstsize += MALLOC_INCR;
+ sdst = (char *) xrealloc((ptr_t) sdst,
+ (size_t) (dstsize * sizeof(char)));
+ edst = &sdst[dstsize];
+ dst = &edst[-MALLOC_INCR];
+ }
+ }
+ *dst = 0;
+ return (sdst);
+}
+
+Char *
+s_strcpy(dst, src)
+ register Char *dst;
+ register const Char *src;
+{
+ register Char *sdst;
+
+ sdst = dst;
+ while ((*dst++ = *src++) != '\0')
+ continue;
+ return (sdst);
+}
+
+Char *
+s_strncpy(dst, src, n)
+ register Char *dst;
+ register const Char *src;
+ register size_t n;
+{
+ register Char *sdst;
+
+ if (n == 0)
+ return(dst);
+
+ sdst = dst;
+ do
+ if ((*dst++ = *src++) == '\0') {
+ while (--n != 0)
+ *dst++ = '\0';
+ return(sdst);
+ }
+ while (--n != 0);
+ return (sdst);
+}
+
+Char *
+s_strcat(dst, src)
+ register Char *dst;
+ register const Char *src;
+{
+ register short *sdst;
+
+ sdst = dst;
+ while (*dst++)
+ continue;
+ --dst;
+ while ((*dst++ = *src++) != '\0')
+ continue;
+ return (sdst);
+}
+
+#ifdef NOTUSED
+Char *
+s_strncat(dst, src, n)
+ register Char *dst;
+ register const Char *src;
+ register size_t n;
+{
+ register Char *sdst;
+
+ if (n == 0)
+ return (dst);
+
+ sdst = dst;
+
+ while (*dst++)
+ continue;
+ --dst;
+
+ do
+ if ((*dst++ = *src++) == '\0')
+ return(sdst);
+ while (--n != 0)
+ continue;
+
+ *dst = '\0';
+ return (sdst);
+}
+
+#endif
+
+Char *
+s_strchr(str, ch)
+ register const Char *str;
+ int ch;
+{
+ do
+ if (*str == ch)
+ return ((Char *) str);
+ while (*str++);
+ return (NULL);
+}
+
+Char *
+s_strrchr(str, ch)
+ register const Char *str;
+ int ch;
+{
+ register const Char *rstr;
+
+ rstr = NULL;
+ do
+ if (*str == ch)
+ rstr = str;
+ while (*str++);
+ return ((Char *) rstr);
+}
+
+size_t
+s_strlen(str)
+ register const Char *str;
+{
+ register size_t n;
+
+ for (n = 0; *str++; n++)
+ continue;
+ return (n);
+}
+
+int
+s_strcmp(str1, str2)
+ register const Char *str1, *str2;
+{
+ for (; *str1 && *str1 == *str2; str1++, str2++)
+ continue;
+ /*
+ * The following case analysis is necessary so that characters which look
+ * negative collate low against normal characters but high against the
+ * end-of-string NUL.
+ */
+ if (*str1 == '\0' && *str2 == '\0')
+ return (0);
+ else if (*str1 == '\0')
+ return (-1);
+ else if (*str2 == '\0')
+ return (1);
+ else
+ return (*str1 - *str2);
+}
+
+int
+s_strncmp(str1, str2, n)
+ register const Char *str1, *str2;
+ register size_t n;
+{
+ if (n == 0)
+ return (0);
+ do {
+ if (*str1 != *str2) {
+ /*
+ * The following case analysis is necessary so that characters
+ * which look negative collate low against normal characters
+ * but high against the end-of-string NUL.
+ */
+ if (*str1 == '\0')
+ return (-1);
+ else if (*str2 == '\0')
+ return (1);
+ else
+ return (*str1 - *str2);
+ }
+ if (*str1 == '\0')
+ return(0);
+ str1++, str2++;
+ } while (--n != 0);
+ return(0);
+}
+
+Char *
+s_strsave(s)
+ register const Char *s;
+{
+ Char *n;
+ register Char *p;
+
+ if (s == 0)
+ s = STRNULL;
+ for (p = (Char *) s; *p++;)
+ continue;
+ n = p = (Char *) xmalloc((size_t)
+ ((((const Char *) p) - s) * sizeof(Char)));
+ while ((*p++ = *s++) != '\0')
+ continue;
+ return (n);
+}
+
+Char *
+s_strspl(cp, dp)
+ const Char *cp, *dp;
+{
+ Char *ep;
+ register Char *p, *q;
+
+ if (!cp)
+ cp = STRNULL;
+ if (!dp)
+ dp = STRNULL;
+ for (p = (Char *) cp; *p++;)
+ continue;
+ for (q = (Char *) dp; *q++;)
+ continue;
+ ep = (Char *) xmalloc((size_t)
+ (((((const Char *) p) - cp) +
+ (((const Char *) q) - dp) - 1) * sizeof(Char)));
+ for (p = ep, q = (Char*) cp; (*p++ = *q++) != '\0';)
+ continue;
+ for (p--, q = (Char *) dp; (*p++ = *q++) != '\0';)
+ continue;
+ return (ep);
+}
+
+Char *
+s_strend(cp)
+ register const Char *cp;
+{
+ if (!cp)
+ return ((Char *) cp);
+ while (*cp)
+ cp++;
+ return ((Char *) cp);
+}
+
+Char *
+s_strstr(s, t)
+ register const Char *s, *t;
+{
+ do {
+ register const Char *ss = s;
+ register const Char *tt = t;
+
+ do
+ if (*tt == '\0')
+ return ((Char *) s);
+ while (*ss++ == *tt++);
+ } while (*s++ != '\0');
+ return (NULL);
+}
+
+#endif /* SHORT_STRINGS */
+
+char *
+short2qstr(src)
+ register const Char *src;
+{
+ static char *sdst = NULL;
+ static size_t dstsize = 0;
+ register char *dst, *edst;
+
+ if (src == NULL)
+ return (NULL);
+
+ if (sdst == NULL) {
+ dstsize = MALLOC_INCR;
+ sdst = (char *) xmalloc((size_t) (dstsize * sizeof(char)));
+ }
+ dst = sdst;
+ edst = &dst[dstsize];
+ while (*src) {
+ if (*src & QUOTE) {
+ *dst++ = '\\';
+ if (dst == edst) {
+ dstsize += MALLOC_INCR;
+ sdst = (char *) xrealloc((ptr_t) sdst,
+ (size_t) (dstsize * sizeof(char)));
+ edst = &sdst[dstsize];
+ dst = &edst[-MALLOC_INCR];
+ }
+ }
+ *dst++ = (char) *src++;
+ if (dst == edst) {
+ dstsize += MALLOC_INCR;
+ sdst = (char *) xrealloc((ptr_t) sdst,
+ (size_t) (dstsize * sizeof(char)));
+ edst = &sdst[dstsize];
+ dst = &edst[-MALLOC_INCR];
+ }
+ }
+ *dst = 0;
+ return (sdst);
+}
diff --git a/contrib/tcsh/tc.vers.c b/contrib/tcsh/tc.vers.c
new file mode 100644
index 0000000..f319b8e
--- /dev/null
+++ b/contrib/tcsh/tc.vers.c
@@ -0,0 +1,169 @@
+/* $Header: /src/pub/tcsh/tc.vers.c,v 3.46 1999/05/11 13:07:54 christos Exp $ */
+/*
+ * tc.vers.c: Version dependent stuff
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+#include "tw.h"
+
+RCSID("$Id: tc.vers.c,v 3.46 1999/05/11 13:07:54 christos Exp $")
+
+#include "patchlevel.h"
+
+
+/* fix_version():
+ * Print a reasonable version string, printing all compile time
+ * options that might affect the user.
+ */
+void
+fix_version()
+{
+#ifdef SHORT_STRINGS
+# define SSSTR "8b"
+#else
+# define SSSTR "7b"
+#endif
+#ifdef NLS
+# define NLSSTR ",nls"
+#else
+# define NLSSTR ""
+#endif
+#ifdef LOGINFIRST
+# define LFSTR ",lf"
+#else
+# define LFSTR ""
+#endif
+#ifdef DOTLAST
+# define DLSTR ",dl"
+#else
+# define DLSTR ""
+#endif
+#ifdef VIDEFAULT
+# define VISTR ",vi"
+#else
+# define VISTR ""
+#endif
+#ifdef TESLA
+# define DTRSTR ",dtr"
+#else
+# define DTRSTR ""
+#endif
+#ifdef KAI
+# define BYESTR ",bye"
+#else
+# define BYESTR ""
+#endif
+#ifdef AUTOLOGOUT
+# define ALSTR ",al"
+#else
+# define ALSTR ""
+#endif
+#ifdef KANJI
+# define KANSTR ",kan"
+#else
+# define KANSTR ""
+#endif
+#ifdef SYSMALLOC
+# define SMSTR ",sm"
+#else
+# define SMSTR ""
+#endif
+#ifdef HASHBANG
+# define HBSTR ",hb"
+#else
+# define HBSTR ""
+#endif
+#ifdef NEWGRP
+# define NGSTR ",ng"
+#else
+# define NGSTR ""
+#endif
+#ifdef REMOTEHOST
+# define RHSTR ",rh"
+#else
+# define RHSTR ""
+#endif
+#ifdef AFS
+# define AFSSTR ",afs"
+#else
+# define AFSSTR ""
+#endif
+#ifdef NODOT
+# define NDSTR ",nd"
+#else
+# define NDSTR ""
+#endif
+#ifdef COLOR_LS_F
+# define COLORSTR ",color"
+#else /* ifndef COLOR_LS_F */
+# define COLORSTR ""
+#endif /* COLOR_LS_F */
+#ifdef DSPMBYTE
+# define DSPMSTR ",dspm"
+#else
+# define DSPMSTR ""
+#endif
+#ifdef COLORCAT
+# define CCATSTR ",ccat"
+#else
+# define CCATSTR ""
+#endif
+/* if you want your local version to say something */
+#ifndef LOCALSTR
+# define LOCALSTR ""
+#endif /* LOCALSTR */
+ char version[BUFSIZE];
+ Char *machtype = tgetenv(STRMACHTYPE);
+ Char *vendor = tgetenv(STRVENDOR);
+ Char *ostype = tgetenv(STROSTYPE);
+
+ if (vendor == NULL)
+ vendor = STRunknown;
+ if (machtype == NULL)
+ machtype = STRunknown;
+ if (ostype == NULL)
+ ostype = STRunknown;
+
+
+ (void) xsnprintf(version, sizeof(version),
+"tcsh %d.%.2d.%.2d (%s) %s (%S-%S-%S) options %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ REV, VERS, PATCHLEVEL, ORIGIN, DATE, machtype, vendor, ostype,
+ SSSTR, NLSSTR, LFSTR, DLSTR, VISTR, DTRSTR, BYESTR,
+ ALSTR, KANSTR, SMSTR, HBSTR, NGSTR, RHSTR, AFSSTR, NDSTR,
+ COLORSTR, DSPMSTR, CCATSTR, LOCALSTR);
+ set(STRversion, SAVE(version), VAR_READWRITE);
+ (void) xsnprintf(version, sizeof(version), "%d.%.2d.%.2d",
+ REV, VERS, PATCHLEVEL);
+ set(STRtcsh, SAVE(version), VAR_READWRITE);
+}
diff --git a/contrib/tcsh/tc.wait.h b/contrib/tcsh/tc.wait.h
new file mode 100644
index 0000000..df93c06
--- /dev/null
+++ b/contrib/tcsh/tc.wait.h
@@ -0,0 +1,159 @@
+/* $Header: /src/pub/tcsh/tc.wait.h,v 3.10 1997/10/27 22:44:39 christos Exp $ */
+/*
+ * tc.wait.h: <sys/wait.h> for machines that don't have it or have it and
+ * is incorrect.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tc_wait
+#define _h_tc_wait
+
+/*
+ * a little complicated #include <sys/wait.h>! :-(
+ * We try to use the system's wait.h when we can...
+ */
+
+#if SYSVREL > 0 && !defined(linux)
+# ifdef hpux
+# ifndef __hpux
+# define NEEDwait
+# else
+# ifndef POSIX
+# define _BSD
+# endif
+# ifndef _CLASSIC_POSIX_TYPES
+# define _CLASSIC_POSIX_TYPES
+# endif
+# include <sys/wait.h> /* 7.0 fixed it again */
+# endif /* __hpux */
+# else /* hpux */
+# if (defined(OREO) || defined(IRIS4D) || defined(POSIX)) && !defined(_VMS_POSIX)
+# include <sys/wait.h>
+# else /* OREO || IRIS4D || POSIX */
+# define NEEDwait
+# endif /* OREO || IRIS4D || POSIX */
+# endif /* hpux */
+#else /* SYSVREL == 0 || linux */
+# ifdef _MINIX
+# undef NEEDwait
+# include "mi.wait.h"
+# else
+# ifndef WINNT
+# include <sys/wait.h>
+# endif /* WINNT */
+# endif /* _MINIX */
+#endif /* SYSVREL == 0 || linux */
+
+#ifdef NEEDwait
+/*
+ * This wait is for big-endians and little endians
+ */
+union wait {
+ int w_status;
+# ifdef _SEQUENT_
+ struct {
+ unsigned short w_Termsig:7;
+ unsigned short w_Coredump:1;
+ unsigned short w_Retcode:8;
+ } w_T;
+ struct {
+ unsigned short w_Stopval:8;
+ unsigned short w_Stopsig:8;
+ } w_S;
+};
+
+# define w_termsig w_T.w_Termsig
+# define w_coredump w_T.w_Coredump
+# define w_retcode w_T.w_Retcode
+# define w_stopval w_S.w_Stopval
+# define w_stopsig w_S.w_Stopsig
+# else /* _SEQUENT_ */
+# if defined(vax) || defined(i386) || defined(_I386)
+ union {
+ struct {
+ unsigned int w_Termsig:7;
+ unsigned int w_Coredump:1;
+ unsigned int w_Retcode:8;
+ unsigned int w_Dummy:16;
+ } w_T;
+ struct {
+ unsigned int w_Stopval:8;
+ unsigned int w_Stopsig:8;
+ unsigned int w_Dummy:16;
+ } w_S;
+ } w_P;
+# else /* mc68000 || sparc || ??? */
+# if defined(_CRAY) || defined(ANY_OTHER_64BIT_MACHINE)
+# define DUMMY_BITS 48
+# else /* _CRAY */
+# define DUMMY_BITS 16
+# endif /* _CRAY */
+ union {
+ struct {
+ unsigned int w_Dummy:DUMMY_BITS;
+ unsigned int w_Retcode:8;
+ unsigned int w_Coredump:1;
+ unsigned int w_Termsig:7;
+ } w_T;
+ struct {
+ unsigned int w_Dummy:DUMMY_BITS;
+ unsigned int w_Stopsig:8;
+ unsigned int w_Stopval:8;
+ } w_S;
+ } w_P;
+# endif /* vax || i386 || _I386 */
+};
+
+# define w_termsig w_P.w_T.w_Termsig
+# define w_coredump w_P.w_T.w_Coredump
+# define w_retcode w_P.w_T.w_Retcode
+# define w_stopval w_P.w_S.w_Stopval
+# define w_stopsig w_P.w_S.w_Stopsig
+# endif /* _SEQUENT_ */
+
+
+# ifndef WNOHANG
+# define WNOHANG 1 /* dont hang in wait */
+# endif
+
+# ifndef WUNTRACED
+# define WUNTRACED 2 /* tell about stopped, untraced children */
+# endif
+
+# define WSTOPPED 0177
+# define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED)
+# define WIFSIGNALED(x) (((x).w_stopval != WSTOPPED) && ((x).w_termsig != 0))
+
+#endif /* NEEDwait */
+
+#endif /* _h_tc_wait */
diff --git a/contrib/tcsh/tc.who.c b/contrib/tcsh/tc.who.c
new file mode 100644
index 0000000..fe80702
--- /dev/null
+++ b/contrib/tcsh/tc.who.c
@@ -0,0 +1,679 @@
+/* $Header: /src/pub/tcsh/tc.who.c,v 3.28 1998/04/08 13:59:13 christos Exp $ */
+/*
+ * tc.who.c: Watch logins and logouts...
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tc.who.c,v 3.28 1998/04/08 13:59:13 christos Exp $")
+
+#include "tc.h"
+
+#ifndef HAVENOUTMP
+/*
+ * kfk 26 Jan 1984 - for login watch functions.
+ */
+#include <ctype.h>
+
+#ifdef HAVEUTMPX
+# include <utmpx.h>
+/* I just redefine a few words here. Changing every occurrence below
+ * seems like too much of work. All UTMP functions have equivalent
+ * UTMPX counterparts, so they can be added all here when needed.
+ * Kimmo Suominen, Oct 14 1991
+ */
+# ifndef _PATH_UTMP
+# define _PATH_UTMP UTMPX_FILE
+# endif /* _PATH_UTMP */
+# define utmp utmpx
+# define ut_time ut_xtime
+#else /* !HAVEUTMPX */
+# ifndef WINNT
+# include <utmp.h>
+# endif /* WINNT */
+#endif /* HAVEUTMPX */
+
+#ifndef BROKEN_CC
+# define UTNAMLEN sizeof(((struct utmp *) 0)->ut_name)
+# define UTLINLEN sizeof(((struct utmp *) 0)->ut_line)
+# ifdef UTHOST
+# ifdef _SEQUENT_
+# define UTHOSTLEN 100
+# else
+# define UTHOSTLEN sizeof(((struct utmp *) 0)->ut_host)
+# endif
+# endif /* UTHOST */
+#else
+/* give poor cc a little help if it needs it */
+struct utmp __ut;
+
+# define UTNAMLEN sizeof(__ut.ut_name)
+# define UTLINLEN sizeof(__ut.ut_line)
+# ifdef UTHOST
+# ifdef _SEQUENT_
+# define UTHOSTLEN 100
+# else
+# define UTHOSTLEN sizeof(__ut.ut_host)
+# endif
+# endif /* UTHOST */
+#endif /* BROKEN_CC */
+
+#ifndef _PATH_UTMP
+# ifdef UTMP_FILE
+# define _PATH_UTMP UTMP_FILE
+# else
+# define _PATH_UTMP "/etc/utmp"
+# endif /* UTMP_FILE */
+#endif /* _PATH_UTMP */
+
+
+struct who {
+ struct who *who_next;
+ struct who *who_prev;
+ char who_name[UTNAMLEN + 1];
+ char who_new[UTNAMLEN + 1];
+ char who_tty[UTLINLEN + 1];
+#ifdef UTHOST
+ char who_host[UTHOSTLEN + 1];
+#endif /* UTHOST */
+ time_t who_time;
+ int who_status;
+};
+
+static struct who whohead, whotail;
+static time_t watch_period = 0;
+static time_t stlast = 0;
+#ifdef WHODEBUG
+static void debugwholist __P((struct who *, struct who *));
+#endif
+static void print_who __P((struct who *));
+
+
+#define ONLINE 01
+#define OFFLINE 02
+#define CHANGED 04
+#define STMASK 07
+#define ANNOUNCE 010
+
+/*
+ * Karl Kleinpaste, 26 Jan 1984.
+ * Initialize the dummy tty list for login watch.
+ * This dummy list eliminates boundary conditions
+ * when doing pointer-chase searches.
+ */
+void
+initwatch()
+{
+ whohead.who_next = &whotail;
+ whotail.who_prev = &whohead;
+ stlast = 1;
+#ifdef WHODEBUG
+ debugwholist(NULL, NULL);
+#endif /* WHODEBUG */
+}
+
+void
+resetwatch()
+{
+ watch_period = 0;
+ stlast = 0;
+}
+
+/*
+ * Karl Kleinpaste, 26 Jan 1984.
+ * Watch /etc/utmp for login/logout changes.
+ */
+void
+watch_login(force)
+ int force;
+{
+ int utmpfd, comp = -1, alldone;
+ int firsttime = stlast == 1;
+#ifdef BSDSIGS
+ sigmask_t omask;
+#endif /* BSDSIGS */
+ struct utmp utmp;
+ struct who *wp, *wpnew;
+ struct varent *v;
+ Char **vp = NULL;
+ time_t t, interval = MAILINTVL;
+ struct stat sta;
+#if defined(UTHOST) && defined(_SEQUENT_)
+ char *host, *ut_find_host();
+#endif
+#ifdef WINNT
+ static int ncbs_posted = 0;
+ USE(utmp);
+ USE(utmpfd);
+ USE(sta);
+ USE(wpnew);
+#endif /* WINNT */
+
+ /* stop SIGINT, lest our login list get trashed. */
+#ifdef BSDSIGS
+ omask = sigblock(sigmask(SIGINT));
+#else
+ (void) sighold(SIGINT);
+#endif
+
+ v = adrof(STRwatch);
+ if (v == NULL && !force) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ return; /* no names to watch */
+ }
+ if (!force) {
+ trim(vp = v->vec);
+ if (blklen(vp) % 2) /* odd # args: 1st == # minutes. */
+ interval = (number(*vp)) ? (getn(*vp++) * 60) : MAILINTVL;
+ }
+ else
+ interval = 0;
+
+ (void) time(&t);
+#ifdef WINNT
+ /*
+ * Since NCB_ASTATs take time, start em async at least 90 secs
+ * before we are due -amol 6/5/97
+ */
+ if (!ncbs_posted) {
+ unsigned long tdiff = t - watch_period;
+ if (!watch_period || ((tdiff > 0) && (tdiff > (interval - 90)))) {
+ start_ncbs(vp);
+ ncbs_posted = 1;
+ }
+ }
+#endif /* WINNT */
+ if (t - watch_period < interval) {
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+ return; /* not long enough yet... */
+ }
+ watch_period = t;
+#ifdef WINNT
+ ncbs_posted = 0;
+#else /* !WINNT */
+
+ /*
+ * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
+ * Don't open utmp all the time, stat it first...
+ */
+ if (stat(_PATH_UTMP, &sta)) {
+ xprintf(CGETS(26, 1, "cannot stat %s. Please \"unset watch\".\n"),
+ _PATH_UTMP);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+ if (stlast == sta.st_mtime) {
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+ stlast = sta.st_mtime;
+ if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
+ xprintf(CGETS(26, 2, "%s cannot be opened. Please \"unset watch\".\n"),
+ _PATH_UTMP);
+# ifdef BSDSIGS
+ (void) sigsetmask(omask);
+# else
+ (void) sigrelse(SIGINT);
+# endif
+ return;
+ }
+
+ /*
+ * xterm clears the entire utmp entry - mark everyone on the status list
+ * OFFLINE or we won't notice X "logouts"
+ */
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ wp->who_status = OFFLINE;
+ wp->who_time = 0;
+ }
+
+ /*
+ * Read in the utmp file, sort the entries, and update existing entries or
+ * add new entries to the status list.
+ */
+ while (read(utmpfd, (char *) &utmp, sizeof utmp) == sizeof utmp) {
+
+# ifdef DEAD_PROCESS
+# ifndef IRIS4D
+ if (utmp.ut_type != USER_PROCESS)
+ continue;
+# else
+ /* Why is that? Cause the utmp file is always corrupted??? */
+ if (utmp.ut_type != USER_PROCESS && utmp.ut_type != DEAD_PROCESS)
+ continue;
+# endif /* IRIS4D */
+# endif /* DEAD_PROCESS */
+
+ if (utmp.ut_name[0] == '\0' && utmp.ut_line[0] == '\0')
+ continue; /* completely void entry */
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS && utmp.ut_line[0] == '\0')
+ continue;
+# endif /* DEAD_PROCESS */
+ wp = whohead.who_next;
+ while (wp->who_next && (comp = strncmp(wp->who_tty, utmp.ut_line, UTLINLEN)) < 0)
+ wp = wp->who_next;/* find that tty! */
+
+ if (wp->who_next && comp == 0) { /* found the tty... */
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS) {
+ wp->who_time = utmp.ut_time;
+ wp->who_status = OFFLINE;
+ }
+ else
+# endif /* DEAD_PROCESS */
+ if (utmp.ut_name[0] == '\0') {
+ wp->who_time = utmp.ut_time;
+ wp->who_status = OFFLINE;
+ }
+ else if (strncmp(utmp.ut_name, wp->who_name, UTNAMLEN) == 0) {
+ /* someone is logged in */
+ wp->who_time = utmp.ut_time;
+ wp->who_status = 0; /* same guy */
+ }
+ else {
+ (void) strncpy(wp->who_new, utmp.ut_name, UTNAMLEN);
+# ifdef UTHOST
+# ifdef _SEQUENT_
+ host = ut_find_host(wp->who_tty);
+ if (host)
+ (void) strncpy(wp->who_host, host, UTHOSTLEN);
+ else
+ wp->who_host[0] = 0;
+# else
+ (void) strncpy(wp->who_host, utmp.ut_host, UTHOSTLEN);
+# endif
+# endif /* UTHOST */
+ wp->who_time = utmp.ut_time;
+ if (wp->who_name[0] == '\0')
+ wp->who_status = ONLINE;
+ else
+ wp->who_status = CHANGED;
+ }
+ }
+ else { /* new tty in utmp */
+ wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
+ (void) strncpy(wpnew->who_tty, utmp.ut_line, UTLINLEN);
+# ifdef UTHOST
+# ifdef _SEQUENT_
+ host = ut_find_host(wpnew->who_tty);
+ if (host)
+ (void) strncpy(wpnew->who_host, host, UTHOSTLEN);
+ else
+ wpnew->who_host[0] = 0;
+# else
+ (void) strncpy(wpnew->who_host, utmp.ut_host, UTHOSTLEN);
+# endif
+# endif /* UTHOST */
+ wpnew->who_time = utmp.ut_time;
+# ifdef DEAD_PROCESS
+ if (utmp.ut_type == DEAD_PROCESS)
+ wpnew->who_status = OFFLINE;
+ else
+# endif /* DEAD_PROCESS */
+ if (utmp.ut_name[0] == '\0')
+ wpnew->who_status = OFFLINE;
+ else {
+ (void) strncpy(wpnew->who_new, utmp.ut_name, UTNAMLEN);
+ wpnew->who_status = ONLINE;
+ }
+# ifdef WHODEBUG
+ debugwholist(wpnew, wp);
+# endif /* WHODEBUG */
+
+ wpnew->who_next = wp; /* link in a new 'who' */
+ wpnew->who_prev = wp->who_prev;
+ wpnew->who_prev->who_next = wpnew;
+ wp->who_prev = wpnew; /* linked in now */
+ }
+ }
+ (void) close(utmpfd);
+# if defined(UTHOST) && defined(_SEQUENT_)
+ endutent();
+# endif
+#endif /* !WINNT */
+
+ if (force || vp == NULL)
+ return;
+
+ /*
+ * The state of all logins is now known, so we can search the user's list
+ * of watchables to print the interesting ones.
+ */
+ for (alldone = 0; !alldone && *vp != NULL && **vp != '\0' &&
+ *(vp + 1) != NULL && **(vp + 1) != '\0';
+ vp += 2) { /* args used in pairs... */
+
+ if (eq(*vp, STRany) && eq(*(vp + 1), STRany))
+ alldone = 1;
+
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ if (wp->who_status & ANNOUNCE ||
+ (!eq(STRany, vp[0]) &&
+ !Gmatch(str2short(wp->who_name), vp[0]) &&
+ !Gmatch(str2short(wp->who_new), vp[0])) ||
+ (!Gmatch(str2short(wp->who_tty), vp[1]) &&
+ !eq(STRany, vp[1])))
+ continue; /* entry doesn't qualify */
+ /* already printed or not right one to print */
+
+
+ if (wp->who_time == 0)/* utmp entry was cleared */
+ wp->who_time = watch_period;
+
+ if ((wp->who_status & OFFLINE) &&
+ (wp->who_name[0] != '\0')) {
+ if (!firsttime)
+ print_who(wp);
+ wp->who_name[0] = '\0';
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ if (wp->who_status & ONLINE) {
+ if (!firsttime)
+ print_who(wp);
+ (void) strcpy(wp->who_name, wp->who_new);
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ if (wp->who_status & CHANGED) {
+ if (!firsttime)
+ print_who(wp);
+ (void) strcpy(wp->who_name, wp->who_new);
+ wp->who_status |= ANNOUNCE;
+ continue;
+ }
+ }
+ }
+#ifdef BSDSIGS
+ (void) sigsetmask(omask);
+#else
+ (void) sigrelse(SIGINT);
+#endif
+}
+
+#ifdef WHODEBUG
+static void
+debugwholist(new, wp)
+ register struct who *new, *wp;
+{
+ register struct who *a;
+
+ a = whohead.who_next;
+ while (a->who_next != NULL) {
+ xprintf("%s/%s -> ", a->who_name, a->who_tty);
+ a = a->who_next;
+ }
+ xprintf("TAIL\n");
+ if (a != &whotail) {
+ xprintf(CGETS(26, 3, "BUG! last element is not whotail!\n"));
+ abort();
+ }
+ a = whotail.who_prev;
+ xprintf(CGETS(26, 4, "backward: "));
+ while (a->who_prev != NULL) {
+ xprintf("%s/%s -> ", a->who_name, a->who_tty);
+ a = a->who_prev;
+ }
+ xprintf("HEAD\n");
+ if (a != &whohead) {
+ xprintf(CGETS(26, 5, "BUG! first element is not whohead!\n"));
+ abort();
+ }
+ if (new)
+ xprintf(CGETS(26, 6, "new: %s/%s\n"), new->who_name, new->who_tty);
+ if (wp)
+ xprintf("wp: %s/%s\n", wp->who_name, wp->who_tty);
+}
+#endif /* WHODEBUG */
+
+
+static void
+print_who(wp)
+ struct who *wp;
+{
+#ifdef UTHOST
+ Char *cp = str2short(CGETS(26, 7, "%n has %a %l from %m."));
+#else
+ Char *cp = str2short(CGETS(26, 8, "%n has %a %l."));
+#endif /* UTHOST */
+ struct varent *vp = adrof(STRwho);
+ Char buf[BUFSIZE];
+
+ if (vp && vp->vec[0])
+ cp = vp->vec[0];
+
+ tprintf(FMT_WHO, buf, cp, BUFSIZE, NULL, wp->who_time, (ptr_t) wp);
+ for (cp = buf; *cp;)
+ xputchar(*cp++);
+ xputchar('\n');
+} /* end print_who */
+
+
+const char *
+who_info(ptr, c, wbuf, wbufsiz)
+ ptr_t ptr;
+ int c;
+ char *wbuf;
+ size_t wbufsiz;
+{
+ struct who *wp = (struct who *) ptr;
+#ifdef UTHOST
+ char *wb = wbuf;
+ int flg;
+ char *pb;
+#endif /* UTHOST */
+
+ switch (c) {
+ case 'n': /* user name */
+ switch (wp->who_status & STMASK) {
+ case ONLINE:
+ case CHANGED:
+ return wp->who_new;
+ case OFFLINE:
+ return wp->who_name;
+ default:
+ break;
+ }
+ break;
+
+ case 'a':
+ switch (wp->who_status & STMASK) {
+ case ONLINE:
+ return CGETS(26, 9, "logged on");
+ case OFFLINE:
+ return CGETS(26, 10, "logged off");
+ case CHANGED:
+ xsnprintf(wbuf, wbufsiz, CGETS(26, 11, "replaced %s on"),
+ wp->who_name);
+ return wbuf;
+ default:
+ break;
+ }
+ break;
+
+#ifdef UTHOST
+ case 'm':
+ if (wp->who_host[0] == '\0')
+ return CGETS(26, 12, "local");
+ else {
+ /* the ':' stuff is for <host>:<display>.<screen> */
+ for (pb = wp->who_host, flg = Isdigit(*pb) ? '\0' : '.';
+ *pb != '\0' &&
+ (*pb != flg || ((pb = strchr(pb, ':')) != 0));
+ pb++) {
+ if (*pb == ':')
+ flg = '\0';
+ *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb;
+ }
+ *wb = '\0';
+ return wbuf;
+ }
+
+ case 'M':
+ if (wp->who_host[0] == '\0')
+ return CGETS(26, 12, "local");
+ else {
+ for (pb = wp->who_host; *pb != '\0'; pb++)
+ *wb++ = Isupper(*pb) ? Tolower(*pb) : *pb;
+ *wb = '\0';
+ return wbuf;
+ }
+#endif /* UTHOST */
+
+ case 'l':
+ return wp->who_tty;
+
+ default:
+ wbuf[0] = '%';
+ wbuf[1] = (char) c;
+ wbuf[2] = '\0';
+ return wbuf;
+ }
+ return NULL;
+}
+
+void
+/*ARGSUSED*/
+dolog(v, c)
+Char **v;
+struct command *c;
+{
+ struct who *wp;
+ struct varent *vp;
+
+ USE(v);
+ USE(c);
+ vp = adrof(STRwatch); /* lint insists vp isn't used unless we */
+ if (vp == NULL) /* unless we assign it outside the if */
+ stderror(ERR_NOWATCH);
+ resetwatch();
+ wp = whohead.who_next;
+ while (wp->who_next != NULL) {
+ wp->who_name[0] = '\0';
+ wp = wp->who_next;
+ }
+}
+
+# ifdef UTHOST
+char *
+utmphost()
+{
+ char *tty = short2str(varval(STRtty));
+ struct who *wp;
+ char *host = NULL;
+
+ watch_login(1);
+
+ for (wp = whohead.who_next; wp->who_next != NULL; wp = wp->who_next) {
+ if (strcmp(tty, wp->who_tty) == 0)
+ host = wp->who_host;
+ wp->who_name[0] = '\0';
+ }
+ resetwatch();
+ return host;
+}
+# endif /* UTHOST */
+
+#ifdef WINNT
+void add_to_who_list(name, mach_nm)
+ char *name;
+ char *mach_nm;
+{
+
+ struct who *wp, *wpnew;
+ int comp = -1;
+
+ wp = whohead.who_next;
+ while (wp->who_next && (comp = strncmp(wp->who_tty,mach_nm,UTLINLEN)) < 0)
+ wp = wp->who_next;/* find that tty! */
+
+ if (wp->who_next && comp == 0) { /* found the tty... */
+
+ if (*name == '\0') {
+ wp->who_time = 0;
+ wp->who_status = OFFLINE;
+ }
+ else if (strncmp(name, wp->who_name, UTNAMLEN) == 0) {
+ /* someone is logged in */
+ wp->who_time = 0;
+ wp->who_status = 0; /* same guy */
+ }
+ else {
+ (void) strncpy(wp->who_new, name, UTNAMLEN);
+ wp->who_time = 0;
+ if (wp->who_name[0] == '\0')
+ wp->who_status = ONLINE;
+ else
+ wp->who_status = CHANGED;
+ }
+ }
+ else {
+ wpnew = (struct who *) xcalloc(1, sizeof *wpnew);
+ (void) strncpy(wpnew->who_tty, mach_nm, UTLINLEN);
+ wpnew->who_time = 0;
+ if (*name == '\0')
+ wpnew->who_status = OFFLINE;
+ else {
+ (void) strncpy(wpnew->who_new, name, UTNAMLEN);
+ wpnew->who_status = ONLINE;
+ }
+#ifdef WHODEBUG
+ debugwholist(wpnew, wp);
+#endif /* WHODEBUG */
+
+ wpnew->who_next = wp; /* link in a new 'who' */
+ wpnew->who_prev = wp->who_prev;
+ wpnew->who_prev->who_next = wpnew;
+ wp->who_prev = wpnew; /* linked in now */
+ }
+}
+#endif /* WINNT */
+#endif /* HAVENOUTMP */
diff --git a/contrib/tcsh/tcsh.man b/contrib/tcsh/tcsh.man
new file mode 100644
index 0000000..8bca9b3
--- /dev/null
+++ b/contrib/tcsh/tcsh.man
@@ -0,0 +1,5078 @@
+.\" Copyright (c) 1980, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Style notes for the tcsh manpage:
+.\"
+.\" - Tags in lists are bold, except in the FILES section where they are
+.\" italic.
+.\"
+.\" - References are bold for section headings and environment and shell
+.\" variables and italic for commands (externals, builtins, aliases, and
+.\" editor commands) and arguments to commands.
+.\"
+.\" - Be careful with the .B and .I macros: they only handle a limited number
+.\" of words. Work around this with \fB and \fI, but only if absolutely
+.\" necessary, since tcsh.man2html uses .B/.I to find name anchors.
+.\"
+.\" - Indent in multiples of 4, usually 8.
+.\"
+.\" - Use `', not '' or "", except of course in shell syntax examples.
+.\" '' at the beginning of a line will vanish!
+.\"
+.\" - Use \-, not -.
+.\"
+.\" - Include the tilde when naming dotfiles. `~/.login', not `.login'.
+.\"
+.\" - Refer to external commands in manpage format, e.g. `csh(1)'. However,
+.\" tcsh is `tcsh', not `tcsh(1)', because this is the tcsh manpage (and
+.\" see the next note anyway).
+.\"
+.\" - Say `the shell', not `tcsh', unless distinguishing between tcsh and csh.
+.\"
+.\" - Say `shell variable'/`environment variable' instead of `variable'
+.\" and `builtin command'/`editor command' instead of `builtin' or `command'
+.\" unless the distinction is absolutely clear from context.
+.\"
+.\" - Use the simple present tense. `The shell uses', not `The shell will use'.
+.\"
+.\" - IMPORTANT: Cross-reference as much as possible. Commands, variables,
+.\" etc. in the reference section should be mentioned in the appropriate
+.\" descriptive section, or at least in the reference-section description
+.\" of another command (or whatever) which is mentioned in a description
+.\" section. Remember to note OS-specific things in "OS variant support",
+.\" new features in NEW FEATURES and referenced external commands in SEE
+.\" ALSO.
+.\"
+.\" - tcsh.man2html depends heavily on the specific nroff commands used in the
+.\" manpage when the script was written. Please stick closely to the style
+.\" used here if you can. In particular, please don't use nroff commands
+.\" which aren't already used herein.
+.\"
+.TH TCSH 1 "16 August 1999" "Astron 6.09.00"
+.SH NAME
+tcsh \- C shell with file name completion and command line editing
+.SH SYNOPSIS
+.B tcsh \fR[\fB\-bcdefFimnqstvVxX\fR] [\fB\-Dname\fR[\fB=value\fR]] [arg ...]
+.br
+.B tcsh \-l
+.SH DESCRIPTION
+\fItcsh\fR is an enhanced but completely compatible version of the Berkeley
+UNIX C shell, \fIcsh\fR(1).
+It is a command language interpreter usable both as an interactive login
+shell and a shell script command processor.
+It includes a command-line editor (see \fBThe command-line editor\fR),
+programmable word completion (see \fBCompletion and listing\fR),
+spelling correction (see \fBSpelling correction\fR),
+a history mechanism (see \fBHistory substitution\fR),
+job control (see \fBJobs\fR)
+and a C-like syntax.
+The \fBNEW FEATURES\fR section describes major enhancements of \fItcsh\fR
+over \fIcsh\fR(1).
+Throughout this manual, features of
+\fItcsh\fR not found in most \fIcsh\fR(1) implementations
+(specifically, the 4.4BSD \fIcsh\fR)
+are labeled with `(+)', and features which are present in \fIcsh\fR(1)
+but not usually documented are labeled with `(u)'.
+.SS "Argument list processing"
+If the first argument (argument 0) to the shell is `\-' then it is a
+login shell. A login shell can be also specified by invoking the shell with
+the \fB\-l\fR flag as the only argument.
+.PP
+The rest of the flag arguments are interpreted as follows:
+.TP 4
+.B \-b
+Forces a ``break'' from option processing, causing any
+further shell arguments to be treated as non-option arguments. The remaining
+arguments will not be interpreted as shell options. This may be used to pass
+options to a shell script without confusion or possible subterfuge. The shell
+will not run a set-user ID script without this option.
+.TP 4
+.B \-c
+Commands are read from the following argument (which must be present, and
+must be a single argument),
+stored in the \fBcommand\fR shell variable for reference, and executed.
+Any remaining arguments are placed in the \fBargv\fR shell variable.
+.TP 4
+.B \-d
+The shell loads the directory stack from \fI~/.cshdirs\fR as described under
+\fBStartup and shutdown\fR, whether or not it is a login shell. (+)
+.TP 4
+.B \-D\fIname\fR[=\fIvalue\fR]
+Sets the environment variable \fIname\fR to \fIvalue\fR. (Domain/OS only) (+)
+.TP 4
+.B \-e
+The shell exits if any invoked command terminates abnormally or
+yields a non-zero exit status.
+.TP 4
+.B \-f
+The shell ignores \fI~/.tcshrc\fR, and thus starts faster.
+.TP 4
+.B \-F
+The shell uses \fIfork\fR(2) instead of \fIvfork\fR(2) to spawn processes. (Convex/OS only) (+)
+.TP 4
+.B \-i
+The shell is interactive and prompts for its top-level input, even if
+it appears to not be a terminal. Shells are interactive without this option if
+their inputs and outputs are terminals.
+.TP 4
+.B \-l
+The shell is a login shell. Only applicable if \fB\-l\fR is the only
+flag specified.
+.TP 4
+.B \-m
+The shell loads \fI~/.tcshrc\fR even if it does not belong to the effective
+user. Newer versions of \fIsu\fR(1) can pass \fB\-m\fR to the shell. (+)
+.TP 4
+.B \-n
+The shell parses commands but does not execute them.
+This aids in debugging shell scripts.
+.TP 4
+.B \-q
+The shell accepts SIGQUIT (see \fBSignal handling\fR) and behaves when
+it is used under a debugger. Job control is disabled. (u)
+.TP 4
+.B \-s
+Command input is taken from the standard input.
+.TP 4
+.B \-t
+The shell reads and executes a single line of input. A `\\' may be used to
+escape the newline at the end of this line and continue onto another line.
+.TP 4
+.B \-v
+Sets the \fBverbose\fR shell variable, so that
+command input is echoed after history substitution.
+.TP 4
+.B \-x
+Sets the \fBecho\fR shell variable, so that commands are echoed
+immediately before execution.
+.TP 4
+.B \-V
+Sets the \fBverbose\fR shell variable even before executing \fI~/.tcshrc\fR.
+.TP 4
+.B \-X
+Is to \fB\-x\fR as \fB\-V\fR is to \fB\-v\fR.
+.PP
+After processing of flag arguments, if arguments remain but none of the
+\fB\-c\fR, \fB\-i\fR, \fB\-s\fR, or \fB\-t\fR options were given, the first
+argument is taken as the name of a file of commands, or ``script'', to
+be executed. The shell opens this file and saves its name for possible
+resubstitution by `$0'. Since many systems use either the standard
+version 6 or version 7 shells whose shell scripts are not compatible
+with this shell, the shell uses such a `standard' shell to execute a script
+whose first character is not a `#', i.e. which does not start with a
+comment.
+.PP
+Remaining arguments are placed in the \fBargv\fR shell variable.
+.SS "Startup and shutdown"
+A login shell begins by executing commands from the system files
+\fI/etc/csh.cshrc\fR and \fI/etc/csh.login\fR.
+It then executes commands from files in the user's \fBhome\fR directory:
+first \fI~/.tcshrc\fR (+)
+or, if \fI~/.tcshrc\fR is not found, \fI~/.cshrc\fR,
+then \fI~/.history\fR (or the value of the \fBhistfile\fR shell variable),
+then \fI~/.login\fR,
+and finally \fI~/.cshdirs\fR (or the value of the \fBdirsfile\fR shell variable) (+).
+The shell may read \fI/etc/csh.login\fR before instead of after
+\fI/etc/csh.cshrc\fR, and \fI~/.login\fR before instead of after
+\fI~/.tcshrc\fR or \fI~/.cshrc\fR and \fI~/.history\fR, if so compiled;
+see the \fBversion\fR shell variable. (+)
+.PP
+Non-login shells read only \fI/etc/csh.cshrc\fR and \fI~/.tcshrc\fR
+or \fI~/.cshrc\fR on startup.
+.PP
+Commands like \fIstty\fR(1) and \fItset\fR(1),
+which need be run only once per login, usually go in one's \fI~/.login\fR file.
+Users who need to use the same set of files with both \fIcsh\fR(1) and
+\fItcsh\fR can have only a \fI~/.cshrc\fR which checks for the existence of the
+\fBtcsh\fR shell variable (q.v.) before using \fItcsh\fR-specific commands,
+or can have both a \fI~/.cshrc\fR and a \fI~/.tcshrc\fR which \fIsource\fRs
+(see the builtin command) \fI~/.cshrc\fR.
+The rest of this manual uses `\fI~/.tcshrc\fR' to mean `\fI~/.tcshrc\fR or,
+if \fI~/.tcshrc\fR is not found, \fI~/.cshrc\fR'.
+.PP
+In the normal case, the shell begins reading commands from the terminal,
+prompting with `> '. (Processing of arguments and the use of the shell to
+process files containing command scripts are described later.)
+The shell repeatedly reads a line of command input, breaks it into words,
+places it on the command history list, parses it and executes each command
+in the line.
+.PP
+One can log out by typing `^D' on an empty line, `logout' or `login' or
+via the shell's autologout mechanism (see the \fBautologout\fR shell variable).
+When a login shell terminates it sets the \fBlogout\fR shell variable to
+`normal' or `automatic' as appropriate, then
+executes commands from the files
+\fI/etc/csh.logout\fR and \fI~/.logout\fR. The shell may drop DTR on logout
+if so compiled; see the \fBversion\fR shell variable.
+.PP
+The names of the system login and logout files vary from system to system for
+compatibility with different \fIcsh\fR(1) variants; see \fBFILES\fR.
+.SS Editing
+We first describe \fBThe command-line editor\fR.
+The \fBCompletion and listing\fR and \fBSpelling correction\fR sections
+describe two sets of functionality which are implemented as editor commands
+but which deserve their own treatment.
+Finally, \fBEditor commands\fR lists and describes
+the editor commands specific to the shell and their default bindings.
+.SS "The command-line editor (+)"
+Command-line input can be edited using key sequences much like those used in
+GNU Emacs or \fIvi\fR(1).
+The editor is active only when the \fBedit\fR shell variable is set, which
+it is by default in interactive shells.
+The \fIbindkey\fR builtin can display and change key bindings.
+Emacs-style key bindings are used by default
+(unless the shell was compiled otherwise; see the \fBversion\fR shell variable),
+but \fIbindkey\fR can change the key bindings to \fIvi\fR-style bindings en masse.
+.PP
+The shell always binds the arrow keys (as defined in the \fBTERMCAP\fR
+environment variable) to
+.PP
+.PD 0
+.RS +4
+.TP 8
+down
+\fIdown-history\fR
+.TP 8
+up
+\fIup-history\fR
+.TP 8
+left
+\fIbackward-char\fR
+.TP 8
+right
+\fIforward-char\fR
+.PD
+.RE
+.PP
+unless doing so would alter another single-character binding.
+One can set the arrow key escape sequences to the empty string with \fIsettc\fR
+to prevent these bindings.
+The ANSI/VT100 sequences for arrow keys are always bound.
+.PP
+Other key bindings are, for the most part, what Emacs and \fIvi\fR(1)
+users would expect and can easily be displayed by \fIbindkey\fR, so there
+is no need to list them here. Likewise, \fIbindkey\fR can list the editor
+commands with a short description of each.
+.PP
+Note that editor commands do not have the same notion of a ``word'' as does the
+shell. The editor delimits words with any non-alphanumeric characters not in
+the shell variable \fBwordchars\fR, while the shell recognizes only whitespace
+and some of the characters with special meanings to it, listed under
+\fBLexical structure\fR.
+.SS "Completion and listing (+)"
+The shell is often able to complete words when given a unique abbreviation.
+Type part of a word (for example `ls /usr/lost') and hit the tab key to
+run the \fIcomplete-word\fR editor command.
+The shell completes the filename `/usr/lost' to `/usr/lost+found/',
+replacing the incomplete word with the complete word in the input buffer.
+(Note the terminal `/'; completion adds a `/' to the
+end of completed directories and a space to the end of other completed words,
+to speed typing and provide a visual indicator of successful completion.
+The \fBaddsuffix\fR shell variable can be unset to prevent this.)
+If no match is found (perhaps `/usr/lost+found' doesn't exist),
+the terminal bell rings.
+If the word is already complete (perhaps there is a `/usr/lost' on your
+system, or perhaps you were thinking too far ahead and typed the whole thing)
+a `/' or space is added to the end if it isn't already there.
+.PP
+Completion works anywhere in the line, not just at the end; completed
+text pushes the rest of the line to the right. Completion in the middle of a word
+often results in leftover characters to the right of the cursor which need
+to be deleted.
+.PP
+Commands and variables can be completed in much the same way.
+For example, typing `em[tab]' would complete `em' to
+`emacs' if \fIemacs\fR were the only command on your system beginning with `em'.
+Completion can find a command in any directory in \fBpath\fR or if
+given a full pathname.
+Typing `echo $ar[tab]' would complete `$ar' to `$argv'
+if no other variable began with `ar'.
+.PP
+The shell parses the input buffer to determine whether the word you want to
+complete should be completed as a filename, command or variable.
+The first word in the buffer and the first word following
+`;', `|', `|&', `&&' or `||' is considered to be a command.
+A word beginning with `$' is considered to be a variable.
+Anything else is a filename. An empty line is `completed' as a filename.
+.PP
+You can list the possible completions of a word at any time by typing `^D'
+to run the \fIdelete-char-or-list-or-eof\fR editor command.
+The shell lists the possible completions using the \fIls\-F\fR builtin (q.v.)
+and reprints the prompt and unfinished command line, for example:
+.IP "" 4
+> ls /usr/l[^D]
+.br
+lbin/ lib/ local/ lost+found/
+.br
+> ls /usr/l
+.PP
+If the \fBautolist\fR shell variable is set, the shell lists the remaining
+choices (if any) whenever completion fails:
+.IP "" 4
+> set autolist
+.br
+> nm /usr/lib/libt[tab]
+.br
+libtermcap.a@ libtermlib.a@
+.br
+> nm /usr/lib/libterm
+.PP
+If \fBautolist\fR is set to `ambiguous', choices are listed only when
+completion fails and adds no new characters to the word being completed.
+.PP
+A filename to be completed can contain variables, your own or others' home
+directories abbreviated with `~' (see \fBFilename substitution\fR) and
+directory stack entries abbreviated with `='
+(see \fBDirectory stack substitution\fR). For example,
+.IP "" 4
+> ls ~k[^D]
+.br
+kahn kas kellogg
+.br
+> ls ~ke[tab]
+.br
+> ls ~kellogg/
+.PP
+or
+.IP "" 4
+> set local = /usr/local
+.br
+> ls $lo[tab]
+.br
+> ls $local/[^D]
+.br
+bin/ etc/ lib/ man/ src/
+.br
+> ls $local/
+.PP
+Note that variables can also be expanded explicitly with the
+\fIexpand-variables\fR editor command.
+.PP
+\fIdelete-char-or-list-or-eof\fR only lists at the end of the line;
+in the middle of a line it deletes the character under the cursor and
+on an empty line it logs one out or, if \fBignoreeof\fR is set, does nothing.
+`M-^D', bound to the editor command \fIlist-choices\fR, lists completion
+possibilities anywhere on a line, and \fIlist-choices\fR (or any one of the
+related editor commands which do or don't delete, list and/or log out,
+listed under \fIdelete-char-or-list-or-eof\fR) can be bound to `^D' with
+the \fIbindkey\fR builtin command if so desired.
+.PP
+The \fIcomplete-word-fwd\fR and \fIcomplete-word-back\fR editor commands
+(not bound to any keys by default) can be used to cycle up and down through
+the list of possible completions, replacing the current word with the next or
+previous word in the list.
+.PP
+The shell variable \fBfignore\fR can be set to a list of suffixes to be
+ignored by completion. Consider the following:
+.IP "" 4
+> ls
+.br
+Makefile condiments.h~ main.o side.c
+.br
+README main.c meal side.o
+.br
+condiments.h main.c~
+.br
+> set fignore = (.o \\~)
+.br
+> emacs ma[^D]
+.br
+main.c main.c~ main.o
+.br
+> emacs ma[tab]
+.br
+> emacs main.c
+.PP
+`main.c~' and `main.o' are ignored by completion (but not listing),
+because they end in suffixes in \fBfignore\fR.
+Note that a `\\' was needed in front of `~' to prevent it from being
+expanded to \fBhome\fR as described under \fBFilename substitution\fR.
+\fBfignore\fR is ignored if only one completion is possible.
+.PP
+If the \fBcomplete\fR shell variable is set to `enhance', completion
+1) ignores case and 2) considers periods, hyphens and underscores
+(`.', `\-' and `_') to be word separators and hyphens and underscores to
+be equivalent. If you had the following files
+.IP "" 4
+comp.lang.c comp.lang.perl comp.std.c++
+.br
+comp.lang.c++ comp.std.c
+.PP
+and typed `mail \-f c.l.c[tab]', it would be completed to
+`mail \-f comp.lang.c', and ^D would list `comp.lang.c' and `comp.lang.c++'.
+`mail \-f c..c++[^D]' would list `comp.lang.c++' and `comp.std.c++'. Typing
+`rm a\-\-file[^D]' in the following directory
+.IP "" 4
+A_silly_file a-hyphenated-file another_silly_file
+.PP
+would list all three files, because case is ignored and hyphens and
+underscores are equivalent. Periods, however, are not equivalent to
+hyphens or underscores.
+.PP
+Completion and listing are affected by several other shell variables:
+\fBrecexact\fR can be set to complete on the shortest possible unique
+match, even if more typing might result in a longer match:
+.IP "" 4
+> ls
+.br
+fodder foo food foonly
+.br
+> set recexact
+.br
+> rm fo[tab]
+.PP
+just beeps, because `fo' could expand to `fod' or `foo', but if we type
+another `o',
+.IP "" 4
+> rm foo[tab]
+.br
+> rm foo
+.PP
+the completion completes on `foo', even though `food' and `foonly'
+also match.
+\fBautoexpand\fR can be set to run the \fIexpand-history\fR editor command
+before each completion attempt, \fBautocorrect\fR can be set to
+spelling-correct the word to be completed (see \fBSpelling correction\fR)
+before each completion attempt and \fBcorrect\fR can be set to complete
+commands automatically after one hits `return'.
+\fBmatchbeep\fR can be set to make completion beep or not beep in a variety
+of situations, and \fBnobeep\fR can be set to never beep at all.
+\fBnostat\fR can be set to a list of directories and/or patterns which
+match directories to prevent the completion mechanism from \fIstat\fR(2)ing
+those directories.
+\fBlistmax\fR and \fBlistmaxrows\fR can be set to limit the number of items
+and rows (respectively) that are listed without asking first.
+\fBrecognize_only_executables\fR can be set to make the shell list only
+executables when listing commands, but it is quite slow.
+.PP
+Finally, the \fIcomplete\fR builtin command can be used to tell the shell how
+to complete words other than filenames, commands and variables.
+Completion and listing do not work on glob-patterns (see \fBFilename substitution\fR),
+but the \fIlist-glob\fR and \fIexpand-glob\fR editor commands perform
+equivalent functions for glob-patterns.
+.SS "Spelling correction (+)"
+The shell can sometimes correct the spelling of filenames, commands and variable names
+as well as completing and listing them.
+.PP
+Individual words can be spelling-corrected with the \fIspell-word\fR
+editor command (usually bound to M-s and M-S)
+and the entire input buffer with \fIspell-line\fR (usually bound to M-$).
+The \fBcorrect\fR shell variable can be set to `cmd' to correct the
+command name or `all' to correct the entire line each time return is typed,
+and \fBautocorrect\fR can be set to correct the word to be completed
+before each completion attempt.
+.PP
+When spelling correction is invoked in any of these ways and
+the shell thinks that any part of the command line is misspelled,
+it prompts with the corrected line:
+.IP "" 4
+> set correct = cmd
+.br
+> lz /usr/bin
+.br
+CORRECT>ls /usr/bin (y|n|e|a)?
+.PP
+One can answer `y' or space to execute the corrected line,
+`e' to leave the uncorrected command in the input buffer,
+`a' to abort the command as if `^C' had been hit, and
+anything else to execute the original line unchanged.
+.PP
+Spelling correction recognizes user-defined completions (see the
+\fIcomplete\fR builtin command). If an input word in a position for
+which a completion is defined resembles a word in the completion list,
+spelling correction registers a misspelling and suggests the latter
+word as a correction. However, if the input word does not match any of
+the possible completions for that position, spelling correction does
+not register a misspelling.
+.PP
+Like completion, spelling correction works anywhere in the line,
+pushing the rest of the line to the right and possibly leaving
+extra characters to the right of the cursor.
+.PP
+Beware: spelling correction is not guaranteed to work the way one intends,
+and is provided mostly as an experimental feature.
+Suggestions and improvements are welcome.
+.SS "Editor commands (+)"
+`bindkey' lists key bindings and `bindkey \-l' lists and briefly describes
+editor commands.
+Only new or especially interesting editor commands are described here.
+See \fIemacs\fR(1) and \fIvi\fR(1) for descriptions of each editor's
+key bindings.
+.PP
+The character or characters to which each command is bound by default is
+given in parentheses. `^\fIcharacter\fR' means a control character and
+`M-\fIcharacter\fR' a meta character, typed as escape-\fIcharacter\fR
+on terminals without a meta key. Case counts, but commands which are bound
+to letters by default are bound to both lower- and uppercase letters for
+convenience.
+.TP 8
+.B complete-word \fR(tab)
+Completes a word as described under \fBCompletion and listing\fR.
+.TP 8
+.B complete-word-back \fR(not bound)
+Like \fIcomplete-word-fwd\fR, but steps up from the end of the list.
+.TP 8
+.B complete-word-fwd \fR(not bound)
+Replaces the current word with the first word in the list of possible
+completions. May be repeated to step down through the list.
+At the end of the list, beeps and reverts to the incomplete word.
+.TP 8
+.B complete-word-raw \fR(^X-tab)
+Like \fIcomplete-word\fR, but ignores user-defined completions.
+.TP 8
+.B copy-prev-word \fR(M-^_)
+Copies the previous word in the current line into the input buffer.
+See also \fIinsert-last-word\fR.
+.TP 8
+.B dabbrev-expand \fR(M-/)
+Expands the current word to the most recent preceding one for which
+the current is a leading substring, wrapping around the history list
+(once) if necessary.
+Repeating \fIdabbrev-expand\fR without any intervening typing
+changes to the next previous word etc., skipping identical matches
+much like \fIhistory-search-backward\fR does.
+.TP 8
+.B delete-char \fR(not bound)
+Deletes the character under the cursor.
+See also \fIdelete-char-or-list-or-eof\fR.
+.TP 8
+.B delete-char-or-eof \fR(not bound)
+Does \fIdelete-char\fR if there is a character under the cursor
+or \fIend-of-file\fR on an empty line.
+See also \fIdelete-char-or-list-or-eof\fR.
+.TP 8
+.B delete-char-or-list \fR(not bound)
+Does \fIdelete-char\fR if there is a character under the cursor
+or \fIlist-choices\fR at the end of the line.
+See also \fIdelete-char-or-list-or-eof\fR.
+.TP 8
+.B delete-char-or-list-or-eof \fR(^D)
+Does \fIdelete-char\fR if there is a character under the cursor,
+\fIlist-choices\fR at the end of the line
+or \fIend-of-file\fR on an empty line.
+See also those three commands, each of which only does a single action, and
+\fIdelete-char-or-eof\fR, \fIdelete-char-or-list\fR and \fIlist-or-eof\fR,
+each of which does a different two out of the three.
+.TP 8
+.B down-history \fR(down-arrow, ^N)
+Like \fIup-history\fR, but steps down, stopping at the original input line.
+.TP 8
+.B end-of-file \fR(not bound)
+Signals an end of file, causing the shell to exit unless the \fBignoreeof\fR
+shell variable (q.v.) is set to prevent this.
+See also \fIdelete-char-or-list-or-eof\fR.
+.TP 8
+.B expand-history \fR(M-space)
+Expands history substitutions in the current word.
+See \fBHistory substitution\fR.
+See also \fImagic-space\fR, \fItoggle-literal-history\fR and
+the \fBautoexpand\fR shell variable.
+.TP 8
+.B expand-glob \fR(^X-*)
+Expands the glob-pattern to the left of the cursor.
+See \fBFilename substitution\fR.
+.TP 8
+.B expand-line \fR(not bound)
+Like \fIexpand-history\fR, but
+expands history substitutions in each word in the input buffer,
+.TP 8
+.B expand-variables \fR(^X-$)
+Expands the variable to the left of the cursor.
+See \fBVariable substitution\fR.
+.TP 8
+.B history-search-backward \fR(M-p, M-P)
+Searches backwards through the history list for a command beginning with
+the current contents of the input buffer up to the cursor and copies it
+into the input buffer.
+The search string may be a glob-pattern (see \fBFilename substitution\fR)
+containing `*', `?', `[]' or `{}'.
+\fIup-history\fR and \fIdown-history\fR will proceed from the
+appropriate point in the history list.
+Emacs mode only.
+See also \fIhistory-search-forward\fR and \fIi-search-back\fR.
+.TP 8
+.B history-search-forward \fR(M-n, M-N)
+Like \fIhistory-search-backward\fR, but searches forward.
+.TP 8
+.B i-search-back \fR(not bound)
+Searches backward like \fIhistory-search-backward\fR, copies the first match
+into the input buffer with the cursor positioned at the end of the pattern,
+and prompts with `bck: ' and the first match. Additional characters may be
+typed to extend the search, \fIi-search-back\fR may be typed to continue
+searching with the same pattern, wrapping around the history list if
+necessary, (\fIi-search-back\fR must be bound to a
+single character for this to work) or one of the following special characters
+may be typed:
+.PP
+.RS +8
+.RS +4
+.PD 0
+.TP 8
+^W
+Appends the rest of the word under the cursor to the search pattern.
+.TP 8
+delete (or any character bound to \fIbackward-delete-char\fR)
+Undoes the effect of the last character typed and deletes a character
+from the search pattern if appropriate.
+.TP 8
+^G
+If the previous search was successful, aborts the entire search.
+If not, goes back to the last successful search.
+.TP 8
+escape
+Ends the search, leaving the current line in the input buffer.
+.RE
+.PD
+.PP
+Any other character not bound to \fIself-insert-command\fR terminates the
+search, leaving the current line in the input buffer, and
+is then interpreted as normal input. In particular, a carriage return
+causes the current line to be executed.
+Emacs mode only.
+See also \fIi-search-fwd\fR and \fIhistory-search-backward\fR.
+.RE
+.TP 8
+.B i-search-fwd \fR(not bound)
+Like \fIi-search-back\fR, but searches forward.
+.TP 8
+.B insert-last-word \fR(M-_)
+Inserts the last word of the previous input line (`!$') into the input buffer.
+See also \fIcopy-prev-word\fR.
+.TP 8
+.B list-choices \fR(M-^D)
+Lists completion possibilities as described under \fBCompletion and listing\fR.
+See also \fIdelete-char-or-list-or-eof\fR and \fIlist-choices-raw\fR.
+.TP 8
+.B list-choices-raw \fR(^X-^D)
+Like \fIlist-choices\fR, but ignores user-defined completions.
+.TP 8
+.B list-glob \fR(^X-g, ^X-G)
+Lists (via the \fIls\-F\fR builtin) matches to the glob-pattern
+(see \fBFilename substitution\fR) to the left of the cursor.
+.TP 8
+.B list-or-eof \fR(not bound)
+Does \fIlist-choices\fR
+or \fIend-of-file\fR on an empty line.
+See also \fIdelete-char-or-list-or-eof\fR.
+.TP 8
+.B magic-space \fR(not bound)
+Expands history substitutions in the current line,
+like \fIexpand-history\fR, and appends a space.
+\fImagic-space\fR is designed to be bound to the spacebar,
+but is not bound by default.
+.TP 8
+.B normalize-command \fR(^X-?)
+Searches for the current word in PATH and, if it is found, replaces it with
+the full path to the executable. Special characters are quoted. Aliases are
+expanded and quoted but commands within aliases are not. This command is
+useful with commands which take commands as arguments, e.g. `dbx' and `sh \-x'.
+.TP 8
+.B normalize-path \fR(^X-n, ^X-N)
+Expands the current word as described under the `expand' setting
+of the \fBsymlinks\fR shell variable.
+.TP 8
+.B overwrite-mode \fR(unbound)
+Toggles between input and overwrite modes.
+.TP 8
+.B run-fg-editor \fR(M-^Z)
+Saves the current input line and
+looks for a stopped job with a name equal to the last component of the
+file name part of the \fBEDITOR\fR or \fBVISUAL\fR environment variables,
+or, if neither is set, `ed' or `vi'.
+If such a job is found, it is restarted as if `fg %\fIjob\fR' had been
+typed. This is used to toggle back and forth between an editor and
+the shell easily. Some people bind this command to `^Z' so they
+can do this even more easily.
+.TP
+.B run-help \fR(M-h, M-H)
+Searches for documentation on the current command, using the same notion of
+`current command' as the completion routines, and prints it. There is no way
+to use a pager; \fIrun-help\fR is designed for short help files.
+If the special alias \fBhelpcommand\fR is defined, it is run with the
+command name as a sole argument. Else,
+documentation should be in a file named \fIcommand\fR.help, \fIcommand\fR.1,
+\fIcommand\fR.6, \fIcommand\fR.8 or \fIcommand\fR, which should be in one
+of the directories listed in the \fBHPATH\fR environment variable.
+If there is more than one help file only the first is printed.
+.TP 8
+.B self-insert-command \fR(text characters)
+In insert mode (the default), inserts the typed character into the input line after the character under the cursor.
+In overwrite mode, replaces the character under the cursor with the typed character.
+The input mode is normally preserved between lines, but the
+\fBinputmode\fR shell variable can be set to `insert' or `overwrite' to put the
+editor in that mode at the beginning of each line.
+See also \fIoverwrite-mode\fR.
+.TP 8
+.B sequence-lead-in \fR(arrow prefix, meta prefix, ^X)
+Indicates that the following characters are part of a
+multi-key sequence. Binding a command to a multi-key sequence really creates
+two bindings: the first character to \fIsequence-lead-in\fR and the
+whole sequence to the command. All sequences beginning with a character
+bound to \fIsequence-lead-in\fR are effectively bound to \fIundefined-key\fR
+unless bound to another command.
+.TP 8
+.B spell-line \fR(M-$)
+Attempts to correct the spelling of each word in the input buffer, like
+\fIspell-word\fR, but ignores words whose first character is one of
+`\-', `!', `^' or `%', or which contain `\\', `*' or `?', to avoid problems
+with switches, substitutions and the like.
+See \fBSpelling correction\fR.
+.TP 8
+.B spell-word \fR(M-s, M-S)
+Attempts to correct the spelling of the current word as described
+under \fBSpelling correction\fR.
+Checks each component of a word which appears to be a pathname.
+.TP 8
+.B toggle-literal-history \fR(M-r, M-R)
+Expands or `unexpands' history substitutions in the input buffer.
+See also \fIexpand-history\fR and the \fBautoexpand\fR shell variable.
+.TP 8
+.B undefined-key \fR(any unbound key)
+Beeps.
+.TP 8
+.B up-history \fR(up-arrow, ^P)
+Copies the previous entry in the history list into the input buffer.
+If \fBhistlit\fR is set, uses the literal form of the entry.
+May be repeated to step up through the history list, stopping at the top.
+.TP 8
+.B vi-search-back \fR(?)
+Prompts with `?' for a search string (which may be a glob-pattern, as with
+\fIhistory-search-backward\fR), searches for it and copies it into the
+input buffer. The bell rings if no match is found.
+Hitting return ends the search and leaves the last match in the input
+buffer.
+Hitting escape ends the search and executes the match.
+\fIvi\fR mode only.
+.TP 8
+.B vi-search-fwd \fR(/)
+Like \fIvi-search-back\fR, but searches forward.
+.TP 8
+.B which-command \fR(M-?)
+Does a \fIwhich\fR (see the description of the builtin command) on the
+first word of the input buffer.
+.SS "Lexical structure"
+The shell splits input lines into words at blanks and tabs. The special
+characters `&', `|', `;', `<', `>', `(', and `)' and the doubled characters
+`&&', `||', `<<' and `>>' are always separate words, whether or not they are
+surrounded by whitespace.
+.PP
+When the shell's input is not a terminal, the character `#' is taken to begin a
+comment. Each `#' and the rest of the input line on which it appears is
+discarded before further parsing.
+.PP
+A special character (including a blank or tab) may be prevented from having
+its special meaning, and possibly made part of another word, by preceding it
+with a backslash (`\\') or enclosing it in single (`''), double (`"') or
+backward (``') quotes. When not otherwise quoted a newline preceded by a `\\'
+is equivalent to a blank, but inside quotes this sequence results in a
+newline.
+.PP
+Furthermore, all \fBSubstitutions\fR (see below) except \fBHistory substitution\fR
+can be prevented by enclosing the strings (or parts of strings)
+in which they appear with single quotes or by quoting the crucial character(s)
+(e.g. `$' or ``' for \fBVariable substitution\fR or \fBCommand substitution\fR respectively)
+with `\\'. (\fBAlias substitution\fR is no exception: quoting in any way any
+character of a word for which an \fIalias\fR has been defined prevents
+substitution of the alias. The usual way of quoting an alias is to precede it
+with a backslash.) \fBHistory substitution\fR is prevented by
+backslashes but not by single quotes. Strings quoted with double or backward
+quotes undergo \fBVariable substitution\fR and \fBCommand substitution\fR, but other
+substitutions are prevented.
+.PP
+Text inside single or double quotes becomes a single word (or part of one).
+Metacharacters in these strings, including blanks and tabs, do not form
+separate words. Only in one special case (see \fBCommand substitution\fR
+below) can a double-quoted string yield parts of more than one word;
+single-quoted strings never do. Backward quotes are special: they signal
+\fBCommand substitution\fR (q.v.), which may result in more than one word.
+.PP
+Quoting complex strings, particularly strings which themselves contain quoting
+characters, can be confusing. Remember that quotes need not be used as they are
+in human writing! It may be easier to quote not an entire string, but only
+those parts of the string which need quoting, using different types of quoting
+to do so if appropriate.
+.PP
+The \fBbackslash_quote\fR shell variable (q.v.) can be set to make backslashes
+always quote `\\', `'', and `"'. (+) This may make complex quoting tasks
+easier, but it can cause syntax errors in \fIcsh\fR(1) scripts.
+.SS Substitutions
+We now describe the various transformations the shell performs on the input in
+the order in which they occur. We note in passing the data structures involved
+and the commands and variables which affect them. Remember that substitutions
+can be prevented by quoting as described under \fBLexical structure\fR.
+.SS "History substitution"
+Each command, or ``event'', input from the terminal is saved in the history
+list. The previous command is always saved, and the \fBhistory\fR shell
+variable can be set to a number to save that many commands. The \fBhistdup\fR
+shell variable can be set to not save duplicate events or consecutive duplicate
+events.
+.PP
+Saved commands are numbered sequentially from 1 and stamped with the time.
+It is not usually necessary to use event numbers, but the current event number
+can be made part of the prompt by placing an `!' in the \fBprompt\fR shell variable.
+.PP
+The shell actually saves history in expanded and literal (unexpanded) forms.
+If the \fBhistlit\fR shell variable is set, commands that display and store
+history use the literal form.
+.PP
+The \fIhistory\fR builtin command can print, store in a file, restore
+and clear the history list at any time,
+and the \fBsavehist\fR and \fBhistfile\fR shell variables can be can be set to
+store the history list automatically on logout and restore it on login.
+.PP
+History substitutions introduce words from the history list into the input
+stream, making it easy to repeat commands, repeat arguments of a previous
+command in the current command, or fix spelling mistakes in the previous
+command with little typing and a high degree of confidence.
+.PP
+History substitutions begin with the character `!'. They may begin anywhere in
+the input stream, but they do not nest. The `!' may be preceded by a `\\' to
+prevent its special meaning; for convenience, a `!' is passed unchanged when it
+is followed by a blank, tab, newline, `=' or `('. History substitutions also
+occur when an input line begins with `^'. This special abbreviation will be
+described later. The characters used to signal history substitution (`!' and
+`^') can be changed by setting the \fBhistchars\fR shell variable. Any input
+line which contains a history substitution is printed before it is executed.
+.PP
+A history substitution may have an ``event specification'', which indicates
+the event from which words are to be taken, a ``word designator'',
+which selects particular words from the chosen event, and/or a ``modifier'',
+which manipulates the selected words.
+.PP
+An event specification can be
+.PP
+.PD 0
+.RS +4
+.TP 8
+.I n
+A number, referring to a particular event
+.TP 8
+\-\fIn\fR
+An offset, referring to the event \fIn\fR before the current event
+.TP 8
+#
+The current event.
+This should be used carefully in \fIcsh\fR(1), where there is no check for
+recursion. \fItcsh\fR allows 10 levels of recursion. (+)
+.TP 8
+!
+The previous event (equivalent to `\-1')
+.TP 8
+.I s
+The most recent event whose first word begins with the string \fIs\fR
+.TP 8
+?\fIs\fR?
+The most recent event which contains the string \fIs\fR.
+The second `?' can be omitted if it is immediately followed by a newline.
+.RE
+.PD
+.PP
+For example, consider this bit of someone's history list:
+.IP "" 4
+\ 9 8:30 nroff \-man wumpus.man
+.br
+10 8:31 cp wumpus.man wumpus.man.old
+.br
+11 8:36 vi wumpus.man
+.br
+12 8:37 diff wumpus.man.old wumpus.man
+.PP
+The commands are shown with their event numbers and time stamps.
+The current event, which we haven't typed in yet, is event 13.
+`!11' and `!\-2' refer to event 11.
+`!!' refers to the previous event, 12. `!!' can be abbreviated `!' if it is
+followed by `:' (`:' is described below).
+`!n' refers to event 9, which begins with `n'.
+`!?old?' also refers to event 12, which contains `old'.
+Without word designators or modifiers history references simply expand to the
+entire event, so we might type `!cp' to redo the copy command or `!!|more'
+if the `diff' output scrolled off the top of the screen.
+.PP
+History references may be insulated from the surrounding text with braces if
+necessary. For example, `!vdoc' would look for a command beginning with
+`vdoc', and, in this example, not find one, but `!{v}doc' would expand
+unambiguously to `vi wumpus.mandoc'.
+Even in braces, history substitutions do not nest.
+.PP
+(+) While \fIcsh\fR(1) expands, for example, `!3d' to event 3 with the
+letter `d' appended to it, \fItcsh\fR expands it to the last event beginning
+with `3d'; only completely numeric arguments are treated as event numbers.
+This makes it possible to recall events beginning with numbers.
+To expand `!3d' as in \fIcsh\fR(1) say `!\\3d'.
+.PP
+To select words from an event we can follow the event specification by a `:'
+and a designator for the desired words. The words of an input line are
+numbered from 0, the first (usually command) word being 0, the second word
+(first argument) being 1, etc. The basic word designators are:
+.PP
+.PD 0
+.RS +4
+.TP 8
+0
+The first (command) word
+.TP 8
+.I n
+The \fIn\fRth argument
+.TP 8
+^
+The first argument, equivalent to `1'
+.TP 8
+$
+The last argument
+.TP 8
+%
+The word matched by an ?\fIs\fR? search
+.TP 8
+.I x\-y
+A range of words
+.TP 8
+.I \-y
+Equivalent to \fI`0\-y'\fR
+.TP 8
+*
+Equivalent to `^\-$', but returns nothing if the event contains only 1 word
+.TP 8
+.I x*
+Equivalent to \fI`x\-$'\fR
+.TP 8
+.I x\-
+Equivalent to \fI`x*'\fR, but omitting the last word (`$')
+.PD
+.RE
+.PP
+Selected words are inserted into the command line separated by single blanks.
+For example, the `diff' command in the previous example might have been
+typed as `diff !!:1.old !!:1' (using `:1' to select the first argument
+from the previous event) or `diff !\-2:2 !\-2:1' to select and swap the
+arguments from the `cp' command. If we didn't care about the order of the
+`diff' we might have said `diff !\-2:1\-2' or simply `diff !\-2:*'.
+The `cp' command might have been written `cp wumpus.man !#:1.old', using `#'
+to refer to the current event.
+`!n:\- hurkle.man' would reuse the first two words from the `nroff' command
+to say `nroff \-man hurkle.man'.
+.PP
+The `:' separating the event specification from the word designator can be
+omitted if the argument selector begins with a `^', `$', `*', `%' or `\-'.
+For example, our `diff' command might have been `diff !!^.old !!^' or,
+equivalently, `diff !!$.old !!$'. However, if `!!' is abbreviated `!',
+an argument selector beginning with `\-' will be interpreted as an event
+specification.
+.PP
+A history reference may have a word designator but no event specification.
+It then references the previous command.
+.ig \" Not true, but we thought it was for a long time ...
+, unless a previous history reference
+occurred on the same line in which case this form repeats the previous
+reference. Thus `!?foo?^ !$' gives the first and last arguments from the
+command matching `?foo?'.
+..
+Continuing our `diff' example, we could have said simply `diff
+!^.old !^' or, to get the arguments in the opposite order, just `diff !*'.
+.PP
+The word or words in a history reference can be edited, or ``modified'',
+by following it with one or more modifiers, each preceded by a `:':
+.PP
+.PD 0
+.RS +4
+.TP 8
+h
+Remove a trailing pathname component, leaving the head.
+.TP 8
+t
+Remove all leading pathname components, leaving the tail.
+.TP 8
+r
+Remove a filename extension `.xxx', leaving the root name.
+.TP 8
+e
+Remove all but the extension.
+.TP 8
+u
+Uppercase the first lowercase letter.
+.TP 8
+l
+Lowercase the first uppercase letter.
+.TP 8
+s\fI/l/r/\fR
+Substitute \fIl\fR for \fIr\fR.
+\fIl\fR is simply a string like \fIr\fR, not a regular expression as in
+the eponymous \fIed\fR(1) command.
+Any character may be used as the delimiter in place of `/';
+a `\\' can be used to quote the delimiter inside \fIl\fR and \fIr\fR.
+The character `&' in the \fIr\fR is replaced by \fIl\fR; `\\' also quotes `&'.
+If \fIl\fR is empty (``''), the \fIl\fR from a previous substitution or the
+\fIs\fR from a previous `?\fIs\fR?' event specification is used.
+The trailing delimiter may be omitted if it is immediately followed by a newline.
+.TP 8
+&
+Repeat the previous substitution.
+.TP 8
+g
+Apply the following modifier once to each word.
+.TP 8
+a (+)
+Apply the following modifier as many times as possible to a single word.
+`a' and `g' can be used together to apply a modifier globally.
+In the current implementation, using the `a' and `s' modifiers together can
+lead to an infinite loop. For example, `:as/f/ff/' will never terminate.
+This behavior might change in the future.
+.TP 8
+p
+Print the new command line but do not execute it.
+.TP 8
+q
+Quote the substituted words, preventing further substitutions.
+.TP 8
+x
+Like q, but break into words at blanks, tabs and newlines.
+.PD
+.RE
+.PP
+Modifiers are applied only to the first modifiable word (unless `g' is used).
+It is an error for no word to be modifiable.
+.PP
+For example, the `diff' command might have been written as `diff wumpus.man.old
+!#^:r', using `:r' to remove `.old' from the first argument on the same line
+(`!#^'). We could say `echo hello out there', then `echo !*:u' to capitalize
+`hello', `echo !*:au' to say it out loud, or `echo !*:agu' to really shout.
+We might follow `mail \-s "I forgot my password" rot' with `!:s/rot/root' to
+correct the spelling of `root' (but see \fBSpelling correction\fR for a
+different approach).
+.PP
+There is a special abbreviation for substitutions.
+`^', when it is the first character on an input line, is equivalent to `!:s^'.
+Thus we might have said `^rot^root' to make the spelling correction in the
+previous example.
+This is the only history substitution which does not explicitly begin with `!'.
+.PP
+(+) In \fIcsh\fR as such, only one modifier may be applied to each history
+or variable expansion. In \fItcsh\fR, more than one may be used, for example
+.IP "" 4
+% mv wumpus.man /usr/man/man1/wumpus.1
+.br
+% man !$:t:r
+.br
+man wumpus
+.PP
+In \fIcsh\fR, the result would be `wumpus.1:r'. A substitution followed by a
+colon may need to be insulated from it with braces:
+.IP "" 4
+> mv a.out /usr/games/wumpus
+.br
+> setenv PATH !$:h:$PATH
+.br
+Bad ! modifier: $.
+.br
+> setenv PATH !{\-2$:h}:$PATH
+.br
+setenv PATH /usr/games:/bin:/usr/bin:.
+.PP
+The first attempt would succeed in \fIcsh\fR but fails in \fItcsh\fR,
+because \fItcsh\fR expects another modifier after the second colon
+rather than `$'.
+.PP
+Finally, history can be accessed through the editor as well as through
+the substitutions just described.
+The \fIup-\fR and \fIdown-history\fR, \fIhistory-search-backward\fR and
+\fI-forward\fR, \fIi-search-back\fR and \fI-fwd\fR,
+\fIvi-search-back\fR and \fI-fwd\fR, \fIcopy-prev-word\fR
+and \fIinsert-last-word\fR editor commands search for
+events in the history list and copy them into the input buffer.
+The \fItoggle-literal-history\fR editor command switches between the
+expanded and literal forms of history lines in the input buffer.
+\fIexpand-history\fR and \fIexpand-line\fR expand history substitutions
+in the current word and in the entire input buffer respectively.
+.SS "Alias substitution"
+The shell maintains a list of aliases which can be set, unset and printed by
+the \fIalias\fR and \fIunalias\fR commands. After a command line is parsed
+into simple commands (see \fBCommands\fR) the first word of each command,
+left-to-right, is checked to see if it has an alias. If so, the first word is
+replaced by the alias. If the alias contains a history reference, it undergoes
+\fBHistory substitution\fR (q.v.) as though the original command were the
+previous input line. If the alias does not contain a history reference, the
+argument list is left untouched.
+.PP
+Thus if the alias for `ls' were `ls \-l' the command `ls /usr' would become `ls
+\-l /usr', the argument list here being undisturbed. If the alias for `lookup'
+were `grep !^ /etc/passwd' then `lookup bill' would become `grep bill
+/etc/passwd'. Aliases can be used to introduce parser metasyntax. For
+example, `alias print 'pr \e!* | lpr'' defines a ``command'' (`print') which
+\fIpr\fR(1)s its arguments to the line printer.
+.PP
+Alias substitution is repeated until the first word of the command has no
+alias. If an alias substitution does not change the first word (as in the
+previous example) it is flagged to prevent a loop. Other loops are detected and
+cause an error.
+.PP
+Some aliases are referred to by the shell; see \fBSpecial aliases\fR.
+.SS "Variable substitution"
+The shell maintains a list of variables, each of which has as value a list of
+zero or more words.
+The values of shell variables can be displayed and changed with the
+\fIset\fR and \fIunset\fR commands.
+The system maintains its own list of ``environment'' variables.
+These can be displayed and changed with \fIprintenv\fR, \fIsetenv\fR and
+\fIunsetenv\fR.
+.PP
+(+) Variables may be made read-only with `set \-r' (q.v.)
+Read-only variables may not be modified or unset;
+attempting to do so will cause an error.
+Once made read-only, a variable cannot be made writable,
+so `set \-r' should be used with caution.
+Environment variables cannot be made read-only.
+.PP
+Some variables are set by the shell or referred to by it.
+For instance, the \fBargv\fR variable is an image of the shell's argument
+list, and words of this variable's value are referred to in special ways.
+Some of the variables referred to by the shell are toggles;
+the shell does not care what their value is, only whether they are set or not.
+For instance, the \fBverbose\fR variable is a toggle which causes command
+input to be echoed. The \fB\-v\fR command line option sets this variable.
+\fBSpecial shell variables\fR lists all variables which are referred to by the shell.
+.PP
+Other operations treat variables numerically. The `@' command permits numeric
+calculations to be performed and the result assigned to a variable. Variable
+values are, however, always represented as (zero or more) strings. For the
+purposes of numeric operations, the null string is considered to be zero, and
+the second and subsequent words of multiword values are ignored.
+.PP
+After the input line is aliased and parsed, and before each command is
+executed, variable substitution is performed keyed by `$' characters. This
+expansion can be prevented by preceding the `$' with a `\e' except within `"'s
+where it \fIalways\fR occurs, and within `''s where it \fInever\fR occurs.
+Strings quoted by ``' are interpreted later (see \fBCommand substitution\fR
+below) so `$' substitution does not occur there until later,
+if at all. A `$' is passed unchanged if followed by a blank, tab, or
+end-of-line.
+.PP
+Input/output redirections are recognized before variable expansion, and are
+variable expanded separately. Otherwise, the command name and entire argument
+list are expanded together. It is thus possible for the first (command) word
+(to this point) to generate more than one word, the first of which becomes the
+command name, and the rest of which become arguments.
+.PP
+Unless enclosed in `"' or given the `:q' modifier the results of variable
+substitution may eventually be command and filename substituted. Within `"', a
+variable whose value consists of multiple words expands to a (portion of a)
+single word, with the words of the variable's value separated by blanks. When
+the `:q' modifier is applied to a substitution the variable will expand to
+multiple words with each word separated by a blank and quoted to prevent later
+command or filename substitution.
+.PP
+The following metasequences are provided for introducing variable values into
+the shell input. Except as noted, it is an error to reference a variable which
+is not set.
+.PP
+.PD 0
+$\fIname\fR
+.TP 8
+${\fIname\fR}
+Substitutes the words of the value of variable \fIname\fR, each separated
+by a blank. Braces insulate \fIname\fR from following characters which would
+otherwise be part of it. Shell variables have names consisting of up to 20
+letters and digits starting with a letter. The underscore character is
+considered a letter. If \fIname\fR is not a shell variable, but is set in the
+environment, then that value is returned (but `:' modifiers and the other forms
+given below are not available in this case).
+.PP
+$\fIname\fR[\fIselector\fR]
+.TP 8
+${\fIname\fR[\fIselector\fR]}
+Substitutes only the selected words from the value of \fIname\fR.
+The \fIselector\fR is subjected to `$' substitution and may consist of
+a single number or two numbers separated by a `\-'.
+The first word of a variable's value is numbered `1'.
+If the first number of a range is omitted it defaults to `1'.
+If the last member of a range is omitted it defaults to `$#\fIname\fR'.
+The \fIselector\fR `*' selects all words.
+It is not an error for a range to be empty if the
+second argument is omitted or in range.
+.TP 8
+$0
+Substitutes the name of the file from which command input
+is being read. An error occurs if the name is not known.
+.PP
+$\fInumber\fR
+.TP 8
+${\fInumber\fR}
+Equivalent to `$argv[\fInumber\fR]'.
+.TP 8
+$*
+Equivalent to `$argv', which is equivalent to `$argv[*]'.
+.PD
+.PP
+The `:' modifiers described under \fBHistory substitution\fR, except for `:p',
+can be applied to the substitutions above. More than one may be used. (+)
+Braces may be needed to insulate a variable substitution from a literal colon
+just as with \fBHistory substitution\fR (q.v.); any modifiers must appear
+within the braces.
+.PP
+The following substitutions can not be modified with `:' modifiers.
+.PP
+.PD 0
+$?\fIname\fR
+.TP 8
+${?\fIname\fR}
+Substitutes the string `1' if \fIname\fR is set, `0' if it is not.
+.TP 8
+$?0
+Substitutes `1' if the current input filename is known, `0' if it is not.
+Always `0' in interactive shells.
+.PP
+$#\fIname\fR
+.TP 8
+${#\fIname\fR}
+Substitutes the number of words in \fIname\fR.
+.TP 8
+$#
+Equivalent to `$#argv'. (+)
+.PP
+$%\fIname\fR
+.TP 8
+${%\fIname\fR}
+Substitutes the number of characters in \fIname\fR. (+)
+.PP
+$%\fInumber\fR
+.TP 8
+${%\fInumber\fR}
+Substitutes the number of characters in $argv[\fInumber\fR]. (+)
+.TP 8
+$?
+Equivalent to `$status'. (+)
+.TP 8
+$$
+Substitutes the (decimal) process number of the (parent) shell.
+.TP 8
+$!
+Substitutes the (decimal) process number of the last
+background process started by this shell. (+)
+.TP 8
+$_
+Substitures the command line of the last command executed. (+)
+.TP 8
+$<
+Substitutes a line from the standard input, with no further interpretation
+thereafter. It can be used to read from the keyboard in a shell script.
+(+) While \fIcsh\fR always quotes $<, as if it were equivalent to `$<:q',
+\fItcsh\fR does not. Furthermore, when \fItcsh\fR is waiting for a line to be
+typed the user may type an interrupt to interrupt the sequence into
+which the line is to be substituted, but \fIcsh\fR does not allow this.
+.PD
+.PP
+The editor command \fIexpand-variables\fR, normally bound to `^X-$',
+can be used to interactively expand individual variables.
+.SS "Command, filename and directory stack substitution"
+The remaining substitutions are applied selectively to the arguments of builtin
+commands. This means that portions of expressions which are not evaluated are
+not subjected to these expansions. For commands which are not internal to the
+shell, the command name is substituted separately from the argument list. This
+occurs very late, after input-output redirection is performed, and in a child
+of the main shell.
+.SS "Command substitution"
+Command substitution is indicated by a command enclosed in ``'. The output
+from such a command is broken into separate words at blanks, tabs and newlines,
+and null words are discarded. The output is variable and command substituted
+and put in place of the original string.
+.PP
+Command substitutions inside double
+quotes (`"') retain blanks and tabs; only newlines force new words. The single
+final newline does not force a new word in any case. It is thus possible for a
+command substitution to yield only part of a word, even if the command outputs
+a complete line.
+.SS "Filename substitution"
+If a word contains any of the characters `*', `?', `[' or `{' or begins with
+the character `~' it is a candidate for filename substitution, also known as
+``globbing''. This word is then regarded as a pattern (``glob-pattern''), and
+replaced with an alphabetically sorted list of file names which match the
+pattern.
+.PP
+In matching filenames, the character `.' at the beginning of a filename or
+immediately following a `/', as well as the character `/' must be matched
+explicitly. The character `*' matches any string of characters, including the
+null string. The character `?' matches any single character. The sequence
+`[...]' matches any one of the characters enclosed. Within `[...]', a pair of
+characters separated by `\-' matches any character lexically between the two.
+.PP
+(+) Some glob-patterns can be negated:
+The sequence `[^...]' matches any single character \fInot\fR specified by the
+characters and/or ranges of characters in the braces.
+.PP
+An entire glob-pattern can also be negated with `^':
+.IP "" 4
+> echo *
+.br
+bang crash crunch ouch
+.br
+> echo ^cr*
+.br
+bang ouch
+.PP
+Glob-patterns which do not use `?', `*', or `[]' or which use `{}' or `~'
+(below) are not negated correctly.
+.PP
+The metanotation `a{b,c,d}e' is a shorthand for `abe ace ade'.
+Left-to-right order is preserved: `/usr/source/s1/{oldls,ls}.c' expands
+to `/usr/source/s1/oldls.c /usr/source/s1/ls.c'. The results of matches are
+sorted separately at a low level to preserve this order:
+`../{memo,*box}' might expand to `../memo ../box ../mbox'.
+(Note that `memo' was not sorted with the results of matching `*box'.)
+It is not an error when this construct expands to files which do not exist,
+but it is possible to get an error from a command to which the expanded list
+is passed.
+This construct may be nested.
+As a special case the words `{', `}' and `{}' are passed undisturbed.
+.PP
+The character `~' at the beginning of a filename refers to home directories.
+Standing alone, i.e. `~', it expands to the invoker's home directory as
+reflected in the value of the \fBhome\fR shell variable. When followed by a
+name consisting of letters, digits and `\-' characters the shell searches for a
+user with that name and substitutes their home directory; thus `~ken' might
+expand to `/usr/ken' and `~ken/chmach' to `/usr/ken/chmach'. If the character
+`~' is followed by a character other than a letter or `/' or appears elsewhere
+than at the beginning of a word, it is left undisturbed.
+A command like `setenv MANPATH /usr/man:/usr/local/man:~/lib/man' does not,
+therefore, do home directory substitution as one might hope.
+.PP
+It is an error for a glob-pattern containing `*', `?', `[' or `~', with or
+without `^', not to match any files. However, only one pattern in a list of
+glob-patterns must match a file (so that, e.g., `rm *.a *.c *.o' would fail
+only if there were no files in the current directory ending in `.a', `.c', or
+`.o'), and if the \fBnonomatch\fR shell variable is set a pattern (or list
+of patterns) which matches nothing is left unchanged rather than causing
+an error.
+.PP
+The \fBnoglob\fR shell variable can be set to prevent filename substitution,
+and the \fIexpand-glob\fR editor command, normally bound to `^X-*', can be
+used to interactively expand individual filename substitutions.
+.SS "Directory stack substitution (+)"
+The directory stack is a list of directories, numbered from zero, used by the
+\fIpushd\fR, \fIpopd\fR and \fIdirs\fR builtin commands (q.v.).
+\fIdirs\fR can print, store in a file, restore and clear the directory stack
+at any time, and the \fBsavedirs\fR and \fBdirsfile\fR shell variables can be set to
+store the directory stack automatically on logout and restore it on login.
+The \fBdirstack\fR shell variable can be examined to see the directory stack and
+set to put arbitrary directories into the directory stack.
+.PP
+The character `=' followed by one or more digits expands to an entry in
+the directory stack. The special case `=\-' expands to the last directory in
+the stack. For example,
+.IP "" 4
+> dirs \-v
+.br
+0 /usr/bin
+.br
+1 /usr/spool/uucp
+.br
+2 /usr/accts/sys
+.br
+> echo =1
+.br
+/usr/spool/uucp
+.br
+> echo =0/calendar
+.br
+/usr/bin/calendar
+.br
+> echo =\-
+.br
+/usr/accts/sys
+.PP
+The \fBnoglob\fR and \fBnonomatch\fR shell variables and the \fIexpand-glob\fR
+editor command apply to directory stack as well as filename substitutions.
+.SS "Other substitutions (+)"
+There are several more transformations involving filenames, not strictly
+related to the above but mentioned here for completeness.
+\fIAny\fR filename may be expanded to a full path when the
+\fBsymlinks\fR variable (q.v.) is set to `expand'.
+Quoting prevents this expansion, and
+the \fInormalize-path\fR editor command does it on demand.
+The \fInormalize-command\fR editor command expands commands in PATH into
+full paths on demand.
+Finally, \fIcd\fR and \fIpushd\fR interpret `\-' as the old working directory
+(equivalent to the shell variable \fBowd\fR).
+This is not a substitution at all, but an abbreviation recognized only by
+those commands. Nonetheless, it too can be prevented by quoting.
+.SS Commands
+The next three sections describe how the shell executes commands and
+deals with their input and output.
+.SS Simple commands, pipelines and sequences
+A simple command is a sequence of words, the first of which specifies the
+command to be executed. A series of simple commands joined by `|' characters
+forms a pipeline. The output of each command in a pipeline is connected to the
+input of the next.
+.PP
+Simple commands and pipelines may be joined into sequences with `;', and will
+be executed sequentially. Commands and pipelines can also be joined into
+sequences with `||' or `&&', indicating, as in the C language, that the second
+is to be executed only if the first fails or succeeds respectively.
+.PP
+A simple command, pipeline or sequence may be placed in parentheses, `()',
+to form a simple command, which may in turn be a component of a pipeline or
+sequence. A command, pipeline or sequence can be executed
+without waiting for it to terminate by following it with an `&'.
+.SS "Builtin and non-builtin command execution"
+Builtin commands are executed within the shell. If any component of a
+pipeline except the last is a builtin command, the pipeline is executed
+in a subshell.
+.PP
+Parenthesized commands are always executed in a subshell.
+.IP "" 4
+(cd; pwd); pwd
+.PP
+thus prints the \fBhome\fR directory, leaving you where you were
+(printing this after the home directory), while
+.IP "" 4
+cd; pwd
+.PP
+leaves you in the \fBhome\fR directory. Parenthesized commands are most often
+used to prevent \fIcd\fR from affecting the current shell.
+.PP
+When a command to be executed is found not to be a builtin command the shell
+attempts to execute the command via \fIexecve\fR(2). Each word in the variable
+\fBpath\fR names a directory in which the shell will look for the
+command. If it is given neither a \fB\-c\fR nor a \fB\-t\fR option, the shell
+hashes the names in these directories into an internal table so that it will
+only try an \fIexecve\fR(2) in a directory if there is a possibility that the
+command resides there. This greatly speeds command location when a large
+number of directories are present in the search path. If this mechanism has
+been turned off (via \fIunhash\fR), if the shell was given a \fB\-c\fR or
+\fB\-t\fR argument or in any case for each directory component of \fBpath\fR
+which does not begin with a `/', the shell concatenates the current working
+directory with the given command name to form a path name of a file which it
+then attempts to execute.
+.PP
+If the file has execute permissions but is not an executable to the system
+(i.e. it is neither an executable binary nor a script which specifies its
+interpreter), then it is assumed to be a file containing shell commands and
+a new shell is spawned to read it. The \fIshell\fR special alias may be set
+to specify an interpreter other than the shell itself.
+.PP
+On systems which do not understand the `#!' script interpreter convention
+the shell may be compiled to emulate it; see the \fBversion\fR shell
+variable\fR. If so, the shell checks the first line of the file to
+see if it is of the form `#!\fIinterpreter\fR \fIarg\fR ...'. If it is,
+the shell starts \fIinterpreter\fR with the given \fIarg\fRs and feeds the
+file to it on standard input.
+.SS Input/output
+The standard input and standard output of a command may be redirected with the
+following syntax:
+.PP
+.PD 0
+.TP 8
+< \fIname
+Open file \fIname\fR (which is first variable, command and filename
+expanded) as the standard input.
+.TP 8
+<< \fIword
+Read the shell input up to a line which is identical to \fIword\fR. \fIword\fR
+is not subjected to variable, filename or command substitution, and each input
+line is compared to \fIword\fR before any substitutions are done on this input
+line. Unless a quoting `\e', `"', `' or ``' appears in \fIword\fR variable and
+command substitution is performed on the intervening lines, allowing `\e' to
+quote `$', `\e' and ``'. Commands which are substituted have all blanks, tabs,
+and newlines preserved, except for the final newline which is dropped. The
+resultant text is placed in an anonymous temporary file which is given to the
+command as standard input.
+.PP
+> \fIname
+.br
+>! \fIname
+.br
+>& \fIname
+.TP 8
+>&! \fIname
+The file \fIname\fR is used as standard output. If the file does not exist
+then it is created; if the file exists, its is truncated, its previous contents
+being lost.
+.RS +8
+.PD
+.PP
+If the shell variable \fBnoclobber\fR is set, then the file must not exist or be a
+character special file (e.g. a terminal or `/dev/null') or an error results.
+This helps prevent accidental destruction of files. In this case the `!' forms
+can be used to suppress this check.
+.PP
+The forms involving `&' route the diagnostic output into the specified file as
+well as the standard output. \fIname\fR is expanded in the same way as `<'
+input filenames are.
+.PD 0
+.RE
+.PP
+>> \fIname
+.br
+>>& \fIname
+.br
+>>! \fIname
+.TP 8
+>>&! \fIname
+Like `>', but appends output to the end of \fIname\fR.
+If the shell variable \fBnoclobber\fR is set, then it is an error for
+the file \fInot\fR to exist, unless one of the `!' forms is given.
+.PD
+.PP
+A command receives the environment in which the shell was invoked as modified
+by the input-output parameters and the presence of the command in a pipeline.
+Thus, unlike some previous shells, commands run from a file of shell commands
+have no access to the text of the commands by default; rather they receive the
+original standard input of the shell. The `<<' mechanism should be used to
+present inline data. This permits shell command scripts to function as
+components of pipelines and allows the shell to block read its input. Note
+that the default standard input for a command run detached is \fInot\fR
+the empty file \fI/dev/null\fR, but the original standard input of the shell.
+If this is a terminal and if the process attempts to read from the terminal,
+then the process will block and the user will be notified (see \fBJobs\fR).
+.PP
+Diagnostic output may be directed through a pipe with the standard output.
+Simply use the form `|&' rather than just `|'.
+.PP
+The shell cannot presently redirect diagnostic output without also redirecting
+standard output, but `(\fIcommand\fR > \fIoutput-file\fR) >& \fIerror-file\fR'
+is often an acceptable workaround. Either \fIoutput-file\fR or
+\fIerror-file\fR may be `/dev/tty' to send output to the terminal.
+.SS Features
+Having described how the shell accepts, parses and executes
+command lines, we now turn to a variety of its useful features.
+.SS "Control flow"
+The shell contains a number of commands which can be used to regulate the
+flow of control in command files (shell scripts) and (in limited but
+useful ways) from terminal input. These commands all operate by forcing the
+shell to reread or skip in its input and, due to the implementation,
+restrict the placement of some of the commands.
+.PP
+The \fIforeach\fR, \fIswitch\fR, and \fIwhile\fR statements, as well as the
+\fIif-then-else\fR form of the \fIif\fR statement, require that the major
+keywords appear in a single simple command on an input line as shown below.
+.PP
+If the shell's input is not seekable, the shell buffers up input whenever
+a loop is being read and performs seeks in this internal buffer to
+accomplish the rereading implied by the loop. (To the extent that this
+allows, backward \fIgoto\fRs will succeed on non-seekable inputs.)
+.SS Expressions
+The \fIif\fR, \fIwhile\fR and \fIexit\fR builtin commands
+use expressions with a common syntax. The expressions can include any
+of the operators described in the next three sections. Note that the \fI@\fR
+builtin command (q.v.) has its own separate syntax.
+.SS "Logical, arithmetical and comparison operators"
+These operators are similar to those of C and have the same precedence.
+They include
+.IP "" 4
+|| && | ^ & == != =~ !~ <= >=
+.br
+< > << >> + \- * / % ! ~ ( )
+.PP
+Here the precedence increases to the right, `==' `!=' `=~' and `!~', `<='
+`>=' `<' and `>', `<<' and `>>', `+' and `\-', `*' `/' and `%' being, in
+groups, at the same level. The `==' `!=' `=~' and `!~' operators compare
+their arguments as strings; all others operate on numbers. The operators
+`=~' and `!~' are like `!=' and `==' except that the right hand side is a
+glob-pattern (see \fBFilename substitution\fR) against which the left hand
+operand is matched. This reduces the need for use of the \fIswitch\fR
+builtin command in shell scripts when all that is really needed is
+pattern matching.
+.PP
+Strings which begin with `0' are considered octal numbers. Null or
+missing arguments are considered `0'. The results of all expressions are
+strings, which represent decimal numbers. It is important to note that
+no two components of an expression can appear in the same word; except
+when adjacent to components of expressions which are syntactically
+significant to the parser (`&' `|' `<' `>' `(' `)') they should be
+surrounded by spaces.
+.SS "Command exit status"
+Commands can be executed in expressions and their exit status
+returned by enclosing them in braces (`{}'). Remember that the braces should
+be separated from the words of the command by spaces. Command executions
+succeed, returning true, i.e. `1', if the command exits with status 0,
+otherwise they fail, returning false, i.e. `0'. If more detailed status
+information is required then the command should be executed outside of an
+expression and the \fBstatus\fR shell variable examined.
+.SS "File inquiry operators"
+Some of these operators perform true/false tests on files and related
+objects. They are of the form \fB\-\fIop file\fR, where \fIop\fR is one of
+.PP
+.PD 0
+.RS +4
+.TP 4
+.B r
+Read access
+.TP 4
+.B w
+Write access
+.TP 4
+.B x
+Execute access
+.TP 4
+.B X
+Executable in the path or shell builtin, e.g. `\-X ls' and `\-X ls\-F' are
+generally true, but `\-X /bin/ls' is not (+)
+.TP 4
+.B e
+Existence
+.TP 4
+.B o
+Ownership
+.TP 4
+.B z
+Zero size
+.TP 4
+.B s
+Non-zero size (+)
+.TP 4
+.B f
+Plain file
+.TP 4
+.B d
+Directory
+.TP 4
+.B l
+Symbolic link (+) *
+.TP 4
+.B b
+Block special file (+)
+.TP 4
+.B c
+Character special file (+)
+.TP 4
+.B p
+Named pipe (fifo) (+) *
+.TP 4
+.B S
+Socket special file (+) *
+.TP 4
+.B u
+Set-user-ID bit is set (+)
+.TP 4
+.B g
+Set-group-ID bit is set (+)
+.TP 4
+.B k
+Sticky bit is set (+)
+.TP 4
+.B t
+\fIfile\fR (which must be a digit) is an open file descriptor
+for a terminal device (+)
+.TP 4
+.B R
+Has been migrated (convex only) (+)
+.TP 4
+.B L
+Applies subsequent operators in a multiple-operator test to a symbolic link
+rather than to the file to which the link points (+) *
+.RE
+.PD
+.PP
+\fIfile\fR is command and filename expanded and then tested to
+see if it has the specified relationship to the real user. If \fIfile\fR
+does not exist or is inaccessible or, for the operators indicated by `*',
+if the specified file type does not exist on the current system,
+then all enquiries return false, i.e. `0'.
+.PP
+These operators may be combined for conciseness: `\-\fIxy file\fR' is
+equivalent to `\-\fIx file\fR && \-\fIy file\fR'. (+) For example, `\-fx' is true
+(returns `1') for plain executable files, but not for directories.
+.PP
+\fBL\fR may be used in a multiple-operator test to apply subsequent operators
+to a symbolic link rather than to the file to which the link points.
+For example, `\-lLo' is true for links owned by the invoking user.
+\fBLr\fR, \fBLw\fR and \fBLx\fR are always true for links and false for
+non-links. \fBL\fR has a different meaning when it is the last operator
+in a multiple-operator test; see below.
+.PP
+It is possible but not useful, and sometimes misleading, to combine operators
+which expect \fIfile\fR to be a file with operators which do not,
+(e.g. \fBX\fR and \fBt\fR). Following \fBL\fR with a non-file operator
+can lead to particularly strange results.
+.PP
+Other operators return other information, i.e. not just `0' or `1'. (+)
+They have the same format as before; \fIop\fR may be one of
+.PP
+.PD 0
+.RS +4
+.TP 8
+.B A
+Last file access time, as the number of seconds since the epoch
+.TP 8
+.B A:
+Like \fBA\fR, but in timestamp format, e.g. `Fri May 14 16:36:10 1993'
+.TP 8
+.B M
+Last file modification time
+.TP 8
+.B M:
+Like \fBM\fR, but in timestamp format
+.TP 8
+.B C
+Last inode modification time
+.TP 8
+.B C:
+Like \fBC\fR, but in timestamp format
+.TP 8
+.B D
+Device number
+.TP 8
+.B I
+Inode number
+.TP 8
+.B F
+Composite \fBf\fRile identifier, in the form \fIdevice\fR:\fIinode\fR
+.TP 8
+.B L
+The name of the file pointed to by a symbolic link
+.TP 8
+.B N
+Number of (hard) links
+.TP 8
+.B P
+Permissions, in octal, without leading zero
+.TP 8
+.B P:
+Like \fBP\fR, with leading zero
+.TP 8
+.B P\fImode
+Equivalent to `\-P \fIfile\fR & \fImode\fR', e.g. `\-P22 \fIfile\fR' returns
+`22' if \fIfile\fR is writable by group and other, `20' if by group only,
+and `0' if by neither
+.TP 8
+.B P\fImode\fB:
+Like \fBP\fImode\fB:\fR, with leading zero
+.TP 8
+.B U
+Numeric userid
+.TP 8
+.B U:
+Username, or the numeric userid if the username is unknown
+.TP 8
+.B G
+Numeric groupid
+.TP 8
+.B G:
+Groupname, or the numeric groupid if the groupname is unknown
+.TP 8
+.B Z
+Size, in bytes
+.RE
+.PD
+.PP
+Only one of these operators may appear in a multiple-operator test, and it
+must be the last. Note that \fBL\fR has a different meaning at the end of and
+elsewhere in a multiple-operator test. Because `0' is a valid return value
+for many of these operators, they do not return `0' when they fail: most
+return `\-1', and \fBF\fR returns `:'.
+.PP
+If the shell is compiled with POSIX defined (see the \fBversion\fR shell
+variable), the result of a file inquiry is based on the permission bits of
+the file and not on the result of the \fIaccess\fR(2) system call.
+For example, if one tests a file with \fB\-w\fR whose permissions would
+ordinarily allow writing but which is on a file system mounted read-only,
+the test will succeed in a POSIX shell but fail in a non-POSIX shell.
+.PP
+File inquiry operators can also be evaluated with the \fIfiletest\fR builtin
+command (q.v.) (+).
+.SS Jobs
+The shell associates a \fIjob\fR with each pipeline. It keeps a table of
+current jobs, printed by the \fIjobs\fR command, and assigns them small integer
+numbers. When a job is started asynchronously with `&', the shell prints a
+line which looks like
+.IP "" 4
+[1] 1234
+.PP
+indicating that the job which was started asynchronously was job number 1 and
+had one (top-level) process, whose process id was 1234.
+.PP
+If you are running a job and wish to do something else you may hit the suspend
+key (usually `^Z'),
+which sends a STOP signal to the current job. The shell will then normally
+indicate that the job has been `Suspended' and print another prompt.
+If the \fBlistjobs\fR shell variable is set, all jobs will be listed
+like the \fIjobs\fR builtin command; if it is set to `long' the listing will
+be in long format, like `jobs \-l'.
+You can then manipulate the state of the suspended job.
+You can put it in the
+``background'' with the \fIbg\fR command or run some other commands and
+eventually bring the job back into the ``foreground'' with \fIfg\fR.
+(See also the \fIrun-fg-editor\fR editor command.)
+A `^Z' takes effect immediately and is like an interrupt
+in that pending output and unread input are discarded when it is typed.
+The \fIwait\fR builtin command causes the shell to wait for all background
+jobs to complete.
+.PP
+The `^]' key sends a delayed suspend signal, which does not generate a STOP
+signal until a program attempts to \fIread\fR(2) it, to the current job.
+This can usefully be typed ahead when you have prepared some commands for a
+job which you wish to stop after it has read them.
+The `^Y' key performs this function in \fIcsh\fR(1); in \fItcsh\fR,
+`^Y' is an editing command. (+)
+.PP
+A job being run in the background stops if it tries to read from the
+terminal. Background jobs are normally allowed to produce output, but this can
+be disabled by giving the command `stty tostop'. If you set this tty option,
+then background jobs will stop when they try to produce output like they do
+when they try to read input.
+.PP
+There are several ways to refer to jobs in the shell. The character `%'
+introduces a job name. If you wish to refer to job number 1, you can name it
+as `%1'. Just naming a job brings it to the foreground; thus `%1' is a synonym
+for `fg %1', bringing job 1 back into the foreground. Similarly, saying `%1 &'
+resumes job 1 in the background, just like `bg %1'. A job can also be named
+by an unambiguous prefix of the string typed in to start it: `%ex' would
+normally restart a suspended \fIex\fR(1) job, if there were only one suspended
+job whose name began with the string `ex'. It is also possible to say
+`%?\fIstring\fR' to specify a job whose text contains \fIstring\fR, if there
+is only one such job.
+.PP
+The shell maintains a notion of the current and previous jobs. In output
+pertaining to jobs, the current job is marked with a `+' and the previous job
+with a `\-'. The abbreviations `%+', `%', and (by analogy with the syntax of
+the \fIhistory\fR mechanism) `%%' all refer to the current job, and `%\-' refers
+to the previous job.
+.PP
+The job control mechanism requires that the \fIstty\fR(1) option `new' be set
+on some systems. It is an artifact from a `new' implementation of the tty
+driver which allows generation of interrupt characters from the keyboard to
+tell jobs to stop. See \fIstty\fR(1) and the \fIsetty\fR builtin command for
+details on setting options in the new tty driver.
+.SS "Status reporting"
+The shell learns immediately whenever a process changes state. It normally
+informs you whenever a job becomes blocked so that no further progress is
+possible, but only just before it prints a prompt. This is done so that it
+does not otherwise disturb your work. If, however, you set the shell variable
+\fBnotify\fR, the shell will notify you immediately of changes of status in
+background jobs. There is also a shell command \fInotify\fR which marks a
+single process so that its status changes will be immediately reported. By
+default \fInotify\fR marks the current process; simply say `notify' after
+starting a background job to mark it.
+.PP
+When you try to leave the shell while jobs are stopped, you will be
+warned that `You have stopped jobs.' You may use the \fIjobs\fR command to see
+what they are. If you do this or immediately try to exit again, the shell will
+not warn you a second time, and the suspended jobs will be terminated.
+.SS "Automatic, periodic and timed events (+)"
+There are various ways to run commands and take other actions automatically
+at various times in the ``life cycle'' of the shell. They are summarized here,
+and described in detail under the appropriate \fBBuiltin commands\fR,
+\fBSpecial shell variables\fR and \fBSpecial aliases\fR.
+.PP
+The \fIsched\fR builtin command puts commands in a scheduled-event list,
+to be executed by the shell at a given time.
+.PP
+The \fIbeepcmd\fR, \fIcwdcmd\fR, \fIperiodic\fR, \fIprecmd\fR, and \fIpostcmd\fR
+\fBSpecial aliases\fR can be set, respectively, to execute commands when the shell wants
+to ring the bell, when the working directory changes, every \fBtperiod\fR
+minutes, before each prompt, and before each command gets executed.
+.PP
+The \fBautologout\fR shell variable can be set to log out or lock the shell
+after a given number of minutes of inactivity.
+.PP
+The \fBmail\fR shell variable can be set to check for new mail periodically.
+.PP
+The \fBprintexitvalue\fR shell variable can be set to print the exit status
+of commands which exit with a status other than zero.
+.PP
+The \fBrmstar\fR shell variable can be set to ask the user, when `rm *' is
+typed, if that is really what was meant.
+.PP
+The \fBtime\fR shell variable can be set to execute the \fItime\fR builtin
+command after the completion of any process that takes more than a given
+number of CPU seconds.
+.PP
+The \fBwatch\fR and \fBwho\fR shell variables can be set to report when
+selected users log in or out, and the \fIlog\fR builtin command reports
+on those users at any time.
+.SS "Native Language System support (+)"
+The shell is eight bit clean
+(if so compiled; see the \fBversion\fR shell variable)
+and thus supports character sets needing this capability.
+NLS support differs depending on whether or not
+the shell was compiled to use the system's NLS (again, see \fBversion\fR).
+In either case, 7-bit ASCII is the default for character classification
+(e.g. which characters are printable) and sorting,
+and changing the \fBLANG\fR or \fBLC_CTYPE\fR environment variables
+causes a check for possible changes in these respects.
+.PP
+When using the system's NLS, the \fIsetlocale\fR(3) function is called
+to determine appropriate character classification and sorting.
+This function typically examines the \fBLANG\fR and \fBLC_CTYPE\fR
+environment variables; refer to the system documentation for further details.
+When not using the system's NLS, the shell simulates it by assuming that the
+ISO 8859-1 character set is used
+whenever either of the \fBLANG\fR and \fBLC_CTYPE\fR variables are set, regardless of
+their values. Sorting is not affected for the simulated NLS.
+.PP
+In addition, with both real and simulated NLS, all printable
+characters in the range \e200\-\e377, i.e. those that have
+M-\fIchar\fR bindings, are automatically rebound to \fIself-insert-command\fR.
+The corresponding binding for the escape-\fIchar\fR sequence, if any, is
+left alone.
+These characters are not rebound if the \fBNOREBIND\fR environment variable
+is set. This may be useful for the simulated NLS or a primitive real NLS
+which assumes full ISO 8859-1. Otherwise, all M-\fIchar\fR bindings in the
+range \e240\-\e377 are effectively undone.
+Explicitly rebinding the relevant keys with \fIbindkey\fR
+is of course still possible.
+.PP
+Unknown characters (i.e. those that are neither printable nor control
+characters) are printed in the format \ennn.
+If the tty is not in 8 bit mode, other 8 bit characters are printed by
+converting them to ASCII and using standout mode. The shell
+never changes the 7/8 bit mode of the tty and tracks user-initiated
+changes of 7/8 bit mode. NLS users (or, for that matter, those who want to
+use a meta key) may need to explicitly set
+the tty in 8 bit mode through the appropriate \fIstty\fR(1)
+command in, e.g., the \fI~/.login\fR file.
+.SS "OS variant support (+)"
+A number of new builtin commands are provided to support features in
+particular operating systems. All are described in detail in the
+\fBBuiltin commands\fR section.
+.PP
+On systems that support TCF (aix-ibm370, aix-ps2),
+\fIgetspath\fR and \fIsetspath\fR get and set the system execution path,
+\fIgetxvers\fR and \fIsetxvers\fR get and set the experimental version prefix
+and \fImigrate\fR migrates processes between sites. The \fIjobs\fR builtin
+prints the site on which each job is executing.
+.PP
+Under Domain/OS, \fIinlib\fR adds shared libraries to the current environment,
+\fIrootnode\fR changes the rootnode and \fIver\fR changes the systype.
+.PP
+Under Mach, \fIsetpath\fR is equivalent to Mach's \fIsetpath\fR(1).
+.PP
+Under Masscomp/RTU and Harris CX/UX, \fIuniverse\fR sets the universe.
+.PP
+Under Harris CX/UX, \fIucb\fR or \fIatt\fR runs a command under the specified
+universe.
+.PP
+Under Convex/OS, \fIwarp\fR prints or sets the universe.
+.PP
+The \fBVENDOR\fR, \fBOSTYPE\fR and \fBMACHTYPE\fR environment variables
+indicate respectively the vendor, operating system and machine type
+(microprocessor class or machine model) of the
+system on which the shell thinks it is running.
+These are particularly useful when sharing one's home directory between several
+types of machines; one can, for example,
+.IP "" 4
+set path = (~/bin.$MACHTYPE /usr/ucb /bin /usr/bin .)
+.PP
+in one's \fI~/.login\fR and put executables compiled for each machine in the
+appropriate directory.
+.PP
+The \fBversion\fR shell
+variable indicates what options were chosen when the shell was compiled.
+.PP
+Note also the \fInewgrp\fR builtin, the \fBafsuser\fR and
+\fBecho_style\fR shell variables and the system-dependent locations of
+the shell's input files (see \fBFILES\fR).
+.SS "Signal handling"
+Login shells ignore interrupts when reading the file \fI~/.logout\fR.
+The shell ignores quit signals unless started with \fB\-q\fR.
+Login shells catch the terminate signal, but non-login shells inherit the
+terminate behavior from their parents.
+Other signals have the values which the shell inherited from its parent.
+.PP
+In shell scripts, the shell's handling of interrupt and terminate signals
+can be controlled with \fIonintr\fR, and its handling of hangups can be
+controlled with \fIhup\fR and \fInohup\fR.
+.PP
+The shell exits on a hangup (see also the \fBlogout\fR shell variable). By
+default, the shell's children do too, but the shell does not send them a
+hangup when it exits. \fIhup\fR arranges for the shell to send a hangup to
+a child when it exits, and \fInohup\fR sets a child to ignore hangups.
+.SS "Terminal management (+)"
+The shell uses three different sets of terminal (``tty'') modes:
+`edit', used when editing, `quote', used when quoting literal characters,
+and `execute', used when executing commands.
+The shell holds some settings in each mode constant, so commands which leave
+the tty in a confused state do not interfere with the shell.
+The shell also matches changes in the speed and padding of the tty.
+The list of tty modes that are kept constant
+can be examined and modified with the \fIsetty\fR builtin.
+Note that although the editor uses CBREAK mode (or its equivalent),
+it takes typed-ahead characters anyway.
+.PP
+The \fIechotc\fR, \fIsettc\fR and \fItelltc\fR commands can be used to
+manipulate and debug terminal capabilities from the command line.
+.PP
+On systems that support SIGWINCH or SIGWINDOW, the shell
+adapts to window resizing automatically and adjusts the environment
+variables \fBLINES\fR and \fBCOLUMNS\fR if set. If the environment
+variable \fBTERMCAP\fR contains li# and co# fields, the shell adjusts
+them to reflect the new window size.
+.SH REFERENCE
+The next sections of this manual describe all of the available
+\fBBuiltin commands\fR, \fBSpecial aliases\fR and
+\fBSpecial shell variables\fR.
+.SS "Builtin commands"
+.TP 8
+.B %\fIjob
+A synonym for the \fIfg\fR builtin command.
+.TP 8
+.B %\fIjob \fB&
+A synonym for the \fIbg\fR builtin command.
+.TP 8
+.B :
+Does nothing, successfully.
+.PP
+.B @
+.br
+.B @ \fIname\fB = \fIexpr
+.br
+.B @ \fIname\fR[\fIindex\fR]\fB = \fIexpr
+.br
+.B @ \fIname\fB++\fR|\fB--
+.PD 0
+.TP 8
+.B @ \fIname\fR[\fIindex\fR]\fB++\fR|\fB--
+The first form prints the values of all shell variables.
+.PD
+.RS +8
+.PP
+The second form assigns the value of \fIexpr\fR to \fIname\fR.
+The third form assigns the value of \fIexpr\fR to the \fIindex\fR'th
+component of \fIname\fR; both \fIname\fR and its \fIindex\fR'th component
+must already exist.
+.PP
+\fIexpr\fR may contain the operators `*', `+', etc. as in C.
+If \fIexpr\fR contains `<', `>', `&' or `' then at least that part of
+\fIexpr\fR must be placed within `()'.
+Note that the syntax of \fIexpr\fR has nothing to do with that described
+under \fBExpressions\fR.
+.PP
+The fourth and fifth forms increment (`++') or decrement (`\-\-') \fIname\fR
+or its \fIindex\fR'th component.
+.PP
+The space between `@' and \fIname\fR is required. The spaces between
+\fIname\fR and `=' and between `=' and \fIexpr\fR are optional. Components of
+\fIexpr\fR must be separated by spaces.
+.RE
+.PD
+.TP 8
+.B alias \fR[\fIname \fR[\fIwordlist\fR]]
+Without arguments, prints all aliases.
+With \fIname\fR, prints the alias for name.
+With \fIname\fR and \fIwordlist\fR, assigns
+\fIwordlist\fR as the alias of \fIname\fR.
+\fIwordlist\fR is command and filename substituted.
+\fIname\fR may not be `alias' or `unalias'.
+See also the \fIunalias\fR builtin command.
+.ig \" Obsolete tcsh command
+.TP 8
+.B aliases \fR[\fIfile\fR] (+)
+Without arguments, prints all aliases.
+With \fIfile\fR, loads a list of aliases from \fIfile\fR, one per line.
+Retained only for downward compatibility.
+..
+.TP 8
+.B alloc
+Shows the amount of dynamic memory acquired, broken down into used and free
+memory. With an argument shows the number of free and used blocks in each size
+category. The categories start at size 8 and double at each step. This
+command's output may vary across system types, since systems other than the VAX
+may use a different memory allocator.
+.TP 8
+.B bg \fR[\fB%\fIjob\fR ...]
+Puts the specified jobs (or, without arguments, the current job)
+into the background, continuing each if it is stopped.
+\fIjob\fR may be a number, a string, `', `%', `+' or `\-' as described
+under \fBJobs\fR.
+.ig \" Obsolete tcsh command
+.TP 8
+.B bind \fR[\fBdefaults\fR|\fBemacs\fR|\fBvi\fR|\fIkey\fR|\fIkey command\fR] (+)
+An older version of \fIbindkey\fR, retained only for downward compatibility.
+Without arguments, lists all bound keys and the editor command to which each is bound.
+`bind defaults', `bind emacs' and `bind vi' are equivalent to
+`bindkey \-d', `bindkey \-e' and `bindkey \-v'.
+With \fIkey\fR, lists the editor command to which \fIkey\fR is bound.
+With \fIkey\fR and \fIcommand\fR, binds the editor command \fIcommand\fR to \fIkey\fR.
+.IP "" 8
+\fIkey\fR may be a literal character,
+a control character written ^\fIcharacter\fR (e.g. `^A'),
+a meta character written M-\fIcharacter\fR (e.g. `M-A')
+or a function key written F-\fIstring\fR (e.g. `F-foo').
+For the function key form to work, the function key prefix must be
+bound to \fIsequence-lead-in\fR and \fIstring\fR must not contain that prefix.
+..
+.PP
+.B bindkey \fR[\fB\-l\fR|\fB\-d\fR|\fB\-e\fR|\fB\-v\fR|\fB\-u\fR] (+)
+.br
+\fBbindkey \fR[\fB\-a\fR] [\fB\-b\fR] [\fB\-k\fR] [\fB\-r\fR] [\fB\-\-\fR] \fIkey \fR(+)
+.PD 0
+.TP 8
+\fBbindkey \fR[\fB\-a\fR] [\fB\-b\fR] [\fB\-k\fR] [\fB\-c\fR|\fB\-s\fR] [\fB\-\-\fR] \fIkey command \fR(+)
+.\" .B macro can't take too many words, so I used \fB in the previous tags
+Without options, the first form lists all bound keys and the editor command to which each is bound,
+the second form lists the editor command to which \fIkey\fR is bound and
+the third form binds the editor command \fIcommand\fR to \fIkey\fR.
+Options include:
+.PD
+.PP
+.PD 0
+.RS +8
+.TP 4
+.B \-l
+Lists all editor commands and a short description of each.
+.TP 4
+.B \-d
+Binds all keys to the standard bindings for the default editor.
+.TP 4
+.B \-e
+Binds all keys to the standard GNU Emacs-like bindings.
+.TP 4
+.B \-v
+Binds all keys to the standard \fIvi\fR(1)-like bindings.
+.TP 4
+.B \-a
+Lists or changes key-bindings in the alternative key map.
+This is the key map used in \fIvi\fR command mode.
+.TP 4
+.B \-b
+\fIkey\fR is interpreted as
+a control character written ^\fIcharacter\fR (e.g. `^A') or
+C-\fIcharacter\fR (e.g. `C-A'),
+a meta character written M-\fIcharacter\fR (e.g. `M-A'),
+a function key written F-\fIstring\fR (e.g. `F-string'),
+or an extended prefix key written X-\fIcharacter\fR (e.g. `X-A').
+.TP 4
+.B \-k
+\fIkey\fR is interpreted as a symbolic arrow key name, which may be one of
+`down', `up', `left' or `right'.
+.TP 4
+.B \-r
+Removes \fIkey\fR's binding.
+Be careful: `bindkey \-r' does \fInot\fR bind \fIkey\fR to
+\fIself-insert-command\fR (q.v.), it unbinds \fIkey\fR completely.
+.TP 4
+.B \-c
+\fIcommand\fR is interpreted as a builtin or external command instead of an
+editor command.
+.TP 4
+.B \-s
+\fIcommand\fR is taken as a literal string and treated as terminal input
+when \fIkey\fR is typed. Bound keys in \fIcommand\fR are themselves
+reinterpreted, and this continues for ten levels of interpretation.
+.TP 4
+.B \-\-
+Forces a break from option processing, so the next word is taken as \fIkey\fR
+even if it begins with '\-'.
+.TP 4
+.B \-u \fR(or any invalid option)
+Prints a usage message.
+.PD
+.PP
+\fIkey\fR may be a single character or a string.
+If a command is bound to a string, the first character of the string is bound to
+\fIsequence-lead-in\fR and the entire string is bound to the command.
+.PP
+Control characters in \fIkey\fR can be literal (they can be typed by preceding
+them with the editor command \fIquoted-insert\fR, normally bound to `^V') or
+written caret-character style, e.g. `^A'. Delete is written `^?'
+(caret-question mark). \fIkey\fR and \fIcommand\fR can contain backslashed
+escape sequences (in the style of System V \fIecho\fR(1)) as follows:
+.RS +4
+.TP 8
+.PD 0
+.B \ea
+Bell
+.TP 8
+.B \eb
+Backspace
+.TP 8
+.B \ee
+Escape
+.TP 8
+.B \ef
+Form feed
+.TP 8
+.B \en
+Newline
+.TP 8
+.B \er
+Carriage return
+.TP 8
+.B \et
+Horizontal tab
+.TP 8
+.B \ev
+Vertical tab
+.TP 8
+.B \e\fInnn
+The ASCII character corresponding to the octal number \fInnn\fR
+.PD
+.RE
+.PP
+`\e' nullifies the special meaning of the following character, if it has
+any, notably `\\' and `^'.
+.RE
+.TP 8
+.B break
+Causes execution to resume after the \fIend\fR of the nearest
+enclosing \fIforeach\fR or \fIwhile\fR. The remaining commands on the
+current line are executed. Multi-level breaks are thus
+possible by writing them all on one line.
+.TP 8
+.B breaksw
+Causes a break from a \fIswitch\fR, resuming after the \fIendsw\fR.
+.TP 8
+.B builtins \fR(+)
+Prints the names of all builtin commands.
+.TP 8
+.B bye \fR(+)
+A synonym for the \fIlogout\fR builtin command.
+Available only if the shell was so compiled;
+see the \fBversion\fR shell variable.
+.TP 8
+.B case \fIlabel\fB:
+A label in a \fIswitch\fR statement as discussed below.
+.TP 8
+.B cd \fR[\fB\-p\fR] [\fB\-l\fR] [\fB\-n\fR|\fB\-v\fR] [\fIname\fR]
+If a directory \fIname\fR is given, changes the shell's working directory
+to \fIname\fR. If not, changes to \fBhome\fR.
+If \fIname\fR is `\-' it is interpreted as the previous working directory
+(see \fBOther substitutions\fR). (+)
+If \fIname\fR is not a subdirectory of the current directory
+(and does not begin with `/', `./' or `../'), each component of the variable
+\fBcdpath\fR is checked to see if it has a subdirectory \fIname\fR. Finally, if
+all else fails but \fIname\fR is a shell variable whose value
+begins with `/', then this is tried to see if it is a directory.
+.RS +8
+.PP
+With \fB\-p\fR, prints the final directory stack, just like \fIdirs\fR.
+The \fB\-l\fR, \fB\-n\fR and \fB\-v\fR flags have the same effect on \fIcd\fR
+as on \fIdirs\fR, and they imply \fB\-p\fR. (+)
+.PP
+See also the \fBimplicitcd\fR shell variable.
+.RE
+.TP 8
+.B chdir
+A synonym for the \fIcd\fR builtin command.
+.TP 8
+.B complete \fR[\fIcommand\fR [\fIword\fB/\fIpattern\fB/\fIlist\fR[\fB:\fIselect\fR]\fB/\fR[[\fIsuffix\fR]\fB/\fR] ...]] (+)
+Without arguments, lists all completions.
+With \fIcommand\fR, lists completions for \fIcommand\fR.
+With \fIcommand\fR and \fIword\fR etc., defines completions.
+.RS +8
+.PP
+\fIcommand\fR may be a full command name or a glob-pattern
+(see \fBFilename substitution\fR). It can begin with `\-' to indicate that
+completion should be used only when \fIcommand\fR is ambiguous.
+.PP
+\fIword\fR specifies which word relative to the current word
+is to be completed, and may be one of the following:
+.PP
+.PD 0
+.RS +4
+.TP 4
+.B c
+Current-word completion.
+\fIpattern\fR is a glob-pattern which must match the beginning of the current word on
+the command line. \fIpattern\fR is ignored when completing the current word.
+.TP 4
+.B C
+Like \fBc\fR, but includes \fIpattern\fR when completing the current word.
+.TP 4
+.B n
+Next-word completion.
+\fIpattern\fR is a glob-pattern which must match the beginning of the previous word on
+the command line.
+.TP 4
+.B N
+Like \fBn\fR, but must match the beginning of the word two before the current word.
+.TP 4
+.B p
+Position-dependent completion.
+\fIpattern\fR is a numeric range, with the same syntax used to index shell
+variables, which must include the current word.
+.PD
+.RE
+.ig \" No longer true in 6.05.04
+.PP
+When \fIpattern\fR is a glob-pattern (for \fBc\fR, \fBC\fR, \fBn\fR and
+\fBN\fR-type completion), a \fIpattern\fR of `*' does not match an empty
+word.
+..
+.PP
+\fIlist\fR, the list of possible completions, may be one of the following:
+.PP
+.PD 0
+.RS +4
+.TP 8
+.B a
+Aliases
+.TP 8
+.B b
+Bindings (editor commands)
+.TP 8
+.B c
+Commands (builtin or external commands)
+.TP 8
+.B C
+External commands which begin with the supplied path prefix
+.TP 8
+.B d
+Directories
+.TP 8
+.B D
+Directories which begin with the supplied path prefix
+.TP 8
+.B e
+Environment variables
+.TP 8
+.B f
+Filenames
+.TP 8
+.B F
+Filenames which begin with the supplied path prefix
+.TP 8
+.B g
+Groupnames
+.TP 8
+.B j
+Jobs
+.TP 8
+.B l
+Limits
+.TP 8
+.B n
+Nothing
+.TP 8
+.B s
+Shell variables
+.TP 8
+.B S
+Signals
+.TP 8
+.B t
+Plain (``text'') files
+.TP 8
+.B T
+Plain (``text'') files which begin with the supplied path prefix
+.TP 8
+.B v
+Any variables
+.TP 8
+.B u
+Usernames
+.TP 8
+.B x
+Like \fBn\fR, but prints \fIselect\fR when \fIlist-choices\fR is used.
+.TP 8
+.B X
+Completions
+.TP 8
+$\fIvar\fR
+Words from the variable \fIvar\fR
+.TP 8
+(...)
+Words from the given list
+.TP 8
+`...`
+Words from the output of command
+.PD
+.RE
+.PP
+\fIselect\fR is an optional glob-pattern.
+If given, only words from \fIlist\fR which match \fIselect\fR are considered
+and the \fBfignore\fR shell variable is ignored.
+The last three types of completion may not have a \fIselect\fR
+pattern, and \fBx\fR uses \fIselect\fR as an explanatory message when
+the \fIlist-choices\fR editor command is used.
+.PP
+\fIsuffix\fR is a single character to be appended to a successful
+completion. If null, no character is appended. If omitted (in which
+case the fourth delimiter can also be omitted), a slash is appended to
+directories and a space to other words.
+.PP
+Now for some examples. Some commands take only directories as arguments,
+so there's no point completing plain files.
+.IP "" 4
+> complete cd 'p/1/d/'
+.PP
+completes only the first word following `cd' (`p/1') with a directory.
+\fBp\fR-type completion can also be used to narrow down command completion:
+.IP "" 4
+> co[^D]
+.br
+complete compress
+.br
+> complete \-co* 'p/0/(compress)/'
+.br
+> co[^D]
+.br
+> compress
+.PP
+This completion completes commands (words in position 0, `p/0')
+which begin with `co' (thus matching `co*') to `compress' (the only
+word in the list).
+The leading `\-' indicates that this completion is to be used only with
+ambiguous commands.
+.IP "" 4
+> complete find 'n/\-user/u/'
+.PP
+is an example of \fBn\fR-type completion. Any word following `find' and
+immediately following `\-user' is completed from the list of users.
+.IP "" 4
+> complete cc 'c/\-I/d/'
+.PP
+demonstrates \fBc\fR-type completion. Any word following `cc' and beginning
+with `\-I' is completed as a directory. `\-I' is not taken as part of the
+directory because we used lowercase \fBc\fR.
+.PP
+Different \fIlist\fRs are useful with different commands.
+.IP "" 4
+> complete alias 'p/1/a/'
+.br
+> complete man 'p/*/c/'
+.br
+> complete set 'p/1/s/'
+.br
+> complete true 'p/1/x:Truth has no options./'
+.PP
+These complete words following `alias' with aliases, `man' with commands,
+and `set' with shell variables.
+`true' doesn't have any options, so \fBx\fR does nothing when completion
+is attempted and prints `Truth has no options.' when completion choices are listed.
+.PP
+.ig \" Changed in 6.05.04
+The \fIman\fR example, and several other examples below, use
+\fBp\fR-type completion, rather than \fBC\fR- or \fBn\fR-type, so that
+`*' will match an empty word.
+..
+Note that the \fIman\fR example, and several other examples below, could
+just as well have used 'c/*' or 'n/*' as 'p/*'.
+.PP
+Words can be completed from a variable evaluated at completion time,
+.IP "" 4
+> complete ftp 'p/1/$hostnames/'
+.br
+> set hostnames = (rtfm.mit.edu tesla.ee.cornell.edu)
+.br
+> ftp [^D]
+.br
+rtfm.mit.edu tesla.ee.cornell.edu
+.br
+> ftp [^C]
+.br
+> set hostnames = (rtfm.mit.edu tesla.ee.cornell.edu uunet.uu.net)
+.br
+> ftp [^D]
+.br
+rtfm.mit.edu tesla.ee.cornell.edu uunet.uu.net
+.PP
+or from a command run at completion time:
+.IP "" 4
+> complete kill 'p/*/`ps | awk \\{print\\ \\$1\\}`/'
+.br
+> kill \-9 [^D]
+.br
+23113 23377 23380 23406 23429 23529 23530 PID
+.PP
+Note that the \fIcomplete\fR command does not itself quote its arguments,
+so the braces, space and `$' in `{print $1}' must be quoted explicitly.
+.PP
+One command can have multiple completions:
+.IP "" 4
+> complete dbx 'p/2/(core)/' 'p/*/c/'
+.PP
+completes the second argument to `dbx' with the word `core' and all other
+arguments with commands. Note that the positional completion is specified
+before the next-word completion.
+Since completions are evaluated from left to right, if
+the next-word completion were specified first it would always match
+and the positional completion would never be executed. This is a
+common mistake when defining a completion.
+.PP
+The \fIselect\fR pattern is useful when a command takes only files with
+particular forms as arguments. For example,
+.IP "" 4
+> complete cc 'p/*/f:*.[cao]/'
+.PP
+completes `cc' arguments only to files ending in `.c', `.a', or `.o'.
+\fIselect\fR can also exclude files, using negation of a glob-pattern as
+described under \fBFilename substitution\fR. One might use
+.IP "" 4
+> complete rm 'p/*/f:^*.{c,h,cc,C,tex,1,man,l,y}/'
+.PP
+to exclude precious source code from `rm' completion. Of course, one
+could still type excluded names manually or override the completion
+mechanism using the \fIcomplete-word-raw\fR or \fIlist-choices-raw\fR
+editor commands (q.v.).
+.PP
+The `C', `D', `F' and `T' \fIlist\fRs are like `c', `d', `f' and `t'
+respectively, but they use the \fIselect\fR argument in a different way: to
+restrict completion to files beginning with a particular path prefix. For
+example, the Elm mail program uses `=' as an abbreviation for one's mail
+directory. One might use
+.IP "" 4
+> complete elm c@=@F:$HOME/Mail/@
+.PP
+to complete `elm \-f =' as if it were `elm \-f ~/Mail/'. Note that we used `@'
+instead of `/' to avoid confusion with the \fIselect\fR argument, and we used
+`$HOME' instead of `~' because home directory substitution only works at the
+beginning of a word.
+.PP
+\fIsuffix\fR is used to add a nonstandard suffix
+(not space or `/' for directories) to completed words.
+.IP "" 4
+> complete finger 'c/*@/$hostnames/' 'p/1/u/@'
+.PP
+completes arguments to `finger' from the list of users, appends an `@',
+and then completes after the `@' from the `hostnames' variable. Note
+again the order in which the completions are specified.
+.PP
+Finally, here's a complex example for inspiration:
+.IP "" 4
+> complete find \\
+.br
+\'n/\-name/f/' 'n/\-newer/f/' 'n/\-{,n}cpio/f/' \e
+.br
+\'n/\-exec/c/' 'n/\-ok/c/' 'n/\-user/u/' \e
+.br
+\'n/\-group/g/' 'n/\-fstype/(nfs 4.2)/' \e
+.br
+\'n/\-type/(b c d f l p s)/' \e
+.br
+\'c/\-/(name newer cpio ncpio exec ok user \e
+.br
+group fstype type atime ctime depth inum \e
+.br
+ls mtime nogroup nouser perm print prune \e
+.br
+size xdev)/' \e
+.br
+\'p/*/d/'
+.PP
+This completes words following `\-name', `\-newer', `\-cpio' or `ncpio'
+(note the pattern which matches both) to files,
+words following `\-exec' or `\-ok' to commands, words following `user'
+and `group' to users and groups respectively
+and words following `\-fstype' or `\-type' to members of the
+given lists. It also completes the switches themselves from the given list
+(note the use of \fBc\fR-type completion)
+and completes anything not otherwise completed to a directory. Whew.
+.PP
+Remember that programmed completions are ignored if the word being completed
+is a tilde substitution (beginning with `~') or a variable (beginning with `$').
+\fIcomplete\fR is an experimental feature, and the syntax may change
+in future versions of the shell.
+See also the \fIuncomplete\fR builtin command.
+.RE
+.TP 8
+.B continue
+Continues execution of the nearest enclosing \fIwhile\fR or \fIforeach\fR.
+The rest of the commands on the current line are executed.
+.TP 8
+.B default:
+Labels the default case in a \fIswitch\fR statement.
+It should come after all \fIcase\fR labels.
+.PP
+.B dirs \fR[\fB\-l\fR] [\fB\-n\fR|\fB\-v\fR]
+.br
+.B dirs \-S\fR|\fB\-L \fR[\fIfilename\fR] (+)
+.PD 0
+.TP 8
+.B dirs \-c \fR(+)
+The first form prints the directory stack. The top of the stack is at the
+left and the first directory in the stack is the current directory.
+With \fB\-l\fR, `~' or `~\fIname\fP' in the output is expanded explicitly
+to \fBhome\fR or the pathname of the home directory for user \fIname\fP. (+)
+With \fB\-n\fR, entries are wrapped before they reach the edge of the screen. (+)
+With \fB\-v\fR, entries are printed one per line, preceded by their stack positions. (+)
+If more than one of \fB\-n\fR or \fB\-v\fR is given, \fB\-v\fR takes precedence.
+\fB\-p\fR is accepted but does nothing.
+.PD
+.RS +8
+.PP
+With \fB\-S\fR, the second form saves the directory stack to \fIfilename\fR
+as a series of \fIcd\fR and \fIpushd\fR commands.
+With \fB\-L\fR, the shell sources \fIfilename\fR, which is presumably
+a directory stack file saved by the \fB\-S\fR option or the \fBsavedirs\fR
+mechanism.
+In either case, \fBdirsfile\fR is used if \fIfilename\fR is not given and
+\fI~/.cshdirs\fR is used if \fBdirsfile\fR is unset.
+.PP
+Note that login shells do the equivalent of `dirs \-L' on startup
+and, if \fBsavedirs\fR is set, `dirs \-S' before exiting.
+Because only \fI~/.tcshrc\fR is normally sourced before \fI~/.cshdirs\fR,
+\fBdirsfile\fR should be set in \fI~/.tcshrc\fR rather than \fI~/.login\fR.
+.PP
+The last form clears the directory stack.
+.RE
+.TP 8
+.B echo \fR[\fB\-n\fR] \fIword\fR ...
+Writes each \fIword\fR to the shell's standard
+output, separated by spaces and terminated with a newline.
+The \fBecho_style\fR shell variable may be set to emulate (or not) the flags and escape
+sequences of the BSD and/or System V versions of \fIecho\fR; see \fIecho\fR(1).
+.TP 8
+.B echotc \fR[\fB\-sv\fR] \fIarg\fR ... (+)
+Exercises the terminal capabilities (see \fItermcap\fR(5)) in \fIargs\fR.
+For example, 'echotc home' sends the cursor to the home position,
+\&'echotc cm 3 10' sends it to column 3 and row 10, and
+\&'echotc ts 0; echo "This is a test."; echotc fs' prints "This is a test."
+in the status line.
+.RS +8
+.PP
+If \fIarg\fR is 'baud', 'cols', 'lines', 'meta' or 'tabs', prints the
+value of that capability ("yes" or "no" indicating that the terminal does
+or does not have that capability). One might use this to make the output
+from a shell script less verbose on slow terminals, or limit command
+output to the number of lines on the screen:
+.IP "" 4
+> set history=`echotc lines`
+.br
+> @ history\-\-
+.PP
+Termcap strings may contain wildcards which will not echo correctly.
+One should use double quotes when setting a shell variable to a terminal
+capability string, as in the following example that places the date in
+the status line:
+.IP "" 4
+> set tosl="`echotc ts 0`"
+.br
+> set frsl="`echotc fs`"
+.br
+> echo \-n "$tosl";date; echo \-n "$frsl"
+.PP
+With \fB\-s\fR, nonexistent capabilities return the empty string rather
+than causing an error.
+With \fB\-v\fR, messages are verbose.
+.RE
+.PP
+.B else
+.br
+.B end
+.br
+.B endif
+.PD 0
+.TP 8
+.B endsw
+See the description of the \fIforeach\fR, \fIif\fR, \fIswitch\fR, and
+\fIwhile\fR statements below.
+.PD
+.TP 8
+.B eval \fIarg\fR ...
+Treats the arguments as input to the
+shell and executes the resulting command(s) in the context
+of the current shell. This is usually used to execute commands
+generated as the result of command or variable substitution,
+since parsing occurs before these substitutions.
+See \fItset\fR(1) for a sample use of \fIeval\fR.
+.TP 8
+.B exec \fIcommand\fR
+Executes the specified command in place of the current shell.
+.TP 8
+.B exit \fR[\fIexpr\fR]
+The shell exits either with the value of the specified \fIexpr\fR
+(an expression, as described under \fBExpressions\fR)
+or, without \fIexpr\fR, with the value of the \fBstatus\fR variable.
+.TP 8
+.B fg \fR[\fB%\fIjob\fR ...]
+Brings the specified jobs (or, without arguments, the current job)
+into the foreground, continuing each if it is stopped.
+\fIjob\fR may be a number, a string, `', `%', `+' or `\-' as described
+under \fBJobs\fR.
+See also the \fIrun-fg-editor\fR editor command.
+.TP 8
+.B filetest \-\fIop file\fR ... (+)
+Applies \fIop\fR (which is a file inquiry operator as described under
+\fBFile inquiry operators\fR) to each \fIfile\fR and returns the results as a
+space-separated list.
+.PP
+.B foreach \fIname \fB(\fIwordlist\fB)
+.br
+\&...
+.PD 0
+.TP 8
+.B end
+Successively sets the variable \fIname\fR to each member of
+\fIwordlist\fR and executes the sequence of commands between this command
+and the matching \fIend\fR. (Both \fIforeach\fR and \fIend\fR
+must appear alone on separate lines.) The builtin command
+\fIcontinue\fR may be used to continue the loop prematurely and
+the builtin command \fIbreak\fR to terminate it prematurely.
+When this command is read from the terminal, the loop is read once
+prompting with `foreach? ' (or \fBprompt2\fR) before any statements in
+the loop are executed. If you make a mistake typing in a
+loop at the terminal you can rub it out.
+.PD
+.TP 8
+.B getspath \fR(+)
+Prints the system execution path. (TCF only)
+.TP 8
+.B getxvers \fR(+)
+Prints the experimental version prefix. (TCF only)
+.TP 8
+.B glob \fIwordlist
+Like \fIecho\fR, but no `\\' escapes are recognized and words are
+delimited by null characters in the output. Useful for
+programs which wish to use the shell to filename expand a list of words.
+.TP 8
+.B goto \fIword
+\fIword\fR is filename and command-substituted to
+yield a string of the form `label'. The shell rewinds its
+input as much as possible, searches for a line of the
+form `label:', possibly preceded by blanks or tabs, and
+continues execution after that line.
+.TP 8
+.B hashstat
+Prints a statistics line indicating how effective the
+internal hash table has been at locating commands (and avoiding
+\fIexec\fR's). An \fIexec\fR is attempted for each component of the
+\fBpath\fR where the hash function indicates a possible hit, and
+in each component which does not begin with a `/'.
+.IP
+On machines without \fIvfork\fR(2), prints only the number and size of
+hash buckets.
+.PP
+.B history \fR[\fB\-hTr\fR] [\fIn\fR]
+.br
+.B history \-S\fR|\fB\-L|\fB\-M \fR[\fIfilename\fR] (+)
+.PD 0
+.TP 8
+.B history \-c \fR(+)
+The first form prints the history event list.
+If \fIn\fR is given only the \fIn\fR most recent events are printed or saved.
+With \fB\-h\fR, the history list is printed without leading numbers. If
+\fB-T\fR is specified, timestamps are printed also in comment form.
+(This can be used to
+produce files suitable for loading with 'history \-L' or 'source \-h'.)
+With \fB\-r\fR, the order of printing is most recent
+first rather than oldest first.
+.PD
+.RS +8
+.PP
+With \fB\-S\fR, the second form saves the history list to \fIfilename\fR.
+If the first word of the \fBsavehist\fR shell variable is set to a
+number, at most that many lines are saved. If the second word of
+\fBsavehist\fR is set to `merge', the history list is merged with the
+existing history file instead of replacing it (if there is one) and
+sorted by time stamp. (+) Merging is intended for an environment like
+the X Window System
+with several shells in simultaneous use. Currently it only
+succeeds when the shells quit nicely one after another.
+.PP
+With \fB\-L\fR, the shell appends \fIfilename\fR, which is presumably a
+history list saved by the \fB\-S\fR option or the \fBsavehist\fR mechanism,
+to the history list.
+\fB\-M\fR is like \fB\-L\fR, but the contents of \fIfilename\fR are merged
+into the history list and sorted by timestamp.
+In either case, \fBhistfile\fR is used if \fIfilename\fR is not given and
+\fI~/.history\fR is used if \fBhistfile\fR is unset.
+`history \-L' is exactly like 'source \-h' except that it does not require a
+filename.
+.PP
+Note that login shells do the equivalent of `history \-L' on startup
+and, if \fBsavehist\fR is set, `history \-S' before exiting.
+Because only \fI~/.tcshrc\fR is normally sourced before \fI~/.history\fR,
+\fBhistfile\fR should be set in \fI~/.tcshrc\fR rather than \fI~/.login\fR.
+.PP
+If \fBhistlit\fR is set, the first and second forms print and save the literal
+(unexpanded) form of the history list.
+.PP
+The last form clears the history list.
+.RE
+.TP 8
+.B hup \fR[\fIcommand\fR] \fR(+)
+With \fIcommand\fR, runs \fIcommand\fR such that it will exit on a hangup
+signal and arranges for the shell to send it a hangup signal when the shell
+exits.
+Note that commands may set their own response to hangups, overriding \fIhup\fR.
+Without an argument (allowed only in a shell script), causes the shell to
+exit on a hangup for the remainder of the script.
+See also \fBSignal handling\fR and the \fInohup\fR builtin command.
+.TP 8
+.B if (\fIexpr\fB) \fIcommand
+If \fIexpr\fR (an expression, as described under \fBExpressions\fR)
+evaluates true, then \fIcommand\fR is executed.
+Variable substitution on \fIcommand\fR happens early, at the same time it
+does for the rest of the \fIif\fR command.
+\fIcommand\fR must be a simple command, not an alias, a pipeline, a command list
+or a parenthesized command list, but it may have arguments.
+Input/output redirection occurs even if \fIexpr\fR is
+false and \fIcommand\fR is thus \fInot\fR executed; this is a bug.
+.PP
+.B if (\fIexpr\fB) then
+.br
+\&...
+.br
+.B else if (\fIexpr2\fB) then
+.br
+\&...
+.br
+.B else
+.br
+\&...
+.PD 0
+.TP 8
+.B endif
+If the specified \fIexpr\fR is true then the commands to the
+first \fIelse\fR are executed; otherwise if \fIexpr2\fR is true then
+the commands to the second \fIelse\fR are executed, etc. Any
+number of \fIelse-if\fR pairs are possible; only one \fIendif\fR is
+needed. The \fIelse\fR part is likewise optional. (The words
+\fIelse\fR and \fIendif\fR must appear at the beginning of input lines;
+the \fIif\fR must appear alone on its input line or after an
+\fIelse\fR.)
+.PD
+.TP 8
+.B inlib \fIshared-library\fR ... (+)
+Adds each \fIshared-library\fR to the current environment. There is no way
+to remove a shared library. (Domain/OS only)
+.TP 8
+.B jobs \fR[\fB\-l\fR]
+Lists the active jobs. With \fB\-l\fR, lists process
+IDs in addition to the normal information. On TCF systems, prints
+the site on which each job is executing.
+.PP
+.B kill \fR[\fB\-\fIsignal\fR] \fB%\fIjob\fR|\fIpid\fR ...
+.PD 0
+.TP 8
+.B kill \-l
+The first form sends the specified \fIsignal\fR (or, if none is given,
+the TERM (terminate) signal) to the specified jobs or processes.
+\fIjob\fR may be a number, a string, `', `%', `+' or `\-' as described
+under \fBJobs\fR.
+Signals are either given by number or by name (as given in
+\fI/usr/include/signal.h\fR, stripped of the prefix `SIG').
+There is no default \fIjob\fR; saying just `kill' does not send a signal
+to the current job. If the signal being sent is TERM (terminate)
+or HUP (hangup), then the job or process is sent a
+CONT (continue) signal as well.
+The second form lists the signal names.
+.PD
+.ig \" Obsolete tcsh command
+.TP 8
+.B linedit \fR(+)
+A synonym for the \fIecho\fR builtin command.
+..
+.TP 8
+.B limit \fR[\fB\-h\fR] [\fIresource\fR [\fImaximum-use\fR]]
+Limits the consumption by the current process and each
+process it creates to not individually exceed \fImaximum-use\fR on
+the specified \fIresource\fR. If no \fImaximum-use\fR is given, then
+the current limit is printed; if no \fIresource\fR is given, then
+all limitations are given. If the \fB\-h\fR flag is given, the
+hard limits are used instead of the current limits. The
+hard limits impose a ceiling on the values of the current
+limits. Only the super-user may raise the hard limits, but
+a user may lower or raise the current limits within the legal range.
+.RS +8
+.PP
+Controllable resources currently include \fIcputime\fR (the
+maximum number of cpu-seconds to be used by each process),
+\fIfilesize\fR (the largest single file which can be created),
+\fIdatasize\fR (the maximum growth of the data+stack region via
+sbrk(2) beyond the end of the program text), \fIstacksize\fR (the
+maximum size of the automatically-extended stack region),
+\fIcoredumpsize\fR (the size of the largest core dump that will be created),
+and \fImemoryuse\fR, the maximum amount of physical memory a process
+may have allocated to it at a given time.
+.PP
+\fImaximum-use\fR may be given as a (floating point or
+integer) number followed by a scale factor. For all limits
+other than \fIcputime\fR the default scale is `k' or `kilobytes'
+(1024 bytes); a scale factor of `m' or `megabytes' may also
+be used. For \fIcputime\fR the default scaling is `seconds',
+while `m' for minutes or `h' for hours, or a time of the
+form `mm:ss' giving minutes and seconds may be used.
+.PP
+For both \fIresource\fR names and scale factors, unambiguous
+prefixes of the names suffice.
+.RE
+.TP 8
+.B log \fR(+)
+Prints the \fBwatch\fR shell variable and reports on each user indicated
+in \fBwatch\fR who is logged in, regardless of when they last logged in.
+See also \fIwatchlog\fR.
+.TP 8
+.B login
+Terminates a login shell, replacing it with an instance of
+\fI/bin/login.\fR This is one way to log off, included for
+compatibility with \fIsh\fR(1).
+.TP 8
+.B logout
+Terminates a login shell. Especially useful if \fBignoreeof\fR is set.
+.TP 8
+.B ls\-F \fR[\-\fIswitch\fR ...] [\fIfile\fR ...] (+)
+Lists files like `ls \-F', but much faster. It identifies each type of
+special file in the listing with a special character:
+.PP
+.RS +8
+.PD 0
+.TP 4
+/
+Directory
+.TP 4
+*
+Executable
+.TP 4
+#
+Block device
+.TP 4
+%
+Character device
+.TP 4
+|
+Named pipe (systems with named pipes only)
+.TP 4
+=
+Socket (systems with sockets only)
+.TP 4
+@
+Symbolic link (systems with symbolic links only)
+.TP 4
++
+Hidden directory (AIX only) or context dependent (HP/UX only)
+.TP 4
+:
+Network special (HP/UX only)
+.PD
+.PP
+If the \fBlistlinks\fR shell variable is set, symbolic links are identified
+in more detail (only, of course, on systems which have them):
+.PP
+.PD 0
+.TP 4
+@
+Symbolic link to a non-directory
+.TP 4
+>
+Symbolic link to a directory
+.TP 4
+&
+Symbolic link to nowhere
+.PD
+.PP
+\fBlistlinks\fR also slows down \fIls\-F\fR and causes partitions holding
+files pointed to by symbolic links to be mounted.
+.PP
+If the \fBlistflags\fR shell variable is set to `x', `a' or `A', or any
+combination thereof (e.g. `xA'), they are used as flags to \fIls\-F\fR,
+making it act like `ls \-xF', `ls \-Fa', `ls \-FA' or a combination
+(e.g. `ls \-FxA').
+On machines where `ls \-C' is not the default, \fIls\-F\fR acts like `ls \-CF',
+unless \fBlistflags\fR contains an `x', in which case it acts like `ls \-xF'.
+\fIls\-F\fR passes its arguments to \fIls\fR(1) if it is given any switches,
+so `alias ls ls\-F' generally does the right thing.
+.PP
+The \fBls\-F\fR builtin can list files using different colors depending on the
+filetype or extension. See the \fBcolor\fR \fItcsh\fR variable and the
+\fBLS_COLORS\fR environment variable.
+.RE
+.PP
+.B migrate \fR[\fB\-\fIsite\fR] \fIpid\fR|\fB%\fIjobid\fR ... (+)
+.PD 0
+.TP 8
+.B migrate \-\fIsite\fR (+)
+The first form migrates the process or job to the site specified or the
+default site determined by the system path.
+The second form is equivalent to `migrate \-\fIsite\fR $$': it migrates the
+current process to the specified site. Migrating the shell
+itself can cause unexpected behavior, since the shell
+does not like to lose its tty. (TCF only)
+.PD
+.TP 8
+.B newgrp \fR[\fB\-\fR] \fIgroup\fR (+)
+Equivalent to `exec newgrp'; see \fInewgrp\fR(1).
+Available only if the shell was so compiled;
+see the \fBversion\fR shell variable.
+.TP 8
+.B nice \fR[\fB+\fInumber\fR] [\fIcommand\fR]
+Sets the scheduling priority for the shell to \fInumber\fR, or, without
+\fInumber\fR, to 4. With \fIcommand\fR, runs \fIcommand\fR at the appropriate
+priority.
+The greater the \fInumber\fR, the less cpu
+the process gets. The super-user may specify negative
+priority by using `nice \-number ...'. Command is always
+executed in a sub-shell, and the restrictions placed on
+commands in simple \fIif\fR statements apply.
+.TP 8
+.B nohup \fR[\fIcommand\fR]
+With \fIcommand\fR, runs \fIcommand\fR such that it will ignore hangup signals.
+Note that commands may set their own response to hangups, overriding \fInohup\fR.
+Without an argument (allowed only in a shell script), causes the shell to
+ignore hangups for the remainder of the script.
+See also \fBSignal handling\fR and the \fIhup\fR builtin command.
+.TP 8
+.B notify \fR[\fB%\fIjob\fR ...]
+Causes the shell to notify the user asynchronously when the status of any
+of the specified jobs (or, without %\fIjob\fR, the current job) changes,
+instead of waiting until the next prompt as is usual.
+\fIjob\fR may be a number, a string, `', `%', `+' or `\-' as described
+under \fBJobs\fR.
+See also the \fBnotify\fR shell variable.
+.TP 8
+.B onintr \fR[\fB\-\fR|\fIlabel\fR]
+Controls the action of the shell on interrupts. Without arguments,
+restores the default action of the shell on interrupts,
+which is to terminate shell scripts or to return to the
+terminal command input level.
+With `\-', causes all interrupts to be ignored.
+With \fIlabel\fR, causes the shell to execute a `goto \fIlabel\fR'
+when an interrupt is received or a child process terminates because it was
+interrupted.
+.IP "" 8
+\fIonintr\fR is ignored if the shell is running detached and in system
+startup files (see \fBFILES\fR), where interrupts are disabled anyway.
+.TP 8
+.B popd \fR[\fB\-p\fR] [\fB\-l\fR] [\fB\-n\fR|\fB\-v\fR] \fR[\fB+\fIn\fR]
+Without arguments, pops the directory stack and returns to the new top directory.
+With a number `+\fIn\fR', discards the \fIn\fR'th entry in the stack.
+.IP "" 8
+Finally, all forms of \fIpopd\fR print the final directory stack,
+just like \fIdirs\fR. The \fBpushdsilent\fR shell variable can be set to
+prevent this and the \fB\-p\fR flag can be given to override \fBpushdsilent\fR.
+The \fB\-l\fR, \fB\-n\fR and \fB\-v\fR flags have the same effect on \fIpopd\fR
+as on \fIdirs\fR. (+)
+.TP 8
+.B printenv \fR[\fIname\fR] (+)
+Prints the names and values of all environment variables or,
+with \fIname\fR, the value of the environment variable \fIname\fR.
+.TP 8
+.B pushd \fR[\fB\-p\fR] [\fB\-l\fR] [\fB\-n\fR|\fB\-v\fR] [\fIname\fR|\fB+\fIn\fR]
+Without arguments, exchanges the top two elements of the directory stack.
+If \fBpushdtohome\fR is set, \fIpushd\fR without arguments does `pushd ~',
+like \fIcd\fR. (+)
+With \fIname\fR, pushes the current working directory onto the directory
+stack and changes to \fIname\fR.
+If \fIname\fR is `\-' it is interpreted as the previous working directory
+(see \fBFilename substitution\fR). (+)
+If \fBdunique\fR is set, \fIpushd\fR removes any instances of \fIname\fR
+from the stack before pushing it onto the stack. (+)
+With a number `+\fIn\fR', rotates the \fIn\fRth element of the
+directory stack around to be the top element and changes to it.
+If \fBdextract\fR is set, however, `pushd +\fIn\fR' extracts the \fIn\fRth
+directory, pushes it onto the top of the stack and changes to it. (+)
+.IP "" 8
+Finally, all forms of \fIpushd\fR print the final directory stack,
+just like \fIdirs\fR. The \fBpushdsilent\fR shell variable can be set to
+prevent this and the \fB\-p\fR flag can be given to override \fBpushdsilent\fR.
+The \fB\-l\fR, \fB\-n\fR and \fB\-v\fR flags have the same effect on \fIpushd\fR
+as on \fIdirs\fR. (+)
+.TP 8
+.B rehash
+Causes the internal hash table of the contents of the
+directories in the \fBpath\fR variable to be recomputed. This is
+needed if new commands are added to directories in \fBpath\fR
+while you are logged in. This should only be necessary if
+you add commands to one of your own directories, or if a
+systems programmer changes the contents of one of the
+system directories. Also flushes the cache of home directories
+built by tilde expansion.
+.TP 8
+.B repeat \fIcount command
+The specified \fIcommand\fR,
+which is subject to the same restrictions as the \fIcommand\fR
+in the one line \fIif\fR statement above, is executed \fIcount\fR times.
+I/O redirections occur exactly once, even if \fIcount\fR is 0.
+.TP 8
+.B rootnode //\fInodename \fR(+)
+Changes the rootnode to //\fInodename\fR, so that `/' will be interpreted
+as `//\fInodename\fR'. (Domain/OS only)
+.PP
+.B sched \fR(+)
+.br
+.B sched \fR[\fB+\fR]\fIhh:mm command\fR \fR(+)
+.PD 0
+.TP 8
+.B sched \-\fIn\fR (+)
+The first form prints the scheduled-event list.
+The \fBsched\fR shell variable may be set to define the format in which
+the scheduled-event list is printed.
+The second form adds \fIcommand\fR to the scheduled-event list.
+For example,
+.PD
+.RS +8
+.IP "" 4
+> sched 11:00 echo It\\'s eleven o\\'clock.
+.PP
+causes the shell to echo `It's eleven o'clock.' at 11 AM.
+The time may be in 12-hour AM/PM format
+.IP "" 4
+> sched 5pm set prompt='[%h] It\\'s after 5; go home: >'
+.PP
+or may be relative to the current time:
+.IP "" 4
+> sched +2:15 /usr/lib/uucp/uucico \-r1 \-sother
+.PP
+A relative time specification may not use AM/PM format.
+The third form removes item \fIn\fR from the event list:
+.IP "" 4
+> sched
+.br
+ 1 Wed Apr 4 15:42 /usr/lib/uucp/uucico \-r1 \-sother
+.br
+ 2 Wed Apr 4 17:00 set prompt=[%h] It's after 5; go home: >
+.br
+> sched \-2
+.br
+> sched
+.br
+ 1 Wed Apr 4 15:42 /usr/lib/uucp/uucico \-r1 \-sother
+.PP
+A command in the scheduled-event list is executed just before the first
+prompt is printed after the time when the command is scheduled.
+It is possible to miss the exact time when the command is to be run, but
+an overdue command will execute at the next prompt.
+A command which comes due while the shell
+is waiting for user input is executed immediately.
+However, normal operation of an already-running command will not
+be interrupted so that a scheduled-event list element may be run.
+.PP
+This mechanism is similar to, but not the same as, the \fIat\fR(1)
+command on some Unix systems.
+Its major disadvantage is that it may not run a command at exactly the
+specified time.
+Its major advantage is that because \fIsched\fR runs directly from
+the shell, it has access to shell variables and other structures.
+This provides a mechanism for changing one's working environment
+based on the time of day.
+.RE
+.PP
+.B set
+.br
+.B set \fIname\fR ...
+.br
+.B set \fIname\fR\fB=\fIword\fR ...
+.br
+.B set [\-r] [\-f|\-l] \fIname\fR\fB=(\fIwordlist\fB)\fR ... (+)
+.br
+.B set \fIname[index]\fR\fB=\fIword\fR ...
+.br
+.B set \-r \fR(+)
+.br
+.B set \-r \fIname\fR ... (+)
+.PD 0
+.TP 8
+.B set \-r \fIname\fR\fB=\fIword\fR ... (+)
+The first form of the command prints the value of all shell variables.
+Variables which contain more than a single word print as a
+parenthesized word list.
+The second form sets \fIname\fR to the null string.
+The third form sets \fIname\fR to the single \fIword\fR.
+The fourth form sets \fIname\fR to the list of words in
+\fIwordlist\fR. In all cases the value is command and filename expanded.
+If \-r is specified, the value is set read-only. If \-f or \-l are
+specified, set only unique words keeping their order.
+\-f prefers the first occurrence of a word, and \-l the last.
+The fifth form sets the \fIindex\fR'th component of name to \fIword\fR;
+this component must already exist.
+The sixth form lists the names (only) of all shell variables which are read-only.
+The seventh form makes \fIname\fR read-only, whether or not it has a value.
+The second form sets \fIname\fR to the null string.
+The eighth form is the same as the third form, but
+make \fIname\fR read-only at the same time.
+.PD
+.IP "" 8
+These arguments can be repeated to set and/or make read-only multiple variables
+in a single set command. Note, however, that variable expansion
+happens for all arguments before any setting occurs. Note also that `=' can
+be adjacent to both \fIname\fR and \fIword\fR or separated from both by
+whitespace, but cannot be adjacent to only one or the other.
+See also the \fIunset\fR builtin command.
+.TP 8
+.B setenv \fR[\fIname \fR[\fIvalue\fR]]
+Without arguments, prints the names and values of all environment variables.
+Given \fIname\fR, sets the environment variable \fIname\fR to \fIvalue\fR
+or, without \fIvalue\fR, to the null string.
+.TP 8
+.B setpath \fIpath \fR(+)
+Equivalent to \fIsetpath\fR(1). (Mach only)
+.TP 8
+.B setspath\fR LOCAL|\fIsite\fR|\fIcpu\fR ... (+)
+Sets the system execution path. (TCF only)
+.TP 8
+.B settc \fIcap value \fR(+)
+Tells the shell to believe that the terminal capability \fIcap\fR
+(as defined in \fItermcap\fR(5)) has the value \fIvalue\fR.
+No sanity checking is done.
+Concept terminal users may have to `settc xn no' to get proper
+wrapping at the rightmost column.
+.TP 8
+.B setty \fR[\fB\-d\fR|\fB\-q\fR|\fB\-x\fR] [\fB\-a\fR] [[\fB+\fR|\fB\-\fR]\fImode\fR] (+)
+Controls which tty modes (see \fBTerminal management\fR)
+the shell does not allow to change.
+\fB\-d\fR, \fB\-q\fR or \fB\-x\fR tells \fIsetty\fR to act
+on the `edit', `quote' or `execute' set of tty modes respectively; without
+\fB\-d\fR, \fB\-q\fR or \fB\-x\fR, `execute' is used.
+.IP "" 8
+Without other arguments, \fIsetty\fR lists the modes in the chosen set
+which are fixed on (`+mode') or off (`\-mode').
+The available modes, and thus the display, vary from system to system.
+With \fB\-a\fR, lists all tty modes in the chosen set
+whether or not they are fixed.
+With \fB+\fImode\fR, \fB\-\fImode\fR or \fImode\fR, fixes \fImode\fR on or off
+or removes control from \fImode\fR in the chosen set.
+For example, `setty +echok echoe' fixes `echok' mode on and allows commands
+to turn `echoe' mode on or off, both when the shell is executing commands.
+.TP 8
+.B setxvers\fR [\fIstring\fR] (+)
+Set the experimental version prefix to \fIstring\fR, or removes it
+if \fIstring\fR is omitted. (TCF only)
+.TP 8
+.B shift \fR[\fIvariable\fR]
+Without arguments, discards \fBargv\fR[1] and shifts the members of
+\fBargv\fR to the left. It is an error for \fBargv\fR not to be set or to have
+less than one word as value. With \fIvariable\fR, performs the
+same function on \fIvariable\fR.
+.TP 8
+.B source \fR[\fB\-h\fR] \fIname\fR [\fIargs\fR ...]
+The shell reads and executes commands from \fIname\fR.
+The commands are not placed on the history list.
+If any \fIargs\fR are given, they are placed in \fBargv\fR. (+)
+\fIsource\fR commands may be nested;
+if they are nested too deeply the shell may run out of file descriptors.
+An error in a \fIsource\fR at any level terminates all nested
+\fIsource\fR commands.
+With \fB\-h\fR, commands are placed on the history list instead of being
+executed, much like `history \-L'.
+.TP 8
+.B stop \fB%\fIjob\fR|\fIpid\fR ...
+Stops the specified jobs or processes which are executing in the background.
+\fIjob\fR may be a number, a string, `', `%', `+' or `\-' as described
+under \fBJobs\fR.
+There is no default \fIjob\fR; saying just `stop' does not stop
+the current job.
+.TP 8
+.B suspend
+Causes the shell to stop in its tracks, much as if it had
+been sent a stop signal with \fB^Z\fR. This is most often used to
+stop shells started by \fIsu\fR(1).
+.PP
+.B switch (\fIstring\fB)
+.br
+.B case \fIstr1\fB:
+.PD 0
+.IP "" 4
+\&...
+.br
+.B breaksw
+.PP
+\&...
+.PP
+.B default:
+.IP "" 4
+\&...
+.br
+.B breaksw
+.TP 8
+.B endsw
+Each case label is successively matched, against the
+specified \fIstring\fR which is first command and filename expanded.
+The file metacharacters `*', `?' and `[...]' may be used
+in the case labels, which are variable expanded. If none
+of the labels match before a `default' label is found, then
+the execution begins after the default label. Each case
+label and the default label must appear at the beginning of
+a line. The command \fIbreaksw\fR causes execution to continue
+after the \fIendsw\fR. Otherwise control may fall through case
+labels and default labels as in C. If no label matches and
+there is no default, execution continues after the \fIendsw\fR.
+.PD
+.TP 8
+.B telltc \fR(+)
+Lists the values of all terminal capabilities (see \fItermcap\fR(5)).
+.TP 8
+.B time \fR[\fIcommand\fR]
+Executes \fIcommand\fR (which must be a simple command, not an alias,
+a pipeline, a command list or a parenthesized command list)
+and prints a time summary as described under the \fBtime\fR variable.
+If necessary, an extra shell is created to print the time statistic when
+the command completes.
+Without \fIcommand\fR, prints a time summary for the current shell and its
+children.
+.TP 8
+.B umask \fR[\fIvalue\fR]
+Sets the file creation mask to \fIvalue\fR, which is given in octal.
+Common values for the mask are
+002, giving all access to the group and read and execute access to others, and
+022, giving read and execute access to the group and others.
+Without \fIvalue\fR, prints the current file creation mask.
+.TP 8
+.B unalias \fIpattern
+.br
+Removes all aliases whose names match \fIpattern\fR.
+`unalias *' thus removes all aliases.
+It is not an error for nothing to be \fIunalias\fRed.
+.TP 8
+.B uncomplete \fIpattern\fR (+)
+Removes all completions whose names match \fIpattern\fR.
+`uncomplete *' thus removes all completions.
+It is not an error for nothing to be \fIuncomplete\fRd.
+.TP 8
+.B unhash
+Disables use of the internal hash table to speed location of
+executed programs.
+.TP 8
+.B universe \fIuniverse\fR (+)
+Sets the universe to \fIuniverse\fR. (Masscomp/RTU only)
+.TP 8
+.B unlimit \fR[\fB\-h\fR] [\fIresource\fR]
+Removes the limitation on \fIresource\fR or, if no \fIresource\fR is
+specified, all \fIresource\fR limitations.
+With \fB\-h\fR, the corresponding hard limits are removed.
+Only the super-user may do this.
+.TP 8
+.B unset \fIpattern
+Removes all variables whose names match \fIpattern\fR, unless they are read-only.
+`unset *' thus removes all variables unless they are read-only;
+this is a bad idea.
+It is not an error for nothing to be \fIunset\fR.
+.TP 8
+.B unsetenv \fIpattern
+Removes all environment variables whose names match \fIpattern\fR.
+`unsetenv *' thus removes all environment variables;
+this is a bad idea.
+It is not an error for nothing to be \fIunsetenv\fRed.
+.TP 8
+.B ver \fR[\fIsystype\fR [\fIcommand\fR]] (+)
+Without arguments, prints \fBSYSTYPE\fR. With \fIsystype\fR, sets \fBSYSTYPE\fR
+to \fIsystype\fR. With \fIsystype\fR and \fIcommand\fR, executes \fIcommand\fR
+under \fIsystype\fR. \fIsystype\fR may be `bsd4.3' or `sys5.3'.
+(Domain/OS only)
+.TP 8
+.B wait
+The shell waits for all background jobs. If the shell is interactive, an
+interrupt will disrupt the wait and cause the shell to print the names and job
+numbers of all outstanding jobs.
+.TP 8
+.B warp \fIuniverse\fR (+)
+Sets the universe to \fIuniverse\fR. (Convex/OS only)
+.TP 8
+.B watchlog \fR(+)
+An alternate name for the \fIlog\fR builtin command (q.v.).
+Available only if the shell was so compiled;
+see the \fBversion\fR shell variable.
+.TP 8
+.B where \fIcommand\fR (+)
+Reports all known instances of \fIcommand\fR, including aliases, builtins and
+executables in \fBpath\fR.
+.TP 8
+.B which\fR \fIcommand\fR (+)
+Displays the command that will be executed by the shell after substitutions,
+\fBpath\fR searching, etc.
+The builtin command is just like \fIwhich\fR(1), but it correctly reports
+\fItcsh\fR aliases and builtins and is 10 to 100 times faster.
+See also the \fIwhich-command\fR editor command.
+.PP
+.B while (\fIexpr\fB)\fR
+.br
+\&...
+.PD 0
+.TP 8
+.B end
+Executes the commands between the \fIwhile\fR and the matching \fIend\fR
+while \fIexpr\fR (an expression, as described under \fBExpressions\fR)
+evaluates non-zero.
+\fIwhile\fR and \fIend\fR must appear alone on their input lines.
+\fIbreak\fR and \fIcontinue\fR may be used to terminate or continue the
+loop prematurely.
+If the input is a terminal, the user is prompted the first time
+through the loop as with \fIforeach\fR.
+.PD
+.SS "Special aliases (+)"
+If set, each of these aliases executes automatically at the indicated time.
+They are all initially undefined.
+.TP 8
+.B beepcmd
+Runs when the shell wants to ring the terminal bell.
+.TP 8
+.B cwdcmd
+Runs after every change of working directory. For example, if the user is
+working on an X window system using \fIxterm\fR(1) and a re-parenting window
+manager that supports title bars such as \fItwm\fR(1) and does
+.RS +8
+.IP "" 4
+> alias cwdcmd 'echo \-n "^[]2;${HOST}:$cwd ^G"'
+.PP
+then the shell will change the title of the running \fIxterm\fR(1)
+to be the name of the host, a colon, and the full current working directory.
+A fancier way to do that is
+.IP "" 4
+> alias cwdcmd 'echo \-n "^[]2;${HOST}:$cwd^G^[]1;${HOST}^G"'
+.PP
+This will put the hostname and working directory on the title bar but
+only the hostname in the icon manager menu.
+.PP
+Note that putting a \fIcd\fR, \fIpushd\fR or \fIpopd\fR in \fIcwdcmd\fR
+may cause an infinite loop. It is the author's opinion that anyone doing
+so will get what they deserve.
+.RE
+.TP 8
+.B helpcommand
+Invoked by the \fBrun-help\fR editor command. The command name for which help
+is sought is passed as sole argument.
+For example, if one does
+.RS +8
+.IP "" 4
+> alias helpcommand '\e!:1 --help'
+.PP
+then the help display of the command itself will be invoked, using the GNU
+help calling convention.
+Currently there is no easy way to account for various calling conventions (eg
+the customary Unix `-h'), except by using a table of many commands.
+.RE
+.TP 8
+.B periodic
+Runs every \fBtperiod\fR minutes. This provides a convenient means for
+checking on common but infrequent changes such as new mail. For example,
+if one does
+.RS +8
+.IP "" 4
+> set tperiod = 30
+.br
+> alias periodic checknews
+.PP
+then the \fIchecknews\fR(1) program runs every 30 minutes.
+If \fIperiodic\fR is set but \fBtperiod\fR is unset or set to 0,
+\fIperiodic\fR behaves like \fIprecmd\fR.
+.RE
+.TP 8
+.B precmd
+Runs just before each prompt is printed. For example, if one does
+.RS +8
+.IP "" 4
+> alias precmd date
+.PP
+then \fIdate\fR(1) runs just before the shell prompts for each command.
+There are no limits on what \fIprecmd\fR can be set to do, but discretion
+should be used.
+.RE
+.TP 8
+.B postcmd
+Runs before each command gets executed.
+.RS +8
+.IP "" 4
+> alias postcmd 'echo \-n "^[]2\e;\e!#^G"'
+.PP
+then executing \fIvi foo.c\fR will put the command string in the xterm title bar.
+.RE
+.TP 8
+.B shell
+Specifies the interpreter for executable scripts which do not themselves
+specify an interpreter. The first word should be a full path name to the
+desired interpreter (e.g. `/bin/csh' or `/usr/local/bin/tcsh').
+.SS "Special shell variables"
+The variables described in this section have special meaning to the shell.
+.PP
+The shell sets \fBaddsuffix\fR, \fBargv\fR, \fBautologout\fR, \fBcommand\fR, \fBecho_style\fR,
+\fBedit\fR, \fBgid\fR, \fBgroup\fR, \fBhome\fR, \fBloginsh\fR, \fBoid\fR, \fBpath\fR,
+\fBprompt\fR, \fBprompt2\fR, \fBprompt3\fR, \fBshell\fR, \fBshlvl\fR,
+\fBtcsh\fR, \fBterm\fR, \fBtty\fR, \fBuid\fR, \fBuser\fR and \fBversion\fR at
+startup; they do not change thereafter unless changed by the user. The shell
+updates \fBcwd\fR, \fBdirstack\fR, \fBowd\fR and \fBstatus\fR when necessary,
+and sets \fBlogout\fR on logout.
+.PP
+The shell synchronizes \fBafsuser\fR, \fBgroup\fR, \fBhome\fR, \fBpath\fR, \fBshlvl\fR,
+\fBterm\fR and \fBuser\fR with the environment variables of the same names:
+whenever the environment variable changes the shell changes the corresponding
+shell variable to match (unless the shell variable is read-only) and vice
+versa. Note that although \fBcwd\fR and \fBPWD\fR have identical meanings, they
+are not synchronized in this manner, and that the shell automatically
+interconverts the different formats of \fBpath\fR and \fBPATH\fR.
+.TP 8
+.B addsuffix \fR(+)
+If set, filename completion adds `/' to the end of directories and a space
+to the end of normal files when they are matched exactly.
+Set by default.
+.TP 8
+.B afsuser \fR(+)
+If set, \fBautologout\fR's autolock feature uses its value instead of
+the local username for kerberos authentication.
+.TP 8
+.B ampm \fR(+)
+If set, all times are shown in 12-hour AM/PM format.
+.TP 8
+.B argv
+The arguments to the shell. Positional parameters are taken from \fBargv\fR,
+i.e. `$1' is replaced by `$argv[1]', etc.
+Set by default, but usually empty in interactive shells.
+.TP 8
+.B autocorrect \fR(+)
+If set, the \fIspell-word\fR editor command is invoked automatically before
+each completion attempt.
+.TP 8
+.B autoexpand \fR(+)
+If set, the \fIexpand-history\fR editor command is invoked automatically
+before each completion attempt.
+.TP 8
+.B autolist \fR(+)
+If set, possibilities are listed after an ambiguous completion.
+If set to `ambiguous', possibilities are listed only when no new
+characters are added by completion.
+.TP 8
+.B autologout \fR(+)
+The first word is the number of minutes of inactivity before automatic
+logout. The optional second word is the number of minutes of inactivity
+before automatic locking.
+When the shell automatically logs out,
+it prints `auto-logout', sets the variable logout to `automatic' and exits.
+When the shell automatically locks, the user is required to enter his password
+to continue working. Five incorrect attempts result in automatic logout.
+Set to `60' (automatic logout after 60 minutes, and no locking) by default
+in login and superuser shells, but not if the shell thinks it is running
+under a window system (i.e. the \fBDISPLAY\fR environment variable is set),
+the tty is a pseudo-tty (pty) or the shell was not so compiled (see the
+\fBversion\fR shell variable).
+See also the \fBafsuser\fR and \fBlogout\fR shell variables.
+.TP 8
+.B backslash_quote \fR(+)
+If set, backslashes (`\\') always quote `\\', `'', and `"'. This may make
+complex quoting tasks easier, but it can cause syntax errors in \fIcsh\fR(1)
+scripts.
+.TP 8
+.B cdpath
+A list of directories in which \fIcd\fR should search for
+subdirectories if they aren't found in the current directory.
+.TP 8
+.B color
+If set, it enables color display for the builtin \fBls\-F\fR and it passes
+\fB\-\-color=auto\fR to \fBls\fR. Alternatively, it can be set to only
+\fBls\-F\fR or only \fBls\fR to enable color only to one command. Setting
+it to nothing is equivalent to setting it to \fB(ls\-F ls)\fR.
+.TP 8
+.B colorcat
+If set, it enables color escape sequence for NLS message files.
+And display colorful NLS messages.
+.TP 8
+.B command \fR(+)
+If set, the command which was passed to the shell with the \fB-c\fR flag (q.v.).
+.TP 8
+.B complete \fR(+)
+If set to `enhance', completion 1) ignores case and 2) considers
+periods, hyphens and underscores (`.', `\-' and `_') to be word
+separators and hyphens and underscores to be equivalent.
+.TP 8
+.B continue_args \fR(+)
+If set to a list of commands, the shell will continue the listed
+commands, instead of starting a new one.
+.TP 8
+.B continue_args \fR(+)
+Same as continue, but the shell will execute:
+.RS +8
+.nf
+ echo `pwd` $argv > ~/.<command-name>_pause; %<command-name>
+.fi
+.RE
+.TP 8
+.B correct \fR(+)
+If set to `cmd', commands are automatically spelling-corrected.
+If set to `complete', commands are automatically completed.
+If set to `all', the entire command line is corrected.
+.TP 8
+.B cwd
+The full pathname of the current directory.
+See also the \fBdirstack\fR and \fBowd\fR shell variables.
+.TP 8
+.B dextract \fR(+)
+If set, `pushd +\fIn\fR' extracts the \fIn\fRth directory from the directory
+stack rather than rotating it to the top.
+.TP 8
+.B dirsfile \fR(+)
+The default location in which `dirs \-S' and `dirs \-L' look for
+a history file. If unset, \fI~/.cshdirs\fR is used.
+Because only \fI~/.tcshrc\fR is normally sourced before \fI~/.cshdirs\fR,
+\fBdirsfile\fR should be set in \fI~/.tcshrc\fR rather than \fI~/.login\fR.
+.TP 8
+.B dirstack \fR(+)
+An array of all the directories on the directory stack.
+`$dirstack[1]' is the current working directory, `$dirstack[2]'
+the first directory on the stack, etc.
+Note that the current working directory is `$dirstack[1]' but `=0' in
+directory stack substitutions, etc.
+One can change the stack arbitrarily by setting \fBdirstack\fR,
+but the first element (the current working directory) is always correct.
+See also the \fBcwd\fR and \fBowd\fR shell variables.
+.TP 8
+.B dspmbyte \fR(+)
+If set to `euc', it enables display and editing EUC-kanji(japanese) code.
+If set to `sjis', it enables display and editing Shift-JIS(japanese) code.
+If set to following format, it enables display and editing original multi-byte code format:
+.RS +8
+.IP "" 4
+> set dspmbyte = 0000....(256 bytes)....0000
+.PP
+table length require \fBjust\fR 256 byte. Each character of 256 characters corresponds from the left from 0x00,0x01... to 0xff of ASCII code. Each character is set to number 0,1,2 and 3. Each number has the following meanings:
+ 0 ... not use for multi-byte character.
+ 1 ... use for first byte of multi-byte charcter.
+ 2 ... use for second byte of multi-byte character.
+ 3 ... use for both of first byte and second byte of multi-byte character.
+ Example:
+ if set `001322', first character(means 0x00 of ASCII code) and second character(means 0x01 of ASCII code) is set to `0'. then, it is not use for multi-byte character.3rd character(0x02) is set '2'. it is use for first byte of multi-byte charcter. 4th character(0x03) is set '3'. it is use for both of first byte and second byte of multi-byte character. 5th and 6th character(0x04,0x05) is set '2'. it is use for second byte of multi-byte charcter.
+.PP
+Because, the ls of GNU fileutils cannot display multi-byte
+filenames without -N ( --literal ) option, if you are using
+it, set the second word of dspmbyte to "ls". If not, for
+example, "ls-F -l" cannot display multi-byte filenames.
+.RE
+.TP 8
+.B dunique \fR(+)
+If set, \fIpushd\fR removes any instances of \fIname\fR
+from the stack before pushing it onto the stack.
+.TP 8
+.B echo
+If set, each command with its arguments is echoed just before it is
+executed. For non-builtin commands all expansions occur before
+echoing. Builtin commands are echoed before command and filename
+substitution, since these substitutions are then done selectively.
+Set by the \fB\-x\fR command line option.
+.TP 8
+.B echo_style \fR(+)
+The style of the \fIecho\fR builtin. May be set to
+.PP
+.RS +8
+.PD 0
+.TP 8
+bsd
+Don't echo a newline if the first argument is `\-n'.
+.TP 8
+sysv
+Recognize backslashed escape sequences in echo strings.
+.TP 8
+both
+Recognize both the `\-n' flag and backslashed escape sequences; the default.
+.TP 8
+none
+Recognize neither.
+.PD
+.PP
+Set by default to the local system default. The BSD and System V
+options are described in the \fIecho\fR(1) manpages on the appropriate
+systems.
+.RE
+.TP 8
+.B edit \fR(+)
+If set, the command-line editor is used. Set by default in interactive
+shells.
+.TP 8
+.B ellipsis \fR(+)
+If set, the `%c'/`%.' and `%C' prompt sequences (see the \fBprompt\fR
+shell variable) indicate skipped directories with an ellipsis (`...')
+instead of `/<skipped>'.
+.TP 8
+.B fignore \fR(+)
+Lists file name suffixes to be ignored by completion.
+.TP 8
+.B filec
+In \fItcsh\fR, completion is always used and this variable is ignored.
+If set in \fIcsh\fR, filename completion is used.
+.TP 8
+.B gid \fR(+)
+The user's real group ID.
+.TP 8
+.B group \fR(+)
+The user's group name.
+.TP 8
+.B histchars
+A string value determining the characters used in \fBHistory
+substitution\fR (q.v.). The first character of its value is used as
+the history substitution character, replacing the default character
+`!'. The second character of its value replaces the character `^' in
+quick substitutions.
+.TP 8
+.B histdup \fR(+)
+Controls handling of duplicate entries in the history list. If set to
+`all' only unique history events are entered in the history list. If
+set to `prev' and the last history event is the same as the current
+command, then the current command is not entered in the history. If
+set to `erase' and the same event is found in the history list, that
+old event gets erased and the current one gets inserted. Note that the
+`prev' and `all' options renumber history events so there are no gaps.
+.TP 8
+.B histfile \fR(+)
+The default location in which `history \-S' and `history \-L' look for
+a history file. If unset, \fI~/.history\fR is used. \fBhistfile\fR is
+useful when sharing the same home directory between different machines,
+or when saving separate histories on different terminals. Because only
+\fI~/.tcshrc\fR is normally sourced before \fI~/.history\fR,
+\fBhistfile\fR should be set in \fI~/.tcshrc\fR rather than
+\fI~/.login\fR.
+.TP 8
+.B histlit \fR(+)
+If set, builtin and editor commands and the \fBsavehist\fR mechanism
+use the literal (unexpanded) form of lines in the history list. See
+also the \fItoggle-literal-history\fR editor command.
+.TP 8
+.B history
+The first word indicates the number of history events to save. The
+optional second word (+) indicates the format in which history is
+printed; if not given, `%h\\t%T\\t%R\\n' is used. The format sequences
+are described below under \fBprompt\fR; note the variable meaning of
+`%R'. Set to `100' by default.
+.TP 8
+.B home
+Initialized to the home directory of the invoker. The filename
+expansion of `\fI~\fR' refers to this variable.
+.TP 8
+.B ignoreeof
+If set to the empty string or `0' and the input device is a terminal,
+the \fIend-of-file\fR command (usually generated by the user by typing
+`^D' on an empty line) causes the shell to print `Use "exit" to leave
+tcsh.' instead of exiting. This prevents the shell from accidentally
+being killed. If set to a number \fIn\fR, the shell ignores \fIn\fR -
+1 consecutive \fIend-of-file\fRs and exits on the \fIn\fRth. (+) If
+unset, `1' is used, i.e. the shell exits on a single `^D'.
+.TP 8
+.B implicitcd \fR(+)
+If set, the shell treats a directory name typed as a command as though
+it were a request to change to that directory. If set to \fIverbose\fR,
+the change of directory is echoed to the standard output. This behavior
+is inhibited in non-interactive shell scripts, or for command strings
+with more than one word. Changing directory takes precedence over
+executing a like-named command, but it is done after alias
+substitutions. Tilde and variable expansions work as expected.
+.TP 8
+.B inputmode \fR(+)
+If set to `insert' or `overwrite', puts the editor into that input mode
+at the beginning of each line.
+.TP 8
+.B listflags \fR(+)
+If set to `x', `a' or `A', or any combination thereof (e.g. `xA'), they
+are used as flags to \fIls\-F\fR, making it act like `ls \-xF', `ls
+\-Fa', `ls \-FA' or a combination (e.g. `ls \-FxA'): `a' shows all
+files (even if they start with a `.'), `A' shows all files but `.' and
+`..', and `x' sorts across instead of down. If the second word of
+\fBlistflags\fR is set, it is used as the path to `ls(1)'.
+.TP 8
+.B listjobs \fR(+)
+If set, all jobs are listed when a job is suspended. If set to `long',
+the listing is in long format.
+.TP 8
+.B listlinks \fR(+)
+If set, the \fIls\-F\fR builtin command shows the type of file to which
+each symbolic link points.
+.TP 8
+.B listmax \fR(+)
+The maximum number of items which the \fIlist-choices\fR editor command
+will list without asking first.
+.TP 8
+.B listmaxrows \fR(+)
+The maximum number of rows of items which the \fIlist-choices\fR editor
+command will list without asking first.
+.TP 8
+.B loginsh \fR(+)
+Set by the shell if it is a login shell. Setting or unsetting it
+within a shell has no effect. See also \fBshlvl\fR.
+.TP 8
+.B logout \fR(+)
+Set by the shell to `normal' before a normal logout, `automatic' before
+an automatic logout, and `hangup' if the shell was killed by a hangup
+signal (see \fBSignal handling\fR). See also the \fBautologout\fR
+shell variable.
+.TP 8
+.B mail
+The names of the files or directories to check for incoming mail,
+separated by whitespace, and optionally preceded by a numeric word.
+Before each prompt, if 10 minutes have passed since the last check, the
+shell checks each file and says `You have new mail.' (or, if \fBmail\fR
+contains multiple files, `You have new mail in \fIname\fR.') if the
+filesize is greater than zero in size and has a modification time
+greater than its access time.
+.PP
+.RS +8
+.PD
+.PP
+If you are in a login shell, then no mail file is reported unless it has
+been modified after the time the shell has started up, in order to prevent
+redundant notifications. Most login programs will tell you whether or not
+you have mail when you log in.
+.PP
+If a file specified in \fBmail\fR is a directory, the shell will count each
+file within that directory as a separate message, and will report `You have
+\fIn\fR mails.' or `You have \fIn\fR mails in \fIname\fR.' as appropriate.
+This functionality is provided primarily for those systems which store mail
+in this manner, such as the Andrew Mail System.
+.PP
+If the first word of \fBmail\fR is numeric it is taken as a different mail
+checking interval, in seconds.
+.PP
+Under very rare circumstances, the shell may report `You have mail.' instead
+of `You have new mail.'
+.RE
+.TP 8
+.B matchbeep \fR(+)
+If set to `never', completion never beeps.
+If set to `nomatch', it beeps only when there is no match.
+If set to `ambiguous, it beeps when there are multiple matches.
+If set to `notunique', it beeps when there is one exact and other longer matches.
+If unset, `ambiguous' is used.
+.TP 8
+.B nobeep \fR(+)
+If set, beeping is completely disabled.
+See also \fBvisiblebell\fR.
+.TP 8
+.B noclobber
+If set, restrictions are placed on output redirection to insure that files
+are not accidentally destroyed and that `>>' redirections refer to existing
+files, as described in the \fBInput/output\fR section.
+.TP 8
+.B noglob
+If set, \fBFilename substitution\fR and \fBDirectory stack substitution\fR
+(q.v.) are inhibited. This is most useful in shell scripts which do not deal
+with filenames, or after a list of filenames has been obtained and further
+expansions are not desirable.
+.TP 8
+.B nokanji \fR(+)
+If set and the shell supports Kanji (see the \fBversion\fR shell variable),
+it is disabled so that the meta key can be used.
+.TP 8
+.B nonomatch
+If set, a \fBFilename substitution\fR or \fBDirectory stack substitution\fR
+(q.v.) which does not match any
+existing files is left untouched rather than causing an error.
+It is still an error for the substitution to be
+malformed, e.g. `echo [' still gives an error.
+.TP 8
+.B nostat \fR(+)
+A list of directories (or glob-patterns which match directories; see
+\fBFilename substitution\fR) that should not be \fIstat\fR(2)ed during a
+completion operation. This is usually used to exclude directories which
+take too much time to \fIstat\fR(2), for example \fI/afs\fR.
+.TP 8
+.B notify
+If set, the shell announces job completions asynchronously.
+The default is to present job completions just before printing a prompt.
+.TP 8
+.B oid \fR(+)
+The user's real organization ID. (Domain/OS only)
+.TP 8
+.B owd \fR(+)
+The old working directory, equivalent to the `\-' used by \fIcd\fR and \fIpushd\fR.
+See also the \fBcwd\fR and \fBdirstack\fR shell variables.
+.TP 8
+.B path
+A list of directories in which to look for executable commands.
+A null word specifies the current directory.
+If there is no \fBpath\fR variable then only full path names will execute.
+\fBpath\fR is set by the shell at startup from the \fBPATH\fR environment
+variable or, if \fBPATH\fR does not exist, to a system-dependent default
+something like `(/usr/local/bin /usr/bsd /bin /usr/bin .)'.
+The shell may put `.' first or last in \fBpath\fR or omit it entirely
+depending on how it was compiled; see the \fBversion\fR shell variable.
+A shell which is given neither the \fB\-c\fR nor the \fB\-t\fR option
+hashes the contents of the directories in \fBpath\fR after
+reading \fI~/.tcshrc\fR and each time \fBpath\fR is reset.
+If one adds a new command to a directory in \fBpath\fR while the shell
+is active, one may need to do a \fIrehash\fR for the shell to find it.
+.TP 8
+.B printexitvalue \fR(+)
+If set and an interactive program exits with a non-zero status, the shell
+prints `Exit \fBstatus\fR'.
+.TP 8
+.B prompt
+The string which is printed before reading each command from the terminal.
+\fBprompt\fR may include any of the following formatting sequences (+), which
+are replaced by the given information:
+.PP
+.RS +8
+.PD 0
+.TP 4
+%/
+The current working directory.
+.TP 4
+%~
+The current working directory, but with one's home directory
+represented by `~' and other users' home directories represented by
+`~user' as per \fBFilename substitution\fR. `~user' substitution
+happens only if the shell has already used `~\fIuser\fR' in a pathname
+in the current session.
+.TP 4
+%c[[0]\fIn\fR], %.[[0]\fIn\fR]
+The trailing component of the current working directory, or \fIn\fR
+trailing components if a digit \fIn\fR is given.
+If \fIn\fR begins with `0', the number of skipped components precede
+the trailing component(s) in the format `/<\fIskipped\fR>trailing'.
+If the \fBellipsis\fR shell variable is set, skipped components
+are represented by an ellipsis so the whole becomes `...trailing'.
+`~' substitution is done as in `%~' above, but the `~' component
+is ignored when counting trailing components.
+.TP 4
+%C
+Like %c, but without `~' substitution.
+.TP 4
+%h, %!, !
+The current history event number.
+.TP 4
+%M
+The full hostname.
+.TP 4
+%m
+The hostname up to the first `.'.
+.TP 4
+%S (%s)
+Start (stop) standout mode.
+.TP 4
+%B (%b)
+Start (stop) boldfacing mode.
+.TP 4
+%U (%u)
+Start (stop) underline mode.
+.TP 4
+%t, %@
+The time of day in 12-hour AM/PM format.
+.TP 4
+%T
+Like `%t', but in 24-hour format (but see the \fBampm\fR shell variable).
+.TP 4
+%p
+The `precise' time of day in 12-hour AM/PM format, with seconds.
+.TP 4
+%P
+Like `%p', but in 24-hour format (but see the \fBampm\fR shell variable).
+.TP 4
+\e\fIc\fR
+\fIc\fR is parsed as in \fIbindkey\fR.
+.TP 4
+^\fIc\fR
+\fIc\fR is parsed as in \fIbindkey\fR.
+.TP 4
+%%
+A single `%'.
+.TP 4
+%n
+The user name.
+.TP 4
+%d
+The weekday in `Day' format.
+.TP 4
+%D
+The day in `dd' format.
+.TP 4
+%w
+The month in `Mon' format.
+.TP 4
+%W
+The month in `mm' format.
+.TP 4
+%y
+The year in `yy' format.
+.TP 4
+%Y
+The year in `yyyy' format.
+.TP 4
+%l
+The shell's tty.
+.TP 4
+%L
+Clears from the end of the prompt to end of the display or the end of the line.
+.TP 4
+%$
+Expands the shell or environment variable name immediately after the `$'.
+.TP 4
+%#
+`>' (or the first character of the \fBpromptchars\fR shell variable)
+for normal users, `#' (or the second character of \fBpromptchars\fR)
+for the superuser.
+.TP 4
+%{\fIstring\fR%}
+Includes \fIstring\fR as a literal escape sequence.
+It should be used only to change terminal attributes and
+should not move the cursor location. This
+cannot be the last sequence in \fBprompt\fR.
+.TP 4
+%?
+The return code of the command executed just before the prompt.
+.TP 4
+%R
+In \fBprompt2\fR, the status of the parser.
+In \fBprompt3\fR, the corrected string.
+In \fBhistory\fR, the history string.
+.PD
+.PP
+`%B', `%S', `%U' and `%{\fIstring\fR%}' are available only in
+eight-bit-clean shells; see the \fBversion\fR shell variable.
+.PP
+The bold, standout and underline sequences are often used to distinguish a
+superuser shell. For example,
+.IP "" 4
+> set prompt = "%m [%h] %B[%@]%b [%/] you rang? "
+.br
+tut [37] \fB[2:54pm]\fR [/usr/accts/sys] you rang? _
+.PP
+Set by default to `%# ' in interactive shells.
+.RE
+.TP 8
+.B prompt2 \fR(+)
+The string with which to prompt in \fIwhile\fR and \fIforeach\fR loops and
+after lines ending in `\\'.
+The same format sequences may be used as in \fBprompt\fR (q.v.);
+note the variable meaning of `%R'.
+Set by default to `%R? ' in interactive shells.
+.TP 8
+.B prompt3 \fR(+)
+The string with which to prompt when confirming automatic spelling correction.
+The same format sequences may be used as in \fBprompt\fR (q.v.);
+note the variable meaning of `%R'.
+Set by default to `CORRECT>%R (y|n|e|a)? ' in interactive shells.
+.TP 8
+.B promptchars \fR(+)
+If set (to a two-character string), the `%#' formatting sequence in the
+\fBprompt\fR shell variable is replaced with the first character for
+normal users and the second character for the superuser.
+.TP 8
+.B pushdtohome \fR(+)
+If set, \fIpushd\fR without arguments does `pushd ~', like \fIcd\fR.
+.TP 8
+.B pushdsilent \fR(+)
+If set, \fIpushd\fR and \fIpopd\fR do not print the directory stack.
+.TP 8
+.B recexact \fR(+)
+If set, completion completes on an exact match even if a longer match is
+possible.
+.TP 8
+.B recognize_only_executables \fR(+)
+If set, command listing displays only files in the path that are
+executable. Slow.
+.TP 8
+.B rmstar \fR(+)
+If set, the user is prompted before `rm *' is executed.
+.TP 8
+.B rprompt \fR(+)
+The string to print on the right-hand side of the screen (after
+the command input) when the prompt is being displayed on the left.
+It recognizes the same formatting characters as \fBprompt\fR.
+It will automatically disappear and reappear as necessary, to ensure that
+command input isn't obscured, and will only appear if the prompt,
+command input, and itself will fit together on the first line.
+If \fBedit\fR isn't set, then \fBrprompt\fR will be printed after
+the prompt and before the command input.
+.TP 8
+.B savedirs \fR(+)
+If set, the shell does `dirs \-S' before exiting.
+If the first word is set to a number, at most that many directory stack
+entries are saved.
+.TP 8
+.B savehist
+If set, the shell does `history \-S' before exiting.
+If the first word is set to a number, at most that many lines are saved.
+(The number must be less than or equal to \fBhistory\fR.)
+If the second word is set to `merge', the history list is merged with
+the existing history file instead of replacing it (if there is one) and
+sorted by time stamp and the most recent events are retained. (+)
+.TP 8
+.B sched \fR(+)
+The format in which the \fIsched\fR builtin command prints scheduled events;
+if not given, `%h\\t%T\\t%R\\n' is used.
+The format sequences are described above under \fBprompt\fR;
+note the variable meaning of `%R'.
+.TP 8
+.B shell
+The file in which the shell resides. This is used in forking
+shells to interpret files which have execute bits set, but
+which are not executable by the system. (See the description
+of \fBBuiltin and non-builtin command execution\fR.) Initialized to the
+(system-dependent) home of the shell.
+.TP 8
+.B shlvl \fR(+)
+The number of nested shells.
+Reset to 1 in login shells.
+See also \fBloginsh\fR.
+.TP 8
+.B status
+The status returned by the last command. If it terminated
+abnormally, then 0200 is added to the status. Builtin commands
+which fail return exit status `1', all other builtin commands
+return status `0'.
+.TP 8
+.B symlinks \fR(+)
+Can be set to several different values to control symbolic link (`symlink')
+resolution:
+.RS +8
+.PP
+If set to `chase', whenever the current directory changes to a directory
+containing a symbolic link, it is expanded to the real name of the directory
+to which the link points. This does not work for the user's home directory;
+this is a bug.
+.PP
+If set to `ignore', the shell tries to construct a current directory
+relative to the current directory before the link was crossed.
+This means that \fIcd\fRing through a symbolic link and then `cd ..'ing
+returns one to the original directory. This only affects builtin commands
+and filename completion.
+.PP
+If set to `expand', the shell tries to fix symbolic links by actually expanding
+arguments which look like path names. This affects any command, not just
+builtins. Unfortunately, this does not work for hard-to-recognize filenames,
+such as those embedded in command options. Expansion may be prevented by
+quoting. While this setting is usually the most convenient, it is sometimes
+misleading and sometimes confusing when it fails to recognize an argument
+which should be expanded. A compromise is to use `ignore' and use the
+editor command \fInormalize-path\fR (bound by default to ^X-n) when necessary.
+.PP
+Some examples are in order. First, let's set up some play directories:
+.IP "" 4
+> cd /tmp
+.br
+> mkdir from from/src to
+.br
+> ln \-s from/src to/dist
+.PP
+Here's the behavior with \fBsymlinks\fR unset,
+.IP "" 4
+> cd /tmp/to/dist; echo $cwd
+.br
+/tmp/to/dist
+.br
+> cd ..; echo $cwd
+.br
+/tmp/from
+.PP
+here's the behavior with \fBsymlinks\fR set to `chase',
+.IP "" 4
+> cd /tmp/to/dst; echo $cwd
+.br
+/tmp/from/src
+.br
+> cd ..; echo $cwd
+.br
+/tmp/from
+.PP
+here's the behavior with \fBsymlinks\fR set to `ignore',
+.IP "" 4
+> cd /tmp/to/dist; echo $cwd
+.br
+/tmp/to/dst
+.br
+> cd ..; echo $cwd
+.br
+/tmp/to
+.PP
+and here's the behavior with \fBsymlinks\fR set to `expand'.
+.IP "" 4
+> cd /tmp/to/dist; echo $cwd
+.br
+/tmp/to/dst
+.br
+> cd ..; echo $cwd
+.br
+/tmp/to
+.br
+> cd /tmp/to/dist; echo $cwd
+.br
+/tmp/to/dst
+.br
+> cd ".."; echo $cwd
+.br
+/tmp/from
+.br
+> /bin/echo ..
+.br
+/tmp/to
+.br
+> /bin/echo ".."
+.br
+\&..
+.PP
+Note that `expand' expansion 1) works just like `ignore' for builtins
+like \fIcd\fR, 2) is prevented by quoting, and 3) happens before
+filenames are passed to non-builtin commands.
+.RE
+.TP 8
+.B tcsh \fR(+)
+The version number of the shell in the format `R.VV.PP',
+where `R' is the major release number, `VV' the current version
+and `PP' the patchlevel.
+.TP 8
+.B term
+The terminal type. Usually set in \fI~/.login\fR as described under
+\fBStartup and shutdown\fR.
+.TP 8
+.B time
+If set to a number, then the \fItime\fR builtin (q.v.) executes automatically
+after each command which takes more than that many CPU seconds.
+If there is a second word, it is used as a format string for the output
+of the \fItime\fR builtin. (u) The following sequences may be used in the
+format string:
+.PP
+.RS +8
+.PD 0
+.TP 4
+%U
+The time the process spent in user mode in cpu seconds.
+.TP 4
+%S
+The time the process spent in kernel mode in cpu seconds.
+.TP 4
+%E
+The elapsed (wall clock) time in seconds.
+.TP 4
+%P
+The CPU percentage computed as (%U + %S) / %E.
+.TP 4
+%W
+Number of times the process was swapped.
+.TP 4
+%X
+The average amount in (shared) text space used in Kbytes.
+.TP 4
+%D
+The average amount in (unshared) data/stack space used in Kbytes.
+.TP 4
+%K
+The total space used (%X + %D) in Kbytes.
+.TP 4
+%M
+The maximum memory the process had in use at any time in Kbytes.
+.TP 4
+%F
+The number of major page faults (page needed to be brought from disk).
+.TP 4
+%R
+The number of minor page faults.
+.TP 4
+%I
+The number of input operations.
+.TP 4
+%O
+The number of output operations.
+.TP 4
+%r
+The number of socket messages received.
+.TP 4
+%s
+The number of socket messages sent.
+.TP 4
+%k
+The number of signals received.
+.TP 4
+%w
+The number of voluntary context switches (waits).
+.TP 4
+%c
+The number of involuntary context switches.
+.PD
+.PP
+Only the first four sequences are supported on systems without BSD resource
+limit functions.
+The default time format is `%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww' for
+systems that support resource usage reporting and `%Uu %Ss %E %P' for
+systems that do not.
+.PP
+Under Sequent's DYNIX/ptx, %X, %D, %K, %r and %s are not
+available, but the following additional sequences are:
+.PP
+.PD 0
+.TP 4
+%Y
+The number of system calls performed.
+.TP 4
+%Z
+The number of pages which are zero-filled on demand.
+.TP 4
+%i
+The number of times a process's resident set size was increased by the kernel.
+.TP 4
+%d
+The number of times a process's resident set size was decreased by the kernel.
+.TP 4
+%l
+The number of read system calls performed.
+.TP 4
+%m
+The number of write system calls performed.
+.TP 4
+%p
+The number of reads from raw disk devices.
+.TP 4
+%q
+The number of writes to raw disk devices.
+.PD
+.PP
+and the default time format is `%Uu %Ss $E %P %I+%Oio %Fpf+%Ww'.
+Note that the CPU percentage can be higher than 100% on multi-processors.
+.RE
+.TP 8
+.B tperiod \fR(+)
+The period, in minutes, between executions of the \fIperiodic\fR special alias.
+.TP 8
+.B tty \fR(+)
+The name of the tty, or empty if not attached to one.
+.TP 8
+.B uid \fR(+)
+The user's real user ID.
+.TP 8
+.B user
+The user's login name.
+.TP 8
+.B verbose
+If set, causes the words of each
+command to be printed, after history substitution (if any).
+Set by the \fB\-v\fR command line option.
+.TP 8
+.B version \fR(+)
+The version ID stamp. It contains the shell's version number (see \fBtcsh\fR),
+origin, release date, vendor, operating system and machine (see \fBVENDOR\fR,
+\fBOSTYPE\fR and \fBMACHTYPE\fR) and a comma-separated
+list of options which were set at compile time.
+Options which are set by default in the distribution are noted.
+.PP
+.RS +8
+.PD 0
+.TP 4
+8b
+The shell is eight bit clean; default
+.TP 4
+7b
+The shell is not eight bit clean
+.TP 4
+nls
+The system's NLS is used; default for systems with NLS
+.TP 4
+lf
+Login shells execute \fI/etc/csh.login\fR before instead of after
+\fI/etc/csh.cshrc\fR and \fI~/.login\fR before instead of after
+\fI~/.tcshrc\fR and \fI~/.history\fR.
+.TP 4
+dl
+`.' is put last in \fBpath\fR for security; default
+.TP 4
+nd
+`.' is omitted from \fBpath\fR for security
+.TP 4
+vi
+\fIvi\fR-style editing is the default rather than \fIemacs\fR
+.TP 4
+dtr
+Login shells drop DTR when exiting
+.TP 4
+bye
+\fIbye\fR is a synonym for \fIlogout\fR and \fIlog\fR
+is an alternate name for \fIwatchlog\fR
+.TP 4
+al
+\fBautologout\fR is enabled; default
+.TP 4
+kan
+Kanji is used and the ISO character set is ignored,
+unless the \fBnokanji\fR shell variable is set
+.TP 4
+sm
+The system's \fImalloc\fR(3) is used
+.TP 4
+hb
+The `#!<program> <args>' convention is emulated when executing shell scripts
+.TP 4
+ng
+The \fInewgrp\fR builtin is available
+.TP 4
+rh
+The shell attempts to set the \fBREMOTEHOST\fR environment variable
+.TP 4
+afs
+The shell verifies your password with the kerberos server if local
+authentication fails. The \fBafsuser\fR shell variable or the
+\fBAFSUSER\fR environment variable override your local username if set.
+.PD
+.PP
+An administrator may enter additional strings to indicate differences
+in the local version.
+.RE
+.TP 8
+.B visiblebell \fR(+)
+If set, a screen flash is used rather than the audible bell.
+See also \fBnobeep\fR.
+.TP 8
+.B watch \fR(+)
+A list of user/terminal pairs to watch for logins and logouts.
+If either the user is `any' all terminals are watched for the given user
+and vice versa.
+Setting \fBwatch\fR to `(any any)' watches all users and terminals.
+For example,
+.RS +8
+.IP "" 4
+set watch = (george ttyd1 any console $user any)
+.PP
+reports activity of the user `george' on ttyd1, any user on the console, and
+oneself (or a trespasser) on any terminal.
+.PP
+Logins and logouts are checked every 10 minutes by default, but the first
+word of \fBwatch\fR can be set to a number to check every so many minutes.
+For example,
+.IP "" 4
+set watch = (1 any any)
+.PP
+reports any login/logout once every minute. For the impatient, the \fIlog\fR
+builtin command triggers a \fBwatch\fR report at any time. All current logins
+are reported (as with the \fIlog\fR builtin) when \fBwatch\fR is first set.
+.PP
+The \fBwho\fR shell variable controls the format of \fBwatch\fR reports.
+.RE
+.TP 8
+.B who \fR(+)
+The format string for \fBwatch\fR messages. The following sequences
+are replaced by the given information:
+.PP
+.RS +8
+.PD 0
+.TP 4
+%n
+The name of the user who logged in/out.
+.TP 4
+%a
+The observed action, i.e. `logged on', `logged off' or `replaced \fIolduser\fR on'.
+.TP 4
+%l
+The terminal (tty) on which the user logged in/out.
+.TP 4
+%M
+The full hostname of the remote host, or `local' if the login/logout was
+from the local host.
+.TP 4
+%m
+The hostname of the remote host up to the first `.'.
+The full name is printed if it is an IP address or an X Window System display.
+.PD
+.PP
+%M and %m are available only on systems which store the remote hostname in
+\fI/etc/utmp\fR.
+If unset, `%n has %a %l from %m.' is used, or `%n has %a %l.' on systems
+which don't store the remote hostname.
+.RE
+.TP 8
+.B wordchars \fR(+)
+A list of non-alphanumeric characters to be considered part of a word by the
+\fIforward-word\fR, \fIbackward-word\fR etc. editor commands.
+If unset, `*?_\-.[]~=' is used.
+.SH ENVIRONMENT
+.TP 8
+.B AFSUSER \fR(+)
+Equivalent to the \fBafsuser\fR shell variable.
+.TP 8
+.B COLUMNS
+The number of columns in the terminal. See \fBTerminal management\fR.
+.TP 8
+.B DISPLAY
+Used by X Window System (see \fIX\fR(1)).
+If set, the shell does not set \fBautologout\fR (q.v.).
+.TP 8
+.B EDITOR
+The pathname to a default editor.
+See also the \fBVISUAL\fR environment variable
+and the \fIrun-fg-editor\fR editor command.
+.TP 8
+.B GROUP \fR(+)
+Equivalent to the \fBgroup\fR shell variable.
+.TP 8
+.B HOME
+Equivalent to the \fBhome\fR shell variable.
+.TP 8
+.B HOST \fR(+)
+Initialized to the name of the machine on which the shell
+is running, as determined by the \fIgethostname\fR(2) system call.
+.TP 8
+.B HOSTTYPE \fR(+)
+Initialized to the type of machine on which the shell
+is running, as determined at compile time. This variable is obsolete and
+will be removed in a future version.
+.TP 8
+.B HPATH \fR(+)
+A colon-separated list of directories in which the \fIrun-help\fR editor
+command looks for command documentation.
+.TP 8
+.B LANG
+Gives the preferred character environment.
+See \fBNative Language System support\fR.
+.TP 8
+.B LC_CTYPE
+If set, only ctype character handling is changed.
+See \fBNative Language System support\fR.
+.TP 8
+.B LINES
+The number of lines in the terminal. See \fBTerminal management\fR.
+.TP 8
+.B LS_COLORS
+The format of this variable is reminiscent of the \fBtermcap(5)\fR
+file format; a colon-separated list of expressions of the form
+"\fIxx=string\fR", where "\fIxx\fR" is a two-character variable name. The
+variables with their associated defaults are:
+.PP
+.RS +8
+.nf
+no 0 Normal (non-filename) text
+fi 0 Regular file
+di 01;34 Directory
+ln 01;36 Symbolic link
+pi 33 Named pipe (FIFO)
+so 01;35 Socket
+bd 01;33 Block device
+cd 01;32 Character device
+ex 01;32 Executable file
+mi (none) Missing file (defaults to fi)
+or (none) Orphaned symbolic link (defaults to ln)
+lc ^[[ Left code
+rc m Right code
+ec (none) End code (replaces lc+no+rc)
+.fi
+.PP
+You only need to include the variables you want to change from
+the default.
+.PP
+File names can also be colorized based on filename extension.
+This is specified in the \fBLS_COLORS\fR variable using the syntax
+\fB"*ext=string"\fR. For example, using ISO 6429 codes, to color
+all C\-language source files blue you would specify \fB"*.c=34"\fR.
+This would color all files ending in \fB.c\fR in blue (34) color.
+.PP
+Control characters can be written either in C\-style\-escaped
+notation, or in stty\-like ^\-notation. The C\-style notation
+adds \fB^[\fR for Escape, \fB\_\fR for a normal space characer,
+and \fB?\fR for Delete. In addition, the \fB^[\fR escape character
+can be used to override the default interpretation of \fB^[\fR,
+\fB^\fR, \fB:\fR and \fB=\fR.
+.PP
+Each file will be written as \fB<lc>\fR \fB<color-code>\fR
+\fB<rc>\fR \fB<filename>\fR \fB<ec>\fR. If the \fB<ec>\fR
+code is undefined, the sequence \fB<lc>\fR \fB<no>
+\fB<rc>\fR will be used instead. This is generally more convenient
+to use, but less general. The left, right and end codes are
+provided so you don't have to type common parts over and over
+again and to support weird terminals; you will generally not
+need to change them at all unless your terminal does not use
+ISO 6429 color sequences but a different system.
+.PP
+If your terminal does use ISO 6429 color codes, you can
+compose the type codes (i.e. all except the \fBlc\fR, \fBrc\fR,
+and \fBec\fR codes) from numerical commands separated by semicolons. The
+most common commands are:
+.PP
+.RS +8
+.PD 0
+.TP 4
+0
+to restore default color
+.TP 4
+1
+for brighter colors
+.TP 4
+4
+for underlined text
+.TP 4
+5
+for flashing text
+.TP 4
+30
+for black foreground
+.TP 4
+31
+for red foreground
+.TP 4
+32
+for green foreground
+.TP 4
+33
+for yellow (or brown) foreground
+.TP 4
+34
+for blue foreground
+.TP 4
+35
+for purple foreground
+.TP 4
+36
+for cyan foreground
+.TP 4
+37
+for white (or gray) foreground
+.TP 4
+40
+for black background
+.TP 4
+41
+for red background
+.TP 4
+42
+for green background
+.TP 4
+43
+for yellow (or brown) background
+.TP 4
+44
+for blue background
+.TP 4
+45
+for purple background
+.TP 4
+46
+for cyan background
+.TP 4
+47
+for white (or gray) background
+.RE
+.PP
+Not all commands will work on all systems or display devices.
+.PP
+A few terminal programs do not recognize the default end code
+properly. If all text gets colorized after you do a directory
+listing, try changing the \fBno\fR and \fBfi\fR codes from 0 to the
+numerical codes for your standard fore- and background colors.
+.RE
+.TP 8
+.B MACHTYPE \fR(+)
+The machine type (microprocessor class or machine model), as determined at compile time.
+.TP 8
+.B NOREBIND \fR(+)
+If set, printable characters are not rebound to \fIself-insert-command\fR.
+See \fBNative Language System support\fR.
+.TP 8
+.B OSTYPE \fR(+)
+The operating system, as determined at compile time.
+.TP 8
+.B PATH
+A colon-separated list of directories in which to look for executables.
+Equivalent to the \fBpath\fR shell variable, but in a different format.
+.TP 8
+.B PWD \fR(+)
+Equivalent to the \fBcwd\fR shell variable, but not synchronized to it;
+updated only after an actual directory change.
+.TP 8
+.B REMOTEHOST \fR(+)
+The host from which the user has logged in remotely, if this is the case and
+the shell is able to determine it. Set only if the shell was so compiled;
+see the \fBversion\fR shell variable.
+.TP 8
+.B SHLVL \fR(+)
+Equivalent to the \fBshlvl\fR shell variable.
+.TP 8
+.B SYSTYPE \fR(+)
+The current system type. (Domain/OS only)
+.TP 8
+.B TERM
+Equivalent to the \fBterm\fR shell variable.
+.TP 8
+.B TERMCAP
+The terminal capability string. See \fBTerminal management\fR.
+.TP 8
+.B USER
+Equivalent to the \fBuser\fR shell variable.
+.TP 8
+.B VENDOR \fR(+)
+The vendor, as determined at compile time.
+.TP 8
+.B VISUAL
+The pathname to a default full-screen editor.
+See also the \fBEDITOR\fR environment variable
+and the \fIrun-fg-editor\fR editor command.
+.SH FILES
+.PD 0
+.TP 16
+.I /etc/csh.cshrc
+Read first by every shell.
+ConvexOS, Stellix and Intel use \fI/etc/cshrc\fR and
+NeXTs use \fI/etc/cshrc.std\fR.
+A/UX, AMIX, Cray and IRIX have no equivalent in \fIcsh\fR(1),
+but read this file in \fItcsh\fR anyway.
+Solaris 2.x does not have it either, but \fItcsh\fR reads \fI/etc/.cshrc\fR. (+)
+.TP 16
+.I /etc/csh.login
+Read by login shells after \fI/etc/csh.cshrc\fR.
+ConvexOS, Stellix and Intel use \fI/etc/login\fR,
+NeXTs use \fI/etc/login.std\fR, Solaris 2.x uses \fI/etc/.login\fR and
+A/UX, AMIX, Cray and IRIX use \fI/etc/cshrc\fR.
+.TP 16
+.I ~/.tcshrc \fR(+)
+Read by every shell after \fI/etc/csh.cshrc\fR or its equivalent.
+.TP 16
+.I ~/.cshrc
+Read by every shell, if \fI~/.tcshrc\fR doesn't exist,
+after \fI/etc/csh.cshrc\fR or its equivalent.
+This manual uses `\fI~/.tcshrc\fR' to mean `\fI~/.tcshrc\fR or,
+if \fI~/.tcshrc\fR is not found, \fI~/.cshrc\fR'.
+.TP 16
+.I ~/.history
+Read by login shells after \fI~/.tcshrc\fR
+if \fBsavehist\fR is set, but see also \fBhistfile\fR.
+.TP 16
+.I ~/.login
+Read by login shells after \fI~/.tcshrc\fR or \fI~/.history\fR.
+The shell may be compiled to read \fI~/.login\fR before instead of after
+\fI~/.tcshrc\fR and \fI~/.history\fR; see the \fBversion\fR shell variable.
+.TP 16
+.I ~/.cshdirs \fR(+)
+Read by login shells after \fI~/.login\fR
+if \fBsavedirs\fR is set, but see also \fBdirsfile\fR.
+.TP 16
+.I /etc/csh.logout
+Read by login shells at logout.
+ConvexOS, Stellix and Intel use \fI/etc/logout\fR and
+NeXTs use \fI/etc/logout.std\fR.
+A/UX, AMIX, Cray and IRIX have no equivalent in \fIcsh\fR(1),
+but read this file in \fItcsh\fR anyway.
+Solaris 2.x does not have it either, but \fItcsh\fR reads \fI/etc/.cshrc\fR. (+)
+.TP 16
+.I ~/.logout
+Read by login shells at logout after \fI/etc/csh.logout\fR or its equivalent.
+.TP 16
+.I /bin/sh
+Used to interpret shell scripts not starting with a `#'.
+.TP 16
+.I /tmp/sh*
+Temporary file for `<<'.
+.TP 16
+.I /etc/passwd
+Source of home directories for `~name' substitutions.
+.PD
+.PP
+The order in which startup files are read may differ if the shell was so
+compiled; see \fBStartup and shutdown\fR and the \fBversion\fR shell variable.
+.SH "NEW FEATURES (+)"
+This manual describes \fItcsh\fR as a single entity,
+but experienced \fIcsh\fR(1) users will want to pay special attention to
+\fItcsh\fR's new features.
+.PP
+A command-line editor, which supports GNU Emacs or \fIvi\fR(1)-style
+key bindings. See \fBThe command-line editor\fR and \fBEditor commands\fR.
+.PP
+Programmable, interactive word completion and listing.
+See \fBCompletion and listing\fR and the \fIcomplete\fR and \fIuncomplete\fR
+builtin commands.
+.PP
+\fBSpelling correction\fR (q.v.) of filenames, commands and variables.
+.PP
+\fBEditor commands\fR (q.v.) which perform other useful functions in the middle of
+typed commands, including documentation lookup (\fIrun-help\fR),
+quick editor restarting (\fIrun-fg-editor\fR) and
+command resolution (\fIwhich-command\fR).
+.PP
+An enhanced history mechanism. Events in the history list are time-stamped.
+See also the \fIhistory\fR command and its associated shell variables,
+the previously undocumented `#' event specifier and new modifiers
+under \fBHistory substitution\fR,
+the \fI*-history\fR, \fIhistory-search-*\fR, \fIi-search-*\fR, \fIvi-search-*\fR and
+\fItoggle-literal-history\fR editor commands
+and the \fBhistlit\fR shell variable.
+.PP
+Enhanced directory parsing and directory stack handling.
+See the \fIcd\fR, \fIpushd\fR, \fIpopd\fR and \fIdirs\fR commands and their associated
+shell variables, the description of \fBDirectory stack substitution\fR,
+the \fBdirstack\fR, \fBowd\fR and \fBsymlinks\fR shell variables and
+the \fInormalize-command\fR and \fInormalize-path\fR editor commands.
+.PP
+Negation in glob-patterns. See \fBFilename substitution\fR.
+.PP
+New \fBFile inquiry operators\fR (q.v.) and a \fIfiletest\fR
+builtin which uses them.
+.PP
+A variety of \fBAutomatic, periodic and timed events\fR (q.v.) including
+scheduled events, special aliases, automatic logout and terminal locking,
+command timing and watching for logins and logouts.
+.PP
+Support for the Native Language System
+(see \fBNative Language System support\fR),
+OS variant features
+(see \fBOS variant support\fR and the \fBecho_style\fR shell variable)
+and system-dependent file locations (see \fBFILES\fR).
+.PP
+Extensive terminal-management capabilities. See \fBTerminal management\fR.
+.PP
+New builtin commands including \fIbuiltins\fR, \fIhup\fR, \fIls\-F\fR,
+\fInewgrp\fR, \fIprintenv\fR, \fIwhich\fR and \fIwhere\fR (q.v.).
+.PP
+New variables that make useful information easily available to the shell.
+See the \fBgid\fR, \fBloginsh\fR, \fBoid\fR, \fBshlvl\fR, \fBtcsh\fR,
+\fBtty\fR, \fBuid\fR and \fBversion\fR shell variables and the \fBHOST\fR,
+\fBREMOTEHOST\fR, \fBVENDOR\fR, \fBOSTYPE\fR and \fBMACHTYPE\fR environment
+variables.
+.PP
+A new syntax for including useful information in the prompt string
+(see \fBprompt\fR).
+and special prompts for loops and spelling correction
+(see \fBprompt2\fR and \fBprompt3\fR).
+.PP
+Read-only variables. See \fBVariable substitution\fR.
+.SH BUGS
+When a suspended command is restarted, the shell prints the directory
+it started in if this is different from the current directory. This can
+be misleading (i.e. wrong) as the job may have changed directories internally.
+.PP
+Shell builtin functions are not stoppable/restartable. Command sequences
+of the form `a ; b ; c' are also not handled gracefully when stopping is
+attempted. If you suspend `b', the shell will then immediately execute
+`c'. This is especially noticeable if this expansion results from an
+\fIalias\fR. It suffices to place the sequence of commands in ()'s to force it
+to a subshell, i.e. `( a ; b ; c )'.
+.PP
+Control over tty output after processes are started is primitive; perhaps
+this will inspire someone to work on a good virtual terminal interface.
+In a virtual terminal interface much more interesting things could be
+done with output control.
+.PP
+Alias substitution is most often used to clumsily simulate shell procedures;
+shell procedures should be provided rather than aliases.
+.PP
+Commands within loops are not placed in the history
+list. Control structures should be parsed rather than being recognized as
+built-in commands. This would allow control commands to be placed anywhere,
+to be combined with `|', and to be used with `&' and `;' metasyntax.
+.PP
+\fIforeach\fR doesn't ignore here documents when looking for its \fIend\fR.
+.PP
+It should be possible to use the `:' modifiers on the output of command
+substitutions.
+.PP
+The screen update for lines longer than the screen width is very poor
+if the terminal cannot move the cursor up (i.e. terminal type `dumb').
+.PP
+\fBHPATH\fR and \fBNOREBIND\fR don't need to be environment variables.
+.PP
+Glob-patterns which do not use `?', `*' or `[]' or which use `{}' or `~'
+are not negated correctly.
+.PP
+The single-command form of \fIif\fR does output redirection even if
+the expression is false and the command is not executed.
+.PP
+\fIls\-F\fR includes file identification characters when sorting filenames
+and does not handle control characters in filenames well. It cannot be
+interrupted.
+.PP
+Report bugs to tcsh-bugs@mx.gw.com, preferably with fixes. If you want to
+help maintain and test tcsh, send mail to listserv@mx.gw.com with the text
+`subscribe tcsh <your name>' on a line by itself in the body. You can
+also `subscribe tcsh-bugs <your name>' to get all bug reports, or
+`subscribe tcsh-diffs <your name>' to get the development list plus
+diffs for each patchlevel.
+.SH THE T IN TCSH
+In 1964, DEC produced the PDP-6. The PDP-10 was a later re-implementation. It
+was re-christened the DECsystem-10 in 1970 or so when DEC brought out the
+second model, the KI10.
+.PP
+TENEX was created at Bolt, Beranek & Newman (a Cambridge, Mass. think tank) in
+1972 as an experiment in demand-paged virtual memory operating systems. They
+built a new pager for the DEC PDP-10 and created the OS to go with it. It was
+extremely successful in academia.
+.PP
+In 1975, DEC brought out a new model of the PDP-10, the KL10; they intended to
+have only a version of TENEX, which they had licensed from BBN, for the new
+box. They called their version TOPS-20 (their capitalization is trademarked).
+A lot of TOPS-10 users (`The OPerating System for PDP-10') objected; thus DEC
+found themselves supporting two incompatible systems on the same hardware--but
+then there were 6 on the PDP-11!
+.PP
+TENEX, and TOPS-20 to version 3, had command completion
+via a user-code-level subroutine library called ULTCMD. With version 3, DEC
+moved all that capability and more into the monitor (`kernel' for you Unix
+types), accessed by the COMND% JSYS (`Jump to SYStem' instruction, the
+supervisor call mechanism [are my IBM roots also showing?]).
+.PP
+The creator of tcsh was impressed by this feature and several others of TENEX
+and TOPS-20, and created a version of csh which mimicked them.
+.SH LIMITATIONS
+Words can be no longer than 1024 characters.
+.PP
+The system limits argument lists to 10240 characters.
+.PP
+The number of arguments to a command which involves filename expansion is
+limited to 1/6th the number of characters allowed in an argument list.
+.PP
+Command substitutions may substitute no more characters than are allowed in
+an argument list.
+.PP
+To detect looping, the shell restricts the number of \fIalias\fR
+substitutions on a single line to 20.
+.SH "SEE ALSO"
+csh(1), emacs(1), ls(1), newgrp(1), sh(1), setpath(1), stty(1), su(1),
+tset(1), vi(1), x(1), access(2), execve(2), fork(2), killpg(2),
+pipe(2), setrlimit(2), sigvec(2), stat(2), umask(2), vfork(2), wait(2),
+malloc(3), setlocale(3), tty(4), a.out(5), termcap(5), environ(7),
+termio(7), Introduction to the C Shell
+.SH VERSION
+This manual documents tcsh 6.09.00 (Astron) 1999-08-16.
+.SH AUTHORS
+.PD 0
+.TP 2
+William Joy
+Original author of \fIcsh\fR(1)
+.TP 2
+J.E. Kulp, IIASA, Laxenburg, Austria
+Job control and directory stack features
+.TP 2
+Ken Greer, HP Labs, 1981
+File name completion
+.TP 2
+Mike Ellis, Fairchild, 1983
+Command name recognition/completion
+.TP 2
+Paul Placeway, Ohio State CIS Dept., 1983-1993
+Command line editor, prompt routines, new glob syntax and numerous fixes
+and speedups
+.TP 2
+Karl Kleinpaste, CCI 1983-4
+Special aliases, directory stack extraction stuff, login/logout watch,
+scheduled events, and the idea of the new prompt format
+.TP 2
+Rayan Zachariassen, University of Toronto, 1984
+\fIls\-F\fR and \fIwhich\fR builtins and numerous bug fixes, modifications
+and speedups
+.TP 2
+Chris Kingsley, Caltech
+Fast storage allocator routines
+.TP 2
+Chris Grevstad, TRW, 1987
+Incorporated 4.3BSD \fIcsh\fR into \fItcsh\fR
+.TP 2
+Christos S. Zoulas, Cornell U. EE Dept., 1987-94
+Ports to HPUX, SVR2 and SVR3, a SysV version of getwd.c, SHORT_STRINGS support
+and a new version of sh.glob.c
+.TP 2
+James J Dempsey, BBN, and Paul Placeway, OSU, 1988
+A/UX port
+.TP 2
+Daniel Long, NNSC, 1988
+\fBwordchars\fR
+.TP 2
+Patrick Wolfe, Kuck and Associates, Inc., 1988
+\fIvi\fR mode cleanup
+.TP 2
+David C Lawrence, Rensselaer Polytechnic Institute, 1989
+\fBautolist\fR and ambiguous completion listing
+.TP 2
+Alec Wolman, DEC, 1989
+Newlines in the prompt
+.TP 2
+Matt Landau, BBN, 1989
+\fI~/.tcshrc\fR
+.TP 2
+Ray Moody, Purdue Physics, 1989
+Magic spacebar history expansion
+.TP 2
+Mordechai ????, Intel, 1989
+printprompt() fixes and additions
+.TP 2
+Kazuhiro Honda, Dept. of Computer Science, Keio University, 1989
+Automatic spelling correction and \fBprompt3\fR
+.TP 2
+Per Hedeland, Ellemtel, Sweden, 1990-
+Various bugfixes, improvements and manual updates
+.TP 2
+Hans J. Albertsson (Sun Sweden)
+\fBampm\fR, \fIsettc\fR and \fItelltc\fR
+.TP 2
+Michael Bloom
+Interrupt handling fixes
+.TP 2
+Michael Fine, Digital Equipment Corp
+Extended key support
+.TP 2
+Eric Schnoebelen, Convex, 1990
+Convex support, lots of \fIcsh\fR bug fixes,
+save and restore of directory stack
+.TP 2
+Ron Flax, Apple, 1990
+A/UX 2.0 (re)port
+.TP 2
+Dan Oscarsson, LTH Sweden, 1990
+NLS support and simulated NLS support for non NLS sites, fixes
+.TP 2
+Johan Widen, SICS Sweden, 1990
+\fBshlvl\fR, Mach support, \fIcorrect-line\fR, 8-bit printing
+.TP 2
+Matt Day, Sanyo Icon, 1990
+POSIX termio support, SysV limit fixes
+.TP 2
+Jaap Vermeulen, Sequent, 1990-91
+Vi mode fixes, expand-line, window change fixes, Symmetry port
+.TP 2
+Martin Boyer, Institut de recherche d'Hydro-Quebec, 1991
+\fBautolist\fR beeping options, modified the history search to search for
+the whole string from the beginning of the line to the cursor.
+.TP 2
+Scott Krotz, Motorola, 1991
+Minix port
+.TP 2
+David Dawes, Sydney U. Australia, Physics Dept., 1991
+SVR4 job control fixes
+.TP 2
+Jose Sousa, Interactive Systems Corp., 1991
+Extended \fIvi\fR fixes and \fIvi\fR delete command
+.TP 2
+Marc Horowitz, MIT, 1991
+ANSIfication fixes, new exec hashing code, imake fixes, \fIwhere\fR
+.TP 2
+Bruce Sterling Woodcock, sterling@netcom.com, 1991-1995
+ETA and Pyramid port, Makefile and lint fixes, \fBignoreeof\fR=n addition, and
+various other portability changes and bug fixes
+.TP 2
+Jeff Fink, 1992
+\fIcomplete-word-fwd\fR and \fIcomplete-word-back\fR
+.TP 2
+Harry C. Pulley, 1992
+Coherent port
+.TP 2
+Andy Phillips, Mullard Space Science Lab U.K., 1992
+VMS-POSIX port
+.TP 2
+Beto Appleton, IBM Corp., 1992
+Walking process group fixes, \fIcsh\fR bug fixes,
+POSIX file tests, POSIX SIGHUP
+.TP 2
+Scott Bolte, Cray Computer Corp., 1992
+CSOS port
+.TP 2
+Kaveh R. Ghazi, Rutgers University, 1992
+Tek, m88k, Titan and Masscomp ports and fixes. Added autoconf support.
+.TP 2
+Mark Linderman, Cornell University, 1992
+OS/2 port
+.TP 2
+Mika Liljeberg, liljeber@kruuna.Helsinki.FI, 1992
+Linux port
+.TP 2
+Tim P. Starrin, NASA Langley Research Center Operations, 1993
+Read-only variables
+.TP 2
+Dave Schweisguth, Yale University, 1993-4
+New manpage and tcsh.man2html
+.TP 2
+Larry Schwimmer, Stanford University, 1993
+AFS and HESIOD patches
+.TP 2
+Luke Mewburn, RMIT University, 1994-6
+Enhanced directory printing in prompt,
+added \fBellipsis\fR and \fBrprompt\fR.
+.TP 2
+Edward Hutchins, Silicon Graphics Inc., 1996
+Added implicit cd.
+.TP 2
+Martin Kraemer, 1997
+Ported to Siemens Nixdorf EBCDIC machine
+.TP 2
+Amol Deshpande, Microsoft, 1997
+Ported to WIN32 (Windows/95 and Windows/NT); wrote all the missing library
+and message catalog code to interface to Windows.
+.TP 2
+Taga Nayuta, 1998
+Color ls additions.
+.PD
+.PP
+.SH "THANKS TO"
+Bryan Dunlap, Clayton Elwell, Karl Kleinpaste, Bob Manson, Steve Romig,
+Diana Smetters, Bob Sutterfield, Mark Verber, Elizabeth Zwicky and all
+the other people at Ohio State for suggestions and encouragement
+.PP
+All the people on the net, for putting up with,
+reporting bugs in, and suggesting new additions to each and every version
+.PP
+Richard M. Alderson III, for writing the `T in tcsh' section
diff --git a/contrib/tcsh/tcsh.man2html b/contrib/tcsh/tcsh.man2html
new file mode 100644
index 0000000..839bcb4
--- /dev/null
+++ b/contrib/tcsh/tcsh.man2html
@@ -0,0 +1,859 @@
+#!/usr/local/bin/perl
+# $Id: tcsh.man2html,v 1.10 1997/10/29 17:27:04 christos Exp $
+
+# tcsh.man2html, Dave Schweisguth <dcs@proton.chem.yale.edu>
+#
+# Notes:
+#
+# Always puts all files in the directory tcsh.html, creating it if necessary.
+# tcsh.html/top.html is the entry point, and tcsh.html/index.html is a symlink
+# to tcsh.html/top.html so one needn't specify a file at all if working through
+# a typically configured server.
+#
+# Designed for tcsh manpage. Guaranteed not to work on manpages not written
+# in the exact same style of nroff -man, i.e. any other manpage.
+#
+# Makes links FROM items which are both a) in particular sections (see
+# Configuration) and b) marked with .B or .I. Makes links TO items which
+# are marked with \fB ... \fR or \fI ... \fR.
+#
+# Designed with X Mosaic in mind and tested lightly with lynx. I've punted on
+# HTML's lack of a .PD equivalent and lynx's different <menu> handling.
+
+# Emulate #!/usr/local/bin/perl on systems without #!
+
+eval '(exit $?0)' && eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
+& eval 'exec /usr/local/bin/perl -S $0 $argv:q' if 0;
+
+### Constants
+
+# Setup
+
+($whatami = $0) =~ s|.*/||; # `basename $0`
+$isatty = -t STDIN;
+
+# Configuration
+
+$index = 0; # Don't make a searchable index CGI script
+$cgibin = 0; # Look for $cgifile in $dir, not $cgibindir
+$shortfiles = 0; # Use long filenames
+$single = 0; # Make single page instead of top and sections
+
+$host = ''; # host:port part of server URL ***
+$updir = ''; # Directories between $host and $dir ***
+$dir = 'tcsh'; # Directory in which to put the pieces *
+$cgifile = 'tcsh.cgi'; # CGI script name **
+$cgibindir = 'cgi-bin'; # CGI directory ***
+$headerfile = 'header'; # HTML file for initial comments *
+$indexfile = 'index'; # Symlink to $topfile *
+$listsfile = 'lists'; # Mailing list description HTML file *
+$outfile = 'tcsh.man'; # Default input file and copy of input file
+$script = $whatami; # Copy of script; filename length must be OK
+$topfile = 'top'; # Top-level HTML file *
+
+# * .htm or .html suffix added later
+# ** Only used with -i or -c
+# *** Only used with -c
+
+# Sections to inline in the top page
+
+%inline_me = ('NAME', 1,
+ 'SYNOPSIS', 1);
+
+# Sections in which to put name anchors and the font in which to look for
+# links to those anchors
+
+%link_me = ('Editor commands', 'I',
+ 'Builtin commands', 'I',
+ 'Special aliases', 'I',
+ 'Special shell variables', 'B',
+ 'ENVIRONMENT', 'B',
+ 'FILES', 'I');
+
+### Arguments and error-checking
+
+# Parse args
+
+while ($#ARGV > -1 && (($first, $rest) = ($ARGV[0] =~ /^-(.)(.*)/))) {
+ # Perl 5 lossage alert
+ if ($first =~ /[CdDGh]/) { # Switches with arguments
+ shift;
+ $arg = $rest ne '' ? $rest : $ARGV[0] ne '' ? shift :
+ &usage("$whatami: -$first requires an argument.\n");
+ } elsif ($rest ne '') {
+ $ARGV[0] = "-$rest";
+ } else {
+ shift;
+ }
+ if ($first eq '1') { $single = 1; }
+ elsif ($first eq 'c') { $cgibin = 1; }
+ elsif ($first eq 'C') { $cgibindir = $arg; }
+ elsif ($first eq 'd') { $updir = $arg; }
+ elsif ($first eq 'D') { $dir = $arg; }
+ elsif ($first eq 'G') { $cgifile = $arg; }
+ elsif ($first eq 'h') { $host = $arg; }
+ elsif ($first eq 'i') { $index = 1; }
+ elsif ($first eq 's') { $shortfiles = 1; }
+ elsif ($first eq 'u') { &usage(0); }
+ else { &usage("$whatami: -$first is not an option.\n"); }
+}
+
+if (@ARGV == 0) {
+ if ($isatty) {
+ $infile = $outfile; # Default input file if interactive
+ } else {
+ $infile = 'STDIN'; # Read STDIN if no args and not a tty
+ }
+} elsif (@ARGV == 1) {
+ $infile = $ARGV[0];
+} else {
+ &usage("$whatami: Please specify one and only one file.\n");
+}
+
+$index = $index || $cgibin; # $index is true if $cgibin is true
+
+if ($cgibin && ! $host) {
+ die "$whatami: Must specify host with -h if using -c.\n";
+}
+
+# Decide on HTML suffix and append it to filenames
+
+$html = $shortfiles ? 'htm' : 'html'; # Max 3-character extension
+$dir .= ".$html"; # Directory in which to put the pieces
+$headerfile .= ".$html"; # HTML file for initial comments
+$topfile .= ".$html"; # Top-level HTML file (or moved notice)
+$indexfile .= ".$html"; # Symlink to $topfile
+$listsfile .= ".$html"; # Mailing list description HTML file
+
+# Check for input file
+
+unless ($infile eq 'STDIN') {
+ die "$whatami: $infile doesn't exist!\n" unless -e $infile;
+ die "$whatami: $infile is unreadable!\n" unless -r _;
+ die "$whatami: $infile is empty!\n" unless -s _;
+}
+
+# Check for output directory and create if necessary
+
+if (-e $dir) {
+ -d _ || die "$whatami: $dir is not a directory!\n";
+ -r _ && -w _ && -x _ || die "$whatami: $dir is inaccessible!\n"
+} else {
+ mkdir($dir, 0755) || die "$whatami: Can't create $dir!\n";
+}
+
+# Slurp manpage
+
+if ($infile eq 'STDIN') {
+ @man = <STDIN>;
+} else {
+ open(MAN, $infile) || die "$whatami: Error opening $infile!\n";
+ @man = <MAN>;
+ close MAN;
+}
+
+# Print manpage to HTML directory (can't use cp if we're reading from STDIN)
+
+open(MAN, ">$dir/$outfile") || die "$whatami: Can't open $dir/$outfile!\n";
+print MAN @man;
+close MAN;
+
+# Copy script to HTML directory
+
+(system("cp $0 $dir") >> 8) && die "$whatami: Can't copy $0 to $dir!\n";
+
+# Link top.html to index.html in case someone looks at tcsh.html/
+
+system("rm -f $dir/$indexfile"); # Some systems can't ln -sf
+(system("ln -s $topfile $dir/$indexfile") >> 8)
+ && die "$whatami: Can't link $topfile to $dir/$indexfile!\n";
+
+### Get title and section headings
+
+$comment = 0; # 0 for text, 1 for ignored text
+@sectionlines = (0); # First line of section
+@sectiontypes = (0); # H or S
+@sectiontexts = ('Header'); # Text of section heading
+@sectionfiles = ($headerfile); # Filename in which to store section
+%name = (); # Array of name anchors
+@name = () if $index; # Ordered array of name anchors
+$font = ''; # '' to not make names, 'B' or 'I' to do so
+
+$line = 0;
+foreach (@man) {
+ if (/^\.ig/) { # Start ignoring
+ $comment = 1;
+ } elsif (/^\.\./) { # Stop ignoring
+ $comment = 0;
+ } elsif (! $comment) { # Not in .ig'ed section; do stuff
+
+ # nroff special characters
+
+ s/\\-/-/g; # \-
+ s/\\^//g; # \^
+ s/^\\'/'/; # leading ' escape
+ s/^\\(\s)/$1/; # leading space escape
+ s/\\(e|\\)/\\/g; # \e, \\; must do this after other escapes
+
+ # HTML special characters; deal with these before adding more
+
+ s/&/&amp\;/g;
+ s/>/&gt\;/g;
+ s/</&lt\;/g;
+
+ # Get title
+
+ if (/^\.TH\s+(\w+)\s+(\w+)\s+\"([^\"]*)\"\s+\"([^\"]*)\"/) {
+ $title = "$1($2) $4 ($3) $1($2)";
+ }
+
+ # Build per-section info arrays
+
+ if (($type, $text) = /^\.S([HS])\s+\"?([^\"]*)\"?/) {
+
+ push(@sectionlines, $line); # Index of first line of section
+ push(@sectiontypes, $type eq 'H' ? 0 : 1); # Type of section
+ $text =~ s/\s*$//; # Remove trailing whitespace
+ push(@sectiontexts, $text); # Title of section (key for href)
+ $text =~ s/\s*\(\+\)$//; # Remove (+)
+ if ($shortfiles) {
+ $file = $#sectionlines; # Short filenames; use number
+ } else {
+ $file = $text; # Long filenames; use title
+ $file =~ s/[\s\/]+/_/g; # Replace whitespace and / with _
+ }
+ $file .= ".$html" unless $single;
+ push(@sectionfiles, $file); # File in which to store section
+ $name{"$text B"} = ($single ? '#' : '') . $file;
+ # Index entry for &make_hrefs
+ push(@name, "$text\t" . $name{"$text B"}) if $index;
+ # Index entry for CGI script
+ # Look for anchors in the rest of this section if $link_me{$text}
+ # is non-null, and mark them with the font which is its value
+
+ $font = $link_me{$text};
+ }
+ &make_name(*name, *font, *file, *index, *_) if $font;
+ }
+ $line++;
+}
+
+### Make top page
+
+open(TOP, ">$dir/$topfile");
+select TOP;
+
+# Top page header
+
+print <<EOP;
+<HEAD>
+<TITLE>$title</TITLE>
+</HEAD>
+<BODY>
+<A NAME="top"></A>
+<H1>$title</H1>
+<HR>
+EOP
+
+# FORM block, if we're making an index
+
+$action = $cgibin ? "http://$host/$cgibindir/$cgifile" : $cgifile;
+
+print <<EOP if $index;
+<FORM METHOD="GET" ACTION="$action">
+Go directly to a section, command or variable: <INPUT NAME="input">
+</FORM>
+EOP
+
+# Table of contents
+
+print <<EOP;
+<H2>
+EOP
+
+foreach $section (1 .. $#sectionlines) {
+ if ($sectiontypes[$section - 1] < $sectiontypes[$section]) {
+ print "</H2> <menu>\n"; # Indent, smaller font
+ } elsif ($sectiontypes[$section - 1] > $sectiontypes[$section]) {
+ print "</menu> <H2>\n"; # Outdent, larger font
+ }
+ if ($inline_me{$sectiontexts[$section]}) { # Section is in %inline_me
+
+ # Print section inline
+
+ print "$sectiontexts[$section]\n";
+ print "</H2> <menu>\n"; # Indent, smaller font
+ &printsectionbody(*man, *sectionlines, *section, *name);
+ print "</menu> <H2>\n"; # Outdent, larger font
+ } else {
+
+ # Print link to section
+
+ print "<A HREF=\"", $single ? '#' : '',
+ "$sectionfiles[$section]\">$sectiontexts[$section]</A><BR>\n";
+ }
+}
+
+print <<EOP;
+</H2>
+EOP
+
+print "<HR>\n" if $single;
+
+### Make sections
+
+foreach $section (0 .. $#sectionlines) {
+
+ # Skip inlined sections
+
+ next if $inline_me{$sectiontexts[$section]};
+
+ if ($single) {
+
+ # Header
+
+ print <<EOP if $section; # Skip header section
+<H2><A NAME="$sectionfiles[$section]">$sectiontexts[$section]</A></H2>
+<menu>
+EOP
+ &printsectionbody(*man, *sectionlines, *section, *name);
+ print <<EOP if $section; # Skip header section
+<A HREF="#top">Table of Contents</A>
+</menu>
+EOP
+
+ } else {
+
+ # Make pointer line for header and trailer
+
+ $pointers = "<A HREF=\"$topfile\">Up</A>";
+ $pointers .= "\n<A HREF=\"$sectionfiles[$section + 1]\">Next</A>"
+ if ($section < $#sectionlines) &&
+ ! $inline_me{$sectiontexts[$section + 1]};
+ $pointers .= "\n<A HREF=\"$sectionfiles[$section - 1]\">Previous</A>"
+ if ($section > 1) && # section 0 is initial comments
+ ! $inline_me{$sectiontexts[$section - 1]};
+
+ # Header
+
+ open(OUT, ">$dir/$sectionfiles[$section]");
+ select OUT;
+ print <<EOP;
+<HEAD>
+<TITLE>$sectiontexts[$section]</TITLE>
+</HEAD>
+<BODY>
+$pointers
+<H2>$sectiontexts[$section]</H2>
+EOP
+ &printsectionbody(*man, *sectionlines, *section, *name);
+
+ # Trailer
+
+ print <<EOP;
+$pointers
+</BODY>
+EOP
+
+ }
+}
+
+select TOP unless $single;
+
+# Top page trailer
+
+print <<EOP;
+</H2>
+<HR>
+Here are the <A HREF="$outfile">nroff manpage</A> (175K)
+from which this HTML version was generated,
+the <A HREF="$script">Perl script</A> which did the conversion
+and the <A HREF="file://ftp.astron.com/pub/tcsh/">
+complete source code</A> for <I>tcsh</I>.
+<HR>
+<I>tcsh</I> is maintained by
+Christos Zoulas <A HREF="mailto:christos\@gw.com">&lt;christos\@gw.com&gt;</A>
+and the <A HREF="$listsfile"><I>tcsh</I> maintainers' mailing list</A>.
+Dave Schweisguth <A HREF="mailto:dcs\@proton.chem.yale.edu">&lt;dcs\@proton.chem.yale.edu&gt;</A>
+wrote the manpage and the HTML conversion script.
+</BODY>
+EOP
+
+close TOP;
+
+### Make lists page
+
+open(LISTS, ">$dir/$listsfile");
+select LISTS;
+while(($_ = <DATA>) ne "END\n") { # Text stored after __END__
+ s/TOPFILEHERE/$topfile/;
+ print;
+}
+close LISTS;
+
+### Make search script
+
+if ($index) {
+
+ # URL of $dir; see comments in search script
+
+ $root = $cgibin
+ ? "'http://$host/" . ($updir ? "$updir/" : '') . "$dir/'"
+ : '"http://$ENV{\'SERVER_NAME\'}:$ENV{\'SERVER_PORT\'}" . (($_ = $ENV{\'SCRIPT_NAME\'}) =~ s|[^/]*$||, $_)';
+
+ # String for passing @name to search script
+
+ $name = join("',\n'", @name);
+
+ open(TOP, ">$dir/$cgifile");
+ select TOP;
+ while(($_ = <DATA>) ne "END\n") { # Text stored after __END__
+ s/ROOTHERE/$root/;
+ s/NAMEHERE/$name/;
+ s/TOPFILEHERE/$topfile/;
+ print;
+ }
+ close TOP;
+ chmod(0755, "$dir/$cgifile") ||
+ die "$whatami: Can't chmod 0755 $dir/$cgifile!\n";
+ warn "$whatami: Don't forget to move $dir/$cgifile to /$cgibindir.\n"
+ if $cgibin;
+}
+
+### That's all, folks
+
+exit;
+
+### Subroutines
+
+# Process and print the body of a section
+
+sub printsectionbody {
+
+ local(*man, *sectionlines, *sline, *name) = @_; # Number of section
+ local($sfirst, $slast, @paralines, @paratypes, $comment, $dl, $pline,
+ $comment, $pfirst, $plast, @para, @tag, $changeindent);
+
+ # Define section boundaries
+
+ $sfirst = $sectionlines[$sline] + 1;
+ if ($sline == $#sectionlines) {
+ $slast = $#man;
+ } else {
+ $slast = $sectionlines[$sline + 1] - 1;
+ }
+
+ # Find paragraph markers, ignoring those between '.ig' and '..'
+
+ if ($man[$sfirst] =~ /^\.[PIT]P/) {
+ @paralines = ();
+ @paratypes = ();
+ } else {
+ @paralines = ($sfirst - 1); # .P follows .S[HS] by default
+ @paratypes = ('P');
+ }
+ $comment = 0;
+ foreach ($sfirst .. $slast) {
+ if ($man[$_] =~ /^\.ig/) { # Start ignoring
+ $comment = 1;
+ } elsif ($man[$_] =~ /^\.\./) { # Stop ignoring
+ $comment = 0;
+ } elsif (! $comment && $man[$_] =~ /^\.([PIT])P/) {
+ push(@paralines, $_);
+ push(@paratypes, $1);
+ }
+ }
+
+ # Process paragraphs
+
+ $changeindent = 0;
+ $dl = 0;
+ foreach $pline (0 .. $#paralines) {
+
+ @para = ();
+ $comment = 0;
+
+ # Define para boundaries
+
+ $pfirst = $paralines[$pline] + 1;
+ if ($pline == $#paralines) {
+ $plast = $slast;
+ } else {
+ $plast = $paralines[$pline + 1] - 1;
+ }
+
+ foreach (@man[$pfirst .. $plast]) {
+ if (/^\.ig/) { # nroff begin ignore
+ if ($comment == 0) {
+ $comment = 2;
+ push(@para, "<!--\n");
+ } elsif ($comment == 1) {
+ $comment = 2;
+ } elsif ($comment == 2) {
+ s/--/-/g; # Remove double-dashes in comments
+ push(@para, $_);
+ }
+ } elsif (/^\.\./) { # nroff end ignore
+ if ($comment == 0) {
+ ;
+ } elsif ($comment == 1) {
+ ;
+ } elsif ($comment == 2) {
+ $comment = 1;
+ }
+ } elsif (/^\.\\\"/) { # nroff comment
+ if ($comment == 0) {
+ $comment = 1;
+ push(@para, "<!--\n");
+ s/^\.\\\"//;
+ } elsif ($comment == 1) {
+ s/^\.\\\"//;
+ } elsif ($comment == 2) {
+ ;
+ }
+ s/--/-/g; # Remove double-dashes in comments
+ push(@para, $_);
+ } else { # Nothing to do with comments
+ if ($comment == 0) {
+ ;
+ } elsif ($comment == 1) {
+ $comment = 0;
+ push(@para, "-->\n");
+ } elsif ($comment == 2) {
+ s/--/-/g; # Remove double-dashes in comments
+ }
+
+ unless ($comment) {
+
+ if (/^\.TH/) { # Title; got this already
+ next;
+ } elsif (/^\.PD/) { # Para spacing; unimplemented
+ next;
+ } elsif (/^\.RS/) { # Indent (one width only)
+ $changeindent++;
+ next;
+ } elsif (/^\.RE/) { # Outdent
+ $changeindent--;
+ next;
+ }
+
+ # Line break
+
+ s/^\.br.*/<BR>/;
+
+ # More nroff special characters
+
+ s/^\\&amp\;//; # leading dot escape; save until
+ # now so leading dots aren't
+ # confused with ends of .igs
+
+ &make_hrefs(*name, *_);
+ }
+ push(@para, $_);
+ }
+ }
+
+ push(@para, "-->\n") if $comment; # Close open comment
+
+ # Print paragraph
+
+ if ($paratypes[$pline] eq 'P') {
+ &font(*para);
+ print @para;
+ } elsif ($paratypes[$pline] eq 'I') {
+ &font(*para);
+ print "<menu>\n",
+ @para,
+ "</menu>\n";
+ } else { # T
+ @tag = shift(@para);
+ &font(*tag);
+ &font(*para);
+ print "<DL compact>\n" unless $dl;
+ print "<DT>\n",
+ @tag,
+ "<DD>\n",
+ @para;
+ if ($pline == $#paratypes || $paratypes[$pline + 1] ne 'T') {
+ # Perl 5 lossage alert
+ # Next para is not a definition list
+ $dl = 0; # Close open definition list
+ print "</DL>\n";
+ } else {
+ $dl = 1; # Leave definition list open
+ }
+ }
+ print "<P>\n";
+
+ # Indent/outdent the *next* para
+
+ while ($changeindent > 0) {
+ print "<menu>\n";
+ $changeindent--;
+ }
+ while ($changeindent < 0) {
+ print "</menu>\n";
+ $changeindent++;
+ }
+ }
+ 1;
+}
+
+# Make one name anchor in a line; cue on fonts (.B or .I) but leave them alone
+
+sub make_name {
+
+ local(*name, *font, *file, *index, *line) = @_;
+ local($text);
+
+ if (($text) = ($line =~ /^\.[BI]\s+([^\s\\]+)/)) { # Found pattern
+
+ if (
+ $text !~ /^-/ # Avoid lists of options
+ && (length($text) > 1 # and history escapes
+ || $text =~ /^[%:@]$/) # Special pleading for %, :, @
+ && ! $name{"$text $font"} # Skip if there's one already
+ ) {
+ # Record link
+
+ $name{"$text $font"} = ($single ? '' : $file) . "#$text";
+ push(@name, "$text\t" . $name{"$text $font"}) if $index;
+
+ # Put in the name anchor
+
+ $line =~ s/^(\.[BI]\s+)([^\s\\]+)/$1<A NAME=\"$text\">$2<\/A>/;
+ }
+ }
+ $line;
+}
+
+# Make all the href anchors in a line; cue on fonts (\fB ... \fR or
+# \fI ... \fR) but leave them alone
+
+sub make_hrefs {
+
+ local(*name, *line) = @_;
+ local(@pieces, $piece);
+
+ @pieces = split(/(\\f[BI][^\\]*\\fR)/, $line);
+
+ $piece = 0;
+ foreach (@pieces) {
+ if (/\\f([BI])([^\\]*)\\fR/ # Found a possibility
+
+ # It's not followed by (, i.e. it's not a manpage reference
+
+ && substr($pieces[$piece + 1], 0, 1) ne '(') {
+ $key = "$2 $1";
+ if ($name{$key}) { # If there's a matching name
+ s/(\\f[BI])([^\\]*)(\\fR)/$1<A HREF=\"$name{$key}\">$2<\/A>$3/;
+ }
+ }
+ $piece++;
+ }
+ $line = join('', @pieces);
+}
+
+# Convert nroff font escapes to HTML
+# Expects comments and breaks to be in HTML form already
+
+sub font {
+
+ local(*para) = @_;
+ local($i, $j, @begin, @end, $part, @pieces, $bold, $italic);
+
+ return 0 if $#para == -1; # Ignore empty paragraphs
+ # Perl 5 lossage alert
+
+ # Find beginning and end of each part between HTML comments
+
+ $i = 0;
+ @begin = ();
+ @end = ();
+ foreach (@para) {
+ push(@begin, $i + 1) if /^-->/ || /^<BR>/;
+ push(@end, $i - 1) if /^<!--/ || /^<BR>/;
+ $i++;
+ }
+ if ($para[0] =~ /^<!--/ || $para[0] =~ /^<BR>/) {
+ shift(@end);
+ } else {
+ unshift(@begin, 0); # Begin at the beginning
+ }
+ if ($para[$#para] =~ /^-->/ || $para[$#para] =~ /^<BR>/) {
+ pop(@begin);
+ } else {
+ push(@end, $#para); # End at the end
+ }
+
+ # Fontify each part
+
+ $bold = $italic = 0;
+ foreach $i (0 .. $#begin) {
+ $* = 1;
+ $part = join('', @para[$begin[$i] .. $end[$i]]);
+ $part =~ s/^\.([BI])\s+(.*)$/\\f$1$2\\fR/g; # .B, .I
+ @pieces = split(/(\\f[BIR])/, $part);
+ $part = '';
+ foreach $j (@pieces) {
+ if ($j eq '\fB') {
+ if ($italic) {
+ $italic = 0;
+ $part .= '</I>';
+ }
+ unless ($bold) {
+ $bold = 1;
+ $part .= '<B>';
+ }
+ } elsif ($j eq '\fI') {
+ if ($bold) {
+ $bold = 0;
+ $part .= '</B>';
+ }
+ unless ($italic) {
+ $italic = 1;
+ $part .= '<I>';
+ }
+ } elsif ($j eq '\fR') {
+ if ($bold) {
+ $bold = 0;
+ $part .= '</B>';
+ } elsif ($italic) {
+ $italic = 0;
+ $part .= '</I>';
+ }
+ } else {
+ $part .= $j;
+ }
+ }
+ $* = 0;
+
+ # Close bold/italic before break
+
+ if ($end[$i] == $#para || $para[$end[$i] + 1] =~ /^<BR>/) {
+ # Perl 5 lossage alert
+ if ($bold) {
+ $bold = 0;
+ $part =~ s/(\n)?$/<\/B>$1\n/;
+ } elsif ($italic) {
+ $italic = 0;
+ $part =~ s/(\n)?$/<\/I>$1\n/;
+ }
+ }
+
+ # Rebuild this section of @para
+
+ foreach $j ($begin[$i] .. $end[$i]) {
+ $part =~ s/^([^\n]*(\n|$))//;
+ $para[$j] = $1;
+ }
+ }
+
+ # Close bold/italic on last non-comment line
+ # Do this only here because fonts pass through comments
+
+ $para[$end[$#end]] =~ s/(\n)?$/<\/B>$1/ if $bold;
+ $para[$end[$#end]] =~ s/(\n)?$/<\/I>$1/ if $italic;
+}
+
+sub usage {
+ local ($message) = $_[0];
+
+ warn $message if $message;
+ warn <<EOP;
+Usage: $whatami [-1icsu] [-C dir] [-d dir] [-h host] [file]
+Without [file], reads from tcsh.man or stdin.
+-1 Makes a single page instead of a table of contents and sections
+-i Makes a CGI searchable index script, tcsh.html/tcsh.cgi, intended
+ for a server which respects the .cgi extension in any directory.
+-c Like -i, but the CGI script is intended for a server which wants
+ scripts in /cgi-bin (or some other privileged directory separate
+ from the rest of the HTML) and must be moved there by hand.
+-C dir Uses /dir instead of /cgi-bin as the CGI bin dir.
+ Meaningless without -c.
+-d dir Uses /dir/tcsh.html instead of /tcsh.html as the HTML dir.
+ Meaningless without -c.
+-D dir Uses /dir.html instead of /tcsh.html as the HTML dir.
+ Meaningless without -c.
+-G name Uses name instead of tcsh.cgi as the name of the CGI script.
+ Meaningless without -c or -i.
+-h host Uses host as the host:port part of the URL to the entry point.
+ Meaningless without -c.
+-s Filenames are shorter (max 8 + 3) but less descriptive.
+-u This message
+EOP
+ exit !! $message;
+}
+
+### Inlined documents. Watch for *HERE tokens.
+
+__END__
+<HEAD>
+<TITLE>The tcsh mailing lists</TITLE>
+</HEAD>
+<BODY>
+<A HREF="TOPFILEHERE">Up</A>
+<H2>The <I>tcsh</I> mailing lists</H2>
+There are three <I>tcsh</I> mailing lists:
+<DL>
+<DT>
+<I>tcsh@mx.gw.com</I>
+<DD>
+The <I>tcsh</I> maintainers and testers' mailing list.
+<DT>
+<I>tcsh-diffs@mx.gw.com</I>
+<DD>
+The same as <I>tcsh@mx.gw.com</I>, plus diffs for each new
+patchlevel of <I>tcsh</I>.
+<DT>
+<I>tcsh-bugs@mx.gw.com</I>
+<DD>
+Bug reports.
+</DL>
+You can subscribe to any of these lists by sending mail to
+<I><A HREF="mailto:listserv@mx.gw.com">listserv@mx.gw.com</A></I> with the
+text "subscribe &lt;list name&gt; &lt;your name&gt;" on a line by
+itself in the body. &lt;list name&gt; is the name of the mailing list,
+without "@mx.gw.com", and &lt;your name&gt; is your real name, not your
+email address. You can also ask the list server for help by sending
+only the word "help".
+<P>
+<A HREF="TOPFILEHERE">Up</A>
+</BODY>
+END
+#!/usr/local/bin/perl
+
+# Emulate #!/usr/local/bin/perl on systems without #!
+
+eval '(exit $?0)' && eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
+& eval 'exec /usr/local/bin/perl -S $0 $argv:q' if 0;
+
+# Setup
+
+# Location: doesn't work with relative URLs, so we need to know where to find
+# the top and section files.
+# If the search engine is in /cgi-bin, we need a hard-coded URL.
+# If the search engine is in the same directory, we can figure it out from CGI
+# environment variables.
+
+$root = ROOTHERE;
+$topfile = 'TOPFILEHERE';
+@name = (
+'NAMEHERE'
+);
+
+# Do the search
+
+$input = $ENV{'QUERY_STRING'};
+$input =~ s/^input=//;
+$input =~ s/\+/ /g;
+print "Status: 302 Found\n";
+if ($input ne '' && ($key = (grep(/^$input/, @name))[0] ||
+ (grep(/^$input/i, @name))[0] ||
+ (grep( /$input/i, @name))[0] )) {
+ $key =~ /\t([^\t]*)$/;
+ print "Location: $root$1\n\n";
+} else {
+ print "Location: $root$topfile\n\n";
+}
+END
diff --git a/contrib/tcsh/termcap.vms b/contrib/tcsh/termcap.vms
new file mode 100644
index 0000000..a56bc15
--- /dev/null
+++ b/contrib/tcsh/termcap.vms
@@ -0,0 +1,51 @@
+# $Id: termcap.vms,v 1.2 1992/10/27 16:18:15 christos Exp $
+# posix /etc/termcap 1992
+#
+# Minimal termcap for VMS/POSIX
+#
+# 7bit vt300 series
+p3|vt300_series|vt300_series|dec vt320:\
+ :hs:\
+ :es:\
+ :ts=\E[1$}\E[;H\E[K:\
+ :fs=\E[0$}:\
+ :ds=\E[1$}\E[D;H\E[K\E[0$}:\
+ :ae=4\E(B:\
+ :al=\E[L:\
+ :as=2\E(<:\
+ :dc=\E[P;\E[:dl=\E[M:\
+ :ei=\E[4l:im=\E[4h:mi:nd=\E[C:se=\E[m:so=\E[7m:sr=\EM:\
+ :ue=\E[m:up=\E[A:us=\E[4m:\
+ :cr=^M:do=^J:nl=^J:bl=^G:co#80:li#24:cl=50\E[;H\E[2J:\
+ :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
+ :ce=\E[K:cd=50\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
+ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:\
+ :is=\E[1;24r\E[24;1H:\
+ :ct=2\E[3g:st=2\EH:\
+ :rf=/usr/lib/tabset/vt100:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:xn:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+#vt200_series
+p2|vt200_series|vt200_series|dec vt220:\
+ :ae=4\E(B:\
+ :al=\E[L:\
+ :as=2\E(<:\
+ :dc=\E[P:dl=\E[M:\
+ :ei=\E[4l:im=\E[4h:mi:nd=\E[C:se=\E[m:so=\E[7m:sr=\EM:\
+ :ue=\E[m:up=\E[A:us=\E[4m:\
+ :cr=^M:do=^J:nl=^J:bl=^G:co#80:li#24:cl=50\E[;H\E[2J:\
+ :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
+ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
+ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:\
+ :is=\E[1;24r\E[24;1H:\
+ :ct=2\E[3g:st=2\EH:\
+ :rf=/usr/lib/tabset/vt100:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:xn:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+# ------------------------
diff --git a/contrib/tcsh/tw.color.c b/contrib/tcsh/tw.color.c
new file mode 100644
index 0000000..a252a8d
--- /dev/null
+++ b/contrib/tcsh/tw.color.c
@@ -0,0 +1,346 @@
+/* $Header: /src/pub/tcsh/tw.color.c,v 1.5 1998/10/25 15:10:48 christos Exp $ */
+/*
+ * tw.color.c: builtin color ls-F
+ */
+/*-
+ * Copyright (c) 1998 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.color.c,v 1.5 1998/10/25 15:10:48 christos Exp $")
+
+#include "tw.h"
+#include "ed.h"
+#include "tc.h"
+
+#ifdef COLOR_LS_F
+
+typedef struct {
+ char *s;
+ int len;
+} Str;
+
+
+#define VAR(suffix,variable,defaultcolor) \
+{ \
+ suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \
+ { defaultcolor, sizeof(defaultcolor) - 1 } \
+}
+#define NOS '\0' /* no suffix */
+
+typedef struct {
+ const char suffix;
+ const char *variable;
+ Str color;
+ Str defaultcolor;
+} Variable;
+
+static Variable variables[] = {
+ VAR('/', "di", "01;34"), /* Directory */
+ VAR('@', "ln", "01;36"), /* Symbolic link */
+ VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */
+ VAR('|', "pi", "33"), /* Named pipe (FIFO) */
+ VAR('=', "so", "01;35"), /* Socket */
+ VAR('#', "bd", "01;33"), /* Block device */
+ VAR('%', "cd", "01;33"), /* Character device */
+ VAR('*', "ex", "01;32"), /* Executable file */
+ VAR(NOS, "fi", "0"), /* Regular file */
+ VAR(NOS, "no", "0"), /* Normal (non-filename) text */
+ VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */
+#ifdef _OSD_POSIX
+ VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/
+#else /* _OSD_POSIX */
+ VAR(NOS, "lc", "\033["), /* Left code */
+#endif /* _OSD_POSIX */
+ VAR(NOS, "rc", "m"), /* Right code */
+ VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */
+};
+
+enum FileType {
+ VDir, VSym, VOrph, VPipe, VSock, VBlock, VChr, VExe,
+ VFile, VNormal, VMiss, VLeft, VRight, VEnd
+};
+
+#define nvariables (sizeof(variables)/sizeof(variables[0]))
+
+typedef struct {
+ Str extension; /* file extension */
+ Str color; /* color string */
+} Extension;
+
+static Extension *extensions = NULL;
+static int nextensions = 0;
+
+static char *colors = NULL;
+bool color_context_ls = FALSE; /* do colored ls */
+static bool color_context_lsmF = FALSE; /* do colored ls-F */
+
+static bool getstring __P((char **, const Char **, Str *, int));
+static void put_color __P((Str *));
+static void print_color __P((Char *, size_t, int));
+
+/* set_color_context():
+ */
+void
+set_color_context()
+{
+ struct varent *vp = adrof(STRcolor);
+
+ if (!vp) {
+ color_context_ls = FALSE;
+ color_context_lsmF = FALSE;
+ }
+ else if (!vp->vec[0] || vp->vec[0][0] == '\0') {
+ color_context_ls = TRUE;
+ color_context_lsmF = TRUE;
+ }
+ else {
+ size_t i;
+
+ color_context_ls = FALSE;
+ color_context_lsmF = FALSE;
+ for (i = 0; vp->vec[i]; i++)
+ if (Strcmp(vp->vec[i], STRls) == 0)
+ color_context_ls = TRUE;
+ else if (Strcmp(vp->vec[i], STRlsmF) == 0)
+ color_context_lsmF = TRUE;
+ }
+}
+
+
+/* getstring():
+ */
+static bool
+getstring(dp, sp, pd, f)
+ char **dp; /* dest buffer */
+ const Char **sp; /* source buffer */
+ Str *pd; /* pointer to dest buffer */
+ int f; /* final character */
+{
+ const Char *s = *sp;
+ char *d = *dp;
+ int sc;
+
+ while (*s && (*s & CHAR) != f && (*s & CHAR) != ':') {
+ if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') {
+ if ((sc = parseescape(&s)) == -1)
+ return 0;
+ else
+ *d++ = (char) sc;
+ }
+ else
+ *d++ = *s++ & CHAR;
+ }
+
+ pd->s = *dp;
+ pd->len = (int) (d - *dp);
+ *sp = s;
+ *dp = d;
+ return *s == f;
+}
+
+
+/* parseLS_COLORS():
+ * Parse the LS_COLORS environment variable
+ */
+void
+parseLS_COLORS(value)
+ Char *value; /* LS_COLOR variable's value */
+{
+ int i;
+ size_t len;
+ const Char *v; /* pointer in value */
+ char *c; /* pointer in colors */
+ Extension *e; /* pointer in extensions */
+
+ /* init */
+ if (extensions)
+ xfree((ptr_t) extensions);
+ for (i = 0; i < nvariables; i++)
+ variables[i].color = variables[i].defaultcolor;
+ colors = NULL;
+ extensions = NULL;
+ nextensions = 0;
+
+ if (value == NULL)
+ return;
+
+ len = Strlen(value);
+ /* allocate memory */
+ i = 1;
+ for (v = value; *v; v++)
+ if ((*v & CHAR) == ':')
+ i++;
+ extensions = (Extension *) xmalloc((size_t) (len + i * sizeof(Extension)));
+ colors = i * sizeof(Extension) + (char *)extensions;
+ nextensions = 0;
+
+ /* init pointers */
+ v = value;
+ c = colors;
+ e = &extensions[0];
+
+ /* parse */
+ while (*v) {
+ switch (*v & CHAR) {
+ case ':':
+ v++;
+ continue;
+
+ case '*': /* :*ext=color: */
+ v++;
+ if (getstring(&c, &v, &e->extension, '=') &&
+ 0 < e->extension.len) {
+ v++;
+ getstring(&c, &v, &e->color, ':');
+ e++;
+ continue;
+ }
+ break;
+
+ default: /* :vl=color: */
+ if (v[0] && v[1] && (v[2] & CHAR) == '=') {
+ for (i = 0; i < nvariables; i++)
+ if (variables[i].variable[0] == (v[0] & CHAR) &&
+ variables[i].variable[1] == (v[1] & CHAR))
+ break;
+ if (i < nvariables) {
+ v += 3;
+ getstring(&c, &v, &variables[i].color, ':');
+ continue;
+ }
+ else
+ stderror(ERR_BADCOLORVAR, v[0], v[1]);
+ }
+ break;
+ }
+ while (*v && (*v & CHAR) != ':')
+ v++;
+ }
+
+ nextensions = (int) (e - extensions);
+}
+
+
+/* put_color():
+ */
+static void
+put_color(color)
+ Str *color;
+{
+ extern bool output_raw; /* PWP: in sh.print.c */
+ size_t i;
+ char *c = color->s;
+ bool original_output_raw = output_raw;
+
+ output_raw = TRUE;
+ for (i = color->len; 0 < i; i--)
+ xputchar(*c++);
+ output_raw = original_output_raw;
+}
+
+
+/* print_color():
+ */
+static void
+print_color(fname, len, suffix)
+ Char *fname;
+ size_t len;
+ int suffix;
+{
+ int i;
+ char *filename = short2str(fname);
+ char *last = filename + len;
+ Str *color = &variables[VFile].color;
+
+ switch (suffix) {
+ case '>': /* File is a symbolic link pointing to
+ * a directory */
+ color = &variables[VDir].color;
+ break;
+ case '+': /* File is a hidden directory [aix] or
+ * context dependent [hpux] */
+ case ':': /* File is network special [hpux] */
+ break;
+ default:
+ for (i = 0; i < nvariables; i++)
+ if (variables[i].suffix != NOS &&
+ variables[i].suffix == suffix) {
+ color = &variables[i].color;
+ break;
+ }
+ if (i == nvariables) {
+ for (i = 0; i < nextensions; i++)
+ if (strncmp(last - extensions[i].extension.len,
+ extensions[i].extension.s,
+ extensions[i].extension.len) == 0) {
+ color = &extensions[i].color;
+ break;
+ }
+ }
+ break;
+ }
+
+ put_color(&variables[VLeft].color);
+ put_color(color);
+ put_color(&variables[VRight].color);
+}
+
+
+/* print_with_color():
+ */
+void
+print_with_color(filename, len, suffix)
+ Char *filename;
+ size_t len;
+ int suffix;
+{
+ if (color_context_lsmF &&
+ (haderr ? (didfds ? is2atty : isdiagatty) :
+ (didfds ? is1atty : isoutatty))) {
+ print_color(filename, len, suffix);
+ xprintf("%S", filename);
+ if (0 < variables[VEnd].color.len)
+ put_color(&variables[VEnd].color);
+ else {
+ put_color(&variables[VLeft].color);
+ put_color(&variables[VNormal].color);
+ put_color(&variables[VRight].color);
+ }
+ xputchar(suffix);
+ }
+ else
+ xprintf("%S%c", filename, suffix);
+}
+
+
+#endif /* COLOR_LS_F */
diff --git a/contrib/tcsh/tw.comp.c b/contrib/tcsh/tw.comp.c
new file mode 100644
index 0000000..6d5652a
--- /dev/null
+++ b/contrib/tcsh/tw.comp.c
@@ -0,0 +1,626 @@
+/* $Header: /src/pub/tcsh/tw.comp.c,v 1.31 1998/10/25 15:10:49 christos Exp $ */
+/*
+ * tw.comp.c: File completion builtin
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.comp.c,v 1.31 1998/10/25 15:10:49 christos Exp $")
+
+#include "tw.h"
+#include "ed.h"
+#include "tc.h"
+
+/* #define TDEBUG */
+struct varent completions;
+
+static int tw_result __P((Char *, Char **));
+static Char **tw_find __P((Char *, struct varent *, int));
+static Char *tw_tok __P((Char *));
+static bool tw_pos __P((Char *, int));
+static void tw_pr __P((Char **));
+static int tw_match __P((Char *, Char *));
+static void tw_prlist __P((struct varent *));
+static Char *tw_dollar __P((Char *,Char **, int, Char *,
+ int, const char *));
+
+/* docomplete():
+ * Add or list completions in the completion list
+ */
+/*ARGSUSED*/
+void
+docomplete(v, t)
+ Char **v;
+ struct command *t;
+{
+ register struct varent *vp;
+ register Char *p;
+
+ USE(t);
+ v++;
+ p = *v++;
+ if (p == 0)
+ tw_prlist(&completions);
+ else if (*v == 0) {
+ vp = adrof1(strip(p), &completions);
+ if (vp)
+ tw_pr(vp->vec), xputchar('\n');
+ }
+ else
+ set1(strip(p), saveblk(v), &completions, VAR_READWRITE);
+} /* end docomplete */
+
+
+/* douncomplete():
+ * Remove completions from the completion list
+ */
+/*ARGSUSED*/
+void
+douncomplete(v, t)
+ Char **v;
+ struct command *t;
+{
+ USE(t);
+ unset1(v, &completions);
+} /* end douncomplete */
+
+
+/* tw_prlist():
+ * Pretty print a list of variables
+ */
+static void
+tw_prlist(p)
+ struct varent *p;
+{
+ register struct varent *c;
+
+ if (setintr)
+#ifdef BSDSIGS
+ (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
+#else /* BSDSIGS */
+ (void) sigrelse(SIGINT);
+#endif /* BSDSIGS */
+
+ for (;;) {
+ while (p->v_left)
+ p = p->v_left;
+x:
+ if (p->v_parent == 0) /* is it the header? */
+ return;
+ xprintf("%s\t", short2str(p->v_name));
+ tw_pr(p->vec);
+ xputchar('\n');
+ if (p->v_right) {
+ p = p->v_right;
+ continue;
+ }
+ do {
+ c = p;
+ p = p->v_parent;
+ } while (p->v_right == c);
+ goto x;
+ }
+} /* end tw_prlist */
+
+
+/* tw_pr():
+ * Pretty print a completion, adding single quotes around
+ * a completion argument and collapsing multiple spaces to one.
+ */
+static void
+tw_pr(cmp)
+ Char **cmp;
+{
+ bool sp, osp;
+ Char *ptr;
+
+ for (; *cmp; cmp++) {
+ xputchar('\'');
+ for (osp = 0, ptr = *cmp; *ptr; ptr++) {
+ sp = Isspace(*ptr);
+ if (sp && osp)
+ continue;
+ xputchar(*ptr);
+ osp = sp;
+ }
+ xputchar('\'');
+ if (cmp[1])
+ xputchar(' ');
+ }
+} /* end tw_pr */
+
+
+/* tw_find():
+ * Find the first matching completion.
+ * For commands we only look at names that start with -
+ */
+static Char **
+tw_find(nam, vp, cmd)
+ Char *nam;
+ register struct varent *vp;
+ int cmd;
+{
+ register Char **rv;
+
+ for (vp = vp->v_left; vp; vp = vp->v_right) {
+ if (vp->v_left && (rv = tw_find(nam, vp, cmd)) != NULL)
+ return rv;
+ if (cmd) {
+ if (vp->v_name[0] != '-')
+ continue;
+ if (Gmatch(nam, &vp->v_name[1]) && vp->vec != NULL)
+ return vp->vec;
+ }
+ else
+ if (Gmatch(nam, vp->v_name) && vp->vec != NULL)
+ return vp->vec;
+ }
+ return NULL;
+} /* end tw_find */
+
+
+/* tw_pos():
+ * Return true if the position is within the specified range
+ */
+static bool
+tw_pos(ran, wno)
+ Char *ran;
+ int wno;
+{
+ Char *p;
+
+ if (ran[0] == '*' && ran[1] == '\0')
+ return 1;
+
+ for (p = ran; *p && *p != '-'; p++)
+ continue;
+
+ if (*p == '\0') /* range == <number> */
+ return wno == getn(ran);
+
+ if (ran == p) /* range = - <number> */
+ return wno <= getn(&ran[1]);
+ *p++ = '\0';
+
+ if (*p == '\0') /* range = <number> - */
+ return getn(ran) <= wno;
+ else /* range = <number> - <number> */
+ return (getn(ran) <= wno) && (wno <= getn(p));
+
+} /* end tw_pos */
+
+
+/* tw_tok():
+ * Return the next word from string, unquoteing it.
+ */
+static Char *
+tw_tok(str)
+ Char *str;
+{
+ static Char *bf = NULL;
+
+ if (str != NULL)
+ bf = str;
+
+ /* skip leading spaces */
+ for (; *bf && Isspace(*bf); bf++)
+ continue;
+
+ for (str = bf; *bf && !Isspace(*bf); bf++) {
+ if (ismeta(*bf))
+ return INVPTR;
+ *bf = *bf & ~QUOTE;
+ }
+ if (*bf != '\0')
+ *bf++ = '\0';
+
+ return *str ? str : NULL;
+} /* end tw_tok */
+
+
+/* tw_match():
+ * Match a string against the pattern given.
+ * and return the number of matched characters
+ * in a prefix of the string.
+ */
+static int
+tw_match(str, pat)
+ Char *str, *pat;
+{
+ Char *estr;
+ int rv = Gnmatch(str, pat, &estr);
+#ifdef TDEBUG
+ xprintf("Gnmatch(%s, ", short2str(str));
+ xprintf("%s, ", short2str(pat));
+ xprintf("%s) = %d [%d]\n", short2str(estr), rv, estr - str);
+#endif /* TDEBUG */
+ return (int) (rv ? estr - str : -1);
+}
+
+
+/* tw_result():
+ * Return what the completion action should be depending on the
+ * string
+ */
+static int
+tw_result(act, pat)
+ Char *act, **pat;
+{
+ int looking;
+ static Char* res = NULL;
+
+ if (res != NULL)
+ xfree((ptr_t) res), res = NULL;
+
+ switch (act[0] & ~QUOTE) {
+ case 'X':
+ looking = TW_COMPLETION;
+ break;
+ case 'S':
+ looking = TW_SIGNAL;
+ break;
+ case 'a':
+ looking = TW_ALIAS;
+ break;
+ case 'b':
+ looking = TW_BINDING;
+ break;
+ case 'c':
+ looking = TW_COMMAND;
+ break;
+ case 'C':
+ looking = TW_PATH | TW_COMMAND;
+ break;
+ case 'd':
+ looking = TW_DIRECTORY;
+ break;
+ case 'D':
+ looking = TW_PATH | TW_DIRECTORY;
+ break;
+ case 'e':
+ looking = TW_ENVVAR;
+ break;
+ case 'f':
+ looking = TW_FILE;
+ break;
+#ifdef COMPAT
+ case 'p':
+#endif /* COMPAT */
+ case 'F':
+ looking = TW_PATH | TW_FILE;
+ break;
+ case 'g':
+ looking = TW_GRPNAME;
+ break;
+ case 'j':
+ looking = TW_JOB;
+ break;
+ case 'l':
+ looking = TW_LIMIT;
+ break;
+ case 'n':
+ looking = TW_NONE;
+ break;
+ case 's':
+ looking = TW_SHELLVAR;
+ break;
+ case 't':
+ looking = TW_TEXT;
+ break;
+ case 'T':
+ looking = TW_PATH | TW_TEXT;
+ break;
+ case 'v':
+ looking = TW_VARIABLE;
+ break;
+ case 'u':
+ looking = TW_USER;
+ break;
+ case 'x':
+ looking = TW_EXPLAIN;
+ break;
+
+ case '$':
+ *pat = res = Strsave(&act[1]);
+ (void) strip(res);
+ return(TW_VARLIST);
+
+ case '(':
+ *pat = res = Strsave(&act[1]);
+ if ((act = Strchr(res, ')')) != NULL)
+ *act = '\0';
+ (void) strip(res);
+ return TW_WORDLIST;
+
+ case '`':
+ res = Strsave(act);
+ if ((act = Strchr(&res[1], '`')) != NULL)
+ *++act = '\0';
+
+ if (didfds == 0) {
+ /*
+ * Make sure that we have some file descriptors to
+ * play with, so that the processes have at least 0, 1, 2
+ * open
+ */
+ (void) dcopy(SHIN, 0);
+ (void) dcopy(SHOUT, 1);
+ (void) dcopy(SHDIAG, 2);
+ }
+ if ((act = globone(res, G_APPEND)) != NULL) {
+ xfree((ptr_t) res), res = NULL;
+ *pat = res = Strsave(act);
+ xfree((ptr_t) act);
+ return TW_WORDLIST;
+ }
+ return TW_ZERO;
+
+ default:
+ stderror(ERR_COMPCOM, short2str(act));
+ return TW_ZERO;
+ }
+
+ switch (act[1] & ~QUOTE) {
+ case '\0':
+ return looking;
+
+ case ':':
+ *pat = res = Strsave(&act[2]);
+ (void) strip(res);
+ return looking;
+
+ default:
+ stderror(ERR_COMPCOM, short2str(act));
+ return TW_ZERO;
+ }
+} /* end tw_result */
+
+
+/* tw_dollar():
+ * Expand $<n> args in buffer
+ */
+static Char *
+tw_dollar(str, wl, nwl, buffer, sep, msg)
+ Char *str, **wl;
+ int nwl;
+ Char *buffer;
+ int sep;
+ const char *msg;
+{
+ Char *sp, *bp = buffer, *ebp = &buffer[MAXPATHLEN];
+
+ for (sp = str; *sp && *sp != sep && bp < ebp;)
+ if (sp[0] == '$' && sp[1] == ':' && Isdigit(sp[sp[2] == '-' ? 3 : 2])) {
+ int num, neg = 0;
+ sp += 2;
+ if (*sp == '-') {
+ neg = 1;
+ sp++;
+ }
+ for (num = *sp++ - '0'; Isdigit(*sp); num += 10 * num + *sp++ - '0')
+ continue;
+ if (neg)
+ num = nwl - num - 1;
+ if (num >= 0 && num < nwl) {
+ Char *ptr;
+ for (ptr = wl[num]; *ptr && bp < ebp - 1; *bp++ = *ptr++)
+ continue;
+
+ }
+ }
+ else
+ *bp++ = *sp++;
+
+ *bp = '\0';
+
+ if (*sp++ == sep)
+ return sp;
+
+ stderror(ERR_COMPMIS, sep, msg, short2str(str));
+ return --sp;
+} /* end tw_dollar */
+
+
+/* tw_complete():
+ * Return the appropriate completion for the command
+ *
+ * valid completion strings are:
+ * p/<range>/<completion>/[<suffix>/] positional
+ * c/<pattern>/<completion>/[<suffix>/] current word ignore pattern
+ * C/<pattern>/<completion>/[<suffix>/] current word with pattern
+ * n/<pattern>/<completion>/[<suffix>/] next word
+ * N/<pattern>/<completion>/[<suffix>/] next-next word
+ */
+int
+tw_complete(line, word, pat, looking, suf)
+ Char *line, **word, **pat;
+ int looking, *suf;
+{
+ Char buf[MAXPATHLEN + 1], **vec, *ptr;
+ Char *wl[MAXPATHLEN/6];
+ static Char nomatch[2] = { (Char) ~0, 0x00 };
+ int wordno, n;
+
+ copyn(buf, line, MAXPATHLEN);
+
+ /* find the command */
+ if ((wl[0] = tw_tok(buf)) == NULL || wl[0] == INVPTR)
+ return TW_ZERO;
+
+ /*
+ * look for hardwired command completions using a globbing
+ * search and for arguments using a normal search.
+ */
+ if ((vec = tw_find(wl[0], &completions, (looking == TW_COMMAND))) == NULL)
+ return looking;
+
+ /* tokenize the line one more time :-( */
+ for (wordno = 1; (wl[wordno] = tw_tok(NULL)) != NULL &&
+ wl[wordno] != INVPTR; wordno++)
+ continue;
+
+ if (wl[wordno] == INVPTR) /* Found a meta character */
+ return TW_ZERO; /* de-activate completions */
+#ifdef TDEBUG
+ {
+ int i;
+ for (i = 0; i < wordno; i++)
+ xprintf("'%s' ", short2str(wl[i]));
+ xprintf("\n");
+ }
+#endif /* TDEBUG */
+
+ /* if the current word is empty move the last word to the next */
+ if (**word == '\0') {
+ wl[wordno] = *word;
+ wordno++;
+ }
+ wl[wordno] = NULL;
+
+
+#ifdef TDEBUG
+ xprintf("\r\n");
+ xprintf(" w#: %d\n", wordno);
+ xprintf("line: %s\n", short2str(line));
+ xprintf(" cmd: %s\n", short2str(wl[0]));
+ xprintf("word: %s\n", short2str(*word));
+ xprintf("last: %s\n", wordno - 2 >= 0 ? short2str(wl[wordno-2]) : "n/a");
+ xprintf("this: %s\n", wordno - 1 >= 0 ? short2str(wl[wordno-1]) : "n/a");
+#endif /* TDEBUG */
+
+ for (;vec != NULL && (ptr = vec[0]) != NULL; vec++) {
+ Char ran[MAXPATHLEN+1],/* The pattern or range X/<range>/XXXX/ */
+ com[MAXPATHLEN+1],/* The completion X/XXXXX/<completion>/ */
+ *pos = NULL; /* scratch pointer */
+ int cmd, sep; /* the command and separator characters */
+
+ if (ptr[0] == '\0')
+ continue;
+
+#ifdef TDEBUG
+ xprintf("match %s\n", short2str(ptr));
+#endif /* TDEBUG */
+
+ switch (cmd = ptr[0]) {
+ case 'N':
+ pos = (wordno - 3 < 0) ? nomatch : wl[wordno - 3];
+ break;
+ case 'n':
+ pos = (wordno - 2 < 0) ? nomatch : wl[wordno - 2];
+ break;
+ case 'c':
+ case 'C':
+ pos = (wordno - 1 < 0) ? nomatch : wl[wordno - 1];
+ break;
+ case 'p':
+ break;
+ default:
+ stderror(ERR_COMPINV, CGETS(27, 1, "command"), cmd);
+ return TW_ZERO;
+ }
+
+ sep = ptr[1];
+ if (!Ispunct(sep)) {
+ stderror(ERR_COMPINV, CGETS(27, 2, "separator"), sep);
+ return TW_ZERO;
+ }
+
+ ptr = tw_dollar(&ptr[2], wl, wordno, ran, sep,
+ CGETS(27, 3, "pattern"));
+ if (ran[0] == '\0') /* check for empty pattern (disallowed) */
+ {
+ stderror(ERR_COMPINC, cmd == 'p' ? CGETS(27, 4, "range") :
+ CGETS(27, 3, "pattern"), "");
+ return TW_ZERO;
+ }
+
+ ptr = tw_dollar(ptr, wl, wordno, com, sep, CGETS(27, 5, "completion"));
+
+ if (*ptr != '\0') {
+ if (*ptr == sep)
+ *suf = ~0;
+ else
+ *suf = *ptr;
+ }
+ else
+ *suf = '\0';
+
+#ifdef TDEBUG
+ xprintf("command: %c\nseparator: %c\n", cmd, sep);
+ xprintf("pattern: %s\n", short2str(ran));
+ xprintf("completion: %s\n", short2str(com));
+ xprintf("suffix: ");
+ switch (*suf) {
+ case 0:
+ xprintf("*auto suffix*\n");
+ break;
+ case ~0:
+ xprintf("*no suffix*\n");
+ break;
+ default:
+ xprintf("%c\n", *suf);
+ break;
+ }
+#endif /* TDEBUG */
+
+ switch (cmd) {
+ case 'p': /* positional completion */
+#ifdef TDEBUG
+ xprintf("p: tw_pos(%s, %d) = ", short2str(ran), wordno - 1);
+ xprintf("%d\n", tw_pos(ran, wordno - 1));
+#endif /* TDEBUG */
+ if (!tw_pos(ran, wordno - 1))
+ continue;
+ return tw_result(com, pat);
+
+ case 'N': /* match with the next-next word */
+ case 'n': /* match with the next word */
+ case 'c': /* match with the current word */
+ case 'C':
+#ifdef TDEBUG
+ xprintf("%c: ", cmd);
+#endif /* TDEBUG */
+ if ((n = tw_match(pos, ran)) < 0)
+ continue;
+ if (cmd == 'c')
+ *word += n;
+ return tw_result(com, pat);
+
+ default:
+ return TW_ZERO; /* Cannot happen */
+ }
+ }
+ *suf = '\0';
+ return TW_ZERO;
+} /* end tw_complete */
diff --git a/contrib/tcsh/tw.decls.h b/contrib/tcsh/tw.decls.h
new file mode 100644
index 0000000..38f47fa
--- /dev/null
+++ b/contrib/tcsh/tw.decls.h
@@ -0,0 +1,126 @@
+/* $Header: /src/pub/tcsh/tw.decls.h,v 3.16 1998/06/27 12:27:44 christos Exp $ */
+/*
+ * tw.decls.h: Tenex external declarations
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tw_decls
+#define _h_tw_decls
+
+/*
+ * tw.help.c
+ */
+extern void do_help __P((Char *));
+
+/*
+ * tw.parse.c
+ */
+extern Char *dollar __P((Char *, const Char *));
+extern int tenematch __P((Char *, int, COMMAND));
+extern int t_search __P((Char *, Char *, COMMAND,
+ int, int, int, Char *,
+ int));
+extern int starting_a_command __P((Char *, Char *));
+extern void copyn __P((Char *, Char *, int));
+extern void catn __P((Char *, Char *, int));
+extern int fcompare __P((Char **, Char **));
+extern void print_by_column __P((Char *, Char *[], int,
+ int));
+extern int StrQcmp __P((Char *, Char *));
+extern Char *tgetenv __P((Char *));
+
+/*
+ * tw.init.c
+ */
+extern void tw_alias_start __P((DIR *, Char *));
+extern void tw_cmd_start __P((DIR *, Char *));
+extern void tw_logname_start __P((DIR *, Char *));
+extern void tw_var_start __P((DIR *, Char *));
+extern void tw_complete_start __P((DIR *, Char *));
+extern void tw_file_start __P((DIR *, Char *));
+extern void tw_vl_start __P((DIR *, Char *));
+extern void tw_wl_start __P((DIR *, Char *));
+extern void tw_bind_start __P((DIR *, Char *));
+extern void tw_limit_start __P((DIR *, Char *));
+extern void tw_sig_start __P((DIR *, Char *));
+extern void tw_job_start __P((DIR *, Char *));
+extern void tw_grpname_start __P((DIR *, Char *));
+extern Char *tw_cmd_next __P((Char *, int *));
+extern Char *tw_logname_next __P((Char *, int *));
+extern Char *tw_shvar_next __P((Char *, int *));
+extern Char *tw_envvar_next __P((Char *, int *));
+extern Char *tw_var_next __P((Char *, int *));
+extern Char *tw_file_next __P((Char *, int *));
+extern Char *tw_wl_next __P((Char *, int *));
+extern Char *tw_bind_next __P((Char *, int *));
+extern Char *tw_limit_next __P((Char *, int *));
+extern Char *tw_sig_next __P((Char *, int *));
+extern Char *tw_job_next __P((Char *, int *));
+extern Char *tw_grpname_next __P((Char *, int *));
+extern void tw_dir_end __P((void));
+extern void tw_cmd_free __P((void));
+extern void tw_logname_end __P((void));
+extern void tw_grpname_end __P((void));
+extern Char *tw_item_add __P((int));
+extern Char **tw_item_get __P((void));
+extern void tw_item_free __P((void));
+extern Char *tw_item_find __P((Char *));
+
+/*
+ * tw.spell.c
+ */
+extern int spell_me __P((Char *, int, int,
+ Char *, int));
+extern int spdir __P((Char *, Char *, Char *,
+ Char *));
+extern int spdist __P((Char *, Char *));
+
+/*
+ * tw.comp.c
+ */
+extern void docomplete __P((Char **,
+ struct command *));
+extern void douncomplete __P((Char **,
+ struct command *));
+extern int tw_complete __P((Char *, Char **,
+ Char **, int, int *));
+#ifdef COLOR_LS_F
+/*
+ * tw.color.c
+ */
+extern void set_color_context __P((void));
+extern void print_with_color __P((Char *, size_t, int));
+extern void parseLS_COLORS __P((Char *));
+#endif /* COLOR_LS_F */
+
+#endif /* _h_tw_decls */
diff --git a/contrib/tcsh/tw.h b/contrib/tcsh/tw.h
new file mode 100644
index 0000000..25b484c
--- /dev/null
+++ b/contrib/tcsh/tw.h
@@ -0,0 +1,110 @@
+/* $Header: /src/pub/tcsh/tw.h,v 3.20 1997/10/02 16:36:35 christos Exp $ */
+/*
+ * tw.h: TwENEX functions headers
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _h_tw
+#define _h_tw
+
+#define TW_PATH 0x1000
+#define TW_ZERO 0x0fff
+
+#define TW_NONE 0x0000
+#define TW_COMMAND 0x0001
+#define TW_VARIABLE 0x0002
+#define TW_LOGNAME 0x0003
+#define TW_FILE 0x0004
+#define TW_DIRECTORY 0x0005
+#define TW_VARLIST 0x0006
+#define TW_USER 0x0007
+#define TW_COMPLETION 0x0008
+#define TW_ALIAS 0x0009
+#define TW_SHELLVAR 0x000a
+#define TW_ENVVAR 0x000b
+#define TW_BINDING 0x000c
+#define TW_WORDLIST 0x000d
+#define TW_LIMIT 0x000e
+#define TW_SIGNAL 0x000f
+#define TW_JOB 0x0010
+#define TW_EXPLAIN 0x0011
+#define TW_TEXT 0x0012
+#define TW_GRPNAME 0x0013
+
+#define TW_EXEC_CHK 0x01
+#define TW_DIR_CHK 0x02
+#define TW_TEXT_CHK 0x04
+
+#define TW_DIR_OK 0x10
+#define TW_PAT_OK 0x20
+#define TW_IGN_OK 0x40
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+#define ON 1
+#define OFF 0
+#define FILSIZ 512 /* Max reasonable file name length */
+#define ESC CTL_ESC('\033')
+#define equal(a, b) (strcmp(a, b) == 0)
+
+#define is_set(var) adrof(var)
+#define ismetahash(a) (ismeta(a) && (a) != '#')
+
+#define SEARCHLIST "HPATH" /* Env. param for helpfile searchlist */
+#define DEFAULTLIST ":/usr/man/cat1:/usr/man/cat8:/usr/man/cat6:/usr/local/man/cat1:/usr/local/man/cat8:/usr/local/man/cat6" /* if no HPATH */
+
+typedef enum {
+ LIST, LIST_ALL, RECOGNIZE, RECOGNIZE_ALL, RECOGNIZE_SCROLL,
+ PRINT_HELP, SPELL, GLOB, GLOB_EXPAND, VARS_EXPAND, PATH_NORMALIZE,
+ COMMAND_NORMALIZE
+} COMMAND;
+
+struct scroll_tab_list {
+ Char *element;
+ struct scroll_tab_list *next;
+} ;
+
+extern struct scroll_tab_list *scroll_tab;
+extern int curchoice;
+
+extern int non_unique_match;
+
+extern int match_unique_match;
+
+#include "tw.decls.h"
+
+#endif /* _h_tw */
diff --git a/contrib/tcsh/tw.help.c b/contrib/tcsh/tw.help.c
new file mode 100644
index 0000000..87c691d
--- /dev/null
+++ b/contrib/tcsh/tw.help.c
@@ -0,0 +1,206 @@
+/* $Header: /src/pub/tcsh/tw.help.c,v 3.16 1999/05/11 13:08:03 christos Exp $ */
+/* tw.help.c: actually look up and print documentation on a file.
+ * Look down the path for an appropriate file, then print it.
+ * Note that the printing is NOT PAGED. This is because the
+ * function is NOT meant to look at manual pages, it only does so
+ * if there is no .help file to look in.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.help.c,v 3.16 1999/05/11 13:08:03 christos Exp $")
+
+#include "tw.h"
+#include "tc.h"
+
+
+static int f = -1;
+static sigret_t cleanf __P((int));
+static Char *skipslist __P((Char *));
+static void nextslist __P((Char *, Char *));
+
+static char *h_ext[] = {
+ ".help", ".1", ".8", ".6", "", NULL
+};
+
+void
+do_help(command)
+ Char *command;
+{
+ Char name[FILSIZ + 1];
+ Char *cmd_p, *ep;
+ char **sp;
+
+ signalfun_t orig_intr;
+ Char curdir[MAXPATHLEN]; /* Current directory being looked at */
+ register Char *hpath; /* The environment parameter */
+ Char full[MAXPATHLEN];
+ char buf[512]; /* full path name and buffer for read */
+ int len; /* length of read buffer */
+ Char *thpath;
+
+
+ /* trim off the whitespace at the beginning */
+ for (cmd_p = command; *cmd_p == ' ' || *cmd_p == '\t'; cmd_p++)
+ continue;
+
+ /* copy the string to a safe place */
+ copyn(name, cmd_p, FILSIZ + 1);
+
+ /* trim off the whitespace that may be at the end */
+ for (cmd_p = name;
+ *cmd_p != ' ' && *cmd_p != '\t' && *cmd_p != '\0'; cmd_p++)
+ continue;
+ *cmd_p = '\0';
+
+ /* if nothing left, return */
+ if (*name == '\0')
+ return;
+
+ if (adrof1(STRhelpcommand, &aliases)) { /* if we have an alias */
+ jmp_buf_t osetexit;
+
+ getexit(osetexit); /* make sure to come back here */
+ if (setexit() == 0)
+ aliasrun(2, STRhelpcommand, name); /* then use it. */
+ resexit(osetexit); /* and finish up */
+ }
+ else { /* else cat something to them */
+ /* got is, now "cat" the file based on the path $HPATH */
+
+ hpath = str2short(getenv(SEARCHLIST));
+ if (hpath == NULL)
+ hpath = str2short(DEFAULTLIST);
+ thpath = hpath = Strsave(hpath);
+
+ for (;;) {
+ if (!*hpath) {
+ xprintf(CGETS(29, 1, "No help file for %S\n"), name);
+ break;
+ }
+ nextslist(hpath, curdir);
+ hpath = skipslist(hpath);
+
+ /*
+ * now make the full path name - try first /bar/foo.help, then
+ * /bar/foo.1, /bar/foo.8, then finally /bar/foo.6. This is so
+ * that you don't spit a binary at the tty when $HPATH == $PATH.
+ */
+ copyn(full, curdir, (int) (sizeof(full) / sizeof(Char)));
+ catn(full, STRslash, (int) (sizeof(full) / sizeof(Char)));
+ catn(full, name, (int) (sizeof(full) / sizeof(Char)));
+ ep = &full[Strlen(full)];
+ for (sp = h_ext; *sp; sp++) {
+ *ep = '\0';
+ catn(full, str2short(*sp), (int) (sizeof(full) / sizeof(Char)));
+ if ((f = open(short2str(full), O_RDONLY)) != -1)
+ break;
+ }
+ if (f != -1) {
+ /* so cat it to the terminal */
+ orig_intr = (signalfun_t) sigset(SIGINT, cleanf);
+ while (f != -1 && (len = read(f, (char *) buf, 512)) > 0)
+ (void) write(SHOUT, (char *) buf, (size_t) len);
+#ifdef convex
+ /* print error in case file is migrated */
+ if (len == -1)
+ stderror(ERR_SYSTEM, progname, strerror(errno));
+#endif /* convex */
+ (void) sigset(SIGINT, orig_intr);
+ if (f != -1)
+ (void) close(f);
+ break;
+ }
+ }
+ xfree((ptr_t) thpath);
+ }
+}
+
+static sigret_t
+/*ARGSUSED*/
+cleanf(snum)
+int snum;
+{
+#ifdef UNRELSIGS
+ if (snum)
+ (void) sigset(SIGINT, cleanf);
+#endif /* UNRELSIGS */
+ if (f != -1)
+ (void) close(f);
+ f = -1;
+#ifndef SIGVOID
+ return (snum);
+#endif
+}
+
+/* these next two are stolen from CMU's man(1) command for looking down
+ * paths. they are prety straight forward. */
+
+/*
+ * nextslist takes a search list and copies the next path in it
+ * to np. A null search list entry is expanded to ".".
+ * If there are no entries in the search list, then np will point
+ * to a null string.
+ */
+
+static void
+nextslist(sl, np)
+ register Char *sl;
+ register Char *np;
+{
+ if (!*sl)
+ *np = '\000';
+ else if (*sl == ':') {
+ *np++ = '.';
+ *np = '\000';
+ }
+ else {
+ while (*sl && *sl != ':')
+ *np++ = *sl++;
+ *np = '\000';
+ }
+}
+
+/*
+ * skipslist returns the pointer to the next entry in the search list.
+ */
+
+static Char *
+skipslist(sl)
+ register Char *sl;
+{
+ while (*sl && *sl++ != ':')
+ continue;
+ return (sl);
+}
diff --git a/contrib/tcsh/tw.init.c b/contrib/tcsh/tw.init.c
new file mode 100644
index 0000000..e040a88
--- /dev/null
+++ b/contrib/tcsh/tw.init.c
@@ -0,0 +1,1087 @@
+/* $Header: /src/pub/tcsh/tw.init.c,v 3.25 1998/10/25 15:10:50 christos Exp $ */
+/*
+ * tw.init.c: Handle lists of things to complete
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.init.c,v 3.25 1998/10/25 15:10:50 christos Exp $")
+
+#include "tw.h"
+#include "ed.h"
+#include "tc.h"
+#include "sh.proc.h"
+
+#if !defined(NSIG) && defined(SIGMAX)
+# define NSIG (SIGMAX+1)
+#endif /* !NSIG && SIGMAX */
+#if !defined(NSIG) && defined(_NSIG)
+# define NSIG _NSIG
+#endif /* !NSIG && _NSIG */
+
+#define TW_INCR 128
+
+typedef struct {
+ Char **list, /* List of command names */
+ *buff; /* Space holding command names */
+ int nlist, /* Number of items */
+ nbuff, /* Current space in name buf */
+ tlist, /* Total space in list */
+ tbuff; /* Total space in name buf */
+} stringlist_t;
+
+
+static struct varent *tw_vptr = NULL; /* Current shell variable */
+static Char **tw_env = NULL; /* Current environment variable */
+static Char *tw_word; /* Current word pointer */
+static struct KeyFuncs *tw_bind = NULL; /* List of the bindings */
+#ifndef HAVENOLIMIT
+static struct limits *tw_limit = NULL; /* List of the resource limits */
+#endif /* HAVENOLIMIT */
+static int tw_index = 0; /* signal and job index */
+static DIR *tw_dir_fd = NULL; /* Current directory descriptor */
+static Char tw_retname[MAXPATHLEN+1]; /* Return buffer */
+static int tw_cmd_got = 0; /* What we need to do */
+static stringlist_t tw_cmd = { NULL, NULL, 0, 0, 0, 0 };
+static stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 };
+#define TW_FL_CMD 0x01
+#define TW_FL_ALIAS 0x02
+#define TW_FL_BUILTIN 0x04
+#define TW_FL_SORT 0x08
+#define TW_FL_REL 0x10
+
+static struct { /* Current element pointer */
+ int cur; /* Current element number */
+ Char **pathv; /* Current element in path */
+ DIR *dfd; /* Current directory descriptor */
+} tw_cmd_state;
+
+
+#ifdef BSDSIGS
+static sigmask_t tw_omask;
+# define TW_HOLD() tw_omask = sigblock(sigmask(SIGINT))
+# define TW_RELS() (void) sigsetmask(tw_omask)
+#else /* !BSDSIGS */
+# define TW_HOLD() (void) sighold(SIGINT)
+# define TW_RELS() (void) sigrelse(SIGINT)
+#endif /* BSDSIGS */
+
+#define SETDIR(dfd) \
+ { \
+ tw_dir_fd = dfd; \
+ if (tw_dir_fd != NULL) \
+ rewinddir(tw_dir_fd); \
+ }
+
+#define CLRDIR(dfd) \
+ if (dfd != NULL) { \
+ TW_HOLD(); \
+ (void) closedir(dfd); \
+ dfd = NULL; \
+ TW_RELS(); \
+ }
+
+static Char *tw_str_add __P((stringlist_t *, int));
+static void tw_str_free __P((stringlist_t *));
+static Char *tw_dir_next __P((DIR *));
+static void tw_cmd_add __P((Char *name));
+static void tw_cmd_cmd __P((void));
+static void tw_cmd_builtin __P((void));
+static void tw_cmd_alias __P((void));
+static void tw_cmd_sort __P((void));
+static void tw_vptr_start __P((struct varent *));
+
+
+/* tw_str_add():
+ * Add an item to the string list
+ */
+static Char *
+tw_str_add(sl, len)
+ stringlist_t *sl;
+ int len;
+{
+ Char *ptr;
+
+ if (sl->tlist <= sl->nlist) {
+ TW_HOLD();
+ sl->tlist += TW_INCR;
+ sl->list = sl->list ?
+ (Char **) xrealloc((ptr_t) sl->list,
+ (size_t) (sl->tlist * sizeof(Char *))) :
+ (Char **) xmalloc((size_t) (sl->tlist * sizeof(Char *)));
+ TW_RELS();
+ }
+ if (sl->tbuff <= sl->nbuff + len) {
+ int i;
+ ptr = sl->buff;
+
+ TW_HOLD();
+ sl->tbuff += TW_INCR + len;
+ sl->buff = sl->buff ?
+ (Char *) xrealloc((ptr_t) sl->buff,
+ (size_t) (sl->tbuff * sizeof(Char))) :
+ (Char *) xmalloc((size_t) (sl->tbuff * sizeof(Char)));
+ /* Re-thread the new pointer list, if changed */
+ if (ptr != NULL && ptr != sl->buff) {
+ int offs = (int) (sl->buff - ptr);
+ for (i = 0; i < sl->nlist; i++)
+ sl->list[i] += offs;
+ }
+ TW_RELS();
+ }
+ ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff];
+ sl->nbuff += len;
+ return ptr;
+} /* tw_str_add */
+
+
+/* tw_str_free():
+ * Free a stringlist
+ */
+static void
+tw_str_free(sl)
+ stringlist_t *sl;
+{
+ TW_HOLD();
+ if (sl->list) {
+ xfree((ptr_t) sl->list);
+ sl->list = NULL;
+ sl->tlist = sl->nlist = 0;
+ }
+ if (sl->buff) {
+ xfree((ptr_t) sl->buff);
+ sl->buff = NULL;
+ sl->tbuff = sl->nbuff = 0;
+ }
+ TW_RELS();
+} /* end tw_str_free */
+
+
+static Char *
+tw_dir_next(dfd)
+ DIR *dfd;
+{
+ register struct dirent *dirp;
+
+ if (dfd == NULL)
+ return NULL;
+
+ if ((dirp = readdir(dfd)) != NULL) {
+ (void) Strcpy(tw_retname, str2short(dirp->d_name));
+ return (tw_retname);
+ }
+ return NULL;
+} /* end tw_dir_next */
+
+
+/* tw_cmd_add():
+ * Add the name to the command list
+ */
+static void
+tw_cmd_add(name)
+ Char *name;
+{
+ int len;
+
+ len = (int) Strlen(name) + 2;
+ (void) Strcpy(tw_str_add(&tw_cmd, len), name);
+} /* end tw_cmd_add */
+
+
+/* tw_cmd_free():
+ * Free the command list
+ */
+void
+tw_cmd_free()
+{
+ CLRDIR(tw_dir_fd)
+ tw_str_free(&tw_cmd);
+ tw_cmd_got = 0;
+} /* end tw_cmd_free */
+
+/* tw_cmd_cmd():
+ * Add system commands to the command list
+ */
+static void
+tw_cmd_cmd()
+{
+ register DIR *dirp;
+ register struct dirent *dp;
+ register Char *dir = NULL, *name;
+ register Char **pv;
+ struct varent *v = adrof(STRpath);
+ struct varent *recexec = adrof(STRrecognize_only_executables);
+ int len;
+
+
+ if (v == NULL) /* if no path */
+ return;
+
+ for (pv = v->vec; *pv; pv++) {
+ if (pv[0][0] != '/') {
+ tw_cmd_got |= TW_FL_REL;
+ continue;
+ }
+
+ if ((dirp = opendir(short2str(*pv))) == NULL)
+ continue;
+
+ if (recexec)
+ dir = Strspl(*pv, STRslash);
+ while ((dp = readdir(dirp)) != NULL) {
+ /* the call to executable() may make this a bit slow */
+ name = str2short(dp->d_name);
+ if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0)))
+ continue;
+ len = (int) Strlen(name) + 2;
+ if (name[0] == '#' || /* emacs temp files */
+ name[0] == '.' || /* .files */
+ name[len - 3] == '~' || /* emacs backups */
+ name[len - 3] == '%') /* textedit backups */
+ continue; /* Ignore! */
+ tw_cmd_add(name);
+ }
+ (void) closedir(dirp);
+ if (recexec)
+ xfree((ptr_t) dir);
+ }
+} /* end tw_cmd_cmd */
+
+
+/* tw_cmd_builtin():
+ * Add builtins to the command list
+ */
+static void
+tw_cmd_builtin()
+{
+ register struct biltins *bptr;
+
+ for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++)
+ if (bptr->bname)
+ tw_cmd_add(str2short(bptr->bname));
+#ifdef WINNT
+ for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++)
+ if (bptr->bname)
+ tw_cmd_add(str2short(bptr->bname));
+#endif /* WINNT*/
+} /* end tw_cmd_builtin */
+
+
+/* tw_cmd_alias():
+ * Add aliases to the command list
+ */
+static void
+tw_cmd_alias()
+{
+ register struct varent *p;
+ register struct varent *c;
+
+ p = &aliases;
+ for (;;) {
+ while (p->v_left)
+ p = p->v_left;
+x:
+ if (p->v_parent == 0) /* is it the header? */
+ return;
+ if (p->v_name)
+ tw_cmd_add(p->v_name);
+ if (p->v_right) {
+ p = p->v_right;
+ continue;
+ }
+ do {
+ c = p;
+ p = p->v_parent;
+ } while (p->v_right == c);
+ goto x;
+ }
+} /* end tw_cmd_alias */
+
+
+/* tw_cmd_sort():
+ * Sort the command list removing duplicate elements
+ */
+static void
+tw_cmd_sort()
+{
+ int fwd, i;
+
+ TW_HOLD();
+ /* sort the list. */
+ qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *),
+ (int (*) __P((const void *, const void *))) fcompare);
+
+ /* get rid of multiple entries */
+ for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) {
+ if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */
+ fwd++; /* increase the forward ref. count */
+ else if (fwd)
+ tw_cmd.list[i - fwd] = tw_cmd.list[i];
+ }
+ /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */
+ if (fwd)
+ tw_cmd.list[i - fwd] = tw_cmd.list[i];
+ tw_cmd.nlist -= fwd;
+ TW_RELS();
+} /* end tw_cmd_sort */
+
+
+/* tw_cmd_start():
+ * Get the command list and sort it, if not done yet.
+ * Reset the current pointer to the beginning of the command list
+ */
+/*ARGSUSED*/
+void
+tw_cmd_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ static Char *defpath[] = { STRNULL, 0 };
+ USE(pat);
+ SETDIR(dfd)
+ if ((tw_cmd_got & TW_FL_CMD) == 0) {
+ tw_cmd_free();
+ tw_cmd_cmd();
+ tw_cmd_got |= TW_FL_CMD;
+ }
+ if ((tw_cmd_got & TW_FL_ALIAS) == 0) {
+ tw_cmd_alias();
+ tw_cmd_got &= ~TW_FL_SORT;
+ tw_cmd_got |= TW_FL_ALIAS;
+ }
+ if ((tw_cmd_got & TW_FL_BUILTIN) == 0) {
+ tw_cmd_builtin();
+ tw_cmd_got &= ~TW_FL_SORT;
+ tw_cmd_got |= TW_FL_BUILTIN;
+ }
+ if ((tw_cmd_got & TW_FL_SORT) == 0) {
+ tw_cmd_sort();
+ tw_cmd_got |= TW_FL_SORT;
+ }
+
+ tw_cmd_state.cur = 0;
+ CLRDIR(tw_cmd_state.dfd)
+ if (tw_cmd_got & TW_FL_REL) {
+ struct varent *vp = adrof(STRpath);
+ if (vp && vp->vec)
+ tw_cmd_state.pathv = vp->vec;
+ else
+ tw_cmd_state.pathv = defpath;
+ }
+ else
+ tw_cmd_state.pathv = defpath;
+} /* tw_cmd_start */
+
+
+/* tw_cmd_next():
+ * Return the next element in the command list or
+ * Look for commands in the relative path components
+ */
+Char *
+tw_cmd_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ Char *ptr = NULL;
+
+ if (tw_cmd_state.cur < tw_cmd.nlist) {
+ *flags = TW_DIR_OK;
+ return tw_cmd.list[tw_cmd_state.cur++];
+ }
+
+ /*
+ * We need to process relatives in the path.
+ */
+ while (((tw_cmd_state.dfd == NULL) ||
+ ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) &&
+ (*tw_cmd_state.pathv != NULL)) {
+
+ CLRDIR(tw_cmd_state.dfd)
+
+ while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/')
+ tw_cmd_state.pathv++;
+ if ((ptr = *tw_cmd_state.pathv) != 0) {
+ /*
+ * We complete directories only on '.' should that
+ * be changed?
+ */
+ if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) {
+ *dir = '\0';
+ tw_cmd_state.dfd = opendir(".");
+ *flags = TW_DIR_OK | TW_EXEC_CHK;
+ }
+ else {
+ copyn(dir, *tw_cmd_state.pathv, FILSIZ);
+ catn(dir, STRslash, FILSIZ);
+ tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv));
+ *flags = TW_EXEC_CHK;
+ }
+ tw_cmd_state.pathv++;
+ }
+ }
+ return ptr;
+} /* end tw_cmd_next */
+
+
+/* tw_vptr_start():
+ * Find the first variable in the variable list
+ */
+static void
+tw_vptr_start(c)
+ struct varent *c;
+{
+ tw_vptr = c; /* start at beginning of variable list */
+
+ for (;;) {
+ while (tw_vptr->v_left)
+ tw_vptr = tw_vptr->v_left;
+x:
+ if (tw_vptr->v_parent == 0) { /* is it the header? */
+ tw_vptr = NULL;
+ return;
+ }
+ if (tw_vptr->v_name)
+ return; /* found first one */
+ if (tw_vptr->v_right) {
+ tw_vptr = tw_vptr->v_right;
+ continue;
+ }
+ do {
+ c = tw_vptr;
+ tw_vptr = tw_vptr->v_parent;
+ } while (tw_vptr->v_right == c);
+ goto x;
+ }
+} /* end tw_shvar_start */
+
+
+/* tw_shvar_next():
+ * Return the next shell variable
+ */
+/*ARGSUSED*/
+Char *
+tw_shvar_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ register struct varent *p;
+ register struct varent *c;
+ register Char *cp;
+
+ USE(flags);
+ USE(dir);
+ if ((p = tw_vptr) == NULL)
+ return (NULL); /* just in case */
+
+ cp = p->v_name; /* we know that this name is here now */
+
+ /* now find the next one */
+ for (;;) {
+ if (p->v_right) { /* if we can go right */
+ p = p->v_right;
+ while (p->v_left)
+ p = p->v_left;
+ }
+ else { /* else go up */
+ do {
+ c = p;
+ p = p->v_parent;
+ } while (p->v_right == c);
+ }
+ if (p->v_parent == 0) { /* is it the header? */
+ tw_vptr = NULL;
+ return (cp);
+ }
+ if (p->v_name) {
+ tw_vptr = p; /* save state for the next call */
+ return (cp);
+ }
+ }
+} /* end tw_shvar_next */
+
+
+/* tw_envvar_next():
+ * Return the next environment variable
+ */
+/*ARGSUSED*/
+Char *
+tw_envvar_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ Char *ps, *pd;
+
+ USE(flags);
+ USE(dir);
+ if (tw_env == NULL || *tw_env == NULL)
+ return (NULL);
+ for (ps = *tw_env, pd = tw_retname;
+ *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++)
+ continue;
+ *pd = '\0';
+ tw_env++;
+ return (tw_retname);
+} /* end tw_envvar_next */
+
+
+/* tw_var_start():
+ * Begin the list of the shell and environment variables
+ */
+/*ARGSUSED*/
+void
+tw_var_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+ tw_vptr_start(&shvhed);
+ tw_env = STR_environ;
+} /* end tw_var_start */
+
+
+/* tw_alias_start():
+ * Begin the list of the shell aliases
+ */
+/*ARGSUSED*/
+void
+tw_alias_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+ tw_vptr_start(&aliases);
+ tw_env = NULL;
+} /* tw_alias_start */
+
+
+/* tw_complete_start():
+ * Begin the list of completions
+ */
+/*ARGSUSED*/
+void
+tw_complete_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ extern struct varent completions;
+
+ USE(pat);
+ SETDIR(dfd)
+ tw_vptr_start(&completions);
+ tw_env = NULL;
+} /* end tw_complete_start */
+
+
+/* tw_var_next():
+ * Return the next shell or environment variable
+ */
+Char *
+tw_var_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ Char *ptr = NULL;
+
+ if (tw_vptr)
+ ptr = tw_shvar_next(dir, flags);
+ if (!ptr && tw_env)
+ ptr = tw_envvar_next(dir, flags);
+ return ptr;
+} /* end tw_var_next */
+
+
+/* tw_logname_start():
+ * Initialize lognames to the beginning of the list
+ */
+/*ARGSUSED*/
+void
+tw_logname_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+#if !defined(_VMS_POSIX) && !defined(WINNT)
+ (void) setpwent(); /* Open passwd file */
+#endif /* !_VMS_POSIX && !WINNT */
+} /* end tw_logname_start */
+
+
+/* tw_logname_next():
+ * Return the next entry from the passwd file
+ */
+/*ARGSUSED*/
+Char *
+tw_logname_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ static Char retname[MAXPATHLEN];
+ struct passwd *pw;
+ /*
+ * We don't want to get interrupted inside getpwent()
+ * because the yellow pages code is not interruptible,
+ * and if we call endpwent() immediatetely after
+ * (in pintr()) we may be freeing an invalid pointer
+ */
+ USE(flags);
+ USE(dir);
+ TW_HOLD();
+#if !defined(_VMS_POSIX) && !defined(WINNT)
+ /* ISC does not declare getpwent()? */
+ pw = (struct passwd *) getpwent();
+#else /* _VMS_POSIX || WINNT */
+ pw = NULL;
+#endif /* !_VMS_POSIX && !WINNT */
+ TW_RELS();
+
+ if (pw == NULL) {
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif
+ return (NULL);
+ }
+ (void) Strcpy(retname, str2short(pw->pw_name));
+ return (retname);
+} /* end tw_logname_next */
+
+
+/* tw_logname_end():
+ * Close the passwd file to finish the logname list
+ */
+void
+tw_logname_end()
+{
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif
+#if !defined(_VMS_POSIX) && !defined(WINNT)
+ (void) endpwent();
+#endif /* !_VMS_POSIX && !WINNT */
+} /* end tw_logname_end */
+
+
+/* tw_grpname_start():
+ * Initialize grpnames to the beginning of the list
+ */
+/*ARGSUSED*/
+void
+tw_grpname_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT)
+ (void) setgrent(); /* Open group file */
+#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */
+} /* end tw_grpname_start */
+
+
+/* tw_grpname_next():
+ * Return the next entry from the group file
+ */
+/*ARGSUSED*/
+Char *
+tw_grpname_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ static Char retname[MAXPATHLEN];
+ struct group *gr;
+ /*
+ * We don't want to get interrupted inside getgrent()
+ * because the yellow pages code is not interruptible,
+ * and if we call endgrent() immediatetely after
+ * (in pintr()) we may be freeing an invalid pointer
+ */
+ USE(flags);
+ USE(dir);
+ TW_HOLD();
+#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT)
+ gr = (struct group *) getgrent();
+#else /* _VMS_POSIX || _OSD_POSIX || WINNT */
+ gr = NULL;
+#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */
+ TW_RELS();
+
+ if (gr == NULL) {
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif
+ return (NULL);
+ }
+ (void) Strcpy(retname, str2short(gr->gr_name));
+ return (retname);
+} /* end tw_grpname_next */
+
+
+/* tw_grpname_end():
+ * Close the group file to finish the groupname list
+ */
+void
+tw_grpname_end()
+{
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif
+#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT)
+ (void) endgrent();
+#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */
+} /* end tw_grpname_end */
+
+/* tw_file_start():
+ * Initialize the directory for the file list
+ */
+/*ARGSUSED*/
+void
+tw_file_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ struct varent *vp;
+ USE(pat);
+ SETDIR(dfd)
+ if ((vp = adrof(STRcdpath)) != NULL)
+ tw_env = vp->vec;
+} /* end tw_file_start */
+
+
+/* tw_file_next():
+ * Return the next file in the directory
+ */
+Char *
+tw_file_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ Char *ptr = tw_dir_next(tw_dir_fd);
+ if (ptr == NULL && (*flags & TW_DIR_OK) != 0) {
+ CLRDIR(tw_dir_fd)
+ while (tw_env && *tw_env)
+ if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL)
+ break;
+ else
+ tw_env++;
+
+ if (tw_dir_fd) {
+ copyn(dir, *tw_env++, MAXPATHLEN);
+ catn(dir, STRslash, MAXPATHLEN);
+ ptr = tw_dir_next(tw_dir_fd);
+ }
+ }
+ return ptr;
+} /* end tw_file_next */
+
+
+/* tw_dir_end():
+ * Clear directory related lists
+ */
+void
+tw_dir_end()
+{
+ CLRDIR(tw_dir_fd)
+ CLRDIR(tw_cmd_state.dfd)
+} /* end tw_dir_end */
+
+
+/* tw_item_free():
+ * Free the item list
+ */
+void
+tw_item_free()
+{
+ tw_str_free(&tw_item);
+} /* end tw_item_free */
+
+
+/* tw_item_get():
+ * Return the list of items
+ */
+Char **
+tw_item_get()
+{
+ return tw_item.list;
+} /* end tw_item_get */
+
+
+/* tw_item_add():
+ * Return a new item
+ */
+Char *
+tw_item_add(len)
+ int len;
+{
+ return tw_str_add(&tw_item, len);
+} /* tw_item_add */
+
+
+/* tw_item_find():
+ * Find the string if it exists in the item list
+ * end return it.
+ */
+Char *
+tw_item_find(str)
+ Char *str;
+{
+ int i;
+
+ if (tw_item.list == NULL || str == NULL)
+ return NULL;
+
+ for (i = 0; i < tw_item.nlist; i++)
+ if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0)
+ return tw_item.list[i];
+ return NULL;
+} /* end tw_item_find */
+
+
+/* tw_vl_start():
+ * Initialize a variable list
+ */
+void
+tw_vl_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ SETDIR(dfd)
+ if ((tw_vptr = adrof(pat)) != NULL) {
+ tw_env = tw_vptr->vec;
+ tw_vptr = NULL;
+ }
+ else
+ tw_env = NULL;
+} /* end tw_vl_start */
+
+
+/*
+ * Initialize a word list
+ */
+void
+tw_wl_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ SETDIR(dfd);
+ tw_word = pat;
+} /* end tw_wl_start */
+
+
+/*
+ * Return the next word from the word list
+ */
+/*ARGSUSED*/
+Char *
+tw_wl_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ USE(flags);
+ if (tw_word == NULL || tw_word[0] == '\0')
+ return NULL;
+
+ while (*tw_word && Isspace(*tw_word)) tw_word++;
+
+ for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++)
+ continue;
+ if (*tw_word)
+ *tw_word++ = '\0';
+ return *dir ? dir : NULL;
+} /* end tw_wl_next */
+
+
+/* tw_bind_start():
+ * Begin the list of the shell bindings
+ */
+/*ARGSUSED*/
+void
+tw_bind_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+ tw_bind = FuncNames;
+} /* end tw_bind_start */
+
+
+/* tw_bind_next():
+ * Begin the list of the shell bindings
+ */
+/*ARGSUSED*/
+Char *
+tw_bind_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ char *ptr;
+ USE(flags);
+ if (tw_bind && tw_bind->name) {
+ for (ptr = tw_bind->name, dir = tw_retname;
+ (*dir++ = (Char) *ptr++) != '\0';)
+ continue;
+ tw_bind++;
+ return(tw_retname);
+ }
+ return NULL;
+} /* end tw_bind_next */
+
+
+/* tw_limit_start():
+ * Begin the list of the shell limitings
+ */
+/*ARGSUSED*/
+void
+tw_limit_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+#ifndef HAVENOLIMIT
+ tw_limit = limits;
+#endif /* ! HAVENOLIMIT */
+} /* end tw_limit_start */
+
+
+/* tw_limit_next():
+ * Begin the list of the shell limitings
+ */
+/*ARGSUSED*/
+Char *
+tw_limit_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+#ifndef HAVENOLIMIT
+ char *ptr;
+ if (tw_limit && tw_limit->limname) {
+ for (ptr = tw_limit->limname, dir = tw_retname;
+ (*dir++ = (Char) *ptr++) != '\0';)
+ continue;
+ tw_limit++;
+ return(tw_retname);
+ }
+#endif /* ! HAVENOLIMIT */
+ USE(flags);
+ return NULL;
+} /* end tw_limit_next */
+
+
+/* tw_sig_start():
+ * Begin the list of the shell sigings
+ */
+/*ARGSUSED*/
+void
+tw_sig_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+ tw_index = 0;
+} /* end tw_sig_start */
+
+
+/* tw_sig_next():
+ * Begin the list of the shell sigings
+ */
+/*ARGSUSED*/
+Char *
+tw_sig_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ char *ptr;
+ extern int nsig;
+ USE(flags);
+ for (;tw_index < nsig; tw_index++) {
+
+ if (mesg[tw_index].iname == NULL)
+ continue;
+
+ for (ptr = mesg[tw_index].iname, dir = tw_retname;
+ (*dir++ = (Char) *ptr++) != '\0';)
+ continue;
+ tw_index++;
+ return(tw_retname);
+ }
+ return NULL;
+} /* end tw_sig_next */
+
+
+/* tw_job_start():
+ * Begin the list of the shell jobings
+ */
+/*ARGSUSED*/
+void
+tw_job_start(dfd, pat)
+ DIR *dfd;
+ Char *pat;
+{
+ USE(pat);
+ SETDIR(dfd)
+ tw_index = 1;
+} /* end tw_job_start */
+
+
+/* tw_job_next():
+ * Begin the list of the shell jobings
+ */
+/*ARGSUSED*/
+Char *
+tw_job_next(dir, flags)
+ Char *dir;
+ int *flags;
+{
+ Char *ptr;
+ struct process *j;
+
+ USE(flags);
+ for (;tw_index <= pmaxindex; tw_index++) {
+ for (j = proclist.p_next; j != NULL; j = j->p_next)
+ if (j->p_index == tw_index && j->p_procid == j->p_jobid)
+ break;
+ if (j == NULL)
+ continue;
+ for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';)
+ continue;
+ *dir = '\0';
+ tw_index++;
+ return(tw_retname);
+ }
+ return NULL;
+} /* end tw_job_next */
diff --git a/contrib/tcsh/tw.parse.c b/contrib/tcsh/tw.parse.c
new file mode 100644
index 0000000..90b4ae8
--- /dev/null
+++ b/contrib/tcsh/tw.parse.c
@@ -0,0 +1,2232 @@
+/* $Header: /src/pub/tcsh/tw.parse.c,v 3.86 1998/10/25 15:10:52 christos Exp $ */
+/*
+ * tw.parse.c: Everyone has taken a shot in this futile effort to
+ * lexically analyze a csh line... Well we cannot good
+ * a job as good as sh.lex.c; but we try. Amazing that
+ * it works considering how many hands have touched this code
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.parse.c,v 3.86 1998/10/25 15:10:52 christos Exp $")
+
+#include "tw.h"
+#include "ed.h"
+#include "tc.h"
+
+#ifdef WINNT
+#include "nt.const.h"
+#endif /* WINNT */
+#define EVEN(x) (((x) & 1) != 1)
+
+#define DOT_NONE 0 /* Don't display dot files */
+#define DOT_NOT 1 /* Don't display dot or dot-dot */
+#define DOT_ALL 2 /* Display all dot files */
+
+/* TW_NONE, TW_COMMAND, TW_VARIABLE, TW_LOGNAME, */
+/* TW_FILE, TW_DIRECTORY, TW_VARLIST, TW_USER, */
+/* TW_COMPLETION, TW_ALIAS, TW_SHELLVAR, TW_ENVVAR, */
+/* TW_BINDING, TW_WORDLIST, TW_LIMIT, TW_SIGNAL */
+/* TW_JOB, TW_EXPLAIN, TW_TEXT, TW_GRPNAME */
+static void (*tw_start_entry[]) __P((DIR *, Char *)) = {
+ tw_file_start, tw_cmd_start, tw_var_start, tw_logname_start,
+ tw_file_start, tw_file_start, tw_vl_start, tw_logname_start,
+ tw_complete_start, tw_alias_start, tw_var_start, tw_var_start,
+ tw_bind_start, tw_wl_start, tw_limit_start, tw_sig_start,
+ tw_job_start, tw_file_start, tw_file_start, tw_grpname_start
+};
+
+static Char * (*tw_next_entry[]) __P((Char *, int *)) = {
+ tw_file_next, tw_cmd_next, tw_var_next, tw_logname_next,
+ tw_file_next, tw_file_next, tw_var_next, tw_logname_next,
+ tw_var_next, tw_var_next, tw_shvar_next, tw_envvar_next,
+ tw_bind_next, tw_wl_next, tw_limit_next, tw_sig_next,
+ tw_job_next, tw_file_next, tw_file_next, tw_grpname_next
+};
+
+static void (*tw_end_entry[]) __P((void)) = {
+ tw_dir_end, tw_dir_end, tw_dir_end, tw_logname_end,
+ tw_dir_end, tw_dir_end, tw_dir_end, tw_logname_end,
+ tw_dir_end, tw_dir_end, tw_dir_end, tw_dir_end,
+ tw_dir_end, tw_dir_end, tw_dir_end, tw_dir_end,
+ tw_dir_end, tw_dir_end, tw_dir_end, tw_grpname_end
+};
+
+/* #define TDEBUG */
+
+/* Set to TRUE if recexact is set and an exact match is found
+ * along with other, longer, matches.
+ */
+
+int curchoice = -1;
+
+int match_unique_match = FALSE;
+int non_unique_match = FALSE;
+static bool SearchNoDirErr = 0; /* t_search returns -2 if dir is unreadable */
+
+/* state so if a completion is interrupted, the input line doesn't get
+ nuked */
+int InsideCompletion = 0;
+
+/* do the expand or list on the command line -- SHOULD BE REPLACED */
+
+extern Char NeedsRedraw; /* from ed.h */
+extern int Tty_raw_mode;
+extern int TermH; /* from the editor routines */
+extern int lbuffed; /* from sh.print.c */
+
+static void extract_dir_and_name __P((Char *, Char *, Char *));
+static int insert_meta __P((Char *, Char *, Char *, bool));
+static Char *tilde __P((Char *, Char *));
+static int expand_dir __P((Char *, Char *, DIR **, COMMAND));
+static bool nostat __P((Char *));
+static Char filetype __P((Char *, Char *));
+static int t_glob __P((Char ***, int));
+static int c_glob __P((Char ***));
+static int is_prefix __P((Char *, Char *));
+static int is_prefixmatch __P((Char *, Char *, int));
+static int is_suffix __P((Char *, Char *));
+static int recognize __P((Char *, Char *, int, int, int));
+static int ignored __P((Char *));
+static int isadirectory __P((Char *, Char *));
+static int tw_collect_items __P((COMMAND, int, Char *, Char *,
+ Char *, Char *, int));
+static int tw_collect __P((COMMAND, int, Char *, Char *,
+ Char **, Char *, int, DIR *));
+static Char tw_suffix __P((int, Char *, Char *, Char *,
+ Char *));
+static void tw_fixword __P((int, Char *, Char *, Char *, int));
+static void tw_list_items __P((int, int, int));
+static void add_scroll_tab __P((Char *));
+static void choose_scroll_tab __P((Char **, int));
+static void free_scroll_tab __P((void));
+static int find_rows __P((Char *[], int, int));
+
+#ifdef notdef
+/*
+ * If we find a set command, then we break a=b to a= and word becomes
+ * b else, we don't break a=b. [don't use that; splits words badly and
+ * messes up tw_complete()]
+ */
+#define isaset(c, w) ((w)[-1] == '=' && \
+ ((c)[0] == 's' && (c)[1] == 'e' && (c)[2] == 't' && \
+ ((c[3] == ' ' || (c)[3] == '\t'))))
+#endif
+
+#define QLINESIZE (INBUFSIZE + 1)
+
+/* TRUE if character must be quoted */
+#define tricky(w) (cmap(w, _META | _DOL | _QF | _QB | _ESC | _GLOB) && w != '#')
+/* TRUE if double quotes don't protect character */
+#define tricky_dq(w) (cmap(w, _DOL | _QB))
+
+/* tenematch():
+ * Return:
+ * > 1: No. of items found
+ * = 1: Exactly one match / spelling corrected
+ * = 0: No match / spelling was correct
+ * < 0: Error (incl spelling correction impossible)
+ */
+int
+tenematch(inputline, num_read, command)
+ Char *inputline; /* match string prefix */
+ int num_read; /* # actually in inputline */
+ COMMAND command; /* LIST or RECOGNIZE or PRINT_HELP */
+
+{
+ Char qline[QLINESIZE];
+ Char qu = 0, *pat = STRNULL;
+ Char *str_end, *cp, *wp, *wordp;
+ Char *cmd_start, *word_start, *word;
+ Char *ocmd_start = NULL, *oword_start = NULL, *oword = NULL;
+ int suf = 0;
+ int space_left;
+ int looking; /* what we are looking for */
+ int search_ret; /* what search returned for debugging */
+ int backq = 0;
+
+ if (num_read > QLINESIZE - 1)
+ return -1;
+ str_end = &inputline[num_read];
+
+ word_start = inputline;
+ word = cmd_start = wp = qline;
+ for (cp = inputline; cp < str_end; cp++) {
+ if (!cmap(qu, _ESC)) {
+ if (cmap(*cp, _QF|_ESC)) {
+ if (qu == 0 || qu == *cp) {
+ qu ^= *cp;
+ continue;
+ }
+ }
+ if (qu != '\'' && cmap(*cp, _QB)) {
+ if ((backq ^= 1) != 0) {
+ ocmd_start = cmd_start;
+ oword_start = word_start;
+ oword = word;
+ word_start = cp + 1;
+ word = cmd_start = wp + 1;
+ }
+ else {
+ cmd_start = ocmd_start;
+ word_start = oword_start;
+ word = oword;
+ }
+ *wp++ = *cp;
+ continue;
+ }
+ }
+ if (iscmdmeta(*cp))
+ cmd_start = wp + 1;
+
+ /* Don't quote '/' to make the recognize stuff work easily */
+ /* Don't quote '$' in double quotes */
+
+ if (cmap(*cp, _ESC) && cp < str_end - 1 && cp[1] == HIST)
+ *wp = *++cp | QUOTE;
+ else if (qu && (tricky(*cp) || *cp == '~') && !(qu == '\"' && tricky_dq(*cp)))
+ *wp = *cp | QUOTE;
+ else
+ *wp = *cp;
+ if (ismetahash(*wp) /* || isaset(cmd_start, wp + 1) */)
+ word = wp + 1, word_start = cp + 1;
+ wp++;
+ if (cmap(qu, _ESC))
+ qu = 0;
+ }
+ *wp = 0;
+
+#ifdef masscomp
+ /*
+ * Avoid a nasty message from the RTU 4.1A & RTU 5.0 compiler concerning
+ * the "overuse of registers". According to the compiler release notes,
+ * incorrect code may be produced unless the offending expression is
+ * rewritten. Therefore, we can't just ignore it, DAS DEC-90.
+ */
+ space_left = QLINESIZE - 1;
+ space_left -= word - qline;
+#else
+ space_left = QLINESIZE - 1 - (int) (word - qline);
+#endif
+
+ /*
+ * SPECIAL HARDCODED COMPLETIONS:
+ * first word of command -> TW_COMMAND
+ * everything else -> TW_ZERO
+ *
+ */
+ looking = starting_a_command(word - 1, qline) ?
+ TW_COMMAND : TW_ZERO;
+
+ wordp = word;
+
+#ifdef TDEBUG
+ xprintf(CGETS(30, 1, "starting_a_command %d\n"), looking);
+ xprintf("\ncmd_start:%S:\n", cmd_start);
+ xprintf("qline:%S:\n", qline);
+ xprintf("qline:");
+ for (wp = qline; *wp; wp++)
+ xprintf("%c", *wp & QUOTE ? '-' : ' ');
+ xprintf(":\n");
+ xprintf("word:%S:\n", word);
+ xprintf("word:");
+ /* Must be last, so wp is still pointing to the end of word */
+ for (wp = word; *wp; wp++)
+ xprintf("%c", *wp & QUOTE ? '-' : ' ');
+ xprintf(":\n");
+#endif
+
+ if ((looking == TW_COMMAND || looking == TW_ZERO) &&
+ (command == RECOGNIZE || command == LIST || command == SPELL ||
+ command == RECOGNIZE_SCROLL)) {
+#ifdef TDEBUG
+ xprintf(CGETS(30, 2, "complete %d "), looking);
+#endif
+ looking = tw_complete(cmd_start, &wordp, &pat, looking, &suf);
+#ifdef TDEBUG
+ xprintf(CGETS(30, 3, "complete %d %S\n"), looking, pat);
+#endif
+ }
+
+ switch (command) {
+ Char buffer[FILSIZ + 1], *bptr;
+ Char *slshp;
+ Char *items[2], **ptr;
+ int i, count;
+
+ case RECOGNIZE:
+ case RECOGNIZE_SCROLL:
+ case RECOGNIZE_ALL:
+ if (adrof(STRautocorrect)) {
+ if ((slshp = Strrchr(wordp, '/')) != NULL && slshp[1] != '\0') {
+ SearchNoDirErr = 1;
+ for (bptr = wordp; bptr < slshp; bptr++) {
+ /*
+ * do not try to correct spelling of words containing
+ * globbing characters
+ */
+ if (isglob(*bptr)) {
+ SearchNoDirErr = 0;
+ break;
+ }
+ }
+ }
+ }
+ else
+ slshp = STRNULL;
+ search_ret = t_search(wordp, wp, command, space_left, looking, 1,
+ pat, suf);
+ SearchNoDirErr = 0;
+
+ if (search_ret == -2) {
+ Char rword[FILSIZ + 1];
+
+ (void) Strcpy(rword, slshp);
+ if (slshp != STRNULL)
+ *slshp = '\0';
+ search_ret = spell_me(wordp, QLINESIZE - (wordp - qline), looking,
+ pat, suf);
+ if (search_ret == 1) {
+ (void) Strcat(wordp, rword);
+ wp = wordp + (int) Strlen(wordp);
+ search_ret = t_search(wordp, wp, command, space_left,
+ looking, 1, pat, suf);
+ }
+ }
+ if (*wp && insert_meta(word_start, str_end, word, !qu) < 0)
+ return -1; /* error inserting */
+ return search_ret;
+
+ case SPELL:
+ for (bptr = word_start; bptr < str_end; bptr++) {
+ /*
+ * do not try to correct spelling of words containing globbing
+ * characters
+ */
+ if (isglob(*bptr))
+ return 0;
+ }
+ search_ret = spell_me(wordp, QLINESIZE - (wordp - qline), looking,
+ pat, suf);
+ if (search_ret == 1) {
+ if (insert_meta(word_start, str_end, word, !qu) < 0)
+ return -1; /* error inserting */
+ }
+ return search_ret;
+
+ case PRINT_HELP:
+ do_help(cmd_start);
+ return 1;
+
+ case GLOB:
+ case GLOB_EXPAND:
+ (void) Strncpy(buffer, wordp, FILSIZ + 1);
+ items[0] = buffer;
+ items[1] = NULL;
+ ptr = items;
+ count = (looking == TW_COMMAND && Strchr(wordp, '/') == 0) ?
+ c_glob(&ptr) :
+ t_glob(&ptr, looking == TW_COMMAND);
+ if (count > 0) {
+ if (command == GLOB)
+ print_by_column(STRNULL, ptr, count, 0);
+ else {
+ DeleteBack(str_end - word_start);/* get rid of old word */
+ for (i = 0; i < count; i++)
+ if (ptr[i] && *ptr[i]) {
+ (void) quote(ptr[i]);
+ if (insert_meta(0, 0, ptr[i], 0) < 0 ||
+ InsertStr(STRspace) < 0) {
+ blkfree(ptr);
+ return -1; /* error inserting */
+ }
+ }
+ }
+ blkfree(ptr);
+ }
+ return count;
+
+ case VARS_EXPAND:
+ if (dollar(buffer, word)) {
+ if (insert_meta(word_start, str_end, buffer, !qu) < 0)
+ return -1; /* error inserting */
+ return 1;
+ }
+ return 0;
+
+ case PATH_NORMALIZE:
+ if ((bptr = dnormalize(wordp, symlinks == SYM_IGNORE ||
+ symlinks == SYM_EXPAND)) != NULL) {
+ (void) Strcpy(buffer, bptr);
+ xfree((ptr_t) bptr);
+ if (insert_meta(word_start, str_end, buffer, !qu) < 0)
+ return -1; /* error inserting */
+ return 1;
+ }
+ return 0;
+
+ case COMMAND_NORMALIZE:
+ if (!cmd_expand(wordp, buffer))
+ return 0;
+ if (insert_meta(word_start, str_end, buffer, !qu) < 0)
+ return -1; /* error inserting */
+ return 1;
+
+ case LIST:
+ case LIST_ALL:
+ search_ret = t_search(wordp, wp, LIST, space_left, looking, 1,
+ pat, suf);
+ return search_ret;
+
+ default:
+ xprintf(CGETS(30, 4, "%s: Internal match error.\n"), progname);
+ return 1;
+
+ }
+} /* end tenematch */
+
+
+/* t_glob():
+ * Return a list of files that match the pattern
+ */
+static int
+t_glob(v, cmd)
+ register Char ***v;
+ int cmd;
+{
+ jmp_buf_t osetexit;
+
+ if (**v == 0)
+ return (0);
+ gflag = 0, tglob(*v);
+ if (gflag) {
+ getexit(osetexit); /* make sure to come back here */
+ if (setexit() == 0)
+ *v = globall(*v);
+ resexit(osetexit);
+ gargv = 0;
+ if (haderr) {
+ haderr = 0;
+ NeedsRedraw = 1;
+ return (-1);
+ }
+ if (*v == 0)
+ return (0);
+ }
+ else
+ return (0);
+
+ if (cmd) {
+ Char **av = *v, *p;
+ int fwd, i, ac = gargc;
+
+ for (i = 0, fwd = 0; i < ac; i++)
+ if (!executable(NULL, av[i], 0)) {
+ fwd++;
+ p = av[i];
+ av[i] = NULL;
+ xfree((ptr_t) p);
+ }
+ else if (fwd)
+ av[i - fwd] = av[i];
+
+ if (fwd)
+ av[i - fwd] = av[i];
+ gargc -= fwd;
+ av[gargc] = NULL;
+ }
+
+ return (gargc);
+} /* end t_glob */
+
+
+/* c_glob():
+ * Return a list of commands that match the pattern
+ */
+static int
+c_glob(v)
+ register Char ***v;
+{
+ Char *pat = **v, *cmd, **av;
+ Char dir[MAXPATHLEN+1];
+ int flag, at, ac;
+
+ if (pat == NULL)
+ return (0);
+
+ ac = 0;
+ at = 10;
+ av = (Char **) xmalloc((size_t) (at * sizeof(Char *)));
+ av[ac] = NULL;
+
+ tw_cmd_start(NULL, NULL);
+ while ((cmd = tw_cmd_next(dir, &flag)) != NULL)
+ if (Gmatch(cmd, pat)) {
+ if (ac + 1 >= at) {
+ at += 10;
+ av = (Char **) xrealloc((ptr_t) av,
+ (size_t) (at * sizeof(Char *)));
+ }
+ av[ac++] = Strsave(cmd);
+ av[ac] = NULL;
+ }
+ tw_dir_end();
+ *v = av;
+
+ return (ac);
+} /* end c_glob */
+
+
+/* insert_meta():
+ * change the word before the cursor.
+ * cp must point to the start of the unquoted word.
+ * cpend to the end of it.
+ * word is the text that has to be substituted.
+ * strategy:
+ * try to keep all the quote characters of the user's input.
+ * change quote type only if necessary.
+ */
+static int
+insert_meta(cp, cpend, word, closequotes)
+ Char *cp;
+ Char *cpend;
+ Char *word;
+ bool closequotes;
+{
+ Char buffer[2 * FILSIZ + 1], *bptr, *wptr;
+ int in_sync = (cp != NULL);
+ int qu = 0;
+ int ndel = (int) (cp ? cpend - cp : 0);
+ Char w, wq;
+
+ for (bptr = buffer, wptr = word;;) {
+ if (bptr > buffer + 2 * FILSIZ - 5)
+ break;
+
+ if (cp >= cpend)
+ in_sync = 0;
+ if (in_sync && !cmap(qu, _ESC) && cmap(*cp, _QF|_ESC))
+ if (qu == 0 || qu == *cp) {
+ qu ^= *cp;
+ *bptr++ = *cp++;
+ continue;
+ }
+ w = *wptr;
+ if (w == 0)
+ break;
+
+ wq = w & QUOTE;
+ w &= ~QUOTE;
+
+ if (cmap(w, _ESC | _QF))
+ wq = QUOTE; /* quotes are always quoted */
+
+ if (!wq && qu && tricky(w) && !(qu == '\"' && tricky_dq(w))) {
+ /* We have to unquote the character */
+ in_sync = 0;
+ if (cmap(qu, _ESC))
+ bptr[-1] = w;
+ else {
+ *bptr++ = (Char) qu;
+ *bptr++ = w;
+ if (wptr[1] == 0)
+ qu = 0;
+ else
+ *bptr++ = (Char) qu;
+ }
+ } else if (qu && w == qu) {
+ in_sync = 0;
+ if (bptr > buffer && bptr[-1] == qu) {
+ /* User misunderstanding :) */
+ bptr[-1] = '\\';
+ *bptr++ = w;
+ qu = 0;
+ } else {
+ *bptr++ = (Char) qu;
+ *bptr++ = '\\';
+ *bptr++ = w;
+ *bptr++ = (Char) qu;
+ }
+ }
+ else if (wq && qu == '\"' && tricky_dq(w)) {
+ in_sync = 0;
+ *bptr++ = (Char) qu;
+ *bptr++ = '\\';
+ *bptr++ = w;
+ *bptr++ = (Char) qu;
+ } else if (wq && ((!qu && (tricky(w) || (w == HISTSUB && bptr == buffer))) || (!cmap(qu, _ESC) && w == HIST))) {
+ in_sync = 0;
+ *bptr++ = '\\';
+ *bptr++ = w;
+ } else {
+ if (in_sync && *cp++ != w)
+ in_sync = 0;
+ *bptr++ = w;
+ }
+ wptr++;
+ if (cmap(qu, _ESC))
+ qu = 0;
+ }
+ if (closequotes && qu && !cmap(qu, _ESC))
+ *bptr++ = (Char) qu;
+ *bptr = '\0';
+ if (ndel)
+ DeleteBack(ndel);
+ return InsertStr(buffer);
+} /* end insert_meta */
+
+
+
+/* is_prefix():
+ * return true if check matches initial chars in template
+ * This differs from PWB imatch in that if check is null
+ * it matches anything
+ */
+static int
+is_prefix(check, template)
+ register Char *check, *template;
+{
+ for (; *check; check++, template++)
+ if ((*check & TRIM) != (*template & TRIM))
+ return (FALSE);
+ return (TRUE);
+} /* end is_prefix */
+
+
+/* is_prefixmatch():
+ * return true if check matches initial chars in template
+ * This differs from PWB imatch in that if check is null
+ * it matches anything
+ * and matches on shortening of commands
+ */
+static int
+is_prefixmatch(check, template, igncase)
+ Char *check, *template;
+ int igncase;
+{
+ Char MCH1, MCH2;
+
+ for (; *check; check++, template++) {
+ if ((*check & TRIM) != (*template & TRIM)) {
+ MCH1 = (*check & TRIM);
+ MCH2 = (*template & TRIM);
+ MCH1 = Isupper(MCH1) ? Tolower(MCH1) : MCH1;
+ MCH2 = Isupper(MCH2) ? Tolower(MCH2) : MCH2;
+ if (MCH1 != MCH2) {
+ if (!igncase && ((*check & TRIM) == '-' ||
+ (*check & TRIM) == '.' ||
+ (*check & TRIM) == '_')) {
+ MCH1 = MCH2 = (*check & TRIM);
+ if (MCH1 == '_') {
+ MCH2 = '-';
+ } else if (MCH1 == '-') {
+ MCH2 = '_';
+ }
+ for (;*template && (*template & TRIM) != MCH1 &&
+ (*template & TRIM) != MCH2; template++)
+ continue;
+ if (!*template) {
+ return (FALSE);
+ }
+ } else {
+ return (FALSE);
+ }
+ }
+ }
+ }
+ return (TRUE);
+} /* end is_prefixmatch */
+
+
+/* is_suffix():
+ * Return true if the chars in template appear at the
+ * end of check, I.e., are it's suffix.
+ */
+static int
+is_suffix(check, template)
+ register Char *check, *template;
+{
+ register Char *t, *c;
+
+ for (t = template; *t++;)
+ continue;
+ for (c = check; *c++;)
+ continue;
+ for (;;) {
+ if (t == template)
+ return 1;
+ if (c == check || (*--t & TRIM) != (*--c & TRIM))
+ return 0;
+ }
+} /* end is_suffix */
+
+
+/* ignored():
+ * Return true if this is an ignored item
+ */
+static int
+ignored(item)
+ register Char *item;
+{
+ struct varent *vp;
+ register Char **cp;
+
+ if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
+ return (FALSE);
+ for (; *cp != NULL; cp++)
+ if (is_suffix(item, *cp))
+ return (TRUE);
+ return (FALSE);
+} /* end ignored */
+
+
+
+/* starting_a_command():
+ * return true if the command starting at wordstart is a command
+ */
+int
+starting_a_command(wordstart, inputline)
+ register Char *wordstart, *inputline;
+{
+ register Char *ptr, *ncmdstart;
+ int count;
+ static Char
+ cmdstart[] = {'`', ';', '&', '(', '|', '\0'},
+ cmdalive[] = {' ', '\t', '\'', '"', '<', '>', '\0'};
+
+ /*
+ * Find if the number of backquotes is odd or even.
+ */
+ for (ptr = wordstart, count = 0;
+ ptr >= inputline;
+ count += (*ptr-- == '`'))
+ continue;
+ /*
+ * if the number of backquotes is even don't include the backquote char in
+ * the list of command starting delimiters [if it is zero, then it does not
+ * matter]
+ */
+ ncmdstart = cmdstart + EVEN(count);
+
+ /*
+ * look for the characters previous to this word if we find a command
+ * starting delimiter we break. if we find whitespace and another previous
+ * word then we are not a command
+ *
+ * count is our state machine: 0 looking for anything 1 found white-space
+ * looking for non-ws
+ */
+ for (count = 0; wordstart >= inputline; wordstart--) {
+ if (*wordstart == '\0')
+ continue;
+ if (Strchr(ncmdstart, *wordstart))
+ break;
+ /*
+ * found white space
+ */
+ if ((ptr = Strchr(cmdalive, *wordstart)) != NULL)
+ count = 1;
+ if (count == 1 && !ptr)
+ return (FALSE);
+ }
+
+ if (wordstart > inputline)
+ switch (*wordstart) {
+ case '&': /* Look for >& */
+ while (wordstart > inputline &&
+ (*--wordstart == ' ' || *wordstart == '\t'))
+ continue;
+ if (*wordstart == '>')
+ return (FALSE);
+ break;
+ case '(': /* check for foreach, if etc. */
+ while (wordstart > inputline &&
+ (*--wordstart == ' ' || *wordstart == '\t'))
+ continue;
+ if (!iscmdmeta(*wordstart) &&
+ (*wordstart != ' ' && *wordstart != '\t'))
+ return (FALSE);
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+} /* end starting_a_command */
+
+
+/* recognize():
+ * Object: extend what user typed up to an ambiguity.
+ * Algorithm:
+ * On first match, copy full item (assume it'll be the only match)
+ * On subsequent matches, shorten exp_name to the first
+ * character mismatch between exp_name and item.
+ * If we shorten it back to the prefix length, stop searching.
+ */
+static int
+recognize(exp_name, item, name_length, numitems, enhanced)
+ Char *exp_name, *item;
+ int name_length, numitems, enhanced;
+{
+ Char MCH1, MCH2;
+ register Char *x, *ent;
+ register int len = 0;
+#ifdef WINNT
+ struct varent *vp;
+ int igncase;
+ igncase = (vp = adrof(STRcomplete)) != NULL &&
+ Strcmp(*(vp->vec), STRigncase) == 0;
+#endif /* WINNT */
+
+ if (numitems == 1) { /* 1st match */
+ copyn(exp_name, item, MAXNAMLEN);
+ return (0);
+ }
+ if (!enhanced
+#ifdef WINNT
+ && !igncase
+#endif /* WINNT */
+ ) {
+ for (x = exp_name, ent = item; *x && (*x & TRIM) == (*ent & TRIM); x++, ent++)
+ len++;
+ } else {
+ for (x = exp_name, ent = item; *x; x++, ent++) {
+ MCH1 = *x & TRIM;
+ MCH2 = *ent & TRIM;
+ MCH1 = Isupper(MCH1) ? Tolower(MCH1) : MCH1;
+ MCH2 = Isupper(MCH2) ? Tolower(MCH2) : MCH2;
+ if (MCH1 != MCH2)
+ break;
+ len++;
+ }
+ if (*x || !*ent) /* Shorter or exact match */
+ copyn(exp_name, item, MAXNAMLEN);
+ }
+ *x = '\0'; /* Shorten at 1st char diff */
+ if (!(match_unique_match || is_set(STRrecexact) || (enhanced && *ent)) && len == name_length) /* Ambiguous to prefix? */
+ return (-1); /* So stop now and save time */
+ return (0);
+} /* end recognize */
+
+
+/* tw_collect_items():
+ * Collect items that match target.
+ * SPELL command:
+ * Returns the spelling distance of the closest match.
+ * else
+ * Returns the number of items found.
+ * If none found, but some ignored items were found,
+ * It returns the -number of ignored items.
+ */
+static int
+tw_collect_items(command, looking, exp_dir, exp_name, target, pat, flags)
+ COMMAND command;
+ int looking;
+ Char *exp_dir, *exp_name, *target, *pat;
+ int flags;
+
+{
+ int done = FALSE; /* Search is done */
+ int showdots; /* Style to show dot files */
+ int nignored = 0; /* Number of fignored items */
+ int numitems = 0; /* Number of matched items */
+ int name_length = (int) Strlen(target); /* Length of prefix (file name) */
+ int exec_check = flags & TW_EXEC_CHK;/* need to check executability */
+ int dir_check = flags & TW_DIR_CHK; /* Need to check for directories */
+ int text_check = flags & TW_TEXT_CHK;/* Need to check for non-directories */
+ int dir_ok = flags & TW_DIR_OK; /* Ignore directories? */
+ int gpat = flags & TW_PAT_OK; /* Match against a pattern */
+ int ignoring = flags & TW_IGN_OK; /* Use fignore? */
+ int d = 4, nd; /* Spelling distance */
+ Char *item, *ptr;
+ Char buf[MAXPATHLEN+1];
+ struct varent *vp;
+ int len, enhanced;
+ int cnt = 0;
+ int igncase = 0;
+
+
+ flags = 0;
+
+ showdots = DOT_NONE;
+ if ((ptr = varval(STRlistflags)) != STRNULL)
+ while (*ptr)
+ switch (*ptr++) {
+ case 'a':
+ showdots = DOT_ALL;
+ break;
+ case 'A':
+ showdots = DOT_NOT;
+ break;
+ default:
+ break;
+ }
+
+ while (!done && (item = (*tw_next_entry[looking])(exp_dir, &flags))) {
+#ifdef TDEBUG
+ xprintf("item = %S\n", item);
+#endif
+ switch (looking) {
+ case TW_FILE:
+ case TW_DIRECTORY:
+ case TW_TEXT:
+ /*
+ * Don't match . files on null prefix match
+ */
+ if (showdots == DOT_NOT && (ISDOT(item) || ISDOTDOT(item)))
+ done = TRUE;
+ if (name_length == 0 && item[0] == '.' && showdots == DOT_NONE)
+ done = TRUE;
+ break;
+
+ case TW_COMMAND:
+ exec_check = flags & TW_EXEC_CHK;
+ dir_ok = flags & TW_DIR_OK;
+ break;
+
+ default:
+ break;
+ }
+
+ if (done) {
+ done = FALSE;
+ continue;
+ }
+
+ switch (command) {
+
+ case SPELL: /* correct the spelling of the last bit */
+ if (name_length == 0) {/* zero-length word can't be misspelled */
+ exp_name[0] = '\0';/* (not trying is important for ~) */
+ d = 0;
+ done = TRUE;
+ break;
+ }
+ if (gpat && !Gmatch(item, pat))
+ break;
+ /*
+ * Swapped the order of the spdist() arguments as suggested
+ * by eeide@asylum.cs.utah.edu (Eric Eide)
+ */
+ nd = spdist(target, item); /* test the item against original */
+ if (nd <= d && nd != 4) {
+ if (!(exec_check && !executable(exp_dir, item, dir_ok))) {
+ (void) Strcpy(exp_name, item);
+ d = nd;
+ if (d == 0) /* if found it exactly */
+ done = TRUE;
+ }
+ }
+ else if (nd == 4) {
+ if (spdir(exp_name, exp_dir, item, target)) {
+ if (exec_check && !executable(exp_dir, exp_name, dir_ok))
+ break;
+#ifdef notdef
+ /*
+ * We don't want to stop immediately, because
+ * we might find an exact/better match later.
+ */
+ d = 0;
+ done = TRUE;
+#endif
+ d = 3;
+ }
+ }
+ break;
+
+ case LIST:
+ case RECOGNIZE:
+ case RECOGNIZE_ALL:
+ case RECOGNIZE_SCROLL:
+
+#ifdef WINNT
+ igncase = (vp = adrof(STRcomplete)) != NULL &&
+ Strcmp(*(vp->vec), STRigncase) == 0;
+#endif /* WINNT */
+ enhanced = (vp = adrof(STRcomplete)) != NULL && !Strcmp(*(vp->vec),STRenhance);
+ if (enhanced || igncase) {
+ if (!is_prefixmatch(target, item, igncase))
+ break;
+ } else {
+ if (!is_prefix(target, item))
+ break;
+ }
+
+ if (exec_check && !executable(exp_dir, item, dir_ok))
+ break;
+
+ if (dir_check && !isadirectory(exp_dir, item))
+ break;
+
+ if (text_check && isadirectory(exp_dir, item))
+ break;
+
+ /*
+ * Only pattern match directories if we're checking
+ * for directories.
+ */
+ if (gpat && !Gmatch(item, pat) &&
+ (dir_check || !isadirectory(exp_dir, item)))
+ break;
+
+ /*
+ * Remove duplicates in command listing and completion
+ * AFEB added code for TW_LOGNAME and TW_USER cases
+ */
+ if (looking == TW_COMMAND || looking == TW_LOGNAME
+ || looking == TW_USER || command == LIST) {
+ copyn(buf, item, MAXPATHLEN);
+ len = (int) Strlen(buf);
+ switch (looking) {
+ case TW_COMMAND:
+ if (!(dir_ok && exec_check))
+ break;
+ if (filetype(exp_dir, item) == '/') {
+ buf[len++] = '/';
+ buf[len] = '\0';
+ }
+ break;
+
+ case TW_FILE:
+ case TW_DIRECTORY:
+ buf[len++] = filetype(exp_dir, item);
+ buf[len] = '\0';
+ break;
+
+ default:
+ break;
+ }
+ if ((looking == TW_COMMAND || looking == TW_USER
+ || looking == TW_LOGNAME) && tw_item_find(buf))
+ break;
+ else {
+ /* maximum length 1 (NULL) + 1 (~ or $) + 1 (filetype) */
+ ptr = tw_item_add(len + 3);
+ copyn(ptr, buf, MAXPATHLEN);
+ if (command == LIST)
+ numitems++;
+ }
+ }
+
+ if (command == RECOGNIZE || command == RECOGNIZE_ALL ||
+ command == RECOGNIZE_SCROLL) {
+ if (ignoring && ignored(item)) {
+ nignored++;
+ break;
+ }
+ else if (command == RECOGNIZE_SCROLL) {
+ add_scroll_tab(item);
+ cnt++;
+ }
+
+ if (match_unique_match || is_set(STRrecexact)) {
+ if (StrQcmp(target, item) == 0) { /* EXACT match */
+ copyn(exp_name, item, MAXNAMLEN);
+ numitems = 1; /* fake into expanding */
+ non_unique_match = TRUE;
+ done = TRUE;
+ break;
+ }
+ }
+ if (recognize(exp_name, item, name_length, ++numitems, enhanced))
+ if (command != RECOGNIZE_SCROLL)
+ done = TRUE;
+ if (enhanced && (int)Strlen(exp_name) < name_length)
+ copyn(exp_name, target, MAXNAMLEN);
+ }
+ break;
+
+ default:
+ break;
+ }
+#ifdef TDEBUG
+ xprintf("done item = %S\n", item);
+#endif
+ }
+
+
+ if (command == RECOGNIZE_SCROLL) {
+ if ((cnt <= curchoice) || (curchoice == -1)) {
+ curchoice = -1;
+ nignored = 0;
+ numitems = 0;
+ } else if (numitems > 1) {
+ if (curchoice < -1)
+ curchoice = cnt - 1;
+ choose_scroll_tab(&exp_name, cnt);
+ numitems = 1;
+ }
+ }
+ free_scroll_tab();
+
+ if (command == SPELL)
+ return d;
+ else {
+ if (ignoring && numitems == 0 && nignored > 0)
+ return -nignored;
+ else
+ return numitems;
+ }
+}
+
+
+/* tw_suffix():
+ * Find and return the appropriate suffix character
+ */
+/*ARGSUSED*/
+static Char
+tw_suffix(looking, exp_dir, exp_name, target, name)
+ int looking;
+ Char *exp_dir, *exp_name, *target, *name;
+{
+ Char *ptr;
+ struct varent *vp;
+
+ USE(name);
+ (void) strip(exp_name);
+
+ switch (looking) {
+
+ case TW_LOGNAME:
+ return '/';
+
+ case TW_VARIABLE:
+ /*
+ * Don't consider array variables or empty variables
+ */
+ if ((vp = adrof(exp_name)) != NULL) {
+ if ((ptr = vp->vec[0]) == NULL || *ptr == '\0' ||
+ vp->vec[1] != NULL)
+ return ' ';
+ }
+ else if ((ptr = tgetenv(exp_name)) == NULL || *ptr == '\0')
+ return ' ';
+
+ *--target = '\0';
+
+ return isadirectory(exp_dir, ptr) ? '/' : ' ';
+
+
+ case TW_DIRECTORY:
+ return '/';
+
+ case TW_COMMAND:
+ case TW_FILE:
+ return isadirectory(exp_dir, exp_name) ? '/' : ' ';
+
+ case TW_ALIAS:
+ case TW_VARLIST:
+ case TW_WORDLIST:
+ case TW_SHELLVAR:
+ case TW_ENVVAR:
+ case TW_USER:
+ case TW_BINDING:
+ case TW_LIMIT:
+ case TW_SIGNAL:
+ case TW_JOB:
+ case TW_COMPLETION:
+ case TW_TEXT:
+ case TW_GRPNAME:
+ return ' ';
+
+ default:
+ return '\0';
+ }
+} /* end tw_suffix */
+
+
+/* tw_fixword():
+ * Repair a word after a spalling or a recognizwe
+ */
+static void
+tw_fixword(looking, word, dir, exp_name, max_word_length)
+ int looking;
+ Char *word, *dir, *exp_name;
+ int max_word_length;
+{
+ Char *ptr;
+
+ switch (looking) {
+ case TW_LOGNAME:
+ copyn(word, STRtilde, 1);
+ break;
+
+ case TW_VARIABLE:
+ if ((ptr = Strrchr(word, '$')) != NULL)
+ *++ptr = '\0'; /* Delete after the dollar */
+ else
+ word[0] = '\0';
+ break;
+
+ case TW_DIRECTORY:
+ case TW_FILE:
+ case TW_TEXT:
+ copyn(word, dir, max_word_length); /* put back dir part */
+ break;
+
+ default:
+ word[0] = '\0';
+ break;
+ }
+
+ (void) quote(exp_name);
+ catn(word, exp_name, max_word_length); /* add extended name */
+} /* end tw_fixword */
+
+
+/* tw_collect():
+ * Collect items. Return -1 in case we were interrupted or
+ * the return value of tw_collect
+ * This is really a wrapper for tw_collect_items, serving two
+ * purposes:
+ * 1. Handles interrupt cleanups.
+ * 2. Retries if we had no matches, but there were ignored matches
+ */
+static int
+tw_collect(command, looking, exp_dir, exp_name, target, pat, flags, dir_fd)
+ COMMAND command;
+ int looking;
+ Char *exp_dir, *exp_name, **target, *pat;
+ int flags;
+ DIR *dir_fd;
+{
+ static int ni; /* static so we don't get clobbered */
+ jmp_buf_t osetexit;
+
+#ifdef TDEBUG
+ xprintf("target = %S\n", *target);
+#endif
+ ni = 0;
+ getexit(osetexit);
+ for (;;) {
+ (*tw_start_entry[looking])(dir_fd, pat);
+ InsideCompletion = 1;
+ if (setexit()) {
+ /* interrupted, clean up */
+ resexit(osetexit);
+ InsideCompletion = 0;
+ haderr = 0;
+
+#if defined(SOLARIS2) && defined(i386) && !defined(__GNUC__)
+ /* Compiler bug? (from PWP) */
+ if ((looking == TW_LOGNAME) || (looking == TW_USER))
+ tw_logname_end();
+ else
+ if (looking == TW_GRPNAME)
+ tw_grpname_end();
+ else
+ tw_dir_end();
+#else /* !(SOLARIS2 && i386 && !__GNUC__) */
+ (*tw_end_entry[looking])();
+#endif /* !(SOLARIS2 && i386 && !__GNUC__) */
+
+ /* flag error */
+ return(-1);
+ }
+ if ((ni = tw_collect_items(command, looking, exp_dir, exp_name,
+ *target, pat,
+ ni >= 0 ? flags :
+ flags & ~TW_IGN_OK)) >= 0) {
+ resexit(osetexit);
+ InsideCompletion = 0;
+
+#if defined(SOLARIS2) && defined(i386) && !defined(__GNUC__)
+ /* Compiler bug? (from PWP) */
+ if ((looking == TW_LOGNAME) || (looking == TW_USER))
+ tw_logname_end();
+ else
+ if (looking == TW_GRPNAME)
+ tw_grpname_end();
+ else
+ tw_dir_end();
+#else /* !(SOLARIS2 && i386 && !__GNUC__) */
+ (*tw_end_entry[looking])();
+#endif /* !(SOLARIS2 && i386 && !__GNUC__) */
+
+ return(ni);
+ }
+ }
+} /* end tw_collect */
+
+
+/* tw_list_items():
+ * List the items that were found
+ *
+ * NOTE instead of looking at numerical vars listmax and listmaxrows
+ * we can look at numerical var listmax, and have a string value
+ * listmaxtype (or similar) than can have values 'items' and 'rows'
+ * (by default interpreted as 'items', for backwards compatibility)
+ */
+static void
+tw_list_items(looking, numitems, list_max)
+ int looking, numitems, list_max;
+{
+ Char *ptr;
+ int max_items = 0;
+ int max_rows = 0;
+
+ if ((ptr = varval(STRlistmax)) != STRNULL) {
+ while (*ptr) {
+ if (!Isdigit(*ptr)) {
+ max_items = 0;
+ break;
+ }
+ max_items = max_items * 10 + *ptr++ - '0';
+ }
+ if ((max_items > 0) && (numitems > max_items) && list_max)
+ max_items = numitems;
+ else
+ max_items = 0;
+ }
+
+ if (max_items == 0 && (ptr = varval(STRlistmaxrows)) != STRNULL) {
+ int rows;
+
+ while (*ptr) {
+ if (!Isdigit(*ptr)) {
+ max_rows = 0;
+ break;
+ }
+ max_rows = max_rows * 10 + *ptr++ - '0';
+ }
+ if (max_rows != 0 && looking != TW_JOB)
+ rows = find_rows(tw_item_get(), numitems, TRUE);
+ else
+ rows = numitems; /* underestimate for lines wider than the termH */
+ if ((max_rows > 0) && (rows > max_rows) && list_max)
+ max_rows = rows;
+ else
+ max_rows = 0;
+ }
+
+
+ if (max_items || max_rows) {
+ char tc;
+ const char *name;
+ int maxs;
+
+ if (max_items) {
+ name = CGETS(30, 5, "items");
+ maxs = max_items;
+ }
+ else {
+ name = CGETS(30, 6, "rows");
+ maxs = max_rows;
+ }
+
+ xprintf(CGETS(30, 7, "There are %d %s, list them anyway? [n/y] "),
+ maxs, name);
+ flush();
+ /* We should be in Rawmode here, so no \n to catch */
+ (void) read(SHIN, &tc, 1);
+ xprintf("%c\r\n", tc); /* echo the char, do a newline */
+ /*
+ * Perhaps we should use the yesexpr from the
+ * actual locale
+ */
+ if (strchr(CGETS(30, 13, "Yy"), tc) == NULL)
+ return;
+ }
+
+ if (looking != TW_SIGNAL)
+ qsort((ptr_t) tw_item_get(), (size_t) numitems, sizeof(Char *),
+ (int (*) __P((const void *, const void *))) fcompare);
+ if (looking != TW_JOB)
+ print_by_column(STRNULL, tw_item_get(), numitems, TRUE);
+ else {
+ /*
+ * print one item on every line because jobs can have spaces
+ * and it is confusing.
+ */
+ int i;
+ Char **w = tw_item_get();
+
+ for (i = 0; i < numitems; i++) {
+ xprintf("%S", w[i]);
+ if (Tty_raw_mode)
+ xputchar('\r');
+ xputchar('\n');
+ }
+ }
+} /* end tw_list_items */
+
+
+/* t_search():
+ * Perform a RECOGNIZE, LIST or SPELL command on string "word".
+ *
+ * Return value:
+ * >= 0: SPELL command: "distance" (see spdist())
+ * other: No. of items found
+ * < 0: Error (message or beep is output)
+ */
+/*ARGSUSED*/
+int
+t_search(word, wp, command, max_word_length, looking, list_max, pat, suf)
+ Char *word, *wp; /* original end-of-word */
+ COMMAND command;
+ int max_word_length, looking, list_max;
+ Char *pat;
+ int suf;
+{
+ int numitems, /* Number of items matched */
+ flags = 0, /* search flags */
+ gpat = pat[0] != '\0', /* Glob pattern search */
+ nd; /* Normalized directory return */
+ Char exp_dir[FILSIZ + 1], /* dir after ~ expansion */
+ dir[FILSIZ + 1], /* /x/y/z/ part in /x/y/z/f */
+ exp_name[MAXNAMLEN + 1], /* the recognized (extended) */
+ name[MAXNAMLEN + 1], /* f part in /d/d/d/f name */
+ *target; /* Target to expand/correct/list */
+ DIR *dir_fd = NULL;
+
+ USE(wp);
+
+ /*
+ * bugfix by Marty Grossman (grossman@CC5.BBN.COM): directory listing can
+ * dump core when interrupted
+ */
+ tw_item_free();
+
+ non_unique_match = FALSE; /* See the recexact code below */
+
+ extract_dir_and_name(word, dir, name);
+
+ /*
+ * SPECIAL HARDCODED COMPLETIONS:
+ * foo$variable -> TW_VARIABLE
+ * ~user -> TW_LOGNAME
+ *
+ */
+ if ((*word == '~') && (Strchr(word, '/') == NULL)) {
+ looking = TW_LOGNAME;
+ target = name;
+ gpat = 0; /* Override pattern mechanism */
+ }
+ else if ((target = Strrchr(name, '$')) != 0 &&
+ (Strchr(name, '/') == NULL)) {
+ target++;
+ looking = TW_VARIABLE;
+ gpat = 0; /* Override pattern mechanism */
+ }
+ else
+ target = name;
+
+ /*
+ * Try to figure out what we should be looking for
+ */
+ if (looking & TW_PATH) {
+ gpat = 0; /* pattern holds the pathname to be used */
+ copyn(exp_dir, pat, MAXNAMLEN);
+ if (exp_dir[Strlen(exp_dir) - 1] != '/')
+ catn(exp_dir, STRslash, MAXNAMLEN);
+ catn(exp_dir, dir, MAXNAMLEN);
+ }
+ else
+ exp_dir[0] = '\0';
+
+ switch (looking & ~TW_PATH) {
+ case TW_NONE:
+ return -1;
+
+ case TW_ZERO:
+ looking = TW_FILE;
+ break;
+
+ case TW_COMMAND:
+ if (Strchr(word, '/') || (looking & TW_PATH)) {
+ looking = TW_FILE;
+ flags |= TW_EXEC_CHK;
+ flags |= TW_DIR_OK;
+ }
+#ifdef notdef
+ /* PWP: don't even bother when doing ALL of the commands */
+ if (looking == TW_COMMAND && (*word == '\0'))
+ return (-1);
+#endif
+ break;
+
+
+ case TW_VARLIST:
+ case TW_WORDLIST:
+ gpat = 0; /* pattern holds the name of the variable */
+ break;
+
+ case TW_EXPLAIN:
+ if (command == LIST && pat != NULL) {
+ xprintf("%S", pat);
+ if (Tty_raw_mode)
+ xputchar('\r');
+ xputchar('\n');
+ }
+ return 2;
+
+ default:
+ break;
+ }
+
+ /*
+ * let fignore work only when we are not using a pattern
+ */
+ flags |= (gpat == 0) ? TW_IGN_OK : TW_PAT_OK;
+
+#ifdef TDEBUG
+ xprintf(CGETS(30, 8, "looking = %d\n"), looking);
+#endif
+
+ switch (looking) {
+ case TW_ALIAS:
+ case TW_SHELLVAR:
+ case TW_ENVVAR:
+ case TW_BINDING:
+ case TW_LIMIT:
+ case TW_SIGNAL:
+ case TW_JOB:
+ case TW_COMPLETION:
+ case TW_GRPNAME:
+ break;
+
+
+ case TW_VARIABLE:
+ if ((nd = expand_dir(dir, exp_dir, &dir_fd, command)) != 0)
+ return nd;
+ break;
+
+ case TW_DIRECTORY:
+ flags |= TW_DIR_CHK;
+
+#ifdef notyet
+ /*
+ * This is supposed to expand the directory stack.
+ * Problems:
+ * 1. Slow
+ * 2. directories with the same name
+ */
+ flags |= TW_DIR_OK;
+#endif
+#ifdef notyet
+ /*
+ * Supposed to do delayed expansion, but it is inconsistent
+ * from a user-interface point of view, since it does not
+ * immediately obey addsuffix
+ */
+ if ((nd = expand_dir(dir, exp_dir, &dir_fd, command)) != 0)
+ return nd;
+ if (isadirectory(exp_dir, name)) {
+ if (exp_dir[0] != '\0' || name[0] != '\0') {
+ catn(dir, name, MAXNAMLEN);
+ if (dir[Strlen(dir) - 1] != '/')
+ catn(dir, STRslash, MAXNAMLEN);
+ if ((nd = expand_dir(dir, exp_dir, &dir_fd, command)) != 0)
+ return nd;
+ if (word[Strlen(word) - 1] != '/')
+ catn(word, STRslash, MAXNAMLEN);
+ name[0] = '\0';
+ }
+ }
+#endif
+ if ((nd = expand_dir(dir, exp_dir, &dir_fd, command)) != 0)
+ return nd;
+ break;
+
+ case TW_TEXT:
+ flags |= TW_TEXT_CHK;
+ /*FALLTHROUGH*/
+ case TW_FILE:
+ if ((nd = expand_dir(dir, exp_dir, &dir_fd, command)) != 0)
+ return nd;
+ break;
+
+ case TW_PATH | TW_TEXT:
+ case TW_PATH | TW_FILE:
+ case TW_PATH | TW_DIRECTORY:
+ case TW_PATH | TW_COMMAND:
+ if ((dir_fd = opendir(short2str(exp_dir))) == NULL) {
+ xprintf("%S: %s\n", exp_dir, strerror(errno));
+ return -1;
+ }
+ if (exp_dir[Strlen(exp_dir) - 1] != '/')
+ catn(exp_dir, STRslash, MAXNAMLEN);
+
+ looking &= ~TW_PATH;
+
+ switch (looking) {
+ case TW_TEXT:
+ flags |= TW_TEXT_CHK;
+ break;
+
+ case TW_FILE:
+ break;
+
+ case TW_DIRECTORY:
+ flags |= TW_DIR_CHK;
+ break;
+
+ case TW_COMMAND:
+ copyn(target, word, MAXNAMLEN); /* so it can match things */
+ break;
+
+ default:
+ abort(); /* Cannot happen */
+ break;
+ }
+ break;
+
+ case TW_LOGNAME:
+ word++;
+ /*FALLTHROUGH*/
+ case TW_USER:
+ /*
+ * Check if the spelling was already correct
+ * From: Rob McMahon <cudcv@cu.warwick.ac.uk>
+ */
+ if (command == SPELL && getpwnam(short2str(word)) != NULL) {
+#ifdef YPBUGS
+ fix_yp_bugs();
+#endif /* YPBUGS */
+ return (0);
+ }
+ copyn(name, word, MAXNAMLEN); /* name sans ~ */
+ if (looking == TW_LOGNAME)
+ word--;
+ break;
+
+ case TW_COMMAND:
+ case TW_VARLIST:
+ case TW_WORDLIST:
+ copyn(target, word, MAXNAMLEN); /* so it can match things */
+ break;
+
+ default:
+ xprintf(CGETS(30, 9,
+ "\n%s internal error: I don't know what I'm looking for!\n"),
+ progname);
+ NeedsRedraw = 1;
+ return (-1);
+ }
+
+ numitems = tw_collect(command, looking, exp_dir, exp_name,
+ &target, pat, flags, dir_fd);
+ if (numitems == -1)
+ return -1;
+
+ switch (command) {
+ case RECOGNIZE:
+ case RECOGNIZE_ALL:
+ case RECOGNIZE_SCROLL:
+ if (numitems <= 0)
+ return (numitems);
+
+ tw_fixword(looking, word, dir, exp_name, max_word_length);
+
+ if (!match_unique_match && is_set(STRaddsuffix) && numitems == 1) {
+ Char suffix[2];
+
+ suffix[1] = '\0';
+ switch (suf) {
+ case 0: /* Automatic suffix */
+ suffix[0] = tw_suffix(looking, exp_dir, exp_name, target, name);
+ break;
+
+ case -1: /* No suffix */
+ return numitems;
+
+ default: /* completion specified suffix */
+ suffix[0] = (Char) suf;
+ break;
+ }
+ catn(word, suffix, max_word_length);
+ }
+ return numitems;
+
+ case LIST:
+ tw_list_items(looking, numitems, list_max);
+ tw_item_free();
+ return (numitems);
+
+ case SPELL:
+ tw_fixword(looking, word, dir, exp_name, max_word_length);
+ return (numitems);
+
+ default:
+ xprintf("Bad tw_command\n");
+ return (0);
+ }
+} /* end t_search */
+
+
+/* extract_dir_and_name():
+ * parse full path in file into 2 parts: directory and file names
+ * Should leave final slash (/) at end of dir.
+ */
+static void
+extract_dir_and_name(path, dir, name)
+ Char *path, *dir, *name;
+{
+ register Char *p;
+
+ p = Strrchr(path, '/');
+#ifdef WINNT
+ if (p == NULL)
+ p = Strrchr(path, ':');
+#endif /* WINNT */
+ if (p == NULL) {
+ copyn(name, path, MAXNAMLEN);
+ dir[0] = '\0';
+ }
+ else {
+ p++;
+ copyn(name, p, MAXNAMLEN);
+ copyn(dir, path, p - path);
+ }
+} /* end extract_dir_and_name */
+
+
+/* dollar():
+ * expand "/$old1/$old2/old3/"
+ * to "/value_of_old1/value_of_old2/old3/"
+ */
+Char *
+dollar(new, old)
+ Char *new;
+ const Char *old;
+{
+ Char *p;
+ size_t space;
+
+ for (space = FILSIZ, p = new; *old && space > 0;)
+ if (*old != '$') {
+ *p++ = *old++;
+ space--;
+ }
+ else {
+ if (expdollar(&p, &old, &space, QUOTE) == NULL)
+ return NULL;
+ }
+ *p = '\0';
+ return (new);
+} /* end dollar */
+
+
+/* tilde():
+ * expand ~person/foo to home_directory_of_person/foo
+ * or =<stack-entry> to <dir in stack entry>
+ */
+static Char *
+tilde(new, old)
+ Char *new, *old;
+{
+ register Char *o, *p;
+
+ switch (old[0]) {
+ case '~':
+ for (p = new, o = &old[1]; *o && *o != '/'; *p++ = *o++)
+ continue;
+ *p = '\0';
+ if (gethdir(new)) {
+ new[0] = '\0';
+ return NULL;
+ }
+ (void) Strcat(new, o);
+ return new;
+
+ case '=':
+ if ((p = globequal(new, old)) == NULL) {
+ *new = '\0';
+ return NULL;
+ }
+ if (p == new)
+ return new;
+ /*FALLTHROUGH*/
+
+ default:
+ (void) Strcpy(new, old);
+ return new;
+ }
+} /* end tilde */
+
+
+/* expand_dir():
+ * Open the directory given, expanding ~user and $var
+ * Optionally normalize the path given
+ */
+static int
+expand_dir(dir, edir, dfd, cmd)
+ Char *dir, *edir;
+ DIR **dfd;
+ COMMAND cmd;
+{
+ Char *nd = NULL;
+ Char tdir[MAXPATHLEN + 1];
+
+ if ((dollar(tdir, dir) == 0) ||
+ (tilde(edir, tdir) == 0) ||
+ !(nd = dnormalize(*edir ? edir : STRdot, symlinks == SYM_IGNORE ||
+ symlinks == SYM_EXPAND)) ||
+ ((*dfd = opendir(short2str(nd))) == NULL)) {
+ xfree((ptr_t) nd);
+ if (cmd == SPELL || SearchNoDirErr)
+ return (-2);
+ /*
+ * From: Amos Shapira <amoss@cs.huji.ac.il>
+ * Print a better message when completion fails
+ */
+ xprintf("\n%S %s\n",
+ *edir ? edir :
+ (*tdir ? tdir : dir),
+ (errno == ENOTDIR ? CGETS(30, 10, "not a directory") :
+ (errno == ENOENT ? CGETS(30, 11, "not found") :
+ CGETS(30, 12, "unreadable"))));
+ NeedsRedraw = 1;
+ return (-1);
+ }
+ if (nd) {
+ if (*dir != '\0') {
+ Char *s, *d, *p;
+
+ /*
+ * Copy and append a / if there was one
+ */
+ for (p = edir; *p; p++)
+ continue;
+ if (*--p == '/') {
+ for (p = nd; *p; p++)
+ continue;
+ if (*--p != '/')
+ p = NULL;
+ }
+ for (d = edir, s = nd; (*d++ = *s++) != '\0';)
+ continue;
+ if (!p) {
+ *d-- = '\0';
+ *d = '/';
+ }
+ }
+ xfree((ptr_t) nd);
+ }
+ return 0;
+} /* end expand_dir */
+
+
+/* nostat():
+ * Returns true if the directory should not be stat'd,
+ * false otherwise.
+ * This way, things won't grind to a halt when you complete in /afs
+ * or very large directories.
+ */
+static bool
+nostat(dir)
+ Char *dir;
+{
+ struct varent *vp;
+ register Char **cp;
+
+ if ((vp = adrof(STRnostat)) == NULL || (cp = vp->vec) == NULL)
+ return FALSE;
+ for (; *cp != NULL; cp++) {
+ if (Strcmp(*cp, STRstar) == 0)
+ return TRUE;
+ if (Gmatch(dir, *cp))
+ return TRUE;
+ }
+ return FALSE;
+} /* end nostat */
+
+
+/* filetype():
+ * Return a character that signifies a filetype
+ * symbology from 4.3 ls command.
+ */
+static Char
+filetype(dir, file)
+ Char *dir, *file;
+{
+ if (dir) {
+ Char path[512];
+ char *ptr;
+ struct stat statb;
+#ifdef S_ISCDF
+ /*
+ * From: veals@crchh84d.bnr.ca (Percy Veals)
+ * An extra stat is required for HPUX CDF files.
+ */
+ struct stat hpstatb;
+#endif /* S_ISCDF */
+
+ if (nostat(dir)) return(' ');
+
+ (void) Strcpy(path, dir);
+ catn(path, file, (int) (sizeof(path) / sizeof(Char)));
+
+ if (lstat(ptr = short2str(path), &statb) != -1)
+ /* see above #define of lstat */
+ {
+#ifdef S_ISLNK
+ if (S_ISLNK(statb.st_mode)) { /* Symbolic link */
+ if (adrof(STRlistlinks)) {
+ if (stat(ptr, &statb) == -1)
+ return ('&');
+ else if (S_ISDIR(statb.st_mode))
+ return ('>');
+ else
+ return ('@');
+ }
+ else
+ return ('@');
+ }
+#endif
+#ifdef S_ISSOCK
+ if (S_ISSOCK(statb.st_mode)) /* Socket */
+ return ('=');
+#endif
+#ifdef S_ISFIFO
+ if (S_ISFIFO(statb.st_mode)) /* Named Pipe */
+ return ('|');
+#endif
+#ifdef S_ISHIDDEN
+ if (S_ISHIDDEN(statb.st_mode)) /* Hidden Directory [aix] */
+ return ('+');
+#endif
+#ifdef S_ISCDF
+ (void) strcat(ptr, "+"); /* Must append a '+' and re-stat(). */
+ if ((stat(ptr, &hpstatb) != -1) && S_ISCDF(hpstatb.st_mode))
+ return ('+'); /* Context Dependent Files [hpux] */
+#endif
+#ifdef S_ISNWK
+ if (S_ISNWK(statb.st_mode)) /* Network Special [hpux] */
+ return (':');
+#endif
+#ifdef S_ISCHR
+ if (S_ISCHR(statb.st_mode)) /* char device */
+ return ('%');
+#endif
+#ifdef S_ISBLK
+ if (S_ISBLK(statb.st_mode)) /* block device */
+ return ('#');
+#endif
+#ifdef S_ISDIR
+ if (S_ISDIR(statb.st_mode)) /* normal Directory */
+ return ('/');
+#endif
+ if (statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ return ('*');
+ }
+ }
+ return (' ');
+} /* end filetype */
+
+
+/* isadirectory():
+ * Return trus if the file is a directory
+ */
+static int
+isadirectory(dir, file) /* return 1 if dir/file is a directory */
+ Char *dir, *file; /* uses stat rather than lstat to get dest. */
+{
+ if (dir) {
+ Char path[MAXPATHLEN];
+ struct stat statb;
+
+ (void) Strcpy(path, dir);
+ catn(path, file, (int) (sizeof(path) / sizeof(Char)));
+ if (stat(short2str(path), &statb) >= 0) { /* resolve through
+ * symlink */
+#ifdef S_ISSOCK
+ if (S_ISSOCK(statb.st_mode)) /* Socket */
+ return 0;
+#endif
+#ifdef S_ISFIFO
+ if (S_ISFIFO(statb.st_mode)) /* Named Pipe */
+ return 0;
+#endif
+ if (S_ISDIR(statb.st_mode)) /* normal Directory */
+ return 1;
+ }
+ }
+ return 0;
+} /* end isadirectory */
+
+
+
+/* find_rows():
+ * Return how many rows needed to print sorted down columns
+ */
+static int
+find_rows(items, count, no_file_suffix)
+ Char *items[];
+ int count, no_file_suffix;
+{
+ register int i, columns, rows;
+ unsigned int maxwidth = 0;
+
+ for (i = 0; i < count; i++) /* find widest string */
+ maxwidth = max(maxwidth, (unsigned int) Strlen(items[i]));
+
+ maxwidth += no_file_suffix ? 1 : 2; /* for the file tag and space */
+ columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */
+ if (!columns)
+ columns = 1;
+ rows = (count + (columns - 1)) / columns;
+
+ return rows;
+} /* end rows_needed_by_print_by_column */
+
+
+/* print_by_column():
+ * Print sorted down columns or across columns when the first
+ * word of $listflags shell variable contains 'x'.
+ *
+ */
+void
+print_by_column(dir, items, count, no_file_suffix)
+ register Char *dir, *items[];
+ int count, no_file_suffix;
+{
+ register int i, r, c, columns, rows;
+ unsigned int w, maxwidth = 0;
+ Char *val;
+ bool across;
+
+ lbuffed = 0; /* turn off line buffering */
+
+
+ across = ((val = varval(STRlistflags)) != STRNULL) &&
+ (Strchr(val, 'x') != NULL);
+
+ for (i = 0; i < count; i++) /* find widest string */
+ maxwidth = max(maxwidth, (unsigned int) Strlen(items[i]));
+
+ maxwidth += no_file_suffix ? 1 : 2; /* for the file tag and space */
+ columns = TermH / maxwidth; /* PWP: terminal size change */
+ if (!columns || !isatty(didfds ? 1 : SHOUT))
+ columns = 1;
+ rows = (count + (columns - 1)) / columns;
+
+ i = -1;
+ for (r = 0; r < rows; r++) {
+ for (c = 0; c < columns; c++) {
+ i = across ? (i + 1) : (c * rows + r);
+
+ if (i < count) {
+ w = (unsigned int) Strlen(items[i]);
+
+#ifdef COLOR_LS_F
+ if (no_file_suffix) {
+ /* Print the command name */
+ Char f = items[i][w - 1];
+ items[i][w - 1] = 0;
+ print_with_color(items[i], w - 1, f);
+ }
+ else {
+ /* Print filename followed by '/' or '*' or ' ' */
+ print_with_color(items[i], w, filetype(dir, items[i]));
+ w++;
+ }
+#else /* ifndef COLOR_LS_F */
+ if (no_file_suffix) {
+ /* Print the command name */
+ xprintf("%S", items[i]);
+ }
+ else {
+ /* Print filename followed by '/' or '*' or ' ' */
+ xprintf("%S%c", items[i],
+ filetype(dir, items[i]));
+ w++;
+ }
+#endif /* COLOR_LS_F */
+
+ if (c < (columns - 1)) /* Not last column? */
+ for (; w < maxwidth; w++)
+ xputchar(' ');
+ }
+ else if (across)
+ break;
+ }
+ if (Tty_raw_mode)
+ xputchar('\r');
+ xputchar('\n');
+ }
+
+ lbuffed = 1; /* turn back on line buffering */
+ flush();
+} /* end print_by_column */
+
+
+/* StrQcmp():
+ * Compare strings ignoring the quoting chars
+ */
+int
+StrQcmp(str1, str2)
+ register Char *str1, *str2;
+{
+ for (; *str1 && samecase(*str1 & TRIM) == samecase(*str2 & TRIM);
+ str1++, str2++)
+ continue;
+ /*
+ * The following case analysis is necessary so that characters which look
+ * negative collate low against normal characters but high against the
+ * end-of-string NUL.
+ */
+ if (*str1 == '\0' && *str2 == '\0')
+ return (0);
+ else if (*str1 == '\0')
+ return (-1);
+ else if (*str2 == '\0')
+ return (1);
+ else
+ return ((*str1 & TRIM) - (*str2 & TRIM));
+} /* end StrQcmp */
+
+
+/* fcompare():
+ * Comparison routine for qsort
+ */
+int
+fcompare(file1, file2)
+ Char **file1, **file2;
+{
+ return (int) collate(*file1, *file2);
+} /* end fcompare */
+
+
+/* catn():
+ * Concatenate src onto tail of des.
+ * Des is a string whose maximum length is count.
+ * Always null terminate.
+ */
+void
+catn(des, src, count)
+ register Char *des, *src;
+ int count;
+{
+ while (--count >= 0 && *des)
+ des++;
+ while (--count >= 0)
+ if ((*des++ = *src++) == 0)
+ return;
+ *des = '\0';
+} /* end catn */
+
+
+/* copyn():
+ * like strncpy but always leave room for trailing \0
+ * and always null terminate.
+ */
+void
+copyn(des, src, count)
+ register Char *des, *src;
+ int count;
+{
+ while (--count >= 0)
+ if ((*des++ = *src++) == 0)
+ return;
+ *des = '\0';
+} /* end copyn */
+
+
+/* tgetenv():
+ * like it's normal string counter-part
+ * [apollo uses that in tc.os.c, so it cannot be static]
+ */
+Char *
+tgetenv(str)
+ Char *str;
+{
+ Char **var;
+ int len, res;
+
+ len = (int) Strlen(str);
+ /* Search the STR_environ for the entry matching str. */
+ for (var = STR_environ; var != NULL && *var != NULL; var++)
+ if (Strlen(*var) >= len && (*var)[len] == '=') {
+ /* Temporarily terminate the string so we can copy the variable
+ name. */
+ (*var)[len] = '\0';
+ res = StrQcmp(*var, str);
+ /* Restore the '=' and return a pointer to the value of the
+ environment variable. */
+ (*var)[len] = '=';
+ if (res == 0)
+ return (&((*var)[len + 1]));
+ }
+ return (NULL);
+} /* end tgetenv */
+
+
+struct scroll_tab_list *scroll_tab = 0;
+
+static void
+add_scroll_tab(item)
+ Char *item;
+{
+ struct scroll_tab_list *new_scroll;
+
+ new_scroll = (struct scroll_tab_list *) xmalloc((size_t)
+ sizeof(struct scroll_tab_list));
+ new_scroll->element = Strsave(item);
+ new_scroll->next = scroll_tab;
+ scroll_tab = new_scroll;
+}
+
+static void
+choose_scroll_tab(exp_name, cnt)
+ Char **exp_name;
+ int cnt;
+{
+ struct scroll_tab_list *loop;
+ int tmp = cnt;
+ Char **ptr;
+
+ ptr = (Char **) xmalloc((size_t) sizeof(Char *) * cnt);
+
+ for(loop = scroll_tab; loop && (tmp >= 0); loop = loop->next)
+ ptr[--tmp] = loop->element;
+
+ qsort((ptr_t) ptr, (size_t) cnt, sizeof(Char *),
+ (int (*) __P((const void *, const void *))) fcompare);
+
+ copyn(*exp_name, ptr[curchoice], (int) Strlen(ptr[curchoice]));
+ xfree((ptr_t) ptr);
+}
+
+static void
+free_scroll_tab()
+{
+ struct scroll_tab_list *loop;
+
+ while(scroll_tab) {
+ loop = scroll_tab;
+ scroll_tab = scroll_tab->next;
+ xfree((ptr_t) loop->element);
+ xfree((ptr_t) loop);
+ }
+}
diff --git a/contrib/tcsh/tw.spell.c b/contrib/tcsh/tw.spell.c
new file mode 100644
index 0000000..e784edd
--- /dev/null
+++ b/contrib/tcsh/tw.spell.c
@@ -0,0 +1,168 @@
+/* $Header: /src/pub/tcsh/tw.spell.c,v 3.14 1996/04/26 19:23:27 christos Exp $ */
+/*
+ * tw.spell.c: Spell check words
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$Id: tw.spell.c,v 3.14 1996/04/26 19:23:27 christos Exp $")
+
+#include "tw.h"
+
+/* spell_me : return corrrectly spelled filename. From K&P spname */
+int
+spell_me(oldname, oldsize, looking, pat, suf)
+ Char *oldname;
+ int oldsize, looking;
+ Char *pat;
+ int suf;
+{
+ /* The +1 is to fool hp's optimizer */
+ Char guess[FILSIZ + 1], newname[FILSIZ + 1];
+ register Char *new = newname, *old = oldname;
+ register Char *p, *cp, *ws;
+ bool foundslash = 0;
+ int retval;
+
+ for (;;) {
+ while (*old == '/') { /* skip '/' */
+ *new++ = *old++;
+ foundslash = 1;
+ }
+ /* do not try to correct spelling of single letter words */
+ if (*old != '\0' && old[1] == '\0')
+ *new++ = *old++;
+ *new = '\0';
+ if (*old == '\0') {
+ retval = (StrQcmp(oldname, newname) != 0);
+ copyn(oldname, newname, oldsize); /* shove it back. */
+ return retval;
+ }
+ p = guess; /* start at beginning of buf */
+ if (newname[0]) /* add current dir if any */
+ for (cp = newname; *cp; cp++)
+ if (p < guess + FILSIZ)
+ *p++ = *cp;
+ ws = p;
+ for (; *old != '/' && *old != '\0'; old++)/* add current file name */
+ if (p < guess + FILSIZ)
+ *p++ = *old;
+ *p = '\0'; /* terminate it */
+
+ /*
+ * Don't tell t_search we're looking for cmd if no '/' in the name so
+ * far but there are later - or it will look for *all* commands
+ */
+ /* (*should* say "looking for directory" whenever '/' is next...) */
+ retval = t_search(guess, p, SPELL, FILSIZ,
+ looking == TW_COMMAND && (foundslash || *old != '/') ?
+ TW_COMMAND : looking, 1, pat, suf);
+ if (retval >= 4 || retval < 0)
+ return -1; /* hopeless */
+ for (p = ws; (*new = *p++) != '\0'; new++)
+ continue;
+ }
+/*NOTREACHED*/
+#ifdef notdef
+ return (0); /* lint on the vax under mtXinu complains! */
+#endif
+}
+
+#define EQ(s,t) (StrQcmp(s,t) == 0)
+
+/*
+ * spdist() is taken from Kernighan & Pike,
+ * _The_UNIX_Programming_Environment_
+ * and adapted somewhat to correspond better to psychological reality.
+ * (Note the changes to the return values)
+ *
+ * According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4),
+ * page 363, the correct order for this is:
+ * OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION
+ * thus, it was exactly backwards in the old version. -- PWP
+ */
+
+int
+spdist(s, t)
+ register Char *s, *t;
+{
+ for (; (*s & TRIM) == (*t & TRIM); t++, s++)
+ if (*t == '\0')
+ return 0; /* exact match */
+ if (*s) {
+ if (*t) {
+ if (s[1] && t[1] && (*s & TRIM) == (t[1] & TRIM) &&
+ (*t & TRIM) == (s[1] & TRIM) && EQ(s + 2, t + 2))
+ return 1; /* transposition */
+ if (EQ(s + 1, t + 1))
+ return 3; /* 1 char mismatch */
+ }
+ if (EQ(s + 1, t))
+ return 2; /* extra character */
+ }
+ if (*t && EQ(s, t + 1))
+ return 1; /* missing character */
+ return 4;
+}
+
+int
+spdir(extended_name, tilded_dir, item, name)
+ Char *extended_name;
+ Char *tilded_dir;
+ Char *item;
+ Char *name;
+{
+ Char path[MAXPATHLEN + 1];
+ Char *s;
+ Char oldch;
+
+ if (ISDOT(item) || ISDOTDOT(item))
+ return 0;
+
+ for (s = name; *s != 0 && (*s & TRIM) == (*item & TRIM); s++, item++)
+ continue;
+ if (*s == 0 || s[1] == 0 || *item != 0)
+ return 0;
+
+ (void) Strcpy(path, tilded_dir);
+ oldch = *s;
+ *s = '/';
+ catn(path, name, (int) (sizeof(path) / sizeof(Char)));
+ if (access(short2str(path), F_OK) == 0) {
+ (void) Strcpy(extended_name, name);
+ return 1;
+ }
+ *s = oldch;
+ return 0;
+}
diff --git a/contrib/tcsh/vms.termcap.c b/contrib/tcsh/vms.termcap.c
new file mode 100644
index 0000000..d48802e
--- /dev/null
+++ b/contrib/tcsh/vms.termcap.c
@@ -0,0 +1,337 @@
+/* $Header: /src/pub/tcsh/vms.termcap.c,v 1.5 1997/10/02 16:36:36 christos Exp $ */
+/*
+ * termcap.c 1.1 20/7/87 agc Joypace Ltd
+ *
+ * Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
+ * This file may be freely distributed provided that this notice
+ * remains attached.
+ *
+ * A public domain implementation of the termcap(3) routines.
+ */
+#include "sh.h"
+RCSID("$Id: vms.termcap.c,v 1.5 1997/10/02 16:36:36 christos Exp $")
+#if defined(_VMS_POSIX) || defined(_OSD_POSIX)
+/* efth 1988-Apr-29
+
+ - Correct when TERM != name and TERMCAP is defined [tgetent]
+ - Correct the comparison for the terminal name [tgetent]
+ - Correct the value of ^x escapes [tgetstr]
+ - Added %r to reverse row/column [tgoto]
+
+ Paul Gillingwater <paul@actrix.gen.nz> July 1992
+ - Modified to allow terminal aliases in termcap file
+ - Uses TERMCAP environment variable for file only
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#define CAPABLEN 2
+
+#define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
+
+char *capab; /* the capability itself */
+
+extern char *getenv(); /* new, improved getenv */
+extern FILE *fopen(); /* old fopen */
+
+/*
+ * tgetent - get the termcap entry for terminal name, and put it
+ * in bp (which must be an array of 1024 chars). Returns 1 if
+ * termcap entry found, 0 if not found, and -1 if file not found.
+ */
+
+int
+tgetent(bp, name)
+char *bp;
+char *name;
+{
+ FILE *fp;
+ char *termfile;
+ char *cp,
+ *ptr, /* temporary pointer */
+ tmp[1024]; /* buffer for terminal name */
+ short len = strlen(name);
+
+ capab = bp;
+
+ /* Use TERMCAP to override default. */
+
+ termfile = getenv("TERMCAP");
+ if (termfile == NULL ) termfile = "/etc/termcap";
+
+ if ((fp = fopen(termfile, "r")) == (FILE *) NULL) {
+ fprintf(stderr, CGETS(31, 1,
+ "Can't open TERMCAP: [%s]\n"), termfile);
+ fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile);
+ sleep(1);
+ return(-1);
+ }
+
+ while (fgets(bp, 1024, fp) != NULL) {
+ /* Any line starting with # or NL is skipped as a comment */
+ if ((*bp == '#') || (*bp == '\n')) continue;
+
+ /* Look for lines which end with two backslashes,
+ and then append the next line. */
+ while (*(cp = &bp[strlen(bp) - 2]) == '\\')
+ fgets(cp, 1024, fp);
+
+ /* Skip over any spaces or tabs */
+ for (++cp ; ISSPACE(*cp) ; cp++);
+
+ /* Make sure "name" matches exactly (efth) */
+
+/* Here we might want to look at any aliases as well. We'll use
+sscanf to look at aliases. These are delimited by '|'. */
+
+ sscanf(bp,"%[^|]",tmp);
+ if (strncmp(name, tmp, len) == 0) {
+ fclose(fp);
+#ifdef DEBUG
+ fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
+ sleep(1);
+#endif /* DEBUG */
+ return(1);
+ }
+ ptr = bp;
+ while ((ptr = strchr(ptr,'|')) != NULL) {
+ ptr++;
+ if (strchr(ptr,'|') == NULL) break;
+ sscanf(ptr,"%[^|]",tmp);
+ if (strncmp(name, tmp, len) == 0) {
+ fclose(fp);
+#ifdef DEBUG
+ fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
+ sleep(1);
+#endif /* DEBUG */
+ return(1);
+ }
+ }
+ }
+ /* If we get here, then we haven't found a match. */
+ fclose(fp);
+#ifdef DEBUG
+ fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
+ name, termfile);
+ sleep(1);
+#endif /* DEBUG */
+ return(0);
+
+}
+
+/*
+ * tgetnum - get the numeric terminal capability corresponding
+ * to id. Returns the value, -1 if invalid.
+ */
+int
+tgetnum(id)
+char *id;
+{
+ char *cp;
+ int ret;
+
+ if ((cp = capab) == NULL || id == NULL)
+ return(-1);
+ while (*++cp != ':')
+ ;
+ for (++cp ; *cp ; cp++) {
+ while (ISSPACE(*cp))
+ cp++;
+ if (strncmp(cp, id, CAPABLEN) == 0) {
+ while (*cp && *cp != ':' && *cp != '#')
+ cp++;
+ if (*cp != '#')
+ return(-1);
+ for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
+ ret = ret * 10 + *cp - '0';
+ return(ret);
+ }
+ while (*cp && *cp != ':')
+ cp++;
+ }
+ return(-1);
+}
+
+/*
+ * tgetflag - get the boolean flag corresponding to id. Returns -1
+ * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
+ * present.
+ */
+int
+tgetflag(id)
+char *id;
+{
+ char *cp;
+
+ if ((cp = capab) == NULL || id == NULL)
+ return(-1);
+ while (*++cp != ':')
+ ;
+ for (++cp ; *cp ; cp++) {
+ while (ISSPACE(*cp))
+ cp++;
+ if (strncmp(cp, id, CAPABLEN) == 0)
+ return(1);
+ while (*cp && *cp != ':')
+ cp++;
+ }
+ return(0);
+}
+
+/*
+ * tgetstr - get the string capability corresponding to id and place
+ * it in area (advancing area at same time). Expand escape sequences
+ * etc. Returns the string, or NULL if it can't do it.
+ */
+char *
+tgetstr(id, area)
+char *id;
+char **area;
+{
+ char *cp;
+ char *ret;
+ int i;
+
+ if ((cp = capab) == NULL || id == NULL)
+ return(NULL);
+ while (*++cp != ':')
+ ;
+ for (++cp ; *cp ; cp++) {
+ while (ISSPACE(*cp))
+ cp++;
+ if (strncmp(cp, id, CAPABLEN) == 0) {
+ while (*cp && *cp != ':' && *cp != '=')
+ cp++;
+ if (*cp != '=')
+ return(NULL);
+ for (ret = *area, cp++; *cp && *cp != ':' ;
+ (*area)++, cp++)
+ switch(*cp) {
+ case '^' :
+ **area = *++cp - '@'; /* fix (efth)*/
+ break;
+ case '\\' :
+ switch(*++cp) {
+ case 'E' :
+ **area = CTL_ESC('\033');
+ break;
+ case 'n' :
+ **area = '\n';
+ break;
+ case 'r' :
+ **area = '\r';
+ break;
+ case 't' :
+ **area = '\t';
+ break;
+ case 'b' :
+ **area = '\b';
+ break;
+ case 'f' :
+ **area = '\f';
+ break;
+ case '0' :
+ case '1' :
+ case '2' :
+ case '3' :
+ for (i=0 ; *cp && ISDIGIT(*cp) ;
+ cp++)
+ i = i * 8 + *cp - '0';
+ **area = i;
+ cp--;
+ break;
+ case '^' :
+ case '\\' :
+ **area = *cp;
+ break;
+ }
+ break;
+ default :
+ **area = *cp;
+ }
+ *(*area)++ = '\0';
+ return(ret);
+ }
+ while (*cp && *cp != ':')
+ cp++;
+ }
+ return(NULL);
+}
+
+/*
+ * tgoto - given the cursor motion string cm, make up the string
+ * for the cursor to go to (destcol, destline), and return the string.
+ * Returns "OOPS" if something's gone wrong, or the string otherwise.
+ */
+char *
+tgoto(cm, destcol, destline)
+char *cm;
+int destcol;
+int destline;
+{
+ register char *rp;
+ static char ret[24];
+ int incr = 0;
+ int argno = 0, numval;
+
+ for (rp = ret ; *cm ; cm++) {
+ switch(*cm) {
+ case '%' :
+ switch(*++cm) {
+ case '+' :
+ numval = (argno == 0 ? destline : destcol);
+ argno = 1 - argno;
+ *rp++ = numval + incr + *++cm;
+ break;
+
+ case '%' :
+ *rp++ = '%';
+ break;
+
+ case 'i' :
+ incr = 1;
+ break;
+
+ case 'd' :
+ numval = (argno == 0 ? destline : destcol);
+ numval += incr;
+ argno = 1 - argno;
+ *rp++ = '0' + (numval/10);
+ *rp++ = '0' + (numval%10);
+ break;
+
+ case 'r' :
+ argno = 1;
+ break;
+ }
+
+ break;
+ default :
+ *rp++ = *cm;
+ }
+ }
+ *rp = '\0';
+ return(ret);
+}
+
+/*
+ * tputs - put the string cp out onto the terminal, using the function
+ * outc. This should do padding for the terminal, but I can't find a
+ * terminal that needs padding at the moment...
+ */
+int
+tputs(cp, affcnt, outc)
+register char *cp;
+int affcnt;
+int (*outc)();
+{
+ if (cp == NULL)
+ return(1);
+ /* do any padding interpretation - left null for MINIX just now */
+ while (*cp)
+ (*outc)(*cp++);
+ return(1);
+}
+#endif /* _VMS_POSIX */
OpenPOWER on IntegriCloud