home *** CD-ROM | disk | FTP | other *** search
- From: pfalstad@phoenix.Princeton.EDU (Paul John Falstad)
- Newsgroups: alt.sources
- Subject: zsh - ksh/tcsh-like shell (part 2 of 8)
- Message-ID: <4743@idunno.Princeton.EDU>
- Date: 14 Dec 90 23:29:51 GMT
-
- ---cut here---cut here---cut here---
- -bash(1),
- -ksh(1),
- -cat(1),
- -cd(1),
- -chmod(1),
- -cut(1),
- -echo(1),
- -emacs(1),
- -env(1),
- -gmacs(1),
- -newgrp(1),
- -stty(1),
- -test(1),
- -umask(1),
- -vi(1),
- -dup(2),
- -exec(2),
- -fork(2),
- -ioctl(2),
- -lseek(2),
- -paste(1),
- -pipe(2),
- -signal(2),
- -umask(2),
- -ulimit(2),
- -wait(2),
- -rand(3),
- -a.out(5),
- -profile(5),
- -environ(7),
- -xtetris(6).
- -.SH AUTHOR
- -Paul Falstad <pfalstad@phoenix.princeton.edu>
- -.PP
- -The command line editor is a hacked-up version
- -of the GNU readline library,
- -written by Brian Fox (<bfox@ai.MIT.Edu>) of the Free
- -Software Foundation. This shell is therefore
- -under the GNU public license. I eventually plan
- -to write my own command line editor to make everything
- -my own code, but \fBzsh\fP will probably still be under
- -the GPL, or perhaps something less restrictive.
- -.SH CAVEATS
- -.PP
- -Using
- -.B fc
- -built-in command within a compound command will cause the whole
- -command to disappear from the history file.
- -.PP
- -Shell functions are put in the function table when their declarations
- -are parsed, not when they are executed. Thus function declarations
- -inside \fBif\fP clauses, for example, will not work as expected.
- -(This is a bug, not a caveat.)
- -.PP
- -The command line editor gets confused if you have termcap sequences
- -(like %S) in your prompt.
- -.PP
- -The main shell does not get along with the command line editor.
- -One of them will have to go.
- -.PP
- -Use of this shell is reserved for faculty, staff,
- -graduate students,
- -and special guests
- -of the Princeton University
- -Computer Science department.
- End of zsh.1
- echo COPYING 1>&2
- sed 's/^-//' >COPYING <<'End of COPYING'
- -
- - GNU GENERAL PUBLIC LICENSE
- - Version 1, February 1989
- -
- - Copyright (C) 1989 Free Software Foundation, Inc.
- - 675 Mass Ave, Cambridge, MA 02139, USA
- - Everyone is permitted to copy and distribute verbatim copies
- - of this license document, but changing it is not allowed.
- -
- - Preamble
- -
- - The license agreements of most software companies try to keep users
- -at the mercy of those companies. By contrast, our General Public
- -License is intended to guarantee your freedom to share and change free
- -software--to make sure the software is free for all its users. The
- -General Public License applies to the Free Software Foundation's
- -software and to any other program whose authors commit to using it.
- -You can use it for your programs, too.
- -
- - When we speak of free software, we are referring to freedom, not
- -price. Specifically, the General Public License is designed to make
- -sure that you have the freedom to give away or sell copies of free
- -software, that you receive source code or can get it if you want it,
- -that you can change the software or use pieces of it in new free
- -programs; and that you know you can do these things.
- -
- - To protect your rights, we need to make restrictions that forbid
- -anyone to deny you these rights or to ask you to surrender the rights.
- -These restrictions translate to certain responsibilities for you if you
- -distribute copies of the software, or if you modify it.
- -
- - For example, if you distribute copies of a such a program, whether
- -gratis or for a fee, you must give the recipients all the rights that
- -you have. You must make sure that they, too, receive or can get the
- -source code. And you must tell them their rights.
- -
- - We protect your rights with two steps: (1) copyright the software, and
- -(2) offer you this license which gives you legal permission to copy,
- -distribute and/or modify the software.
- -
- - Also, for each author's protection and ours, we want to make certain
- -that everyone understands that there is no warranty for this free
- -software. If the software is modified by someone else and passed on, we
- -want its recipients to know that what they have is not the original, so
- -that any problems introduced by others will not reflect on the original
- -authors' reputations.
- -
- - The precise terms and conditions for copying, distribution and
- -modification follow.
- -
- - GNU GENERAL PUBLIC LICENSE
- - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- -
- - 0. This License Agreement applies to any program or other work which
- -contains a notice placed by the copyright holder saying it may be
- -distributed under the terms of this General Public License. The
- -"Program", below, refers to any such program or work, and a "work based
- -on the Program" means either the Program or any work containing the
- -Program or a portion of it, either verbatim or with modifications. Each
- -licensee is addressed as "you".
- -
- - 1. You may copy and distribute verbatim copies of the Program's source
- -code as you receive it, in any medium, provided that you conspicuously and
- -appropriately publish on each copy an appropriate copyright notice and
- -disclaimer of warranty; keep intact all the notices that refer to this
- -General Public License and to the absence of any warranty; and give any
- -other recipients of the Program a copy of this General Public License
- -along with the Program. You may charge a fee for the physical act of
- -transferring a copy.
- -
- - 2. You may modify your copy or copies of the Program or any portion of
- -it, and copy and distribute such modifications under the terms of Paragraph
- -1 above, provided that you also do the following:
- -
- - a) cause the modified files to carry prominent notices stating that
- - you changed the files and the date of any change; and
- -
- - b) cause the whole of any work that you distribute or publish, that
- - in whole or in part contains the Program or any part thereof, either
- - with or without modifications, to be licensed at no charge to all
- - third parties under the terms of this General Public License (except
- - that you may choose to grant warranty protection to some or all
- - third parties, at your option).
- -
- - c) If the modified program normally reads commands interactively when
- - run, you must cause it, when started running for such interactive use
- - in the simplest and most usual way, to print or display an
- - announcement including an appropriate copyright notice and a notice
- - that there is no warranty (or else, saying that you provide a
- - warranty) and that users may redistribute the program under these
- - conditions, and telling the user how to view a copy of this General
- - Public License.
- -
- - d) You may charge a fee for the physical act of transferring a
- - copy, and you may at your option offer warranty protection in
- - exchange for a fee.
- -
- -Mere aggregation of another independent work with the Program (or its
- -derivative) on a volume of a storage or distribution medium does not bring
- -the other work under the scope of these terms.
- -
- - 3. You may copy and distribute the Program (or a portion or derivative of
- -it, under Paragraph 2) in object code or executable form under the terms of
- -Paragraphs 1 and 2 above provided that you also do one of the following:
- -
- - a) accompany it with the complete corresponding machine-readable
- - source code, which must be distributed under the terms of
- - Paragraphs 1 and 2 above; or,
- -
- - b) accompany it with a written offer, valid for at least three
- - years, to give any third party free (except for a nominal charge
- - for the cost of distribution) a complete machine-readable copy of the
- - corresponding source code, to be distributed under the terms of
- - Paragraphs 1 and 2 above; or,
- -
- - c) accompany it with the information you received as to where the
- - corresponding source code may be obtained. (This alternative is
- - allowed only for noncommercial distribution and only if you
- - received the program in object code or executable form alone.)
- -
- -Source code for a work means the preferred form of the work for making
- -modifications to it. For an executable file, complete source code means
- -all the source code for all modules it contains; but, as a special
- -exception, it need not include source code for modules which are standard
- -libraries that accompany the operating system on which the executable
- -file runs, or for standard header files or definitions files that
- -accompany that operating system.
- -
- - 4. You may not copy, modify, sublicense, distribute or transfer the
- -Program except as expressly provided under this General Public License.
- -Any attempt otherwise to copy, modify, sublicense, distribute or transfer
- -the Program is void, and will automatically terminate your rights to use
- -the Program under this License. However, parties who have received
- -copies, or rights to use copies, from you under this General Public
- -License will not have their licenses terminated so long as such parties
- -remain in full compliance.
- -
- - 5. By copying, distributing or modifying the Program (or any work based
- -on the Program) you indicate your acceptance of this license to do so,
- -and all its terms and conditions.
- -
- - 6. Each time you redistribute the Program (or any work based on the
- -Program), the recipient automatically receives a license from the original
- -licensor to copy, distribute or modify the Program subject to these
- -terms and conditions. You may not impose any further restrictions on the
- -recipients' exercise of the rights granted herein.
- -
- - 7. The Free Software Foundation may publish revised and/or new versions
- -of the General Public License from time to time. Such new versions will
- -be similar in spirit to the present version, but may differ in detail to
- -address new problems or concerns.
- -
- -Each version is given a distinguishing version number. If the Program
- -specifies a version number of the license which applies to it and "any
- -later version", you have the option of following the terms and conditions
- -either of that version or of any later version published by the Free
- -Software Foundation. If the Program does not specify a version number of
- -the license, you may choose any version ever published by the Free Software
- -Foundation.
- -
- - 8. If you wish to incorporate parts of the Program into other free
- -programs whose distribution conditions are different, write to the author
- -to ask for permission. For software which is copyrighted by the Free
- -Software Foundation, write to the Free Software Foundation; we sometimes
- -make exceptions for this. Our decision will be guided by the two goals
- -of preserving the free status of all derivatives of our free software and
- -of promoting the sharing and reuse of software generally.
- -
- - NO WARRANTY
- -
- - 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
- -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
- -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
- -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
- -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
- -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
- -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
- -REPAIR OR CORRECTION.
- -
- - 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
- -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
- -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
- -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
- -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
- -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
- -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
- -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
- -POSSIBILITY OF SUCH DAMAGES.
- -
- - END OF TERMS AND CONDITIONS
- -
- - Appendix: How to Apply These Terms to Your New Programs
- -
- - If you develop a new program, and you want it to be of the greatest
- -possible use to humanity, the best way to achieve this is to make it
- -free software which everyone can redistribute and change under these
- -terms.
- -
- - To do so, attach the following notices to the program. It is safest to
- -attach them to the start of each source file to most effectively convey
- -the exclusion of warranty; and each file should have at least the
- -"copyright" line and a pointer to where the full notice is found.
- -
- - <one line to give the program's name and a brief idea of what it does.>
- - Copyright (C) 19yy <name of author>
- -
- - This program is free software; you can redistribute it and/or modify
- - it under the terms of the GNU General Public License as published by
- - the Free Software Foundation; either version 1, or (at your option)
- - any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU General Public License for more details.
- -
- - You should have received a copy of the GNU General Public License
- - along with this program; if not, write to the Free Software
- - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- -
- -Also add information on how to contact you by electronic and paper mail.
- -
- -If the program is interactive, make it output a short notice like this
- -when it starts in an interactive mode:
- -
- - Gnomovision version 69, Copyright (C) 19xx name of author
- - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- - This is free software, and you are welcome to redistribute it
- - under certain conditions; type `show c' for details.
- -
- -The hypothetical commands `show w' and `show c' should show the
- -appropriate parts of the General Public License. Of course, the
- -commands you use may be called something other than `show w' and `show
- -c'; they could even be mouse-clicks or menu items--whatever suits your
- -program.
- -
- -You should also get your employer (if you work as a programmer) or your
- -school, if any, to sign a "copyright disclaimer" for the program, if
- -necessary. Here a sample; alter the names:
- -
- - Yoyodyne, Inc., hereby disclaims all copyright interest in the
- - program `Gnomovision' (a program to direct compilers to make passes
- - at assemblers) written by James Hacker.
- -
- - <signature of Ty Coon>, 1 April 1989
- - Ty Coon, President of Vice
- -
- -That's all there is to it!
- End of COPYING
- echo README 1>&2
- sed 's/^-//' >README <<'End of README'
- -Read "INSTALL" for information on getting this shell running.
- -
- -zsh is free software. See the file COPYING for copying permission.
- -
- - This shell was "developed" by me, Paul Falstad, a sophomore at Princeton
- -University. I borrowed _heavily_ from ksh, bash, tcsh, sh, and csh, as
- -well as adding a few (IMHO) useful features. zsh was at first intended
- -to be a subset of csh for the Commodore Amiga, but the project sort of
- -ballooned; now I want it to be a cross between ksh and tcsh. It should
- -be a powerful "command and programming language" that is well-designed
- -and logical (like ksh), but it should also be built for humans (like
- -tcsh), with all the neat features like spell checking, login/logout
- -watching and termcap support that are probably too weird to make it into
- -an AT&T product. This version of the shell has fallen far short of that
- -goal; I just wanted to release _something_, because this is obviously
- -going to be an extremely long project.
- -
- - This is version v1.0 of zsh. I incorporated the GNU "readline"
- -editor, written by Brian Fox, into the shell, just to make my life
- -temporarily easier. I made lots of changes to it, so if there are any
- -bugs in the editor, they're probably my fault. readline will not be a
- -part of the next version of zsh.
- -
- - If anyone has any questions, suggestions, comments, bugs, flames, or
- -any other mail of any kind, send it to pfalstad@phoenix.princeton.edu.
- -Thanks to Kartik Subbarao, Daniel Bernstein ("Yay. So sell it."),
- -Kennedy Lemke, Chet Ramey (for the bash man page, and for putting features
- -in the man page that weren't in our version of bash), Brian Fox (for
- -helping me put off a lot of work, and for writing bash), Richard M. Stallman
- -(for gdb and gcc; not for emacs though ;-) ) and many others.
- -
- End of README
- echo INSTALL 1>&2
- sed 's/^-//' >INSTALL <<'End of INSTALL'
- -I was not able to port zsh to many platforms because I don't have
- -accounts on many platforms. It shouldn't be too much trouble if you
- -manage to decipher my code. I have tested zsh on SunOS 4.1, SunOS 4.0.3,
- -4.3BSD UNIX.
- -
- -You need to edit the files config.h, config.local.h, makefile, and
- -readline/Makefile. The comments should make clear what you have to do.
- -Note that the files in the readline directory have been greatly
- -modified, so you can't just copy over your changes from bash if you
- -have it installed.
- -
- -Once you have done that, you might be able to do a make without any
- -problem. If you have trouble, and can't get zsh to work, send me mail,
- -and I'll try to help. If anyone manages to get zsh ported to some other
- -platform, please mail me so I can tell other people about your changes
- -and incorporate them into the next version.
- -
- End of INSTALL
- echo makefile 1>&2
- sed 's/^-//' >makefile <<'End of makefile'
- -#! /bin/make -f
- -#
- -# makefile for zsh
- -#
- -# This file is part of zsh, the Z shell.
- -#
- -# zsh is free software; no one can prevent you from reading the source
- -# code, or giving it to someone else.
- -# This file is copyrighted under the GNU General Public License, which
- -# can be found in the file called COPYING.
- -#
- -# Copyright (C) 1990 Paul Falstad
- -#
- -# zsh is distributed in the hope that it will be useful, but
- -# WITHOUT ANY WARRANTY. No author or distributor accepts
- -# responsibility to anyone for the consequences of using it or for
- -# whether it serves any particular purpose or works at all, unless he
- -# says so in writing. Refer to the GNU General Public License
- -# for full details.
- -#
- -# Everyone is granted permission to copy, modify and redistribute
- -# zsh, but only under the conditions described in the GNU General Public
- -# License. A copy of this license is supposed to have been given to you
- -# along with zsh so you can know your rights and responsibilities.
- -# It should be in a file named COPYING.
- -#
- -# Among other things, the copyright notice and this notice must be
- -# preserved on all copies.
- -#
- -OBJS=hist.o glob.o table.o subst.o builtin.o loop.o vars.o\
- -parse.o lex.o init.o jobs.o exec.o zhistory.o utils.o math.o test.o
- -READLINE=readline/funmap.o readline/keymaps.o readline/readline.o
- -BINDIR=/usr/local/bin
- -MANDIR=/usr/local/man/man1
- -CFLAGS=-O -fstrength-reduce -fomit-frame-pointer -finline-functions \
- - -fsigned-char -fdelayed-branch
- -CC=gcc
- -ZSHPATH=zsh
- -THINGS_TO_TAR=zsh.1 COPYING README INSTALL makefile sample.zshrc \
- -sample.zlogin sample.zshrc.mine sample.zlogin.mine \
- -alias.pro builtin.c builtin.pro config.h config.local.h \
- -exec.c exec.pro funcs.h glob.c glob.pro hist.c hist.pro init.c \
- -init.pro jobs.c jobs.pro lex.c lex.pro loop.c loop.pro math.c \
- -math.pro parse.c parse.pro subst.c subst.pro table.c \
- -table.pro test.c test.pro utils.c utils.pro vars.c vars.pro zhistory.c \
- -readline/chardefs.h readline/emacs_keymap.c \
- -readline/funmap.c readline/history.h readline/keymaps.c \
- -readline/keymaps.h readline/readline.c readline/readline.h \
- -readline/vi_keymap.c readline/vi_mode.c readline/Makefile \
- -zsh.h proto
- -
- -.c.o:
- - $(CC) $(CFLAGS) -c -o $*.o $<
- -
- -$(ZSHPATH): $(OBJS) $(READLINE)
- - $(CC) -o $(ZSHPATH) $(OBJS) $(READLINE) -s -ltermcap
- -
- -$(OBJS): config.h
- -
- -zhistory.o: readline/history.h
- -
- -$(READLINE):
- - cd readline;make
- -
- -clean:
- - rm -f *.o zsh core readline/*.o
- -
- -install: zsh
- - install -s -m 755 zsh $(BINDIR)
- - install -m 444 zsh.1 $(MANDIR)
- -
- -tar: zsh.tar.Z
- -
- -zsh.tar: $(THINGS_TO_TAR)
- - tar -cf zsh.tar $(THINGS_TO_TAR)
- -
- -zsh.tar.Z: zsh.tar
- - compress -f zsh.tar
- -
- -shar: $(THINGS_TO_TAR)
- - bundle $(THINGS_TO_TAR) > zsh.shar
- -
- End of makefile
- echo sample.zshrc 1>&2
- sed 's/^-//' >sample.zshrc <<'End of sample.zshrc'
- -setenv() { export $1=$2 }
- -
- -umask 022
- -
- -PATH=$HOME/scr:$HOME/bin/$HOSTTYPE:/usr/local/bin:/usr/ucb:\
- -/usr/bin:/bin:/usr/local/bin/X11:/usr/etc:/etc
- -CDPATH=$HOME:/usr:/
- -export MANPATH=/usr/man:/usr/local/man
- -
- -HISTSIZE=50
- -setopt ignoreeof
- -
- -PROMPT='%n@%m [%h] %# '
- -
- -alias a alias
- -
- -a vi. 'vi ~/.cshrc'
- -a s. '. ~/.cshrc'
- -a more. 'more ~/.cshrc'
- -
- -chpwd() { pwd; ls -F }
- -lsl() { ls -algF $* | more }
- -
- -a back cd -
- -a h history
- -a cls /usr/ucb/clear
- -a type cat
- -a copy cp
- -a move mv
- -a del rm
- -a lo exit
- -a lsa 'ls -aF'
- -a dir 'ls -l'
- -a ll 'ls -F'
- -
- End of sample.zshrc
- echo sample.zlogin 1>&2
- sed 's/^-//' >sample.zlogin <<'End of sample.zlogin'
- -eval $(tset -Q -s '?xterm')
- -stty dec crt kill ^U dsusp ^X
- -msgs -q
- -date
- -biff y
- -
- -WATCH=$(echo $(<~/.friends) | tr ' ' :)
- -MAIL=/usr/spool/mail/$USERNAME
- -export DISPLAY=$(hostname):0.0
- -
- -limit coredumpsize 0
- -/usr/games/fortune
- -uptime
- End of sample.zlogin
- echo sample.zshrc.mine 1>&2
- sed 's/^-//' >sample.zshrc.mine <<'End of sample.zshrc.mine'
- -#
- -# my rc file for zsh
- -#
- -PATH=~/scr:~/bin/$HOSTTYPE:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:\
- -/u/maruchck/scr:/u/cs320/bin:/u/maruchck/bin:\
- -/usr/princeton/bin/X11:/usr/etc:/etc
- -CDPATH=~:~/src/cs320:~/src
- -umask 022
- -alias a alias
- -a pd pushd
- -a pop popd
- -limit core 0
- -a c cp
- -a grep egrep
- -a ps sps
- -a j jobs
- -a hide 'ARGV0=$(randline ~/pub/strings) '
- -a rn hide /usr/princeton/bin/rn.4.1
- -a v mv
- -a t cat
- -a where hostname'; echo >/dev/null'
- -a l ls -AF
- -a m make
- -a mm hide less
- -a talk hide talk
- -a h history
- -a a.out ./a.out
- -a more less
- -a strings strings -
- -a lock lock -p
- -a nw 'l -ltr | tail'
- -a -a 'M' \| less
- -a -a 'GF' \| fgrep -f ~/.friends
- -a -a 'sub' subbarao
- -a -a 'mjm' maruchck
- -a -a 'paswd' '<(ypcat passwd)'
- -a -a 'cex' '/u/pup/centrex'
- -a rable ls -AFltrd '*(R)'
- -a nrable ls -AFltrd '*(^R)'
- -a ';' vi
- -a 0 vi
- -a '<<' more
- -mostglob egrep sed
- -noglob find
- -PROMPT='Z %h %M:%~ '
- -FCEDIT=vi
- -LESSTERM=$(echo $TERMCAP | sed s/:ti=[^:]*:te=[^:]*:/:ti=:te=:/)
- -a less TERMCAP='"$LESSTERM"' /usr/princeton/bin/less
- -zsh=~/src/zsh
- -a k9 kill -9
- -cx() { chmod +x $* }
- -acx() { chmod 755 $* }
- -mere() { nroff -man -Tman $1 | less -s }
- -
- -[ `tty` = /dev/console ] || {
- - PERIOD=40
- - periodic() {
- - echo checking news... # check news every 40 minutes
- - rn -c
- - }
- -}
- -
- -randline() {
- - integer z;
- - z=$(wc -l <$1)
- - sed -n $[RANDOM%z+1]p $1
- - unset z
- -}
- -
- -eval "proto () { $(grep -v '^#' ~/scr/proto) }"
- -
- -snoop() {
- - (( $# )) || set `users`
- - fgrep -i -f </u/pup/st{udents,aff} <(
- - for i
- - do
- - ypmatch $i passwd
- - done | cut -d: -f5 | cut -d, -f1 |
- - awk '{ printf "%s,%s\n",$NF,substr($1,1,1) }')
- -}
- -
- -MAIL=/usr/spool/mail/pfalstad
- -MAILCHECK=30
- -HISTSIZE=600
- -setopt notify globdots autolist correct dextract pushdtohome cdablevars
- -unsetopt bgnice
- -WATCH=$(echo $(<~/.friends) | tr ' ' :)
- -WATCHFMT='%n %a %l from %m at %t.'
- -LOGCHECK=0
- -
- -[ -t ] && {
- - (cd ; hostname >! .where)
- -}
- -
- -export MANPATH=/usr/man:/usr/princeton/man:/u/cad/man
- -
- -setenv() { export $1=$2 }
- -
- End of sample.zshrc.mine
- echo sample.zlogin.mine 1>&2
- sed 's/^-//' >sample.zlogin.mine <<'End of sample.zlogin.mine'
- -#
- -# my login file for zsh
- -#
- -cd
- -ls -l /etc/motd
- -stty dec new cr0
- -eval $(tset -s -Q '?xterm')
- -stty -tabs
- -umask 022
- -export MAIL=/usr/spool/mail/$USER
- -MAILCHECK=60
- -# biff y
- -msgs -fp
- -uptime
- -/usr/games/fortune
- -log
- -echo Thought for the day: $(randline ~/pub/commands)
- -from 2>/dev/null
- -cat .todo
- -cat '. '
- -echo last login $(date) on $(hostname) >! .' '
- End of sample.zlogin.mine
- echo alias.pro 1>&2
- sed 's/^-//' >alias.pro <<'End of alias.pro'
- -char *dynread(char stop);
- -int filesub(void **namptr);
- -char *gethome(char *user,int len);
- -char *completehome(char *user,int len);
- -char *getsparmval(char *s,int len);
- -void setparml(char *s,int len,char *v);
- -void parmsub(table list);
- -void parminsall(table l,Node *nn,char **aptr,char **bptr);
- -void comminsall(table l,Node *nn,char **aptr,char **bptr);
- -void parmsuber(void **aptr,char **bptr);
- -void modify(void **str,char **ptr);
- -void tabmodify(table tab,char **ptr);
- -int napply(int (*func)(void **),table list);
- -int napplysplit(int (*func)(void **),table list);
- -void split(Node node,table list);
- -char *dstackent(int val);
- -void doshfuncs(comm comm);
- -void execshfunc(comm comm);
- -struct anode *mkanode(char *txt,int cmflag);
- -char *docompsubs(char *str,int *i);
- -void docmdsubs(char **str);
- -void dovarsubs(char **str);
- End of alias.pro
- echo builtin.c 1>&2
- sed 's/^-//' >builtin.c <<'End of builtin.c'
- -/*
- -
- - builtin.c - handles builtin commands
- -
- - This file is part of zsh, the Z shell.
- -
- - zsh is free software; no one can prevent you from reading the source
- - code, or giving it to someone else.
- - This file is copyrighted under the GNU General Public License, which
- - can be found in the file called COPYING.
- -
- - Copyright (C) 1990 Paul Falstad
- -
- - zsh is distributed in the hope that it will be useful, but
- - WITHOUT ANY WARRANTY. No author or distributor accepts
- - responsibility to anyone for the consequences of using it or for
- - whether it serves any particular purpose or works at all, unless he
- - says so in writing. Refer to the GNU General Public License
- - for full details.
- -
- - Everyone is granted permission to copy, modify and redistribute
- - zsh, but only under the conditions described in the GNU General Public
- - License. A copy of this license is supposed to have been given to you
- - along with zsh so you can know your rights and responsibilities.
- - It should be in a file named COPYING.
- -
- - Among other things, the copyright notice and this notice must be
- - preserved on all copies.
- -
- -*/
- -
- -#include "zsh.h"
- -#include "funcs.h"
- -#include <sys/signal.h>
- -#include <sys/fcntl.h>
- -#include <sys/errno.h>
- -#include <utmp.h>
- -#define MAXPATHLEN 1024
- -
- -int echo(comm comm)
- -{
- -table list;
- -char *str;
- -int nline = 1;
- -
- - list = comm->args;
- - if (full(list))
- - if (!strcmp("--",list->first->dat))
- - free(getnode(list));
- - else if (!strcmp("-n",list->first->dat))
- - {
- - free(getnode(list));
- - nline = 0;
- - }
- - if (str = getnode(list))
- - {
- - printf("%s",str);
- - free(str);
- - while (str = getnode(list))
- - {
- - printf(" %s",str);
- - free(str);
- - }
- - }
- - if (nline)
- - printf("\n");
- - return 0;
- -}
- -
- -/* print the directory stack */
- -
- -void pdstack(void)
- -{
- -Node node;
- -
- - printdir(cwd);
- - for (node = dirstack->first; node; node = node->next)
- - {
- - putchar(' ');
- - printdir(node->dat);
- - }
- - putchar('\n');
- -}
- -
- -/* exit */
- -
- -int zexit(comm comm)
- -{
- - if (interact)
- - if (!stopmsg)
- - {
- - checkjobs();
- - if (stopmsg)
- - {
- - stopmsg = 2;
- - return 1;
- - }
- - }
- - else
- - killrunjobs();
- - if (islogin && unset(NORCS))
- - sourcehome(".zlogout");
- - if (comm && full(comm->args))
- - lastval = atoi(getnode(comm->args));
- - if (sigtrapped[SIGEXIT])
- - dotrap(SIGEXIT);
- - exit(lastval); return 0;
- -}
- -
- -/* return */
- -
- -int zreturn(comm comm)
- -{
- - if (full(comm->args))
- - lastval = atoi(getnode(comm->args));
- - retflag = 1;
- - return lastval;
- -}
- -
- -int logout(comm comm)
- -{
- - if (!islogin)
- - {
- - zerrnam("logout","not login shell");
- - return 1;
- - }
- - return zexit(comm);
- -}
- -
- -int Unset(comm comm)
- -{
- -table list = comm->args;
- -char *s;
- -
- - while (full(list))
- - {
- - s = getnode(list);
- - unsetparm(s);
- - free(s);
- - }
- - return 0;
- -}
- -
- -int set(comm comm)
- -{
- -char *s,*t;
- -
- - if (!full(comm->args))
- - {
- - char **p = environ;
- -
- - while (*p)
- - puts(*p++);
- - listhtable(parmhtab,(void (*)(char *,char *)) pparm);
- - return 0;
- - }
- - s = getnode(comm->args);
- - t = getnode(pparms);
- - freetable(pparms,freestr);
- - pparms = newtable();
- - addnode(pparms,t);
- - while (s)
- - {
- - addnode(pparms,s);
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -struct option {
- - char *name;
- - char id;
- - };
- -
- -static struct option optns[] = {
- - "clobber",'1',
- - "nobadpattern",'2',
- - "nonomatch",'3',
- - "globdots",'4',
- - "notify",'5',
- - "allexport",'a',
- - "errexit",'e',
- - "bgnice",'6',
- - "ignoreeof",'7',
- - "keyword",'k',
- - "markdirs",'8',
- - "monitor",'m',
- - "noexec",'n',
- - "noglob",'F',
- - "norcs",'f',
- - "shinstdin",'s',
- - "nounset",'u',
- - "verbose",'v',
- - "xtrace",'x',
- - "interactive",'i',
- - "autolist",'9',
- - "correct",'0',
- - "dextract",'A',
- - "nobeep",'B',
- - "printexitvalue",'C',
- - "pushdtohome",'D',
- - "pushdsilent",'E',
- - "nullglob",'G',
- - "rmstarsilent",'H',
- - "ignorebraces",'I',
- - "cdablevars",'J',
- - "nobanghist",'K',
- - NULL,0
- -};
- -
- -int setopt(comm comm)
- -{
- - return csetopt(comm,0);
- -}
- -
- -int unsetopt(comm comm)
- -{
- - return csetopt(comm,1);
- -}
- -
- -/* common code for setopt and unsetopt */
- -
- -int csetopt(comm comm,int isun)
- -{
- -char *s,*os,*cmd;
- -int flag;
- -struct option *opp;
- -
- - cmd = (isun) ? "unsetopt" : "setopt";
- - if (!full(comm->args))
- - {
- - if (isun)
- - return 0;
- - for (opp = optns; opp->name; opp++)
- - if (opts[opp->id] == OPT_SET)
- - puts(opp->name);
- - return 0;
- - }
- - while ((os = s = getnode(comm->args)) && ((flag = *s == '-') || *s == '+'))
- - {
- - while (*++s)
- - if (*s == INTERACTIVE || *s == MONITOR)
- - zerrnam(cmd,"can't change that option");
- - else if (opts[*s & 0x7f] != OPT_INVALID)
- - opts[*s & 0x7f] = (flag^isun) ? OPT_SET : OPT_UNSET;
- - else
- - zerrnam(cmd,"illegal option: %c",*s);
- - free(os);
- - }
- - if (!s)
- - return 0;
- - while (s)
- - {
- - for (opp = optns; opp->name; opp++)
- - if (!strcmp(opp->name,s))
- - break;
- - if (opp->name)
- - {
- - if (opp->id == INTERACTIVE || opp->id == MONITOR)
- - zerrnam(cmd,"can't change that option");
- - else
- - opts[opp->id] = (isun) ? OPT_UNSET : OPT_SET;
- - }
- - else
- - {
- - zerrnam(cmd,"no such option: %s",s);
- - free(s);
- - return 1;
- - }
- - free(s);
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -/* print a positional parameter */
- -
- -void pparm(char *s,struct pmnode *t)
- -{
- - if (s && t)
- - if (t->isint)
- - printf("%s=%ld\n",s,t->u.val);
- - else
- - {
- - printf("%s=",s);
- - niceprint(t->u.str);
- - putchar('\n');
- - }
- -}
- -
- -int dirs(comm comm)
- -{
- - if (comm->args->first)
- - {
- - if (dirstack)
- - freetable(dirstack,freestr);
- - dirstack = comm->args;
- - comm->args = NULL;
- - }
- - else
- - pdstack();
- - return 0;
- -}
- -
- -/* call func once for each entry in a hash table */
- -
- -void listhtable(htable ht,void (*func)(char *,char *))
- -{
- -int t0;
- -struct hnode *hn;
- -
- - for (t0 = ht->hsize-1; t0 >= 0; t0--)
- - for (hn = ht->nodes[t0]; hn; hn = hn->hchain)
- - func(hn->nam,hn->dat);
- -}
- -
- -/* print an alias (used with listhtable) */
- -
- -void palias(char *s,struct anode *t)
- -{
- - if (t && t->cmd >= 0)
- - {
- - printf((t->cmd) ? "alias %-13s " : "alias -a %-10s ",s);
- - niceprint(t->text);
- - putchar('\n');
- - }
- -}
- -
- -/* print a shell function (used with listhtable) */
- -
- -void pshfunc(char *s,list l)
- -{
- -char *t;
- -
- - t = getltext(l);
- - untokenize(t);
- - printf("%s() {\n%s\n}\n",s,t);
- - free(t);
- -}
- -
- -void niceprint(char *s)
- -{
- - niceprintf(s,stdout);
- -}
- -
- -void niceprintf(char *s,FILE *f)
- -{
- - for (; *s; s++)
- - {
- - if (*s >= 32 && *s <= 126)
- - fputc(*s,f);
- - else if (*s == '\n')
- - {
- - putc('\\',f);
- - putc('n',f);
- - }
- - else
- - {
- - putc('^',f);
- - fputc(*s | 0x40,f);
- - }
- - }
- -}
- -
- -/* build a command line from a linked list */
- -
- -char *buildline(table t)
- -{
- -char *str = strdup(""),*s,*os;
- -
- - while (s = getnode(t))
- - {
- - os = str;
- - str = (*os) ? tricat(os," ",s) : strdup(s);
- - free(s);
- - free(os);
- - }
- - return str;
- -}
- -
- -int Alias(comm comm)
- -{
- -char *s1,*s2;
- -int anyflag = 0;
- -
- - if (!(s1 = getnode(comm->args)))
- - {
- - listhtable(alhtab,(void (*)(char *,char *)) palias);
- - return 0;
- - }
- - if (!strcmp(s1,"-a"))
- - {
- - anyflag = 1;
- - free(s1);
- - if (!(s1 = getnode(comm->args)))
- - {
- - zerrnam("alias","alias -a requires 2 arguments");
- - return 1;
- - }
- - }
- - if (!comm->args->first)
- - {
- - palias(s1,gethnode(s1,alhtab));
- - free(s1);
- - return 0;
- - }
- - s2 = buildline(comm->args);
- - addhnode(s1,mkanode(s2,!anyflag),alhtab,freeanode);
- - return 0;
- -}
- -
- -int cd(comm comm)
- -{
- - if (!full(comm->args))
- - return chcd("cd",strdup(getparm("HOME")));
- - if (comm->args->first->next)
- - {
- - char *s,*t,*u,*v;
- - int sl,tl;
- -
- - if (comm->args->first->next->next)
- - {
- - zerrnam("cd","too many arguments");
- - return 1;
- - }
- - s = getnode(comm->args);
- - t = getnode(comm->args);
- - if (!(u = (char *) strstr(cwd,s)))
- - {
- - zerrnam("cd","string not in pwd: %s",s);
- - return 1;
- - }
- - sl = strlen(s);
- - tl = strlen(t);
- - v = zalloc((u-cwd)+tl+strlen(u+sl)+1);
- - strncpy(v,cwd,u-cwd);
- - strcpy(v+(u-cwd),t);
- - strcat(v,u+sl);
- - free(s);
- - free(t);
- - return chcd("cd",v);
- - }
- - return chcd("cd",getnode(comm->args));
- -}
- -
- -int dot(comm comm)
- -{
- -char *s;
- -
- - if (!full(comm->args))
- - return 1;
- - s = getnode(comm->args);
- - if (source(s))
- - {
- - zerrnam(".","%e: %s",errno,s);
- - free(s);
- - return 1;
- - }
- - free(s);
- - return 0;
- -}
- -
- -int Umask(comm comm)
- -{
- -char *s,*t;
- -int t0;
- -
- - if (!full(comm->args))
- - {
- - t0 = umask(0);
- - umask(t0);
- - printf("%03o\n",t0);
- - return 0;
- - }
- - s = getnode(comm->args);
- - t0 = strtol(s,&t,8);
- - if (*t)
- - {
- - zerrnam("umask","bad umask");
- - free(s);
- - return 1;
- - }
- - umask(t0);
- - free(s);
- - return 0;
- -}
- -
- -int which(comm comm)
- -{
- -struct chnode *chn;
- -struct anode *a;
- -char *str = getnode(comm->args),*cnam;
- -
- - if (!str)
- - {
- - zerrnam("which","argument required");
- - return 1;
- - }
- - if ((a = gethnode(str,alhtab)) && a->cmd)
- - {
- - if (a->cmd < 0)
- - printf("%s: shell reserved word\n",str);
- - else
- - printf("%s: aliased to %s\n",str,a->text);
- - free(str);
- - return 0;
- - }
- - if (gethnode(str,shfunchtab))
- - printf("%s: shell function\n",str);
- - else if (chn = gethnode(str,chtab))
- - {
- - if (chn->type != BUILTIN)
- - puts(chn->u.nam);
- - else
- - printf("%s: shell built-in command\n",str);
- - }
- - else if (!(cnam = findcmd(str)))
- - {
- - zerr("command not found: %s",str);
- - free(str);
- - return 1;
- - }
- - else
- - puts(cnam);
- - free(str);
- - return 0;
- -}
- -
- -int popd(comm comm)
- -{
- -int val = 0;
- -char *s;
- -Node node;
- -
- - if (comm->args->first && *(s = comm->args->first->dat) == '+')
- - val = atoi(s+1);
- - if (val--)
- - {
- - if (val < 0)
- - node = dirstack->last;
- - else
- - for (node = dirstack->first; val && node; node = node->next,
- - val--);
- - free(remnode(dirstack,node));
- - if (unset(PUSHDSILENT))
- - pdstack();
- - return 0;
- - }
- - else
- - {
- - if (!full(dirstack))
- - {
- - zerrnam("popd","dir stack empty");
- - return 1;
- - }
- - val = chcd("popd",getnode(dirstack));
- - if (unset(PUSHDSILENT))
- - pdstack();
- - return val;
- - }
- -}
- -
- -int pushd(comm comm)
- -{
- -char *s;
- -int num;
- -
- - if (comm->args->first)
- - {
- - s = getnode(comm->args);
- -
- - if (*s == '+')
- - {
- - if (!(num = atoi(s+1)))
- - {
- - free(s);
- - return 0;
- - }
- - free(s);
- - if (isset(DEXTRACT))
- - {
- - Node n = dirstack->first;
- -
- - insnode(dirstack,(Node) dirstack,strdup(cwd));
- - while (--num && n)
- - n = n->next;
- - if (!n)
- - {
- - zerrnam("pushd","not that many dir stack entries");
- - return 1;
- - }
- - insnode(dirstack,(Node) dirstack,remnode(dirstack,n));
- - }
- - else
- - {
- - addnode(dirstack,strdup(cwd));
- - while(--num)
- - addnode(dirstack,getnode(dirstack));
- - }
- - num = chcd("pushd",getnode(dirstack));
- - if (unset(PUSHDSILENT))
- - pdstack();
- - return num;
- - }
- - pushnode(dirstack,strdup(cwd));
- - num = chcd("pushd",s);
- - if (num)
- - free(getnode(dirstack));
- - else if (unset(PUSHDSILENT))
- - pdstack();
- - return num;
- - }
- - else
- - {
- - char *s;
- -
- - if (isset(PUSHDTOHOME))
- - s = strdup(getparm("HOME"));
- - else
- - s = getnode(dirstack);
- - if (!s)
- - {
- - zerrnam("pushd","dir stack empty");
- - return 1;
- - }
- - pushnode(dirstack,strdup(cwd));
- - num = chcd("pushd",s);
- - if (num)
- - free(getnode(dirstack));
- - else if (unset(PUSHDSILENT))
- - pdstack();
- - return num;
- - }
- -}
- -
- -/* common code for pushd, popd, cd */
- -
- -int chcd(char *cnam,char *cd)
- -{
- -char *s,*t;
- -char buf[MAXPATHLEN],*new = cd;
- -int t0,val,esav,pnew = 0;
- -
- - if (cd[0] == '-' && !cd[1])
- - {
- - free(cd);
- - cd = getparm("OLDPWD");
- - cd = strdup((cd) ? cd : ".");
- - }
- - if (*cd == '/')
- - {
- - val = chdir(new = cd);
- - esav = errno;
- - }
- - else
- - for (t0 = 0; t0 != cdpathct; t0++)
- - {
- - sprintf(buf,"%s/%s",cdpath[t0],cd);
- - if ((val = chdir(new = buf)) != -1)
- - {
- - if (t0)
- - pnew = 1;
- - break;
- - }
- - if (t0 && errno != ENOENT && errno != ENOTDIR)
- - zerrnam(cnam,"warning: %e: %s",errno,buf);
- - if (!t0)
- - esav = errno;
- - }
- - if (val == -1 && errno == ENOENT)
- - {
- - t = strdup(cd);
- - if (isset(CDABLEVARS) && (s = getparm(t)) && *s == '/')
- - if (chdir(new = s) != -1)
- - {
- - val = 0;
- - pnew = 1;
- - goto goneto;
- - }
- - free(t);
- - zerrnam(cnam,"%e: %s",esav,cd);
- - free(cd);
- - return 1;
- - }
- -goneto:
- - if (val == -1)
- - {
- - zerrnam(cnam,"%e: %s",esav,cd);
- - free(cd);
- - return 1;
- - }
- - else
- - {
- - list l;
- -
- - if (cwd)
- - setparm(strdup("OLDPWD"),cwd,0,0);
- - cwd = findcwd(new);
- - setparm(strdup("PWD"),strdup(cwd),0,0);
- - if (pnew)
- - {
- - printdir(cwd);
- - putchar('\n');
- - }
- - if (l = gethnode("chpwd",shfunchtab))
- - newrunlist(l);
- - }
- - return 0;
- -}
- -
- -int shift(comm comm)
- -{
- -char *s;
- -int sh = 1;
- -
- - if (comm->args->first && (s = comm->args->first->dat))
- - sh = atoi(s);
- - while (sh-- && pparms->first->next)
- - remnode(pparms,pparms->first->next);
- - return 0;
- -}
- -
- -int unhash(comm comm)
- -{
- -char *s;
- -
- - if (!(s = getnode(comm->args)))
- - {
- - zerrnam("unhash","argument required");
- - return 1;
- - }
- - while (s)
- - {
- - if (!gethnode(s,chtab))
- - {
- - zerrnam("unhash","not in command table: %s",s);
- - return 1;
- - }
- - free(remhnode(s,chtab));
- - free(s);
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -int rehash(comm comm)
- -{
- - parsepath();
- - return 0;
- -}
- -
- -int hash(comm comm)
- -{
- -char *s,*t;
- -struct chnode *chn;
- -
- - if (!(s = getnode(comm->args)) || !(t = getnode(comm->args)))
- - {
- - zerrnam("hash","not enough arguments");
- - if (s)
- - free(s);
- - return 1;
- - }
- - chn = alloc(sizeof(struct chnode));
- - chn->type = EXCMD_PREDOT;
- - chn->globstat = GLOB;
- - chn->u.nam = t;
- - addhnode(s,chn,chtab,freechnode);
- - return 0;
- -}
- -
- -int Break(comm comm)
- -{
- -char *s;
- -
- - if (!loops)
- - {
- - zerrnam("break","not in loop");
- - return 1;
- - }
- - if (!(s = getnode(comm->args)))
- - breaks = 1;
- - else if (atoi(s))
- - {
- - breaks = atoi(s);
- - free(s);
- - }
- - else
- - {
- - zerrnam("break","numeric argument required");
- - free(s);
- - return 1;
- - }
- - return 0;
- -}
- -
- -int colon(comm comm)
- -{
- - return 0;
- -}
- -
- -int Glob(comm comm)
- -{
- -struct chnode *chn;
- -char *s;
- -
- - while (s = getnode(comm->args))
- - {
- - chn = gethnode(s,chtab);
- - free(s);
- - if (chn)
- - chn->globstat = GLOB;
- - }
- - return 0;
- -}
- -
- -int noglob(comm comm)
- -{
- -struct chnode *chn;
- -char *s;
- -
- - while (s = getnode(comm->args))
- - {
- - chn = gethnode(s,chtab);
- - free(s);
- - if (chn)
- - chn->globstat = NOGLOB;
- - }
- - return 0;
- -}
- -
- -int mostglob(comm comm)
- -{
- -struct chnode *chn;
- -char *s;
- -
- - while (s = getnode(comm->args))
- - {
- - chn = gethnode(s,chtab);
- - free(s);
- - if (chn)
- - chn->globstat = MOSTGLOB;
- - }
- - return 0;
- -}
- -
- -int unfunction(comm comm)
- -{
- -char *s1;
- -list l;
- -
- - while (s1 = getnode(comm->args))
- - {
- - unsettrap(s1);
- - if (l = remhnode(s1,shfunchtab))
- - freelist(l);
- - free(s1);
- - }
- - return 0;
- -}
- -
- -int unalias(comm comm)
- -{
- -char *s1;
- -struct anode *an;
- -
- - while (s1 = getnode(comm->args))
- - {
- - if (an = remhnode(s1,alhtab))
- - freeanode(an);
- - free(s1);
- - }
- - return 0;
- -}
- -
- -/* != 0 if s is a prefix of t */
- -
- -int prefix(char *s,char *t)
- -{
- - while (*s && *t && *s == *t) s++,t++;
- - return (!*s);
- -}
- -
- -/* convert %%, %1, %foo, %?bar? to a job number */
- -
- -int getjob(char *s,char *prog)
- -{
- -int t0,retval;
- -char *os = s;
- -
- - if (*s++ != '%')
- - {
- - zerrnam(prog,"bad job specifier");
- - retval = -1; goto done;
- - }
- - if (*s == '%' || *s == '+' || !*s)
- - {
- - if (topjob == -1)
- - {
- - zerrnam(prog,"no current job");
- - retval = -1; goto done;
- - }
- - retval = topjob; goto done;
- - }
- - if (*s == '-')
- - {
- - if (prevjob == -1)
- - {
- - zerrnam(prog,"no previous job");
- - retval = -1; goto done;
- - }
- - retval = prevjob; goto done;
- - }
- - if (isdigit(*s))
- - {
- - t0 = atoi(s);
- - if (t0 && t0 < MAXJOB && jobtab[t0].stat && t0 != curjob)
- - { retval = t0; goto done; }
- - zerrnam(prog,"no such job");
- - retval = -1; goto done;
- - }
- - if (*s == '?')
- - {
- - struct procnode *pn;
- -
- - for (t0 = 0; t0 != MAXJOB; t0++)
- - if (jobtab[t0].stat && t0 != curjob)
- - for (pn = jobtab[t0].procs; pn; pn = pn->next)
- - if (strstr(pn->text,s+1))
- - { retval = t0; goto done; }
- - zerrnam(prog,"job not found: %s",s);
- - retval = -1; goto done;
- - }
- - for (t0 = 0; t0 != MAXJOB; t0++)
- - if (jobtab[t0].stat && jobtab[t0].procs && t0 != curjob &&
- - prefix(s,jobtab[t0].procs->text))
- - { retval = t0; goto done; }
- - zerrnam(prog,"job not found: %s",s);
- - retval = -1;
- -done:
- - free(os);
- - return retval;
- -}
- -
- -int fg(comm comm)
- -{
- -char *s1;
- -int ocj = curjob,job;
- -
- - scanjobs();
- - if (!jobbing)
- - {
- - zerr("no job control in this shell.");
- - return 1;
- - }
- - if (s1 = getnode(comm->args))
- - job = getjob(s1,"fg");
- - else
- - {
- - if (topjob == -1 || topjob == curjob)
- - {
- - zerrnam("fg","no current job");
- - return 1;
- - }
- - job = topjob;
- - }
- - if (job == -1)
- - return 1;
- - makerunning(jobtab+job);
- - if (topjob == job)
- - {
- - topjob = prevjob;
- - prevjob = job;
- - }
- - if (prevjob == job)
- - setprevjob();
- - printjob(jobtab+job,-1);
- - curjob = job;
- - if (strcmp(jobtab[job].cwd,cwd))
- - {
- - printf("(pwd: ");
- - printdir(jobtab[job].cwd);
- - printf(")\n");
- - }
- - settyinfo(&jobtab[job].ttyinfo);
- - attachtty(jobtab[job].gleader);
- - killpg(jobtab[job].gleader,SIGCONT);
- - waitjobs();
- - curjob = ocj;
- - return 0;
- -}
- -
- -int bg(comm comm)
- -{
- -char *s1;
- -int job,stopped;
- -
- - scanjobs();
- - if (!jobbing)
- - {
- - zerr("no job control in this shell.");
- - return 1;
- - }
- - if (s1 = getnode(comm->args))
- - job = getjob(s1,"bg");
- - else
- - {
- - if (topjob == -1 || topjob == curjob)
- - {
- - zerrnam("bg","no current job");
- - return 1;
- - }
- - job = topjob;
- - }
- - if (job == -1)
- - return 1;
- - if (!(jobtab[job].stat & STAT_STOPPED))
- - {
- - zerrnam("bg","job already in background");
- - return 1;
- - }
- - stopped = jobtab[job].stat & STAT_STOPPED;
- - if (stopped)
- - makerunning(jobtab+job);
- - if (topjob == job)
- - {
- - topjob = prevjob;
- - prevjob = -1;
- - }
- - if (prevjob == job)
- - prevjob = -1;
- - if (prevjob == -1)
- - setprevjob();
- - if (topjob == -1)
- - {
- - topjob = prevjob;
- - setprevjob();
- - }
- - printjob(jobtab+job,(stopped) ? -1 : 0);
- - if (stopped)
- - killpg(jobtab[job].gleader,SIGCONT);
- - return 0;
- -}
- -
- -int jobs(comm comm)
- -{
- -int job,lng = 0;
- -
- - if (full(comm->args))
- - {
- - if (comm->args->first->next || (strcmp(comm->args->first->dat,"-l")
- - && strcmp(comm->args->first->dat,"-p")))
- - {
- - zerrnam("jobs","usage: jobs [ -lp ]");
- - return 1;
- - }
- - lng = (strcmp(comm->args->first->dat,"-l")) ? 2 : 1;
- - }
- - for (job = 0; job != MAXJOB; job++)
- - if (job != curjob && jobtab[job].stat)
- - printjob(job+jobtab,lng);
- - stopmsg = 2;
- - return 0;
- -}
- -
- -int Kill(comm comm)
- -{
- -int sig = SIGTERM;
- -char *s;
- -
- - s = getnode(comm->args);
- - if (s && *s == '-')
- - {
- - if (isdigit(s[1]))
- - sig = atoi(s+1);
- - else
- - {
- - if (s[1] == 'l' && s[2] == '\0')
- - {
- - printf("%s",sigs[0]);
- - for (sig = 1; sig != SIGCOUNT; sig++)
- - printf(" %s",sigs[sig]);
- - putchar('\n');
- - return 0;
- - }
- - for (sig = 0; sig != SIGCOUNT; sig++)
- - if (!strcmp(sigs[sig],s+1))
- - break;
- - if (sig == SIGCOUNT)
- - {
- - zerrnam("kill","unknown signal: SIG%s",s+1);
- - zerrnam("kill","type kill -l for a list of signals");
- - return 1;
- - }
- - }
- - s = getnode(comm->args);
- - }
- - while (s)
- - {
- - if (*s == '%')
- - {
- - int job = getjob(s,"kill");
- -
- - if (killjb(jobtab+job,sig) == -1)
- - {
- - zerrnam("kill","kill failed: %e",errno);
- - return 1;
- - }
- - if (jobtab[job].stat & STAT_STOPPED && sig == SIGCONT)
- - jobtab[job].stat &= ~STAT_STOPPED;
- - if (sig != SIGKILL)
- - killpg(jobtab[job].gleader,SIGCONT);
- - }
- - else
- - if (kill(atoi(s),sig) == -1)
- - {
- - zerrnam("kill","kill failed: %e");
- - return 1;
- - }
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -int export(comm comm)
- -{
- -char *s,*t;
- -struct pmnode *pm;
- -
- - while (s = getnode(comm->args))
- - {
- - if (t = strchr(s,'='))
- - {
- - *t = '\0';
- - if (pm = gethnode(s,parmhtab))
- - freepm(remhnode(s,parmhtab));
- - *t = '=';
- - putenv(s);
- - }
- - else
- - {
- - if (!(pm = gethnode(s,parmhtab)))
- - {
- - if (!getenv(s))
- - {
- - zerrnam("export","parameter not set: %s",s);
- - free(s);
- - return 1;
- - }
- - }
- - else if (pm->isint)
- - {
- - zerrnam("export","can't export integer parameters");
- - free(s);
- - return 1;
- - }
- - else
- - {
- - t = tricat(s,"=",pm->u.str);
- - putenv(t);
- - free(remhnode(s,parmhtab));
- - }
- - }
- - }
- - return 0;
- -}
- -
- -int integer(comm comm)
- -{
- -char *s,*t;
- -struct pmnode *uu;
- -
- - while (s = getnode(comm->args))
- - {
- - if (t = strchr(s,'='))
- - {
- - *t = '\0';
- - setparm(s,t+1,0,1);
- - *t = '=';
- - }
- - else
- - {
- - uu = gethnode(s,parmhtab);
- - if (uu)
- - {
- - if (!uu->isint)
- - {
- - uu->isint = 1;
- - uu->u.val = matheval(uu->u.str);
- - }
- - }
- - else
- - setiparm(s,0,1);
- - }
- - }
- - return 0;
- -}
- -
- -static char *recs[] = {
- - "cputime","filesize","datasize","stacksize","coredumpsize",
- - "resident","descriptors"
- - };
- -
- -int limit(comm comm)
- -{
- -char *s;
- -int hard = 0,t0,lim;
- -long val;
- -
- - if (!(s = getnode(comm->args)))
- - {
- - showlimits(0,-1);
- - return 0;
- - }
- - if (!strcmp(s,"-s"))
- - {
- - if (full(comm->args))
- - zerr("limit","arguments after -s ignored");
- - for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - if (setrlimit(t0,limits+t0) < 0)
- - zerr("limit","setrlimit failed: %e",errno);
- - return 0;
- - }
- - if (!strcmp(s,"-h"))
- - {
- - hard = 1;
- - free(s);
- - if (!(s = getnode(comm->args)))
- - {
- - showlimits(1,-1);
- - return 0;
- - }
- - }
- - while (s)
- - {
- - for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - if (!strncmp(recs[t0],s,strlen(s)))
- - {
- - if (lim != -1)
- - lim = -2;
- - else
- - lim = t0;
- - }
- - if (lim < 0)
- - {
- - zerrnam("limit",
- - (lim == -2) ? "ambiguous resource specification: %s"
- - : "no such resource: %s",s);
- - free(s);
- - return 1;
- - }
- - free(s);
- - if (!(s = getnode(comm->args)))
- - {
- - showlimits(hard,lim);
- - return 0;
- - }
- - if (!lim)
- - {
- - char *ss = s;
- -
- - val = strtol(s,&s,10);
- - if (*s)
- - if ((*s == 'h' || *s == 'H') && !s[1])
- - val *= 3600L;
- - else if ((*s == 'm' || *s == 'M') && !s[1])
- - val *= 60L;
- - else if (*s == ':')
- - val = val*60+strtol(s+1,&s,10);
- - else
- - {
- - zerrnam("limit","unknown scaling factor: %s",s);
- - free(ss);
- - return 1;
- - }
- - }
- -#ifdef RLIMIT_NOFILE
- - else if (lim == RLIMIT_NOFILE)
- - val = strtol(s,&s,10);
- -#endif
- - else
- - {
- - char *ss = s;
- -
- - val = strtol(s,&s,10);
- - if (!*s || ((*s == 'k' || *s == 'K') && !s[1]))
- - val *= 1024L;
- - else if ((*s == 'M' || *s == 'm') && !s[1])
- - val *= 1024L*1024;
- - else
- - {
- - zerrnam("limit","unknown scaling factor: %s",s);
- - free(ss);
- - return 1;
- - }
- - free(ss);
- - }
- - if (hard)
- - if (val > limits[lim].rlim_max && geteuid())
- - {
- - zerrnam("limit","can't raise hard limits");
- - return 1;
- - }
- - else
- - {
- - limits[lim].rlim_max = val;
- - if (limits[lim].rlim_max < limits[lim].rlim_cur)
- - limits[lim].rlim_cur = limits[lim].rlim_max;
- - }
- - else
- - if (val > limits[lim].rlim_max)
- - {
- - zerrnam("limit","limit exceeds hard limit");
- - return 1;
- - }
- - else
- - limits[lim].rlim_cur = val;
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -int unlimit(comm comm)
- -{
- -char *s = getnode(comm->args);
- -int hard = 0,t0,lim;
- -
- - if (s && !strcmp(s,"-h"))
- - {
- - hard = 1;
- - if (geteuid())
- - {
- - zerrnam("unlimit","can't remove hard limits");
- - return 1;
- - }
- - free(s);
- - s = getnode(comm->args);
- - }
- - if (!s)
- - {
- - for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - {
- - if (hard)
- - limits[t0].rlim_max = RLIM_INFINITY;
- - else
- - limits[t0].rlim_cur = limits[t0].rlim_max;
- - }
- - return 0;
- - }
- - while (s)
- - {
- - for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - if (!strncmp(recs[t0],s,strlen(s)))
- - {
- - if (lim != -1)
- - lim = -2;
- - else
- - lim = t0;
- - }
- - if (lim < 0)
- - {
- - zerrnam("unlimit",
- - (lim == -2) ? "ambiguous resource specification: %s"
- - : "no such resource: %s",s);
- - free(s);
- - return 1;
- - }
- - free(s);
- - if (hard)
- - limits[lim].rlim_max = RLIM_INFINITY;
- - else
- - limits[lim].rlim_cur = limits[lim].rlim_max;
- - s = getnode(comm->args);
- - }
- - return 0;
- -}
- -
- -void showlimits(int hard,int lim)
- -{
- -int t0;
- -long val;
- -
- - for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - if (t0 == lim || lim == -1)
- - {
- - printf("%-16s",recs[t0]);
- - val = (hard) ? limits[t0].rlim_max : limits[t0].rlim_cur;
- - if (val == RLIM_INFINITY)
- - printf("unlimited\n");
- - else if (!t0)
- - printf("%d:%02d:%02d\n",(int) (val/3600),
- - (int) (val/60) % 60,(int) (val % 60));
- -#ifdef RLIMIT_NOFILE
- - else if (t0 == RLIMIT_NOFILE)
- - printf("%d\n",(int) val);
- -#endif
- - else if (val >= 1024L*1024L)
- - printf("%ldMb\n",val/(1024L*1024L));
- - else
- - printf("%ldKb\n",val/1024L);
- - }
- -}
- -
- -int sched(comm comm)
- -{
- -char *s = getnode(comm->args);
- -time_t t;
- -long h,m;
- -struct tm *tm;
- -struct schnode *sch,*sch2,*schl;
- -int t0;
- -
- - if (s && *s == '-')
- - {
- - t0 = atoi(s+1);
- -
- - if (!t0)
- - {
- - zerrnam("sched","usage for delete: sched -<item#>.");
- - return 1;
- - }
- - for (schl = (struct schnode *) &scheds, sch = scheds, t0--;
- - sch && t0; sch = (schl = sch)->next, t0--);
- - if (!sch)
- - {
- - zerrnam("sched","not that many entries");
- - return 1;
- - }
- - schl->next = sch->next;
- - free(sch->cmd);
- - free(sch);
- - return 0;
- - }
- - if (s && !full(comm->args))
- - {
- - zerrnam("sched","not enough arguments");
- - return 1;
- - }
- - if (!s)
- - {
- - char tbuf[40];
- -
- - for (t0 = 1, sch = scheds; sch; sch = sch->next,t0++)
- - {
- - t = sch->time;
- - tm = localtime(&t);
- - strftime(tbuf,20,"%a %b %e %k:%M:%S",tm);
- - printf("%3d %s %s\n",t0,tbuf,sch->cmd);
- - }
- - return 0;
- - }
- - if (*s == '+')
- - {
- - h = strtol(s+1,&s,10);
- - if (*s != ':')
- - {
- - zerrnam("sched","bad time specifier");
- - return 1;
- - }
- - m = strtol(s+1,&s,10);
- - if (*s)
- - {
- - zerrnam("sched","bad time specifier");
- - return 1;
- - }
- - t = time(NULL)+h*3600+m*60;
- - }
- - else
- - {
- - h = strtol(s,&s,10);
- - if (*s != ':')
- - {
- - zerrnam("sched","bad time specifier");
- - return 1;
- - }
- - m = strtol(s+1,&s,10);
- - if (*s && *s != 'a' && *s != 'p')
- - {
- - zerrnam("sched","bad time specifier");
- - return 1;
- - }
- - t = time(NULL);
- - tm = localtime(&t);
- - t -= tm->tm_sec+tm->tm_min*60+tm->tm_hour*3600;
- - if (*s == 'p')
- - h += 12;
- - t += h*3600+m*60;
- - if (t < time(NULL))
- - t += 3600*24;
- - }
- - sch = alloc(sizeof(struct schnode));
- - sch->time = t;
- - sch->cmd = buildline(comm->args);
- - sch->next = NULL;
- - for (sch2 = (struct schnode *) &scheds; sch2->next; sch2 = sch2->next);
- - sch2->next = sch;
- - return 0;
- -}
- -
- -int eval(comm comm)
- -{
- -char *s = buildline(comm->args);
- -list list;
- -
- - hungets(s);
- - strinbeg();
- - if (!(list = parlist(1)))
- - {
- - hflush();
- - strinend();
- - return 1;
- - }
- - strinend();
- - runlist(list);
- - return lastval;
- -}
- -
- -int Brk(comm comm)
- -{
- - printf("%lx\n",(long) sbrk(0));
- - return 0;
- -}
- -
- -static struct utmp *wtab;
- -static int wtabsz;
- -
- -int log(comm comm)
- -{
- - if (!getparm("WATCH"))
- - return 1;
- - if (wtab)
- - free(wtab);
- - wtab = (struct utmp *) zalloc(1);
- - wtabsz = 0;
- - watch();
- - return 0;
- -}
- -
- -int let(comm comm)
- -{
- -char *str;
- -long val;
- -
- - while (str = getnode(comm->args))
- - val = matheval(str);
- - return !val;
- -}
- -
- -int Read(comm comm)
- -{
- -char *str,*pmpt;
- -int r = 0,bsiz,c,gotnl = 0;
- -char *buf,*bptr;
- -char cc;
- -
- - str = getnode(comm->args);
- - if (str && !strcmp(str,"-r"))
- - {
- - r = 1;
- - str = getnode(comm->args);
- - }
- - if (!str)
- - str = strdup("REPLY");
- - if (interact)
- - {
- - for (pmpt = str; *pmpt && *pmpt != '?'; pmpt++);
- - if (*pmpt++)
- - {
- - write(2,pmpt,strlen(pmpt));
- - *pmpt = '\0';
- - }
- - }
- - while (full(comm->args))
- - {
- - buf = bptr = zalloc(bsiz = 64);
- - FOREVER
- - {
- - if (gotnl)
- - break;
- - if (read(0,&cc,1) == 1)
- - c = cc;
- - else
- - c = EOF;
- - if (c == EOF || znspace(c))
- - break;
- - *bptr++ = c;
- - if (bptr == buf+bsiz)
- - {
- - buf = realloc(buf,bsiz *= 2);
- - bptr = buf+(bsiz/2);
- - }
- - }
- - if (c == EOF)
- - return 1;
- - if (c == '\n')
- - gotnl = 1;
- - *bptr = '\0';
- - setparm(str,buf,0,0);
- - str = getnode(comm->args);
- - }
- - buf = bptr = zalloc(bsiz = 64);
- - if (!gotnl)
- - FOREVER
- - {
- - if (read(0,&cc,1) == 1)
- - c = cc;
- - else
- - c = EOF;
- - if (c == EOF || c == '\n')
- - break;
- - *bptr++ = c;
- - if (bptr == buf+bsiz)
- - {
- - buf = realloc(buf,bsiz *= 2);
- - bptr = buf+(bsiz/2);
- - }
- - *bptr = '\0';
- - }
- - if (c == EOF)
- - return 1;
- - setparm(str,buf,0,0);
- - return 0;
- -}
- -
- -int fc(comm comm)
- -{
- -char *ename = getparm("FCEDIT"),*str,*s;
- -int n = 0,l = 0,r = 0,first = -1,last = -1,retval;
- -table subs = NULL;
- -
- - if (!interact)
- - {
- - zerrnam("fc","not interactive shell");
- - return 1;
- - }
- - remhist();
- - if (!ename)
- - ename = DEFFCEDIT;
- - str = getnode(comm->args);
- - for (; str && *str == '-' && str[1] && !isdigit(str[1]);
- - str = getnode(comm->args))
- - while (str[1])
- - switch(*++str)
- - {
- - case 'e':
- - if (str[1])
- - {
- - zerrnam("fc","editor name expected after -e");
- - return 1;
- - }
- - ename = getnode(comm->args);
- - if (!ename)
- - {
- - zerrnam("fc","editor name expected after -e");
- - return 1;
- - }
- - break;
- - case 'n':
- - n = 1;
- - break;
- - case 'l':
- - l = 1;
- - break;
- - case 'r':
- - r = 1;
- - break;
- - default:
- - zerrnam("fc","bad option: %c",*str);
- - return 1;
- - }
- - subs = newtable();
- - while (str)
- - {
- - for (s = str; *s && *s != '='; s++);
- - if (!*s)
- - break;
- - *s++ = '\0';
- - addnode(subs,str);
- - addnode(subs,s);
- - str = getnode(comm->args);
- - }
- - if (str)
- - {
- - first = fcgetcomm(str);
- - if (first == -1)
- - {
- - freetable(subs,freestr);
- - return 1;
- - }
- - str = getnode(comm->args);
- - }
- - if (str)
- - {
- - last = fcgetcomm(str);
- - if (last == -1)
- - {
- - freetable(subs,freestr);
- - return 1;
- - }
- - if (full(comm->args))
- - {
- - zerrnam("fc","too many arguments");
- - freetable(subs,freestr);
- - return 1;
- - }
- - }
- - if (first == -1)
- - {
- - first = (l) ? cev-16 : cev;
- - if (last == -1)
- - last = cev;
- - }
- - if (first < tfev)
- - first = tfev;
- - if (last == -1)
- - last = first;
- - if (l)
- - retval = fclist(stdout,!n,r,first,last,subs);
- - else
- - {
- - FILE *out;
- - char *fn = gettemp();
- -
- - out = fopen(fn,"w");
- - if (!out)
- - zerrnam("fc","can't open temp file: %e",errno);
- - else
- - {
- - retval = 1;
- - if (!fclist(out,0,r,first,last,subs))
- - if (fcedit(ename,fn))
- - if (stuff(fn))
- - zerrnam("fc","%e: %s",errno,s);
- - else
- - retval = 0;
- - }
- - unlink(fn);
- - free(fn);
- - }
- - freetable(subs,freestr);
- - return retval;
- -}
- -
- -/* get the history event associated with s */
- -
- -int fcgetcomm(char *s)
- -{
- -int cmd;
- -
- - if (cmd = atoi(s))
- - {
- - if (cmd < 0)
- - cmd = cev+cmd+1;
- - return cmd;
- - }
- - cmd = hcomsearch(s);
- - if (cmd == -1)
- - zerrnam("fc","event not found: %s",s);
- - return cmd;
- -}
- -
- -/* list a series of history events to a file */
- -
- -int fclist(FILE *f,int n,int r,int first,int last,table subs)
- -{
- -int done = 0,ct;
- -Node node;
- -char *s;
- -
- - if (!subs->first)
- - done = 1;
- - last -= first;
- - first -= tfev;
- - if (r)
- - first += last;
- - for (node = histlist->first,ct = first; ct && node;
- - node = node->next, ct--);
- - first += tfev;
- - while (last-- >= 0)
- - {
- - if (!node)
- - {
- - zerrnam("fc","no such event: %d",first);
- - return 1;
- - }
- - s = makehlist(node->dat,0);
- - done |= fcsubs(&s,subs);
- - if (n)
- - fprintf(f,"%5d ",first);
- - if (f == stdout)
- - {
- - niceprintf(s,f);
- - putc('\n',f);
- - }
- - else
- - fprintf(f,"%s\n",s);
- - node = (r) ? node->last : node->next;
- - (r) ? first-- : first++;
- - }
- - if (f != stdout)
- - fclose(f);
- - if (!done)
- - {
- - zerrnam("fc","no substitutions performed");
- - return 1;
- - }
- - return 0;
- -}
- -
- -/* perform old=new substituion */
- -
- -int fcsubs(char **sp,table tab)
- -{
- -Node n;
- -char *s1,*s2,*s3,*s4,*s = *sp,*s5;
- -int subbed = 0;
- -
- - for (n = tab->first; n; )
- - {
- - s1 = n->dat;
- - n = n->next;
- - s2 = n->dat;
- - n = n->next;
- - s5 = s;
- - while (s3 = (char *) strstr(s5,s1))
- - {
- - s4 = zalloc(1+(s3-s)+strlen(s2)+strlen(s3+strlen(s1)));
- - strncpy(s4,s,s3-s);
- - s4[s3-s] = '\0';
- - strcat(s4,s2);
- - s5 = s4+strlen(s4);
- - strcat(s4,s3+strlen(s1));
- - free(s);
- - s = s4;
- - subbed = 1;
- - }
- - }
- - *sp = s;
- - return subbed;
- -}
- -
- -int fcedit(char *ename,char *fn)
- -{
- - if (!strcmp(ename,"-"))
- - return 1;
- - return !zyztem(ename,fn);
- -}
- -
- -int disown(comm comm)
- -{
- -char *str;
- -int t0;
- -static struct jobnode zero;
- -
- - while (str = getnode(comm->args))
- - {
- - t0 = getjob(str,"disown");
- - if (t0 == -1)
- - return 1;
- - jobtab[t0] = zero;
- - }
- - return 0;
- -}
- -
- -int function(comm comm)
- -{
- - if (full(comm->args))
- - {
- - zerrnam("function","too many arguments");
- - return 1;
- - }
- - listhtable(shfunchtab,(void (*)(char *,char *)) pshfunc);
- - return 0;
- -}
- -
- -int (*funcs[])(comm) = {
- - echo,zexit,logout,Unset,dirs,
- - Alias,cd,which,popd,
- - dot,pushd,shift,unhash,Break,
- - colon,Glob,noglob,mostglob,unalias,
- - fg,bg,jobs,Kill,export,
- - Umask,cd,limit,unlimit,eval,
- - unfunction,set,Brk,log,builtin,
- - sched,let,fc,
- - rehash,hash,disown,test,Read,
- - integer,setopt,unsetopt,zreturn,function,
- - test,
- - NULL
- - };
- -char *funcnams[] = {
- - "echo","exit","logout","unset","dirs",
- - "alias","cd","which","popd",
- - ".","pushd","shift","unhash","break",
- - ":","glob","noglob","mostglob","unalias",
- - "fg","bg","jobs","kill","export",
- - "umask","chdir","limit","unlimit","eval",
- - "unfunction","set","brk","log","builtin",
- - "sched","let","fc",
- - "rehash","hash","disown","test","read",
- - "integer","setopt","unsetopt","return","function",
- - "["
- - };
- -
- -int builtin(comm comm)
- -{
- -char *s;
- -int t0;
- -
- - s = getnode(comm->args);
- - if (!s)
- - {
- - zerrnam("builtin","not enough arguments");
- - return 1;
- - }
- - for (t0 = 0; funcs[t0]; t0++)
- - if (!strcmp(funcnams[t0],s))
- - break;
- - if (!funcs[t0])
- - {
- - zerrnam("builtin","no such builtin: %s",s);
- - return 1;
- - }
- - return (funcs[t0])(comm);
- -}
- -
- -/* add builtins to the command hash table */
- -
- -void addintern(htable ht)
- -{
- -int (**ptr)(comm);
- -struct chnode *ch;
- -char **nam;
- -
- - for (ptr = funcs, nam = funcnams; *ptr; ptr++,nam++)
- - {
- - ch = alloc(sizeof(struct chnode));
- - ch->type = BUILTIN;
- - ch->u.func = *ptr;
- - addhnode(strdup(*nam),ch,ht,freechnode);
- - }
- -}
- -
- -/* get the time of login/logout for WATCH */
- -
- -static time_t getlogtime(struct utmp *u,int inout)
- -{
- -FILE *in;
- -struct utmp uu;
- -int first = 1;
- -
- - if (inout)
- - return u->ut_time;
- - if (!(in = fopen(WTMP_FILE,"r")))
- - return time(NULL);
- - fseek(in,0,2);
- - do
- - {
- - if (fseek(in,((first) ? -1 : -2)*sizeof(struct utmp),1))
- - {
- - fclose(in);
- - return time(NULL);
- - }
- - first = 0;
- - if (!fread(&uu,sizeof(struct utmp),1,in))
- - {
- - fclose(in);
- - return time(NULL);
- - }
- - }
- - while (memcmp(&uu,u,sizeof(struct utmp)));
- - do
- - if (!fread(&uu,sizeof(struct utmp),1,in))
- - {
- - fclose(in);
- - return time(NULL);
- - }
- - while (strncmp(uu.ut_line,u->ut_line,8));
- - fclose(in);
- - return uu.ut_time;
- -}
- -
- -/* print a login/logout event */
- -
- -static void watchlog2(int inout,struct utmp *u,char *fmt)
- -{
- -char *p,buf[40],*bf;
- -int i;
- -time_t timet;
- -struct tm *tm = NULL;
- -
- - while (*fmt)
- - if (*fmt != '%')
- - putchar(*fmt++);
- - else
- - {
- - fmt++;
- - switch(*fmt++)
- - {
- - case 'n':
- - printf("%.*s",8,u->ut_name);
- - break;
- - case 'a':
- - printf("%s",(!inout) ? "logged off" : "logged on");
- - break;
- - case 'l':
- - printf("%.*s",5,u->ut_line+3);
- - break;
- - case 'm':
- - for (p = u->ut_host,i = 16; i && *p;i--,p++)
- - {
- - if (*p == '.' && !isdigit(p[1]))
- - break;
- - putchar(*p);
- - }
- - break;
- - case 'M':
- - printf("%.*s",16,u->ut_host);
- - break;
- - case 't':
- - case '@':
- - timet = getlogtime(u,inout);
- - tm = localtime(&timet);
- - strftime(buf,40,"%l:%M%p",tm);
- - printf("%s",(*buf == ' ') ? buf+1 : buf);
- - break;
- - case 'T':
- - timet = getlogtime(u,inout);
- - tm = localtime(&timet);
- - strftime(buf,40,"%k:%M",tm);
- - printf("%s",buf);
- - break;
- - case 'w':
- - timet = getlogtime(u,inout);
- - tm = localtime(&timet);
- - strftime(buf,40,"%a %e",tm);
- - printf("%s",buf);
- - break;
- - case 'W':
- - timet = getlogtime(u,inout);
- - tm = localtime(&timet);
- - strftime(buf,40,"%m/%d/%y",tm);
- - printf("%s",buf);
- - break;
- - case 'D':
- - timet = getlogtime(u,inout);
- - tm = localtime(&timet);
- - strftime(buf,40,"%y-%m-%d",tm);
- - printf("%s",buf);
- - break;
- - case '%':
- - putchar('%');
- - break;
- - case 'S':
- - bf = buf;
- - if (tgetstr("so",&bf))
- - fputs(buf,stdout);
- - break;
- - case 's':
- - bf = buf;
- - if (tgetstr("se",&bf))
- - fputs(buf,stdout);
- - break;
- - case 'B':
- - bf = buf;
- - if (tgetstr("md",&bf))
- - fputs(buf,stdout);
- - break;
- - case 'b':
- - bf = buf;
- - if (tgetstr("me",&bf))
- - fputs(buf,stdout);
- - break;
- - case 'U':
- - bf = buf;
- - if (tgetstr("us",&bf))
- - fputs(buf,stdout);
- - break;
- - case 'u':
- - bf = buf;
- - if (tgetstr("ue",&bf))
- - fputs(buf,stdout);
- - break;
- - default:
- - putchar('%');
- - putchar(fmt[-1]);
- - break;
- - }
- - }
- - putchar('\n');
- -}
- -
- -/* check the list for login/logouts */
- -
- -static void watchlog(int inout,struct utmp *u,char *w,char *fmt)
- -{
- -char *v;
- -
- - if (!strcmp(w,"all"))
- - {
- - watchlog2(inout,u,fmt);
- - return;
- - }
- - for(;;)
- - if (v = strchr(w,':'))
- - {
- - if (!strncmp(u->ut_name,w,v-w))
- - watchlog2(inout,u,fmt);
- - w = v+1;
- - }
- - else
- - {
- - if (!strncmp(u->ut_name,w,8))
- - watchlog2(inout,u,fmt);
- - break;
- - }
- -}
- -
- -/* compare 2 utmp entries */
- -
- -static int ucmp(struct utmp *u,struct utmp *v)
- -{
- - if (u->ut_time == v->ut_time)
- - return strncmp(u->ut_line,v->ut_line,8);
- - return u->ut_time - v->ut_time;
- -}
- -
- -/* initialize the user list */
- -
- -void readwtab(void)
- -{
- -struct utmp *uptr;
- -int wtabmax = 32;
- -FILE *in;
- -
- - wtabsz = 0;
- - uptr = wtab = (struct utmp *) zalloc(wtabmax*sizeof(struct utmp));
- - in = fopen(UTMP_FILE,"r");
- - while (fread(uptr,sizeof(struct utmp),1,in))
- - if (uptr->ut_host[0])
- - {
- - uptr++;
- - if (++wtabsz == wtabmax)
- - uptr = (wtab = (struct utmp *) realloc(wtab,(wtabmax*=2)*
- - sizeof(struct utmp)))+wtabsz;
- - }
- - fclose(in);
- - if (wtabsz)
- - qsort(wtab,wtabsz,sizeof(struct utmp),ucmp);
- -}
- -
- -/* check for login/logout events; executed before each prompt
- - if WATCH is set */
- -
- -void watch(void)
- -{
- -char *s = getparm("WATCH");
- -char *fmt = getparm("WATCHFMT");
- -FILE *in;
- -int utabsz = 0,utabmax = wtabsz+4,uct,wct;
- -struct utmp *utab,*uptr,*wptr;
- -
- - holdintr();
- - if (!fmt)
- - fmt = "%n has %a %l from %m.";
- - if (!wtab)
- - {
- - readwtab();
- - noholdintr();
- - return;
- - }
- - uptr = utab = (struct utmp *) zalloc(utabmax*sizeof(struct utmp));
- - in = fopen(UTMP_FILE,"r");
- - while (fread(uptr,sizeof *uptr,1,in))
- - if (uptr->ut_host[0])
- - {
- - uptr++;
- - if (++utabsz == utabmax)
- - uptr = (utab = (struct utmp *) realloc(utab,(utabmax*=2)*
- - sizeof(struct utmp)))+utabsz;
- - }
- - fclose(in);
- - noholdintr();
- - if (errflag)
- - {
- - free(utab);
- - return;
- - }
- - if (utabsz)
- - qsort(utab,utabsz,sizeof(struct utmp),ucmp);
- -
- - wct = wtabsz; uct = utabsz;
- - uptr = utab; wptr = wtab;
- - if (errflag)
- - {
- - free(utab);
- - return;
- - }
- - while ((uct || wct) && !errflag)
- - if (!uct || (wct && ucmp(uptr,wptr) > 0))
- - wct--,watchlog(0,wptr++,s,fmt);
- - else if (!wct || (uct && ucmp(uptr,wptr) < 0))
- - uct--,watchlog(1,uptr++,s,fmt);
- - else
- - uptr++,wptr++,wct--,uct--;
- - free(wtab);
- - wtab = utab;
- - wtabsz = utabsz;
- - fflush(stdout);
- -}
- -
- End of builtin.c
- echo builtin.pro 1>&2
- sed 's/^-//' >builtin.pro <<'End of builtin.pro'
- -int echo(comm comm);
- -void pdstack(void);
- -int zexit(comm comm);
- -int zreturn(comm comm);
- -int logout(comm comm);
- -int Unset(comm comm);
- -int set(comm comm);
- -int setopt(comm comm);
- -int unsetopt(comm comm);
- -int csetopt(comm comm,int isun);
- -void pparm(char *s,struct pmnode *t);
- -int dirs(comm comm);
- -void listhtable(htable ht,void (*func)(char *,char *));
- -void palias(char *s,struct anode *t);
- -void pshfunc(char *s,list l);
- -void niceprint(char *s);
- -void niceprintf(char *s,FILE *f);
- -char *buildline(table t);
- -int Alias(comm comm);
- -int cd(comm comm);
- -int dot(comm comm);
- -int Umask(comm comm);
- -int which(comm comm);
- -int popd(comm comm);
- -int pushd(comm comm);
- -int chcd(char *cnam,char *cd);
- -int shift(comm comm);
- -int unhash(comm comm);
- -int rehash(comm comm);
- -int hash(comm comm);
- -int Break(comm comm);
- -int colon(comm comm);
- -int Glob(comm comm);
- -int noglob(comm comm);
- -int mostglob(comm comm);
- -int unfunction(comm comm);
- -int unalias(comm comm);
- -int prefix(char *s,char *t);
- -int getjob(char *s,char *prog);
- -int fg(comm comm);
- -int bg(comm comm);
- -int jobs(comm comm);
- -int Kill(comm comm);
- -int export(comm comm);
- -int integer(comm comm);
- -int limit(comm comm);
- -int unlimit(comm comm);
- -void showlimits(int hard,int lim);
- -int sched(comm comm);
- -int eval(comm comm);
- -int Brk(comm comm);
- -int log(comm comm);
- -int let(comm comm);
- -int Read(comm comm);
- -int fc(comm comm);
- -int fcgetcomm(char *s);
- -int fclist(FILE *f,int n,int r,int first,int last,table subs);
- -int fcsubs(char **sp,table tab);
- -int fcedit(char *ename,char *fn);
- -int disown(comm comm);
- -int function(comm comm);
- -int builtin(comm comm);
- -void addintern(htable ht);
- -void readwtab(void);
- -void watch(void);
- End of builtin.pro
- echo config.h 1>&2
- sed 's/^-//' >config.h <<'End of config.h'
- -/*
- -
- - config.h - configuration file
- -
- - This file is part of zsh, the Z shell.
- -
- - zsh is free software; no one can prevent you from reading the source
- - code, or giving it to someone else.
- - This file is copyrighted under the GNU General Public License, which
- - can be found in the file called COPYING.
- -
- - Copyright (C) 1990 Paul Falstad
- -
- - zsh is distributed in the hope that it will be useful, but
- - WITHOUT ANY WARRANTY. No author or distributor accepts
- - responsibility to anyone for the consequences of using it or for
- - whether it serves any particular purpose or works at all, unless he
- - says so in writing. Refer to the GNU General Public License
- - for full details.
- -
- - Everyone is granted permission to copy, modify and redistribute
- - zsh, but only under the conditions described in the GNU General Public
- - License. A copy of this license is supposed to have been given to you
- - along with zsh so you can know your rights and responsibilities.
- - It should be in a file named COPYING.
- -
- - Among other things, the copyright notice and this notice must be
- - preserved on all copies.
- -
- -*/
- -
- -/* define this if you have WAITPID */
- -
- -#define WAITPID
- -
- -/* define if the return type of signal handlers is int */
- -
- -/* #define INTHANDTYPE */
- -
- -/* the return type of handlers */
- -
- -#define HANDTYPE void
- -
- -/* define this if you have putenv */
- -
- -#define PUTENV
- -
- -/* define this if you have strstr */
- -
- -#define STRSTR
- -
- -/* define this if you have strftime */
- -
- -/* #define STRFTIME */
- -
- -/* define if you have struct termios, else struct sgttyb */
- -
- -#define TERMIOS
- -
- -#include "config.local.h"
- -
- End of config.h
- echo config.local.h 1>&2
- sed 's/^-//' >config.local.h <<'End of config.local.h'
- -/*
- -
- - config.local.h - local machine configuration file
- -
- - This file is part of zsh, the Z shell.
- -
- - zsh is free software; no one can prevent you from reading the source
- - code, or giving it to someone else.
- - This file is copyrighted under the GNU General Public License, which
- - can be found in the file called COPYING.
- -
- - Copyright (C) 1990 Paul Falstad
- -
- - zsh is distributed in the hope that it will be useful, but
- - WITHOUT ANY WARRANTY. No author or distributor accepts
- - responsibility to anyone for the consequences of using it or for
- - whether it serves any particular purpose or works at all, unless he
- - says so in writing. Refer to the GNU General Public License
- - for full details.
- -
- - Everyone is granted permission to copy, modify and redistribute
- - zsh, but only under the conditions described in the GNU General Public
- - License. A copy of this license is supposed to have been given to you
- - along with zsh so you can know your rights and responsibilities.
- - It should be in a file named COPYING.
- -
- - Among other things, the copyright notice and this notice must be
- - preserved on all copies.
- -
- -*/
- -
- -/* a string corresponding to the host type */
- -
- -#define HOSTTYP "sun4"
- -
- -/* define if you prefer "suspended" to "stopped" */
- -
- -#define USE_SUSPENDED
- -
- -/* the path of zsh in the file system */
- -
- -#define MYSELF "/usr/princeton/bin/zsh"
- -
- -/* the default editor for the fc builtin */
- -
- -#define DEFFCEDIT "/usr/ucb/vi"
- -
- -/* the file to source whenever zsh is run; if undefined, don't source
- - anything */
- -
- -#define GLOBALZSHRC "/etc/zshrc"
- -
- -/* the file to source whenever zsh is run as a login shell; if
- - undefined, don't source anything */
- -
- -#define GLOBALZLOGIN "/etc/zlogin"
- -
- -/* the default HISTSIZE */
- -
- -#define DEFAULT_HISTSIZE 128
- -
- -/* the path of utmp */
- -
- -#define UTMP_FILE "/etc/utmp"
- -
- -/* the path of wtmp */
- -
- -#define WTMP_FILE "/var/adm/wtmp"
- -
- -/* define if you have problems with job control or tty modes.
- - gcc-cpp does not seem to handle ioctls correctly. */
- -
- -/*#define BUGGY_GCC*/
- -
- -/* define if you like interactive comments */
- -
- -/*#define INTERACTIVE_COMMENTS*/
- -
- -/* define if you want warnings about nonexistent path components */
- -
- -#define PATH_WARNINGS
- -
- End of config.local.h
- echo exec.c 1>&2
- sed 's/^-//' >exec.c <<'End of exec.c'
- -/*
- -
- - exec.c - command execution
- -
- - This file is part of zsh, the Z shell.
- -
- - zsh is free software; no one can prevent you from reading the source
- - code, or giving it to someone else.
- - This file is copyrighted under the GNU General Public License, which
- - can be found in the file called COPYING.
- -
- - Copyright (C) 1990 Paul Falstad
- -
- - zsh is distributed in the hope that it will be useful, but
- - WITHOUT ANY WARRANTY. No author or distributor accepts
- - responsibility to anyone for the consequences of using it or for
- - whether it serves any particular purpose or works at all, unless he
- - says so in writing. Refer to the GNU General Public License
- - for full details.
- -
- - Everyone is granted permission to copy, modify and redistribute
- - zsh, but only under the conditions described in the GNU General Public
- - License. A copy of this license is supposed to have been given to you
- - along with zsh so you can know your rights and responsibilities.
- - It should be in a file named COPYING.
- -
- - Among other things, the copyright notice and this notice must be
- - preserved on all copies.
- -
- -*/
- -
- -#include "zsh.h"
- -#include "funcs.h"
- -#include <sys/errno.h>
- -#include <sys/dir.h>
- -
- -#define execerr() { if (forked) exit(1); freecmd(comm); \
- - closemnodes(mfds); errflag = 1; return; }
- -#define magicerr() { if (magic) putc('\n',stderr); errflag = 1; }
- -
- -/* execute a string */
- -
- -void execstring(char *s)
- -{
- -list l;
- -
- - hungets(strdup("\n"));
- - hungets(s);
- - strinbeg();
- - if (!(l = parlist(1)))
- - {
- - strinend();
- - hflush();
- - return;
- - }
- - if (peek != EOF && peek != EMPTY)
- - {
- - strinend();
- - hflush();
- - return;
- - }
- - strinend();
- - execlist(l);
- -}
- -
- -/* duplicate a list and run it */
- -
- -void newrunlist(list l)
- -{
- -list a = duplist(l); runlist(a);
- -}
- -
- -/* fork and set limits */
- -
- -int phork(void)
- -{
- -int pid = fork(),t0;
- -
- - if (pid == -1)
- - {
- - zerr("fork failed: %e",errno);
- - return -1;
- - }
- - if (!pid)
- - for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
- - setrlimit(t0,limits+t0);
- - return pid;
- -}
- -
- -/* execute a current shell command */
- -
- -void execcursh(comm comm)
- -{
- - runlist(comm->left);
- - comm->left = NULL;
- -}
- -
- -/* execve an external command */
- -
- -void execute(char *arg0,table args)
- -{
- -char **argv;
- -char *z,*s,buf[MAXPATHLEN],buf2[MAXPATHLEN];
- -struct chnode *cn;
- -int t0,tl,ee = 0;
- -
- -#define zexecve(X,Y,Z) {execve(z=(X),Y,Z);\
- - if(errno!=ENOENT){ee = errno;strcpy(buf2,buf);}}
- -
- - cn = gethnode(arg0,chtab);
- - if (s = getenv("STTY"))
- - zyztem("stty",s);
- - if (z = getenv("ARGV0"))
- - z = strdup(z);
- - else
- - z = arg0;
- - argv = makecline(z,args);
- - fixsigs();
- - if (cn)
- - {
- - if (cn->type == EXCMD_POSTDOT)
- - {zexecve(arg0,argv,environ);}
- - {zexecve(cn->u.nam,argv,environ);}
- - }
- - for (s = arg0; *s; s++)
- - if (*s == '/')
- - {
- - execve(arg0,argv,environ);
- - zerr("%e: %s",errno,arg0);
- - _exit(1);
- - }
- - for (t0 = pathct; t0; t0--,path++)
- - if (**path == '.')
- - {zexecve(arg0,argv,environ);}
- - else
- - {
- - tl = strlen(*path);
- - strcpy(buf,*path);
- - buf[tl] = '/';
- - if (strlen(arg0)+strlen(buf)+1 >= MAXPATHLEN)
- - {
- - zerr("command too long: %s",arg0);
- - _exit(1);
- - }
- - strcpy(buf+tl+1,arg0);
- - {zexecve(buf,argv,environ);}
- - }
- - if (ee)
- - {
- - z = buf2;
- - errno = ee;
- - goto errs;
- - }
- - zerr("command not found: %s",arg0);
- - _exit(1);
- -errs:
- - zerr("%e: %s",errno,z);
- - _exit(1);
- -}
- -
- -#define try(X) { if (!access(X,X_OK)) return strdup(X); }
- -
- -/* get the pathname of a command */
- -
- -char *findcmd(char *arg0)
- -{
- -char *s,buf[MAXPATHLEN];
- -int t0,tl;
- -struct chnode *cn = gethnode(arg0,chtab);
- -char **pp = path;
- -
- - if (cn)
- - {
- - if (cn->type == EXCMD_POSTDOT)
- - {
- - strcpy(buf,"./");
- - strcat(buf,arg0);
- - try(buf);
- - }
- - try(cn->u.nam);
- - }
- - for (s = arg0; *s; s++)
- - if (*s == '/')
- - {
- - try(arg0);
- - goto failed;
- - }
- - for (t0 = pathct; t0; t0--,pp++)
- - if (**pp == '.')
- - {
- - strcpy(buf,"./");
- - strcat(buf,arg0);
- - try(buf);
- - }
- - else
- - {
- - tl = strlen(*pp);
- - strcpy(buf,*pp);
- - buf[tl] = '/';
- - strcpy(buf+tl+1,arg0);
- - try(buf);
- - }
- -failed:
- - return NULL;
- -}
- -
- -void execlist(list list)
- -{
- - execlist1(list);
- - freelist(list);
- -}
- -
- -void execlist1(list list)
- -{
- - if (breaks)
- - return;
- - switch(list->type)
- - {
- - case SYNC:
- - case ASYNC:
- - execlist2(list->left,list->type,!list->right);
- - if (sigtrapped[SIGDEBUG])
- - dotrap(SIGDEBUG);
- - if (sigtrapped[SIGERR] && lastval)
- - dotrap(SIGERR);
- - if (list->right && !retflag)
- - execlist1(list->right);
- - break;
- - }
- -}
- -
- -void execlist2(list2 list,int type,int last1)
- -{
- - switch(list->type)
- - {
- - case END:
- - execpline(list,type,last1);
- - break;
- - case ORNEXT:
- - if (!execpline(list,SYNC,0))
- - execlist2(list->right,type,last1);
- - break;
- - case ANDNEXT:
- - if (execpline(list,SYNC,0))
- - execlist2(list->right,type,last1);
- - break;
- - }
- -}
- -
- -int execpline(list2 l,int how,int last1)
- -{
- -int ipipe[2] = {0,0},opipe[2] = {0,0};
- -
- - sigblock(sigmask(SIGCHLD));
- - curjob = getfreejob();
- - initjob(l->flags);
- - if (l->flags & PFLAG_COPROC)
- - {
- - how = ASYNC;
- - mpipe(ipipe);
- - mpipe(opipe);
- - if (spin)
- - {
- - close(spin);
- - close(spout);
- - }
- - spin = ipipe[0];
- - spout = opipe[1];
- - }
- - execpline2(l->left,how,opipe[0],ipipe[1],last1);
- - if (how == ASYNC)
- - {
- - spawnjob();
- - sigsetmask(0);
- - return 1;
- - }
- - else
- - {
- - waitjobs();
- - sigsetmask(0);
- - if (l->flags & PFLAG_NOT)
- - lastval = !lastval;
- - return !lastval;
- - }
- -}
- -
- -void execpline2(pline pline,int how,int input,int output,int last1)
- -{
- -int pid;
- -int pipes[2];
- -
- - if (breaks)
- - return;
- - if (!pline)
- - return;
- - if (pline->type == END)
- - {
- - execcomm(pline->left,input,output,how==ASYNC,last1);
- - pline->left = NULL;
- - }
- - else
- - {
- - mpipe(pipes);
- -
- - /* if we are doing "foo | bar" where foo is a current
- - shell command, do foo in the current shell and do
- - the rest of the pipeline in a subshell. */
- -
- - if (pline->left->type >= CURSH && how == SYNC)
- - {
- - if (!(pid = fork()))
- - {
- ---cut here---cut here---cut here---
-