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 -.PP -The command line editor is a hacked-up version -of the GNU readline library, -written by Brian Fox () 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. - - - Copyright (C) 19yy - - 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. - - , 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 ! .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 -#include -#include -#include -#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 -."); - 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 -#include - -#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---