diff options
author | June McEnroe <june@causal.agency> | 2019-06-28 22:28:32 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2019-06-28 22:28:32 -0400 |
commit | 2a0976b40a2b3888f9ba9f2d047f81b98837dc58 (patch) | |
tree | 0bdcc7964063ffbb9945b5538c4e1c42b91b2b64 /bin/catsh | |
parent | Set HISTSIZE in catsh (diff) | |
download | src-2a0976b40a2b3888f9ba9f2d047f81b98837dc58.tar.gz src-2a0976b40a2b3888f9ba9f2d047f81b98837dc58.zip |
Rename catsh to 1sh
Yes it's another rename because I felt like catsh was too long. 1sh is short and unique.
Diffstat (limited to 'bin/catsh')
118 files changed, 0 insertions, 47295 deletions
diff --git a/bin/catsh/.gitignore b/bin/catsh/.gitignore deleted file mode 100644 index b17c0219..00000000 --- a/bin/catsh/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.o -.depend -builtins.c -builtins.h -catsh -config.mk -mknodes -mksyntax -nodes.c -nodes.h -syntax.c -syntax.h -token.h diff --git a/bin/catsh/Makefile b/bin/catsh/Makefile deleted file mode 100644 index 092d8be6..00000000 --- a/bin/catsh/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -PREFIX = /usr/local -MANDIR = $(PREFIX)/share/man - -CFLAGS += -std=c99 -Wall -Wextra -DSHELL -Ilibedit -LDLIBS = -lcurses - --include config.mk - -SRCS += alias.c -SRCS += arith_yacc.c -SRCS += arith_yylex.c -SRCS += cd.c -SRCS += echo.c -SRCS += error.c -SRCS += eval.c -SRCS += exec.c -SRCS += expand.c -SRCS += histedit.c -SRCS += input.c -SRCS += jobs.c -SRCS += kill.c -SRCS += mail.c -SRCS += main.c -SRCS += memalloc.c -SRCS += miscbltin.c -SRCS += mystring.c -SRCS += options.c -SRCS += output.c -SRCS += parser.c -SRCS += printf.c -SRCS += redir.c -SRCS += show.c -SRCS += test.c -SRCS += trap.c -SRCS += var.c - -GENSRCS = builtins.c nodes.c syntax.c -GENHDRS = builtins.h nodes.h syntax.h token.h - -SRCS += $(GENSRCS) -OBJS = $(SRCS:.c=.o) libedit/libedit.a - -MAN1 = catsh.1 catsh-kill.1 catsh-printf.1 catsh-test.1 - -all: tags catsh - -catsh: $(OBJS) - $(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@ - -$(OBJS): $(GENHDRS) - -libedit/libedit.a: - $(MAKE) -C libedit libedit.a - -builtins.c builtins.h: mkbuiltins builtins.def - sh mkbuiltins . - -nodes.c nodes.h: mknodes nodetypes nodes.c.pat - ./mknodes nodetypes nodes.c.pat - -syntax.c syntax.h: mksyntax - ./mksyntax - -token.h: mktokens - sh mktokens - -tags: *.h *.c - ctags -w *.h *.c - -depend: $(SRCS) $(GENHDRS) - $(CC) $(CFLAGS) -MM $(SRCS) > .depend - --include .depend - -clean: - rm -f catsh $(OBJS) mknodes mksyntax $(GENSRCS) $(GENHDRS) tags .depend - -install: catsh $(MAN1) - install -d $(PREFIX)/bin $(MANDIR)/man1 - install catsh $(PREFIX)/bin - install -m 644 $(MAN1) $(MANDIR)/man1 - -uninstall: - rm -f $(PREFIX)/bin/catsh $(MAN1:%=$(MANDIR)/man1/%) - -shell: - grep -q '^$(PREFIX)/bin/catsh$$' /etc/shells \ - || echo '$(PREFIX)/bin/catsh' >> /etc/shells - -unshell: - sed -i sed '\;^$(PREFIX)/bin/catsh$$;d' /etc/shells diff --git a/bin/catsh/TOUR b/bin/catsh/TOUR deleted file mode 100644 index 68330af0..00000000 --- a/bin/catsh/TOUR +++ /dev/null @@ -1,301 +0,0 @@ -# @(#)TOUR 8.1 (Berkeley) 5/31/93 -# $FreeBSD: releng/12.0/bin/sh/TOUR 317882 2017-05-06 13:28:42Z jilles $ - -NOTE -- This is the original TOUR paper distributed with ash and -does not represent the current state of the shell. It is provided anyway -since it provides helpful information for how the shell is structured, -but be warned that things have changed -- the current shell is -still under development. - -================================================================ - - A Tour through Ash - - Copyright 1989 by Kenneth Almquist. - - -DIRECTORIES: The subdirectory bltin contains commands which can -be compiled stand-alone. The rest of the source is in the main -ash directory. - -SOURCE CODE GENERATORS: Files whose names begin with "mk" are -programs that generate source code. A complete list of these -programs is: - - program input files generates - ------- ----------- --------- - mkbuiltins builtins.def builtins.h builtins.c - mknodes nodetypes nodes.h nodes.c - mksyntax - syntax.h syntax.c - mktokens - token.h - -There are undoubtedly too many of these. - -EXCEPTIONS: Code for dealing with exceptions appears in -exceptions.c. The C language doesn't include exception handling, -so I implement it using setjmp and longjmp. The global variable -exception contains the type of exception. EXERROR is raised by -calling error. EXINT is an interrupt. - -INTERRUPTS: In an interactive shell, an interrupt will cause an -EXINT exception to return to the main command loop. (Exception: -EXINT is not raised if the user traps interrupts using the trap -command.) The INTOFF and INTON macros (defined in exception.h) -provide uninterruptible critical sections. Between the execution -of INTOFF and the execution of INTON, interrupt signals will be -held for later delivery. INTOFF and INTON can be nested. - -MEMALLOC.C: Memalloc.c defines versions of malloc and realloc -which call error when there is no memory left. It also defines a -stack oriented memory allocation scheme. Allocating off a stack -is probably more efficient than allocation using malloc, but the -big advantage is that when an exception occurs all we have to do -to free up the memory in use at the time of the exception is to -restore the stack pointer. The stack is implemented using a -linked list of blocks. - -STPUTC: If the stack were contiguous, it would be easy to store -strings on the stack without knowing in advance how long the -string was going to be: - p = stackptr; - *p++ = c; /* repeated as many times as needed */ - stackptr = p; -The following three macros (defined in memalloc.h) perform these -operations, but grow the stack if you run off the end: - STARTSTACKSTR(p); - STPUTC(c, p); /* repeated as many times as needed */ - grabstackstr(p); - -We now start a top-down look at the code: - -MAIN.C: The main routine performs some initialization, executes -the user's profile if necessary, and calls cmdloop. Cmdloop -repeatedly parses and executes commands. - -OPTIONS.C: This file contains the option processing code. It is -called from main to parse the shell arguments when the shell is -invoked, and it also contains the set builtin. The -i and -m op- -tions (the latter turns on job control) require changes in signal -handling. The routines setjobctl (in jobs.c) and setinteractive -(in trap.c) are called to handle changes to these options. - -PARSING: The parser code is all in parser.c. A recursive des- -cent parser is used. Syntax tables (generated by mksyntax) are -used to classify characters during lexical analysis. There are -four tables: one for normal use, one for use when inside single -quotes and dollar single quotes, one for use when inside double -quotes and one for use in arithmetic. The tables are machine -dependent because they are indexed by character variables and -the range of a char varies from machine to machine. - -PARSE OUTPUT: The output of the parser consists of a tree of -nodes. The various types of nodes are defined in the file node- -types. - -Nodes of type NARG are used to represent both words and the con- -tents of here documents. An early version of ash kept the con- -tents of here documents in temporary files, but keeping here do- -cuments in memory typically results in significantly better per- -formance. It would have been nice to make it an option to use -temporary files for here documents, for the benefit of small -machines, but the code to keep track of when to delete the tem- -porary files was complex and I never fixed all the bugs in it. -(AT&T has been maintaining the Bourne shell for more than ten -years, and to the best of my knowledge they still haven't gotten -it to handle temporary files correctly in obscure cases.) - -The text field of a NARG structure points to the text of the -word. The text consists of ordinary characters and a number of -special codes defined in parser.h. The special codes are: - - CTLVAR Parameter expansion - CTLENDVAR End of parameter expansion - CTLBACKQ Command substitution - CTLBACKQ|CTLQUOTE Command substitution inside double quotes - CTLARI Arithmetic expansion - CTLENDARI End of arithmetic expansion - CTLESC Escape next character - -A variable substitution contains the following elements: - - CTLVAR type name '=' [ alternative-text CTLENDVAR ] - -The type field is a single character specifying the type of sub- -stitution. The possible types are: - - VSNORMAL $var - VSMINUS ${var-text} - VSMINUS|VSNUL ${var:-text} - VSPLUS ${var+text} - VSPLUS|VSNUL ${var:+text} - VSQUESTION ${var?text} - VSQUESTION|VSNUL ${var:?text} - VSASSIGN ${var=text} - VSASSIGN|VSNUL ${var:=text} - VSTRIMLEFT ${var#text} - VSTRIMLEFTMAX ${var##text} - VSTRIMRIGHT ${var%text} - VSTRIMRIGHTMAX ${var%%text} - VSLENGTH ${#var} - VSERROR delayed error - -In addition, the type field will have the VSQUOTE flag set if the -variable is enclosed in double quotes and the VSLINENO flag if -LINENO is being expanded (the parameter name is the decimal line -number). The parameter's name comes next, terminated by an equals -sign. If the type is not VSNORMAL (including when it is VSLENGTH), -then the text field in the substitution follows, terminated by a -CTLENDVAR byte. - -The type VSERROR is used to allow parsing bad substitutions like -${var[7]} and generate an error when they are expanded. - -Commands in back quotes are parsed and stored in a linked list. -The locations of these commands in the string are indicated by -CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether -the back quotes were enclosed in double quotes. - -Arithmetic expansion starts with CTLARI and ends with CTLENDARI. - -The character CTLESC escapes the next character, so that in case -any of the CTL characters mentioned above appear in the input, -they can be passed through transparently. CTLESC is also used to -escape '*', '?', '[', and '!' characters which were quoted by the -user and thus should not be used for file name generation. - -CTLESC characters have proved to be particularly tricky to get -right. In the case of here documents which are not subject to -variable and command substitution, the parser doesn't insert any -CTLESC characters to begin with (so the contents of the text -field can be written without any processing). Other here docu- -ments, and words which are not subject to file name generation, -have the CTLESC characters removed during the variable and command -substitution phase. Words which are subject to file name -generation have the CTLESC characters removed as part of the file -name phase. - -EXECUTION: Command execution is handled by the following files: - eval.c The top level routines. - redir.c Code to handle redirection of input and output. - jobs.c Code to handle forking, waiting, and job control. - exec.c Code to do path searches and the actual exec sys call. - expand.c Code to evaluate arguments. - var.c Maintains the variable symbol table. Called from expand.c. - -EVAL.C: Evaltree recursively executes a parse tree. The exit -status is returned in the global variable exitstatus. The alter- -native entry evalbackcmd is called to evaluate commands in back -quotes. It saves the result in memory if the command is a buil- -tin; otherwise it forks off a child to execute the command and -connects the standard output of the child to a pipe. - -JOBS.C: To create a process, you call makejob to return a job -structure, and then call forkshell (passing the job structure as -an argument) to create the process. Waitforjob waits for a job -to complete. These routines take care of process groups if job -control is defined. - -REDIR.C: Ash allows file descriptors to be redirected and then -restored without forking off a child process. This is accom- -plished by duplicating the original file descriptors. The redir- -tab structure records where the file descriptors have been dupli- -cated to. - -EXEC.C: The routine find_command locates a command, and enters -the command in the hash table if it is not already there. The -third argument specifies whether it is to print an error message -if the command is not found. (When a pipeline is set up, -find_command is called for all the commands in the pipeline be- -fore any forking is done, so to get the commands into the hash -table of the parent process. But to make command hashing as -transparent as possible, we silently ignore errors at that point -and only print error messages if the command cannot be found -later.) - -The routine shellexec is the interface to the exec system call. - -EXPAND.C: As the routine argstr generates words by parameter -expansion, command substitution and arithmetic expansion, it -performs word splitting on the result. As each word is output, -the routine expandmeta performs file name generation (if enabled). - -VAR.C: Variables are stored in a hash table. Probably we should -switch to extensible hashing. The variable name is stored in the -same string as the value (using the format "name=value") so that -no string copying is needed to create the environment of a com- -mand. Variables which the shell references internally are preal- -located so that the shell can reference the values of these vari- -ables without doing a lookup. - -When a program is run, the code in eval.c sticks any environment -variables which precede the command (as in "PATH=xxx command") in -the variable table as the simplest way to strip duplicates, and -then calls "environment" to get the value of the environment. - -BUILTIN COMMANDS: The procedures for handling these are scat- -tered throughout the code, depending on which location appears -most appropriate. They can be recognized because their names al- -ways end in "cmd". The mapping from names to procedures is -specified in the file builtins.def, which is processed by the -mkbuiltins command. - -A builtin command is invoked with argc and argv set up like a -normal program. A builtin command is allowed to overwrite its -arguments. Builtin routines can call nextopt to do option pars- -ing. This is kind of like getopt, but you don't pass argc and -argv to it. Builtin routines can also call error. This routine -normally terminates the shell (or returns to the main command -loop if the shell is interactive), but when called from a non- -special builtin command it causes the builtin command to -terminate with an exit status of 2. - -The directory bltins contains commands which can be compiled in- -dependently but can also be built into the shell for efficiency -reasons. The header file bltin.h takes care of most of the -differences between the ash and the stand-alone environment. -The user should call the main routine "main", and #define main to -be the name of the routine to use when the program is linked into -ash. This #define should appear before bltin.h is included; -bltin.h will #undef main if the program is to be compiled -stand-alone. A similar approach is used for a few utilities from -bin and usr.bin. - -CD.C: This file defines the cd and pwd builtins. - -SIGNALS: Trap.c implements the trap command. The routine set- -signal figures out what action should be taken when a signal is -received and invokes the signal system call to set the signal ac- -tion appropriately. When a signal that a user has set a trap for -is caught, the routine "onsig" sets a flag. The routine dotrap -is called at appropriate points to actually handle the signal. -When an interrupt is caught and no trap has been set for that -signal, the routine "onint" in error.c is called. - -OUTPUT: Ash uses its own output routines. There are three out- -put structures allocated. "Output" represents the standard out- -put, "errout" the standard error, and "memout" contains output -which is to be stored in memory. This last is used when a buil- -tin command appears in backquotes, to allow its output to be col- -lected without doing any I/O through the UNIX operating system. -The variables out1 and out2 normally point to output and errout, -respectively, but they are set to point to memout when appropri- -ate inside backquotes. - -INPUT: The basic input routine is pgetc, which reads from the -current input file. There is a stack of input files; the current -input file is the top file on this stack. The code allows the -input to come from a string rather than a file. (This is for the --c option and the "." and eval builtin commands.) The global -variable plinno is saved and restored when files are pushed and -popped from the stack. The parser routines store the number of -the current line in this variable. - -DEBUGGING: If DEBUG is defined in shell.h, then the shell will -write debugging information to the file $HOME/trace. Most of -this is done using the TRACE macro, which takes a set of printf -arguments inside two sets of parenthesis. Example: -"TRACE(("n=%d0, n))". The double parenthesis are necessary be- -cause the preprocessor can't handle functions with a variable -number of arguments. Defining DEBUG also causes the shell to -generate a core dump if it is sent a quit signal. The tracing -code is in show.c. diff --git a/bin/catsh/alias.c b/bin/catsh/alias.c deleted file mode 100644 index 593e7457..00000000 --- a/bin/catsh/alias.c +++ /dev/null @@ -1,256 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/alias.c 317039 2017-04-16 22:10:02Z jilles $"); - -#include <stdlib.h> -#include "shell.h" -#include "output.h" -#include "error.h" -#include "memalloc.h" -#include "mystring.h" -#include "alias.h" -#include "options.h" -#include "builtins.h" - -#define ATABSIZE 39 - -static struct alias *atab[ATABSIZE]; -static int aliases; - -static void setalias(const char *, const char *); -static int unalias(const char *); -static struct alias **hashalias(const char *); - -static -void -setalias(const char *name, const char *val) -{ - struct alias *ap, **app; - - unalias(name); - app = hashalias(name); - INTOFF; - ap = ckmalloc(sizeof (struct alias)); - ap->name = savestr(name); - ap->val = savestr(val); - ap->flag = 0; - ap->next = *app; - *app = ap; - aliases++; - INTON; -} - -static void -freealias(struct alias *ap) -{ - ckfree(ap->name); - ckfree(ap->val); - ckfree(ap); -} - -static int -unalias(const char *name) -{ - struct alias *ap, **app; - - app = hashalias(name); - - for (ap = *app; ap; app = &(ap->next), ap = ap->next) { - if (equal(name, ap->name)) { - /* - * if the alias is currently in use (i.e. its - * buffer is being used by the input routine) we - * just null out the name instead of freeing it. - * We could clear it out later, but this situation - * is so rare that it hardly seems worth it. - */ - if (ap->flag & ALIASINUSE) - *ap->name = '\0'; - else { - INTOFF; - *app = ap->next; - freealias(ap); - INTON; - } - aliases--; - return (0); - } - } - - return (1); -} - -static void -rmaliases(void) -{ - struct alias *ap, **app; - int i; - - INTOFF; - for (i = 0; i < ATABSIZE; i++) { - app = &atab[i]; - while (*app) { - ap = *app; - if (ap->flag & ALIASINUSE) { - *ap->name = '\0'; - app = &(*app)->next; - } else { - *app = ap->next; - freealias(ap); - } - } - } - aliases = 0; - INTON; -} - -struct alias * -lookupalias(const char *name, int check) -{ - struct alias *ap; - - if (aliases == 0) - return (NULL); - for (ap = *hashalias(name); ap; ap = ap->next) { - if (equal(name, ap->name)) { - if (check && (ap->flag & ALIASINUSE)) - return (NULL); - return (ap); - } - } - - return (NULL); -} - -static int -comparealiases(const void *p1, const void *p2) -{ - const struct alias *const *a1 = p1; - const struct alias *const *a2 = p2; - - return strcmp((*a1)->name, (*a2)->name); -} - -static void -printalias(const struct alias *a) -{ - out1fmt("%s=", a->name); - out1qstr(a->val); - out1c('\n'); -} - -static void -printaliases(void) -{ - int i, j; - struct alias **sorted, *ap; - - INTOFF; - sorted = ckmalloc(aliases * sizeof(*sorted)); - j = 0; - for (i = 0; i < ATABSIZE; i++) - for (ap = atab[i]; ap; ap = ap->next) - if (*ap->name != '\0') - sorted[j++] = ap; - qsort(sorted, aliases, sizeof(*sorted), comparealiases); - for (i = 0; i < aliases; i++) { - printalias(sorted[i]); - if (int_pending()) - break; - } - ckfree(sorted); - INTON; -} - -int -aliascmd(int argc __unused, char **argv __unused) -{ - char *n, *v; - int ret = 0; - struct alias *ap; - - nextopt(""); - - if (*argptr == NULL) { - printaliases(); - return (0); - } - while ((n = *argptr++) != NULL) { - if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */ - if ((ap = lookupalias(n, 0)) == NULL) { - warning("%s: not found", n); - ret = 1; - } else - printalias(ap); - else { - *v++ = '\0'; - setalias(n, v); - } - } - - return (ret); -} - -int -unaliascmd(int argc __unused, char **argv __unused) -{ - int i; - - while ((i = nextopt("a")) != '\0') { - if (i == 'a') { - rmaliases(); - return (0); - } - } - for (i = 0; *argptr; argptr++) - i |= unalias(*argptr); - - return (i); -} - -static struct alias ** -hashalias(const char *p) -{ - unsigned int hashval; - - hashval = (unsigned char)*p << 4; - while (*p) - hashval+= *p++; - return &atab[hashval % ATABSIZE]; -} diff --git a/bin/catsh/alias.h b/bin/catsh/alias.h deleted file mode 100644 index 837f1305..00000000 --- a/bin/catsh/alias.h +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)alias.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/alias.h 314436 2017-02-28 23:42:47Z imp $ - */ - -#define ALIASINUSE 1 - -struct alias { - struct alias *next; - char *name; - char *val; - int flag; -}; - -struct alias *lookupalias(const char *, int); diff --git a/bin/catsh/arith.h b/bin/catsh/arith.h deleted file mode 100644 index 364092fa..00000000 --- a/bin/catsh/arith.h +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)arith.h 1.1 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/arith.h 315511 2017-03-18 20:41:07Z jilles $ - */ - -#include "shell.h" - -#define DIGITS(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3) - -arith_t arith(const char *); diff --git a/bin/catsh/arith_yacc.c b/bin/catsh/arith_yacc.c deleted file mode 100644 index 604096aa..00000000 --- a/bin/catsh/arith_yacc.c +++ /dev/null @@ -1,381 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 2007 - * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/arith_yacc.c 270246 2014-08-20 20:15:43Z jilles $"); - -#include <limits.h> -#include <errno.h> -#include <inttypes.h> -#include <stdlib.h> -#include <stdio.h> -#include "arith.h" -#include "arith_yacc.h" -#include "expand.h" -#include "shell.h" -#include "error.h" -#include "memalloc.h" -#include "output.h" -#include "options.h" -#include "var.h" - -#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ -#error Arithmetic tokens are out of order. -#endif - -static const char *arith_startbuf; - -const char *arith_buf; -union yystype yylval; - -static int last_token; - -#define ARITH_PRECEDENCE(op, prec) [op - ARITH_BINOP_MIN] = prec - -static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = { - ARITH_PRECEDENCE(ARITH_MUL, 0), - ARITH_PRECEDENCE(ARITH_DIV, 0), - ARITH_PRECEDENCE(ARITH_REM, 0), - ARITH_PRECEDENCE(ARITH_ADD, 1), - ARITH_PRECEDENCE(ARITH_SUB, 1), - ARITH_PRECEDENCE(ARITH_LSHIFT, 2), - ARITH_PRECEDENCE(ARITH_RSHIFT, 2), - ARITH_PRECEDENCE(ARITH_LT, 3), - ARITH_PRECEDENCE(ARITH_LE, 3), - ARITH_PRECEDENCE(ARITH_GT, 3), - ARITH_PRECEDENCE(ARITH_GE, 3), - ARITH_PRECEDENCE(ARITH_EQ, 4), - ARITH_PRECEDENCE(ARITH_NE, 4), - ARITH_PRECEDENCE(ARITH_BAND, 5), - ARITH_PRECEDENCE(ARITH_BXOR, 6), - ARITH_PRECEDENCE(ARITH_BOR, 7), -}; - -#define ARITH_MAX_PREC 8 - -int letcmd(int, char **); - -static __dead2 void yyerror(const char *s) -{ - error("arithmetic expression: %s: \"%s\"", s, arith_startbuf); - /* NOTREACHED */ -} - -static arith_t arith_lookupvarint(char *varname) -{ - const char *str; - char *p; - arith_t result; - - str = lookupvar(varname); - if (uflag && str == NULL) - yyerror("variable not set"); - if (str == NULL || *str == '\0') - str = "0"; - errno = 0; - result = strtoarith_t(str, &p, 0); - if (errno != 0 || *p != '\0') - yyerror("variable conversion error"); - return result; -} - -static inline int arith_prec(int op) -{ - return prec[op - ARITH_BINOP_MIN]; -} - -static inline int higher_prec(int op1, int op2) -{ - return arith_prec(op1) < arith_prec(op2); -} - -static arith_t do_binop(int op, arith_t a, arith_t b) -{ - - switch (op) { - default: - case ARITH_REM: - case ARITH_DIV: - if (!b) - yyerror("division by zero"); - if (a == ARITH_MIN && b == -1) - yyerror("divide error"); - return op == ARITH_REM ? a % b : a / b; - case ARITH_MUL: - return (uintmax_t)a * (uintmax_t)b; - case ARITH_ADD: - return (uintmax_t)a + (uintmax_t)b; - case ARITH_SUB: - return (uintmax_t)a - (uintmax_t)b; - case ARITH_LSHIFT: - return (uintmax_t)a << (b & (sizeof(uintmax_t) * CHAR_BIT - 1)); - case ARITH_RSHIFT: - return a >> (b & (sizeof(uintmax_t) * CHAR_BIT - 1)); - case ARITH_LT: - return a < b; - case ARITH_LE: - return a <= b; - case ARITH_GT: - return a > b; - case ARITH_GE: - return a >= b; - case ARITH_EQ: - return a == b; - case ARITH_NE: - return a != b; - case ARITH_BAND: - return a & b; - case ARITH_BXOR: - return a ^ b; - case ARITH_BOR: - return a | b; - } -} - -static arith_t assignment(int var, int noeval); - -static arith_t primary(int token, union yystype *val, int op, int noeval) -{ - arith_t result; - -again: - switch (token) { - case ARITH_LPAREN: - result = assignment(op, noeval); - if (last_token != ARITH_RPAREN) - yyerror("expecting ')'"); - last_token = yylex(); - return result; - case ARITH_NUM: - last_token = op; - return val->val; - case ARITH_VAR: - last_token = op; - return noeval ? val->val : arith_lookupvarint(val->name); - case ARITH_ADD: - token = op; - *val = yylval; - op = yylex(); - goto again; - case ARITH_SUB: - *val = yylval; - return -primary(op, val, yylex(), noeval); - case ARITH_NOT: - *val = yylval; - return !primary(op, val, yylex(), noeval); - case ARITH_BNOT: - *val = yylval; - return ~primary(op, val, yylex(), noeval); - default: - yyerror("expecting primary"); - } -} - -static arith_t binop2(arith_t a, int op, int precedence, int noeval) -{ - for (;;) { - union yystype val; - arith_t b; - int op2; - int token; - - token = yylex(); - val = yylval; - - b = primary(token, &val, yylex(), noeval); - - op2 = last_token; - if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX && - higher_prec(op2, op)) { - b = binop2(b, op2, arith_prec(op), noeval); - op2 = last_token; - } - - a = noeval ? b : do_binop(op, a, b); - - if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX || - arith_prec(op2) >= precedence) - return a; - - op = op2; - } -} - -static arith_t binop(int token, union yystype *val, int op, int noeval) -{ - arith_t a = primary(token, val, op, noeval); - - op = last_token; - if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX) - return a; - - return binop2(a, op, ARITH_MAX_PREC, noeval); -} - -static arith_t and(int token, union yystype *val, int op, int noeval) -{ - arith_t a = binop(token, val, op, noeval); - arith_t b; - - op = last_token; - if (op != ARITH_AND) - return a; - - token = yylex(); - *val = yylval; - - b = and(token, val, yylex(), noeval | !a); - - return a && b; -} - -static arith_t or(int token, union yystype *val, int op, int noeval) -{ - arith_t a = and(token, val, op, noeval); - arith_t b; - - op = last_token; - if (op != ARITH_OR) - return a; - - token = yylex(); - *val = yylval; - - b = or(token, val, yylex(), noeval | !!a); - - return a || b; -} - -static arith_t cond(int token, union yystype *val, int op, int noeval) -{ - arith_t a = or(token, val, op, noeval); - arith_t b; - arith_t c; - - if (last_token != ARITH_QMARK) - return a; - - b = assignment(yylex(), noeval | !a); - - if (last_token != ARITH_COLON) - yyerror("expecting ':'"); - - token = yylex(); - *val = yylval; - - c = cond(token, val, yylex(), noeval | !!a); - - return a ? b : c; -} - -static arith_t assignment(int var, int noeval) -{ - union yystype val = yylval; - int op = yylex(); - arith_t result; - char sresult[DIGITS(result) + 1]; - - if (var != ARITH_VAR) - return cond(var, &val, op, noeval); - - if (op != ARITH_ASS && (op < ARITH_ASS_MIN || op >= ARITH_ASS_MAX)) - return cond(var, &val, op, noeval); - - result = assignment(yylex(), noeval); - if (noeval) - return result; - - if (op != ARITH_ASS) - result = do_binop(op - 11, arith_lookupvarint(val.name), result); - snprintf(sresult, sizeof(sresult), ARITH_FORMAT_STR, result); - setvar(val.name, sresult, 0); - return result; -} - -arith_t arith(const char *s) -{ - struct stackmark smark; - arith_t result; - - setstackmark(&smark); - - arith_buf = arith_startbuf = s; - - result = assignment(yylex(), 0); - - if (last_token) - yyerror("expecting EOF"); - - popstackmark(&smark); - - return result; -} - -/* - * The exp(1) builtin. - */ -int -letcmd(int argc, char **argv) -{ - const char *p; - char *concat; - char **ap; - arith_t i; - - if (argc > 1) { - p = argv[1]; - if (argc > 2) { - /* - * Concatenate arguments. - */ - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { - while (*p) - STPUTC(*p++, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); - } - STPUTC('\0', concat); - p = grabstackstr(concat); - } - } else - p = ""; - - i = arith(p); - - out1fmt(ARITH_FORMAT_STR "\n", i); - return !i; -} diff --git a/bin/catsh/arith_yacc.h b/bin/catsh/arith_yacc.h deleted file mode 100644 index 2dc43526..00000000 --- a/bin/catsh/arith_yacc.h +++ /dev/null @@ -1,93 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 2007 - * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: releng/12.0/bin/sh/arith_yacc.h 279503 2015-03-01 21:46:55Z jilles $ - */ - -#define ARITH_ASS 1 - -#define ARITH_OR 2 -#define ARITH_AND 3 -#define ARITH_BAD 4 -#define ARITH_NUM 5 -#define ARITH_VAR 6 -#define ARITH_NOT 7 - -#define ARITH_BINOP_MIN 8 -#define ARITH_LE 8 -#define ARITH_GE 9 -#define ARITH_LT 10 -#define ARITH_GT 11 -#define ARITH_EQ 12 -#define ARITH_REM 13 -#define ARITH_BAND 14 -#define ARITH_LSHIFT 15 -#define ARITH_RSHIFT 16 -#define ARITH_MUL 17 -#define ARITH_ADD 18 -#define ARITH_BOR 19 -#define ARITH_SUB 20 -#define ARITH_BXOR 21 -#define ARITH_DIV 22 -#define ARITH_NE 23 -#define ARITH_BINOP_MAX 24 - -#define ARITH_ASS_MIN 24 -#define ARITH_REMASS 24 -#define ARITH_BANDASS 25 -#define ARITH_LSHIFTASS 26 -#define ARITH_RSHIFTASS 27 -#define ARITH_MULASS 28 -#define ARITH_ADDASS 29 -#define ARITH_BORASS 30 -#define ARITH_SUBASS 31 -#define ARITH_BXORASS 32 -#define ARITH_DIVASS 33 -#define ARITH_ASS_MAX 34 - -#define ARITH_LPAREN 34 -#define ARITH_RPAREN 35 -#define ARITH_BNOT 36 -#define ARITH_QMARK 37 -#define ARITH_COLON 38 - -extern const char *arith_buf; - -union yystype { - arith_t val; - char *name; -}; - -extern union yystype yylval; - -int yylex(void); diff --git a/bin/catsh/arith_yylex.c b/bin/catsh/arith_yylex.c deleted file mode 100644 index 0f38c878..00000000 --- a/bin/catsh/arith_yylex.c +++ /dev/null @@ -1,248 +0,0 @@ -/*- - * Copyright (c) 2002 - * Herbert Xu. - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/arith_yylex.c 279503 2015-03-01 21:46:55Z jilles $"); - -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> -#include "shell.h" -#include "arith_yacc.h" -#include "expand.h" -#include "error.h" -#include "memalloc.h" -#include "parser.h" -#include "syntax.h" - -#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ -#error Arithmetic tokens are out of order. -#endif - -int -yylex(void) -{ - int value; - const char *buf = arith_buf; - char *end; - const char *p; - - for (;;) { - value = *buf; - switch (value) { - case ' ': - case '\t': - case '\n': - buf++; - continue; - default: - return ARITH_BAD; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - yylval.val = strtoarith_t(buf, &end, 0); - arith_buf = end; - return ARITH_NUM; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - case '_': - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': - p = buf; - while (buf++, is_in_name(*buf)) - ; - yylval.name = stalloc(buf - p + 1); - memcpy(yylval.name, p, buf - p); - yylval.name[buf - p] = '\0'; - value = ARITH_VAR; - goto out; - case '=': - value += ARITH_ASS - '='; -checkeq: - buf++; -checkeqcur: - if (*buf != '=') - goto out; - value += 11; - break; - case '>': - switch (*++buf) { - case '=': - value += ARITH_GE - '>'; - break; - case '>': - value += ARITH_RSHIFT - '>'; - goto checkeq; - default: - value += ARITH_GT - '>'; - goto out; - } - break; - case '<': - switch (*++buf) { - case '=': - value += ARITH_LE - '<'; - break; - case '<': - value += ARITH_LSHIFT - '<'; - goto checkeq; - default: - value += ARITH_LT - '<'; - goto out; - } - break; - case '|': - if (*++buf != '|') { - value += ARITH_BOR - '|'; - goto checkeqcur; - } - value += ARITH_OR - '|'; - break; - case '&': - if (*++buf != '&') { - value += ARITH_BAND - '&'; - goto checkeqcur; - } - value += ARITH_AND - '&'; - break; - case '!': - if (*++buf != '=') { - value += ARITH_NOT - '!'; - goto out; - } - value += ARITH_NE - '!'; - break; - case 0: - goto out; - case '(': - value += ARITH_LPAREN - '('; - break; - case ')': - value += ARITH_RPAREN - ')'; - break; - case '*': - value += ARITH_MUL - '*'; - goto checkeq; - case '/': - value += ARITH_DIV - '/'; - goto checkeq; - case '%': - value += ARITH_REM - '%'; - goto checkeq; - case '+': - if (buf[1] == '+') - return ARITH_BAD; - value += ARITH_ADD - '+'; - goto checkeq; - case '-': - if (buf[1] == '-') - return ARITH_BAD; - value += ARITH_SUB - '-'; - goto checkeq; - case '~': - value += ARITH_BNOT - '~'; - break; - case '^': - value += ARITH_BXOR - '^'; - goto checkeq; - case '?': - value += ARITH_QMARK - '?'; - break; - case ':': - value += ARITH_COLON - ':'; - break; - } - break; - } - - buf++; -out: - arith_buf = buf; - return value; -} diff --git a/bin/catsh/bltin.h b/bin/catsh/bltin.h deleted file mode 100644 index e9adb878..00000000 --- a/bin/catsh/bltin.h +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bltin.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/bltin/bltin.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -/* - * This file is included by programs which are optionally built into the - * shell. If SHELL is defined, we try to map the standard UNIX library - * routines to ash routines using defines. - */ - -#include "shell.h" -#include "mystring.h" -#ifdef SHELL -#include "error.h" -#include "output.h" -#include "builtins.h" -#define FILE struct output -#undef stdout -#define stdout out1 -#undef stderr -#define stderr out2 -#define printf out1fmt -#undef putc -#define putc(c, file) outc(c, file) -#undef putchar -#define putchar(c) out1c(c) -#define fprintf outfmt -#define fputs outstr -#define fwrite(ptr, size, nmemb, file) outbin(ptr, (size) * (nmemb), file) -#define fflush flushout -#define INITARGS(argv) -#define warnx warning -#define warn(fmt, ...) warning(fmt ": %s", __VA_ARGS__, strerror(errno)) -#define errx(exitstatus, ...) error(__VA_ARGS__) - -#else -#undef NULL -#include <stdio.h> -#undef main -#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else -#endif - -#include <unistd.h> - -pointer stalloc(int); -int killjob(const char *, int); - -extern char *commandname; diff --git a/bin/catsh/builtins.def b/bin/catsh/builtins.def deleted file mode 100644 index b3295a9b..00000000 --- a/bin/catsh/builtins.def +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh - - -#- -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)builtins.def 8.4 (Berkeley) 5/4/95 -# $FreeBSD: releng/12.0/bin/sh/builtins.def 319576 2017-06-04 21:02:48Z bdrewery $ - -# -# This file lists all the builtin commands. The first column is the name -# of a C routine. -# The -j flag specifies that this command is to be excluded from systems -# without job control. -# The -h flag specifies that this command is to be excluded from systems -# based on the NO_HISTORY compile-time symbol. -# The -n flag specifies that this command can safely be run in the same -# process when it is the only command in a command substitution. Some -# commands have special logic defined in safe_builtin(). -# The -s flag specifies that this is a POSIX 'special built-in' command. -# The rest of the line specifies the command name or names used to run the -# command. The entry for bltincmd, which is run when the user does not specify -# a command, must come first. -# -# NOTE: bltincmd must come first! - -bltincmd -n builtin -aliascmd alias -bgcmd -j bg -bindcmd bind -breakcmd -s break -s continue -cdcmd cd chdir -commandcmd -n command -dotcmd -s . -echocmd -n echo -evalcmd -s eval -execcmd -s exec -exitcmd -s exit -letcmd let -exportcmd -s export -s readonly -#exprcmd expr -falsecmd -n false -fgcmd -j fg -freebsd_wordexpcmd freebsd_wordexp -getoptscmd getopts -hashcmd hash -histcmd -h fc -jobidcmd -n jobid -jobscmd -n jobs -killcmd -n kill -localcmd local -printfcmd -n printf -pwdcmd -n pwd -readcmd read -returncmd -s return -setcmd -s set -setvarcmd setvar -shiftcmd -s shift -testcmd -n test [ -timescmd -n -s times -trapcmd -s trap -truecmd -n -s : true -typecmd -n type -ulimitcmd ulimit -umaskcmd umask -unaliascmd unalias -unsetcmd -s unset -waitcmd wait -wordexpcmd wordexp diff --git a/bin/catsh/catsh-kill.1 b/bin/catsh/catsh-kill.1 deleted file mode 100644 index 405efff2..00000000 --- a/bin/catsh/catsh-kill.1 +++ /dev/null @@ -1,157 +0,0 @@ -.\"- -.\" Copyright (c) 1980, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)kill.1 8.2 (Berkeley) 4/28/95 -.\" $FreeBSD: releng/12.0/bin/kill/kill.1 314436 2017-02-28 23:42:47Z imp $ -.\" -.Dd October 3, 2016 -.Dt CATSH-KILL 1 -.Os -.Sh NAME -.Nm kill -.Nd terminate or signal a process -.Sh SYNOPSIS -.Nm -.Op Fl s Ar signal_name -.Ar pid ... -.Nm -.Fl l -.Op Ar exit_status -.Nm -.Fl Ar signal_name -.Ar pid ... -.Nm -.Fl Ar signal_number -.Ar pid ... -.Sh DESCRIPTION -The -.Nm -utility sends a signal to the processes specified by the -.Ar pid -operands. -.Pp -Only the super-user may send signals to other users' processes. -.Pp -The options are as follows: -.Bl -tag -width indent -.It Fl s Ar signal_name -A symbolic signal name specifying the signal to be sent instead of the -default -.Dv TERM . -.It Fl l Op Ar exit_status -If no operand is given, list the signal names; otherwise, write -the signal name corresponding to -.Ar exit_status . -.It Fl Ar signal_name -A symbolic signal name specifying the signal to be sent instead of the -default -.Dv TERM . -.It Fl Ar signal_number -A non-negative decimal integer, specifying the signal to be sent instead -of the default -.Dv TERM . -.El -.Pp -The following PIDs have special meanings: -.Bl -tag -width indent -.It -1 -If superuser, broadcast the signal to all processes; otherwise broadcast -to all processes belonging to the user. -.El -.Pp -Some of the more commonly used signals: -.Pp -.Bl -tag -width indent -compact -.It 1 -HUP (hang up) -.It 2 -INT (interrupt) -.It 3 -QUIT (quit) -.It 6 -ABRT (abort) -.It 9 -KILL (non-catchable, non-ignorable kill) -.It 14 -ALRM (alarm clock) -.It 15 -TERM (software termination signal) -.El -.Pp -Some shells may provide a builtin -.Nm -command which is similar or identical to this utility. -Consult the -.Xr builtin 1 -manual page. -.Sh EXIT STATUS -.Ex -std -.Sh EXAMPLES -Terminate -the processes with PIDs 142 and 157: -.Pp -.Dl "kill 142 157" -.Pp -Send the hangup signal -.Pq Dv SIGHUP -to the process with PID 507: -.Pp -.Dl "kill -s HUP 507" -.Pp -Terminate the process group with PGID 117: -.Pp -.Dl "kill -- -117" -.Sh SEE ALSO -.Xr builtin 1 , -.Xr csh 1 , -.Xr killall 1 , -.Xr ps 1 , -.Xr sh 1 , -.Xr kill 2 , -.Xr sigaction 2 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -.Sh HISTORY -A -.Nm -command appeared in -.At v3 -in section 8 of the manual. -.Sh BUGS -A replacement for the command -.Dq Li kill 0 -for -.Xr csh 1 -users should be provided. diff --git a/bin/catsh/catsh-printf.1 b/bin/catsh/catsh-printf.1 deleted file mode 100644 index 5c8a4fa3..00000000 --- a/bin/catsh/catsh-printf.1 +++ /dev/null @@ -1,382 +0,0 @@ -.\" Copyright (c) 1989, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)printf.1 8.1 (Berkeley) 6/6/93 -.\" $FreeBSD: releng/12.0/usr.bin/printf/printf.1 314436 2017-02-28 23:42:47Z imp $ -.\" -.Dd April 21, 2014 -.Dt CATSH-PRINTF 1 -.Os -.Sh NAME -.Nm printf -.Nd formatted output -.Sh SYNOPSIS -.Nm -.Ar format Op Ar arguments ... -.Sh DESCRIPTION -The -.Nm -utility formats and prints its arguments, after the first, under control -of the -.Ar format . -The -.Ar format -is a character string which contains three types of objects: plain characters, -which are simply copied to standard output, character escape sequences which -are converted and copied to the standard output, and format specifications, -each of which causes printing of the next successive -.Ar argument . -.Pp -The -.Ar arguments -after the first are treated as strings if the corresponding format is -either -.Cm c , b -or -.Cm s ; -otherwise it is evaluated as a C constant, with the following extensions: -.Pp -.Bl -bullet -offset indent -compact -.It -A leading plus or minus sign is allowed. -.It -If the leading character is a single or double quote, the value is the -character code of the next character. -.El -.Pp -The format string is reused as often as necessary to satisfy the -.Ar arguments . -Any extra format specifications are evaluated with zero or the null -string. -.Pp -Character escape sequences are in backslash notation as defined in the -.St -ansiC , -with extensions. -The characters and their meanings -are as follows: -.Pp -.Bl -tag -width Ds -offset indent -compact -.It Cm \ea -Write a <bell> character. -.It Cm \eb -Write a <backspace> character. -.It Cm \ec -Ignore remaining characters in this string. -.It Cm \ef -Write a <form-feed> character. -.It Cm \en -Write a <new-line> character. -.It Cm \er -Write a <carriage return> character. -.It Cm \et -Write a <tab> character. -.It Cm \ev -Write a <vertical tab> character. -.It Cm \e\' -Write a <single quote> character. -.It Cm \e\e -Write a backslash character. -.It Cm \e Ns Ar num -Write a byte whose -value is the 1-, 2-, or 3-digit -octal number -.Ar num . -Multibyte characters can be constructed using multiple -.Cm \e Ns Ar num -sequences. -.El -.Pp -Each format specification is introduced by the percent character -(``%''). -The remainder of the format specification includes, -in the following order: -.Bl -tag -width Ds -.It "Zero or more of the following flags:" -.Bl -tag -width Ds -.It Cm # -A `#' character -specifying that the value should be printed in an ``alternate form''. -For -.Cm b , c , d , s -and -.Cm u -formats, this option has no effect. -For the -.Cm o -formats the precision of the number is increased to force the first -character of the output string to a zero. -For the -.Cm x -.Pq Cm X -format, a non-zero result has the string -.Li 0x -.Pq Li 0X -prepended to it. -For -.Cm a , A , e , E , f , F , g -and -.Cm G -formats, the result will always contain a decimal point, even if no -digits follow the point (normally, a decimal point only appears in the -results of those formats if a digit follows the decimal point). -For -.Cm g -and -.Cm G -formats, trailing zeros are not removed from the result as they -would otherwise be; -.It Cm \&\- -A minus sign `\-' which specifies -.Em left adjustment -of the output in the indicated field; -.It Cm \&+ -A `+' character specifying that there should always be -a sign placed before the number when using signed formats. -.It Sq \&\ \& -A space specifying that a blank should be left before a positive number -for a signed format. -A `+' overrides a space if both are used; -.It Cm \&0 -A zero `0' character indicating that zero-padding should be used -rather than blank-padding. -A `\-' overrides a `0' if both are used; -.El -.It "Field Width:" -An optional digit string specifying a -.Em field width ; -if the output string has fewer bytes than the field width it will -be blank-padded on the left (or right, if the left-adjustment indicator -has been given) to make up the field width (note that a leading zero -is a flag, but an embedded zero is part of a field width); -.It Precision: -An optional period, -.Sq Cm \&.\& , -followed by an optional digit string giving a -.Em precision -which specifies the number of digits to appear after the decimal point, -for -.Cm e -and -.Cm f -formats, or the maximum number of bytes to be printed -from a string; if the digit string is missing, the precision is treated -as zero; -.It Format: -A character which indicates the type of format to use (one of -.Cm diouxXfFeEgGaAcsb ) . -The uppercase formats differ from their lowercase counterparts only in -that the output of the former is entirely in uppercase. -The floating-point format specifiers -.Pq Cm fFeEgGaA -may be prefixed by an -.Cm L -to request that additional precision be used, if available. -.El -.Pp -A field width or precision may be -.Sq Cm \&* -instead of a digit string. -In this case an -.Ar argument -supplies the field width or precision. -.Pp -The format characters and their meanings are: -.Bl -tag -width Fl -.It Cm diouXx -The -.Ar argument -is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, -or unsigned hexadecimal (X or x), respectively. -.It Cm fF -The -.Ar argument -is printed in the style `[\-]ddd.ddd' where the number of d's -after the decimal point is equal to the precision specification for -the argument. -If the precision is missing, 6 digits are given; if the precision -is explicitly 0, no digits and no decimal point are printed. -The values \*[If] and \*[Na] are printed as -.Ql inf -and -.Ql nan , -respectively. -.It Cm eE -The -.Ar argument -is printed in the style -.Cm e -.Sm off -.Sq Op - Ar d.ddd No \(+- Ar dd -.Sm on -where there -is one digit before the decimal point and the number after is equal to -the precision specification for the argument; when the precision is -missing, 6 digits are produced. -The values \*[If] and \*[Na] are printed as -.Ql inf -and -.Ql nan , -respectively. -.It Cm gG -The -.Ar argument -is printed in style -.Cm f -.Pq Cm F -or in style -.Cm e -.Pq Cm E -whichever gives full precision in minimum space. -.It Cm aA -The -.Ar argument -is printed in style -.Sm off -.Sq Op - Ar h.hhh No \(+- Li p Ar d -.Sm on -where there is one digit before the hexadecimal point and the number -after is equal to the precision specification for the argument; -when the precision is missing, enough digits are produced to convey -the argument's exact double-precision floating-point representation. -The values \*[If] and \*[Na] are printed as -.Ql inf -and -.Ql nan , -respectively. -.It Cm c -The first byte of -.Ar argument -is printed. -.It Cm s -Bytes from the string -.Ar argument -are printed until the end is reached or until the number of bytes -indicated by the precision specification is reached; however if the -precision is 0 or missing, the string is printed entirely. -.It Cm b -As for -.Cm s , -but interpret character escapes in backslash notation in the string -.Ar argument . -The permitted escape sequences are slightly different in that -octal escapes are -.Cm \e0 Ns Ar num -instead of -.Cm \e Ns Ar num . -.It Cm n$ -Allows reordering of the output according to -.Ar argument . -.It Cm \&% -Print a `%'; no argument is used. -.El -.Pp -The decimal point -character is defined in the program's locale (category -.Dv LC_NUMERIC ) . -.Pp -In no case does a non-existent or small field width cause truncation of -a field; padding takes place only if the specified field width exceeds -the actual width. -.Pp -Some shells may provide a builtin -.Nm -command which is similar or identical to this utility. -Consult the -.Xr builtin 1 -manual page. -.Sh EXIT STATUS -.Ex -std -.Sh COMPATIBILITY -The traditional -.Bx -behavior of converting arguments of numeric formats not beginning -with a digit to the -.Tn ASCII -code of the first character is not supported. -.Sh SEE ALSO -.Xr builtin 1 , -.Xr echo 1 , -.Xr sh 1 , -.Xr printf 3 -.Sh STANDARDS -The -.Nm -command is expected to be compatible with the -.St -p1003.2 -specification. -.Sh HISTORY -The -.Nm -command appeared in -.Bx 4.3 Reno . -It is modeled -after the standard library function, -.Xr printf 3 . -.Sh CAVEATS -.Tn ANSI -hexadecimal character constants were deliberately not provided. -.Pp -Trying to print a dash ("-") as the first character causes -.Nm -to interpret the dash as a program argument. -.Nm -- -must be used before -.Ar format . -.Pp -If the locale contains multibyte characters -(such as UTF-8), -the -.Cm c -format and -.Cm b -and -.Cm s -formats with a precision -may not operate as expected. -.Sh BUGS -Since the floating point numbers are translated from -.Tn ASCII -to floating-point and -then back again, floating-point precision may be lost. -(By default, the number is translated to an IEEE-754 double-precision -value before being printed. -The -.Cm L -modifier may produce additional precision, depending on the hardware platform.) -.Pp -The escape sequence \e000 is the string terminator. -When present in the argument for the -.Cm b -format, the argument will be truncated at the \e000 character. -.Pp -Multibyte characters are not recognized in format strings (this is only -a problem if -.Ql % -can appear inside a multibyte character). diff --git a/bin/catsh/catsh-test.1 b/bin/catsh/catsh-test.1 deleted file mode 100644 index fa97af5a..00000000 --- a/bin/catsh/catsh-test.1 +++ /dev/null @@ -1,395 +0,0 @@ -.\"- -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)test.1 8.1 (Berkeley) 5/31/93 -.\" $FreeBSD: releng/12.0/bin/test/test.1 314436 2017-02-28 23:42:47Z imp $ -.\" -.Dd October 5, 2016 -.Dt CATSH-TEST 1 -.Os -.Sh NAME -.Nm test , -.Nm \&[ -.Nd condition evaluation utility -.Sh SYNOPSIS -.Nm -.Ar expression -.Nm \&[ -.Ar expression Cm \&] -.Sh DESCRIPTION -The -.Nm -utility evaluates the expression and, if it evaluates -to true, returns a zero (true) exit status; otherwise -it returns 1 (false). -If there is no expression, -.Nm -also -returns 1 (false). -.Pp -All operators and flags are separate arguments to the -.Nm -utility. -.Pp -The following primaries are used to construct expression: -.Bl -tag -width Ar -.It Fl b Ar file -True if -.Ar file -exists and is a block special -file. -.It Fl c Ar file -True if -.Ar file -exists and is a character -special file. -.It Fl d Ar file -True if -.Ar file -exists and is a directory. -.It Fl e Ar file -True if -.Ar file -exists (regardless of type). -.It Fl f Ar file -True if -.Ar file -exists and is a regular file. -.It Fl g Ar file -True if -.Ar file -exists and its set group ID flag -is set. -.It Fl h Ar file -True if -.Ar file -exists and is a symbolic link. -This operator is retained for compatibility with previous versions of -this program. -Do not rely on its existence; use -.Fl L -instead. -.It Fl k Ar file -True if -.Ar file -exists and its sticky bit is set. -.It Fl n Ar string -True if the length of -.Ar string -is nonzero. -.It Fl p Ar file -True if -.Ar file -is a named pipe -.Pq Tn FIFO . -.It Fl r Ar file -True if -.Ar file -exists and is readable. -.It Fl s Ar file -True if -.Ar file -exists and has a size greater -than zero. -.It Fl t Ar file_descriptor -True if the file whose file descriptor number -is -.Ar file_descriptor -is open and is associated with a terminal. -.It Fl u Ar file -True if -.Ar file -exists and its set user ID flag -is set. -.It Fl w Ar file -True if -.Ar file -exists and is writable. -True -indicates only that the write flag is on. -The file is not writable on a read-only file -system even if this test indicates true. -.It Fl x Ar file -True if -.Ar file -exists and is executable. -True -indicates only that the execute flag is on. -If -.Ar file -is a directory, true indicates that -.Ar file -can be searched. -.It Fl z Ar string -True if the length of -.Ar string -is zero. -.It Fl L Ar file -True if -.Ar file -exists and is a symbolic link. -.It Fl O Ar file -True if -.Ar file -exists and its owner matches the effective user id of this process. -.It Fl G Ar file -True if -.Ar file -exists and its group matches the effective group id of this process. -.It Fl S Ar file -True if -.Ar file -exists and is a socket. -.It Ar file1 Fl nt Ar file2 -True if -.Ar file1 -exists and is newer than -.Ar file2 . -.It Ar file1 Fl ot Ar file2 -True if -.Ar file1 -exists and is older than -.Ar file2 . -.It Ar file1 Fl ef Ar file2 -True if -.Ar file1 -and -.Ar file2 -exist and refer to the same file. -.It Ar string -True if -.Ar string -is not the null -string. -.It Ar s1 Cm = Ar s2 -True if the strings -.Ar s1 -and -.Ar s2 -are identical. -.It Ar s1 Cm != Ar s2 -True if the strings -.Ar s1 -and -.Ar s2 -are not identical. -.It Ar s1 Cm < Ar s2 -True if string -.Ar s1 -comes before -.Ar s2 -based on the binary value of their characters. -.It Ar s1 Cm > Ar s2 -True if string -.Ar s1 -comes after -.Ar s2 -based on the binary value of their characters. -.It Ar n1 Fl eq Ar n2 -True if the integers -.Ar n1 -and -.Ar n2 -are algebraically -equal. -.It Ar n1 Fl ne Ar n2 -True if the integers -.Ar n1 -and -.Ar n2 -are not -algebraically equal. -.It Ar n1 Fl gt Ar n2 -True if the integer -.Ar n1 -is algebraically -greater than the integer -.Ar n2 . -.It Ar n1 Fl ge Ar n2 -True if the integer -.Ar n1 -is algebraically -greater than or equal to the integer -.Ar n2 . -.It Ar n1 Fl lt Ar n2 -True if the integer -.Ar n1 -is algebraically less -than the integer -.Ar n2 . -.It Ar n1 Fl le Ar n2 -True if the integer -.Ar n1 -is algebraically less -than or equal to the integer -.Ar n2 . -.El -.Pp -If -.Ar file -is a symbolic link, -.Nm -will fully dereference it and then evaluate the expression -against the file referenced, except for the -.Fl h -and -.Fl L -primaries. -.Pp -These primaries can be combined with the following operators: -.Bl -tag -width Ar -.It Cm \&! Ar expression -True if -.Ar expression -is false. -.It Ar expression1 Fl a Ar expression2 -True if both -.Ar expression1 -and -.Ar expression2 -are true. -.It Ar expression1 Fl o Ar expression2 -True if either -.Ar expression1 -or -.Ar expression2 -are true. -.It Cm \&( Ar expression Cm \&) -True if expression is true. -.El -.Pp -The -.Fl a -operator has higher precedence than the -.Fl o -operator. -.Pp -Some shells may provide a builtin -.Nm -command which is similar or identical to this utility. -Consult the -.Xr builtin 1 -manual page. -.Sh GRAMMAR AMBIGUITY -The -.Nm -grammar is inherently ambiguous. -In order to assure a degree of consistency, -the cases described in the -.St -p1003.2 , -section D11.2/4.62.4, standard -are evaluated consistently according to the rules specified in the -standards document. -All other cases are subject to the ambiguity in the -command semantics. -.Pp -In particular, only expressions containing -.Fl a , -.Fl o , -.Cm \&( -or -.Cm \&) -can be ambiguous. -.Sh EXIT STATUS -The -.Nm -utility exits with one of the following values: -.Bl -tag -width indent -.It 0 -expression evaluated to true. -.It 1 -expression evaluated to false or expression was -missing. -.It >1 -An error occurred. -.El -.Sh EXAMPLES -Implement -.Li test FILE1 -nt FILE2 -using only -.Tn POSIX -functionality: -.Pp -.Dl test -n \&"$(find -L -- FILE1 -prune -newer FILE2 2>/dev/null)\&" -.Pp -This can be modified using non-standard -.Xr find 1 -primaries like -.Cm -newerca -to compare other timestamps. -.Sh COMPATIBILITY -For compatibility with some other implementations, -the -.Cm = -primary can be substituted with -.Cm == -with the same meaning. -.Sh SEE ALSO -.Xr builtin 1 , -.Xr expr 1 , -.Xr find 1 , -.Xr sh 1 , -.Xr stat 1 , -.Xr symlink 7 -.Sh STANDARDS -The -.Nm -utility implements a superset of the -.St -p1003.2 -specification. -The primaries -.Cm < , -.Cm == , -.Cm > , -.Fl ef , -.Fl nt , -.Fl ot , -.Fl G , -and -.Fl O -are extensions. -.Sh HISTORY -A -.Nm -utility appeared in -.At v7 . -.Sh BUGS -Both sides are always evaluated in -.Fl a -and -.Fl o . -For instance, the writable status of -.Pa file -will be tested by the following command even though the former expression -indicated false, which results in a gratuitous access to the file system: -.Dl "[ -z abc -a -w file ]" -To avoid this, write -.Dl "[ -z abc ] && [ -w file ]" diff --git a/bin/catsh/catsh.1 b/bin/catsh/catsh.1 deleted file mode 100644 index e013a452..00000000 --- a/bin/catsh/catsh.1 +++ /dev/null @@ -1,3258 +0,0 @@ -.\"- -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Kenneth Almquist. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 -.\" $FreeBSD: releng/12.0/bin/sh/sh.1 336483 2018-07-19 13:09:29Z 0mp $ -. -.Dd June 24, 2019 -.Dt CATSH 1 -.Os -. -.Sh NAME -.Nm catsh -.Nd a shell -. -.Sh SYNOPSIS -.Nm -.Op Fl /+abCEefhIimnPpTuVvx -.Op Fl /+o Ar longname -.Oo -.Ar script -.Op Ar arg ... -.Oc -. -.Nm -.Op Fl /+abCEefhIimnPpTuVvx -.Op Fl /+o Ar longname -.Fl c Ar string -.Oo -.Ar name -.Op Ar arg ... -.Oc -. -.Nm -.Op Fl /+abCEefhIimnPpTuVvx -.Op Fl /+o Ar longname -.Fl s -.Op Ar arg ... -. -.Sh DESCRIPTION -The -.Nm -utility is a command interpreter. -The current version of -.Nm -is close to the -.St -p1003.1 -specification for the shell. -It only supports features -designated by POSIX, -plus a few Berkeley extensions. -This man page is not intended to be a tutorial nor a complete -specification of the shell. -. -.Ss Overview -The shell is a command that reads lines from -either a file or the terminal, interprets them, and -generally executes other commands. -It is the program that is started when a user logs into the system, -although a user can select a different shell with the -.Xr chsh 1 -command. -The shell -implements a language that has flow control constructs, -a macro facility that provides a variety of features in -addition to data storage, along with built-in history and line -editing capabilities. -It incorporates many features to -aid interactive use and has the advantage that the interpretative -language is common to both interactive and non-interactive -use (shell scripts). -That is, commands can be typed directly -to the running shell or can be put into a file, -which can be executed directly by the shell. -. -.Ss Invocation -.\" -.\" XXX This next sentence is incredibly confusing. -.\" -If no arguments are present and if the standard input of the shell -is connected to a terminal -(or if the -.Fl i -option is set), -the shell is considered an interactive shell. -An interactive shell -generally prompts before each command and handles programming -and command errors differently (as described below). -When first starting, the shell inspects argument 0, and -if it begins with a dash -.Pq Ql - , -the shell is also considered a login shell. -This is normally done automatically by the system -when the user first logs in. -A login shell first reads commands -from the files -.Pa /etc/profile -and then -.Pa .profile -in a user's home directory, -if they exist. -If the environment variable -.Ev ENV -is set on entry to a shell, or is set in the -.Pa .profile -of a login shell, the shell then subjects its value to parameter expansion -and arithmetic expansion and reads commands from the named file. -Therefore, a user should place commands that are to be executed only -at login time in the -.Pa .profile -file, and commands that are executed for every shell inside the -.Ev ENV -file. -The default value of -.Ev ENV -is: -.Pp -.Dl "ENV=$XDG_CONFIG_HOME/catsh/env.sh" -. -.Pp -The first non-option argument specified on the command line -will be treated as the -name of a file from which to read commands (a shell script), and -the remaining arguments are set as the positional parameters -of the shell -.Li ( $1 , $2 , -etc.). -Otherwise, the shell reads commands -from its standard input. -. -.Pp -Unlike older versions of -.Xr sh 1 -the -.Ev ENV -script is only sourced on invocation of interactive shells. -This -closes a well-known, and sometimes easily exploitable security -hole related to poorly thought out -.Ev ENV -scripts. -. -.Ss Argument List Processing -All of the single letter options to -.Nm -have a corresponding long name, -with the exception of -.Fl c -and -.Fl /+o . -These long names are provided next to the single letter options -in the descriptions below. -The long name for an option may be specified as an argument to the -.Fl /+o -option of -.Nm . -Once the shell is running, -the long name for an option may be specified as an argument to the -.Fl /+o -option of the -.Ic set -built-in command -(described later in the section called -.Sx Built-in Commands ) . -Introducing an option with a dash -.Pq Ql - -enables the option, -while using a plus -.Pq Ql + -disables the option. -A -.Dq Li -- -or plain -.Ql - -will stop option processing and will force the remaining -words on the command line to be treated as arguments. -The -.Fl /+o -and -.Fl c -options do not have long names. -They take arguments and are described after the single letter options. -. -.Bl -tag -width indent -.It Fl a Li allexport -Flag variables for export when assignments are made to them. -. -.It Fl b Li notify -Enable asynchronous notification of background job -completion. -(UNIMPLEMENTED) -. -.It Fl C Li noclobber -Do not overwrite existing files with -.Ql > . -. -.It Fl E Li emacs -Enable the built-in -.Xr emacs 1 -command line editor (disables the -.Fl V -option if it has been set; -set automatically when interactive on terminals). -. -.It Fl e Li errexit -Exit immediately if any untested command fails in non-interactive mode. -The exit status of a command is considered to be -explicitly tested if the command is part of the list used to control -an -.Ic if , elif , while , -or -.Ic until ; -if the command is the left -hand operand of an -.Dq Li && -or -.Dq Li || -operator; or if the command is a pipeline preceded by the -.Ic !\& -keyword. -If a shell function is executed and its exit status is explicitly -tested, all commands of the function are considered to be tested as -well. -. -.Pp -It is recommended to check for failures explicitly -instead of relying on -.Fl e -because it tends to behave in unexpected ways, -particularly in larger scripts. -. -.It Fl f Li noglob -Disable pathname expansion. -. -.It Fl h Li trackall -A do-nothing option for POSIX compliance. -. -.It Fl I Li ignoreeof -Ignore -.Dv EOF Ap s -from input when in interactive mode. -. -.It Fl i Li interactive -Force the shell to behave interactively. -. -.It Fl m Li monitor -Turn on job control (set automatically when interactive). -A new process group is created for each pipeline (called a job). -It is possible to suspend jobs or to have them run in the foreground or -in the background. -In a non-interactive shell, -this option can be set even if no terminal is available -and is useful to place processes in separate process groups. -. -.It Fl n Li noexec -If not interactive, read commands but do not -execute them. -This is useful for checking the -syntax of shell scripts. -. -.It Fl P Li physical -Change the default for the -.Ic cd -and -.Ic pwd -commands from -.Fl L -(logical directory layout) -to -.Fl P -(physical directory layout). -. -.It Fl p Li privileged -Turn on privileged mode. -This mode is enabled on startup -if either the effective user or group ID is not equal to the -real user or group ID. -Turning this mode off sets the -effective user and group IDs to the real user and group IDs. -When this mode is enabled for interactive shells, the file -.Pa /etc/suid_profile -is sourced instead of -.Pa ~/.profile -after -.Pa /etc/profile -is sourced, and the contents of the -.Ev ENV -variable are ignored. -. -.It Fl s Li stdin -Read commands from standard input (set automatically -if no file arguments are present). -This option has -no effect when set after the shell has already started -running (i.e., when set with the -.Ic set -command). -. -.It Fl T Li trapsasync -When waiting for a child, execute traps immediately. -If this option is not set, -traps are executed after the child exits, -as specified in -.St -p1003.2 . -This nonstandard option is useful for putting guarding shells around -children that block signals. -The surrounding shell may kill the child -or it may just return control to the tty and leave the child alone, -like this: -.Bd -literal -offset indent -catsh -T -c "trap 'exit 1' 2 ; some-blocking-program" -.Ed -. -.It Fl u Li nounset -Write a message to standard error when attempting -to expand a variable, a positional parameter or -the special parameter -.Va \&! -that is not set, and if the -shell is not interactive, exit immediately. -. -.It Fl V Li vi -Enable the built-in -.Xr vi 1 -command line editor (disables -.Fl E -if it has been set). -. -.It Fl v Li verbose -The shell writes its input to standard error -as it is read. -Useful for debugging. -. -.It Fl x Li xtrace -Write each command -(preceded by the value of the -.Va PS4 -variable subjected to parameter expansion and arithmetic expansion) -to standard error before it is executed. -Useful for debugging. -. -.It Li nolog -Another do-nothing option for POSIX compliance. -It only has a long name. -.El -. -.Pp -The -.Fl c -option causes the commands to be read from the -.Ar string -operand instead of from the standard input. -Keep in mind that this option only accepts a single string as its -argument, hence multi-word strings must be quoted. -. -.Pp -The -.Fl /+o -option takes as its only argument the long name of an option -to be enabled or disabled. -For example, the following two invocations of -.Nm -both enable the built-in -.Xr emacs 1 -command line editor: -.Bd -literal -offset indent -set -E -set -o emacs -.Ed -. -.Pp -If used without an argument, the -.Fl o -option displays the current option settings in a human-readable format. -If -.Cm +o -is used without an argument, the current option settings are output -in a format suitable for re-input into the shell. -. -.Ss Lexical Structure -The shell reads input in terms of lines from a file and breaks -it up into words at whitespace (blanks and tabs), and at -certain sequences of -characters called -.Dq operators , -which are special to the shell. -There are two types of operators: control operators and -redirection operators (their meaning is discussed later). -The following is a list of valid operators: -. -.Bl -tag -width indent -.It Control operators: -.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact -.It Li & Ta Li && Ta Li \&( Ta Li \&) Ta Li \en -.It Li ;; Ta Li ;& Ta Li \&; Ta Li \&| Ta Li || -.El -. -.It Redirection operators: -.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact -.It Li < Ta Li > Ta Li << Ta Li >> Ta Li <> -.It Li <& Ta Li >& Ta Li <<- Ta Li >| Ta \& -.El -.El -. -.Pp -The character -.Ql # -introduces a comment if used at the beginning of a word. -The word starting with -.Ql # -and the rest of the line are ignored. -. -.Pp -ASCII -.Dv NUL -characters (character code 0) are not allowed in shell input. -. -.Ss Quoting -Quoting is used to remove the special meaning of certain characters -or words to the shell, such as operators, whitespace, keywords, -or alias names. -. -.Pp -There are four types of quoting: matched single quotes, -dollar-single quotes, -matched double quotes, and backslash. -. -.Bl -tag -width indent -.It Single Quotes -Enclosing characters in single quotes preserves the literal -meaning of all the characters (except single quotes, making -it impossible to put single-quotes in a single-quoted string). -. -.It Dollar-Single Quotes -Enclosing characters between -.Li $' -and -.Li ' -preserves the literal meaning of all characters -except backslashes and single quotes. -A backslash introduces a C-style escape sequence: -. -.Bl -tag -width xUnnnnnnnn -.It \ea -Alert (ring the terminal bell) -.It \eb -Backspace -.It \ec Ns Ar c -The control character denoted by -.Li ^ Ns Ar c -in -.Xr stty 1 . -If -.Ar c -is a backslash, it must be doubled. -.It \ee -The ESC character (ASCII 0x1b) -.It \ef -Formfeed -.It \en -Newline -.It \er -Carriage return -.It \et -Horizontal tab -.It \ev -Vertical tab -.It \e\e -Literal backslash -.It \e\&' -Literal single-quote -.It \e\&" -Literal double-quote -.It \e Ns Ar nnn -The byte whose octal value is -.Ar nnn -(one to three digits) -.It \ex Ns Ar nn -The byte whose hexadecimal value is -.Ar nn -(one or more digits only the last two of which are used) -.It \eu Ns Ar nnnn -The Unicode code point -.Ar nnnn -(four hexadecimal digits) -.It \eU Ns Ar nnnnnnnn -The Unicode code point -.Ar nnnnnnnn -(eight hexadecimal digits) -.El -. -.Pp -The sequences for Unicode code points are currently only useful with -UTF-8 locales. -They reject code point 0 and UTF-16 surrogates. -. -.Pp -If an escape sequence would produce a byte with value 0, -that byte and the rest of the string until the matching single-quote -are ignored. -. -.Pp -Any other string starting with a backslash is an error. -. -.It Double Quotes -Enclosing characters within double quotes preserves the literal -meaning of all characters except dollar sign -.Pq Ql $ , -backquote -.Pq Ql ` , -and backslash -.Pq Ql \e . -The backslash inside double quotes is historically weird. -It remains literal unless it precedes the following characters, -which it serves to quote: -. -.Pp -.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact -.It Li $ Ta Li ` Ta Li \&" Ta Li \e Ta Li \en -.El -. -.It Backslash -A backslash preserves the literal meaning of the following -character, with the exception of the newline character -.Pq Ql \en . -A backslash preceding a newline is treated as a line continuation. -.El -. -.Ss Keywords -Keywords or reserved words are words that have special meaning to the -shell and are recognized at the beginning of a line and -after a control operator. -The following are keywords: -.Bl -column "doneXX" "elifXX" "elseXX" "untilXX" "whileX" -offset center -.It Li \&! Ta { Ta } Ta Ic case Ta Ic do -.It Ic done Ta Ic elif Ta Ic else Ta Ic esac Ta Ic fi -.It Ic for Ta Ic if Ta Ic then Ta Ic until Ta Ic while -.El -. -.Ss Aliases -An alias is a name and corresponding value set using the -.Ic alias -built-in command. -Wherever the command word of a simple command may occur, -and after checking for keywords if a keyword may occur, the shell -checks the word to see if it matches an alias. -If it does, it replaces it in the input stream with its value. -For example, if there is an alias called -.Dq Li lf -with the value -.Dq Li "ls -F" , -then the input -.Pp -.Dl "lf foobar" -.Pp -would become -.Pp -.Dl "ls -F foobar" -. -.Pp -Aliases are also recognized after an alias -whose value ends with a space or tab. -For example, if there is also an alias called -.Dq Li nohup -with the value -.Dq Li "nohup " , -then the input -.Pp -.Dl "nohup lf foobar" -.Pp -would become -.Pp -.Dl "nohup ls -F foobar" -. -.Pp -Aliases provide a convenient way for naive users to -create shorthands for commands without having to learn how -to create functions with arguments. -Using aliases in scripts is discouraged -because the command that defines them must be executed -before the code that uses them is parsed. -This is fragile and not portable. -. -.Pp -An alias name may be escaped in a command line, so that it is not -replaced by its alias value, by using quoting characters within or -adjacent to the alias name. -This is most often done by prefixing -an alias name with a backslash to execute a function, built-in, or -normal program with the same name. -See the -.Sx Quoting -subsection. -. -.Ss Commands -The shell interprets the words it reads according to a -language, the specification of which is outside the scope -of this man page (refer to the BNF in the -.St -p1003.2 -document). -Essentially though, a line is read and if -the first word of the line (or after a control operator) -is not a keyword, then the shell has recognized a -simple command. -Otherwise, a complex command or some -other special construct may have been recognized. -. -.Ss Simple Commands -If a simple command has been recognized, the shell performs -the following actions: -. -.Bl -enum -.It -Leading words of the form -.Dq Li name=value -are stripped off and assigned to the environment of -the simple command -(they do not affect expansions). -Redirection operators and -their arguments (as described below) are stripped -off and saved for processing. -. -.It -The remaining words are expanded as described in -the section called -.Sx Word Expansions , -and the first remaining word is considered the command -name and the command is located. -The remaining -words are considered the arguments of the command. -If no command name resulted, then the -.Dq Li name=value -variable assignments recognized in 1) affect the -current shell. -. -.It -Redirections are performed as described in -the next section. -.El -. -.Ss Redirections -Redirections are used to change where a command reads its input -or sends its output. -In general, redirections open, close, or -duplicate an existing reference to a file. -The overall format -used for redirection is: -.Pp -.D1 Oo Ar n Oc Ar redir-op file -. -.Pp -The -.Ar redir-op -is one of the redirection operators mentioned -previously. -The following gives some examples of how these -operators can be used. -Note that stdin and stdout are commonly used abbreviations -for standard input and standard output respectively. -. -.Bl -tag -width "1234567890XX" -offset indent -.It Oo Ar n Oc Ns Li > Ar file -redirect stdout (or file descriptor -.Ar n ) -to -.Ar file -. -.It Oo Ar n Oc Ns Li >| Ar file -same as above, but override the -.Fl C -option -. -.It Oo Ar n Oc Ns Li >> Ar file -append stdout (or file descriptor -.Ar n ) -to -.Ar file -. -.It Oo Ar n Oc Ns Li < Ar file -redirect stdin (or file descriptor -.Ar n ) -from -.Ar file -. -.It Oo Ar n Oc Ns Li <> Ar file -redirect stdin (or file descriptor -.Ar n ) -to and from -.Ar file -. -.It Oo Ar n1 Oc Ns Li <& Ns Ar n2 -duplicate stdin (or file descriptor -.Ar n1 ) -from file descriptor -.Ar n2 -. -.It Oo Ar n Oc Ns Li <&- -close stdin (or file descriptor -.Ar n ) -. -.It Oo Ar n1 Oc Ns Li >& Ns Ar n2 -duplicate stdout (or file descriptor -.Ar n1 ) -to file descriptor -.Ar n2 -. -.It Oo Ar n Oc Ns Li >&- -close stdout (or file descriptor -.Ar n ) -.El -. -.Pp -The following redirection is often called a -.Dq here-document . -.Bd -unfilled -offset indent -.Oo Ar n Oc Ns Li << Ar delimiter -.Ar here-doc-text -.Ar ... -.Ar delimiter -.Ed -. -.Pp -All the text on successive lines up to the delimiter is -saved away and made available to the command on standard -input, or file descriptor -.Ar n -if it is specified. -If the -.Ar delimiter -as specified on the initial line is quoted, then the -.Ar here-doc-text -is treated literally, otherwise the text is subjected to -parameter expansion, command substitution, and arithmetic -expansion (as described in the section on -.Sx Word Expansions ) . -If the operator is -.Dq Li <<- -instead of -.Dq Li << , -then leading tabs -in the -.Ar here-doc-text -are stripped. -. -.Ss Search and Execution -There are three types of commands: shell functions, -built-in commands, and normal programs. -The command is searched for (by name) in that order. -The three types of commands are all executed in a different way. -. -.Pp -When a shell function is executed, all of the shell positional -parameters (except -.Li $0 , -which remains unchanged) are -set to the arguments of the shell function. -The variables which are explicitly placed in the environment of -the command (by placing assignments to them before the -function name) are made local to the function and are set -to the values given. -Then the command given in the function definition is executed. -The positional parameters are restored to their original values -when the command completes. -This all occurs within the current shell. -. -.Pp -Shell built-in commands are executed internally to the shell, without -spawning a new process. -There are two kinds of built-in commands: regular and special. -Assignments before special builtins persist after they finish -executing and assignment errors, redirection errors and certain -operand errors cause a script to be aborted. -Special builtins cannot be overridden with a function. -Both regular and special builtins can affect the shell in ways -normal programs cannot. -. -.Pp -Otherwise, if the command name does not match a function -or built-in command, the command is searched for as a normal -program in the file system (as described in the next section). -When a normal program is executed, the shell runs the program, -passing the arguments and the environment to the program. -If the program is not a normal executable file -(i.e., if it does not begin with the -.Dq "magic number" -whose ASCII representation is -.Dq Li #! , -resulting in an -.Er ENOEXEC -return value from -.Xr execve 2 ) -but appears to be a text file, -the shell will run a new instance of -.Nm -to interpret it. -. -.Pp -Note that previous versions of this document -and the source code itself misleadingly and sporadically -refer to a shell script without a magic number -as a -.Dq "shell procedure" . -. -.Ss Path Search -When locating a command, the shell first looks to see if -it has a shell function by that name. -Then it looks for a -built-in command by that name. -If a built-in command is not found, -one of two things happen: -. -.Bl -enum -.It -Command names containing a slash are simply executed without -performing any searches. -. -.It -The shell searches each entry in the -.Va PATH -variable -in turn for the command. -The value of the -.Va PATH -variable should be a series of -entries separated by colons. -Each entry consists of a -directory name. -The current directory -may be indicated implicitly by an empty directory name, -or explicitly by a single period. -.El -. -.Ss Command Exit Status -Each command has an exit status that can influence the behavior -of other shell commands. -The paradigm is that a command exits -with zero for normal or success, and non-zero for failure, -error, or a false indication. -The man page for each command -should indicate the various exit codes and what they mean. -Additionally, the built-in commands return exit codes, as does -an executed shell function. -. -.Pp -If a command is terminated by a signal, its exit status is greater than 128. -The signal name can be found by passing the exit status to -.Li kill -l . -. -.Pp -If there is no command word, -the exit status is the exit status of the last command substitution executed, -or zero if the command does not contain any command substitutions. -. -.Ss Complex Commands -Complex commands are combinations of simple commands -with control operators or keywords, together creating a larger complex -command. -More generally, a command is one of the following: -. -.Bl -item -offset indent -.It -simple command -.It -pipeline -.It -list or compound-list -.It -compound command -.It -function definition -.El -. -.Pp -Unless otherwise stated, the exit status of a command is -that of the last simple command executed by the command, -or zero if no simple command was executed. -. -.Ss Pipelines -A pipeline is a sequence of one or more commands separated -by the control operator -.Ql \&| . -The standard output of all but -the last command is connected to the standard input -of the next command. -The standard output of the last -command is inherited from the shell, as usual. -. -.Pp -The format for a pipeline is: -.Pp -.D1 Oo Li \&! Oc Ar command1 Op Li \&| Ar command2 ... -. -.Pp -The standard output of -.Ar command1 -is connected to the standard input of -.Ar command2 . -The standard input, standard output, or -both of a command is considered to be assigned by the -pipeline before any redirection specified by redirection -operators that are part of the command. -. -.Pp -Note that unlike some other shells, -.Nm -executes each process in a pipeline with more than one command -in a subshell environment and as a child of the -.Nm -process. -. -.Pp -If the pipeline is not in the background (discussed later), -the shell waits for all commands to complete. -. -.Pp -If the keyword -.Ic !\& -does not precede the pipeline, the -exit status is the exit status of the last command specified -in the pipeline. -Otherwise, the exit status is the logical -NOT of the exit status of the last command. -That is, if -the last command returns zero, the exit status is 1; if -the last command returns greater than zero, the exit status -is zero. -. -.Pp -Because pipeline assignment of standard input or standard -output or both takes place before redirection, it can be -modified by redirection. -For example: -.Pp -.Dl "command1 2>&1 | command2" -. -.Pp -sends both the standard output and standard error of -.Ar command1 -to the standard input of -.Ar command2 . -. -.Pp -A -.Ql \&; -or newline terminator causes the preceding -AND-OR-list -(described below in the section called -.Sx Short-Circuit List Operators ) -to be executed sequentially; -an -.Ql & -causes asynchronous execution of the preceding AND-OR-list. -. -.Ss Background Commands (&) -If a command is terminated by the control operator ampersand -.Pq Ql & , -the shell executes the command in a subshell environment (see -.Sx Grouping Commands Together -below) and asynchronously; -the shell does not wait for the command to finish -before executing the next command. -. -.Pp -The format for running a command in background is: -.Pp -.D1 Ar command1 Li & Op Ar command2 Li & Ar ... -. -.Pp -If the shell is not interactive, the standard input of an -asynchronous command is set to -.Pa /dev/null . -. -.Pp -The exit status is zero. -. -.Ss Lists (Generally Speaking) -A list is a sequence of zero or more commands separated by -newlines, semicolons, or ampersands, -and optionally terminated by one of these three characters. -The commands in a -list are executed in the order they are written. -If command is followed by an ampersand, the shell starts the -command and immediately proceeds onto the next command; -otherwise it waits for the command to terminate before -proceeding to the next one. -. -.Ss Short-Circuit List Operators -.Dq Li && -and -.Dq Li || -are AND-OR list operators. -.Dq Li && -executes the first command, and then executes the second command -if the exit status of the first command is zero. -.Dq Li || -is similar, but executes the second command if the exit -status of the first command is nonzero. -.Dq Li && -and -.Dq Li || -both have the same priority. -. -.Ss Flow-Control Constructs (if, while, for, case) -The syntax of the -.Ic if -command is: -.Bd -unfilled -offset indent -compact -.Ic if Ar list -.Ic then Ar list -.Oo Ic elif Ar list -.Ic then Ar list Oc Ar ... -.Op Ic else Ar list -.Ic fi -.Ed -. -.Pp -The exit status is that of selected -.Ic then -or -.Ic else -list, -or zero if no list was selected. -. -.Pp -The syntax of the -.Ic while -command is: -.Bd -unfilled -offset indent -compact -.Ic while Ar list -.Ic do Ar list -.Ic done -.Ed -. -.Pp -The two lists are executed repeatedly while the exit status of the -first list is zero. -The -.Ic until -command is similar, but has the word -.Ic until -in place of -.Ic while , -which causes it to -repeat until the exit status of the first list is zero. -. -.Pp -The exit status is that of the last execution of the second list, -or zero if it was never executed. -. -.Pp -The syntax of the -.Ic for -command is: -.Bd -unfilled -offset indent -compact -.Ic for Ar variable Op Ic in Ar word ... -.Ic do Ar list -.Ic done -.Ed -. -.Pp -If -.Ic in -and the following words are omitted, -.Ic in Li \&"$@\&" -is used instead. -The words are expanded, and then the list is executed -repeatedly with the variable set to each word in turn. -The -.Ic do -and -.Ic done -commands may be replaced with -.Ql { -and -.Ql } . -. -.Pp -The syntax of the -.Ic break -and -.Ic continue -commands is: -.D1 Ic break Op Ar num -.D1 Ic continue Op Ar num -. -.Pp -The -.Ic break -command terminates the -.Ar num -innermost -.Ic for -or -.Ic while -loops. -The -.Ic continue -command continues with the next iteration of the innermost loop. -These are implemented as special built-in commands. -. -.Pp -The syntax of the -.Ic case -command is: -.Bd -unfilled -offset indent -compact -.Ic case Ar word Ic in -.Ar pattern ) Ar list Li ;; -.Ar ... -.Ic esac -.Ed -. -.Pp -The pattern can actually be one or more patterns -(see -.Sx Shell Patterns -described later), -separated by -.Ql \&| -characters. -Tilde expansion, parameter expansion, command substitution, -arithmetic expansion and quote removal are applied to the word. -Then, each pattern is expanded in turn using tilde expansion, -parameter expansion, command substitution and arithmetic expansion and -the expanded form of the word is checked against it. -If a match is found, the corresponding list is executed. -If the selected list is terminated by the control operator -.Ql ;& -instead of -.Ql ;; , -execution continues with the next list, -continuing until a list terminated with -.Ql ;; -or the end of the -.Ic case -command. -. -.Ss Grouping Commands Together -Commands may be grouped by writing either -.Pp -.Sm off -.Bd -literal -offset -ident -.Po Ar list Pc -.Ed -.Sm on -.Pp -or -.Bd -literal -offset -ident -.No { Ar list ; } -.Ed -. -.Pp -The first form executes the commands in a subshell environment. -A subshell environment has its own copy of: -.Bl -enum -.It -The current working directory as set by -.Ic cd . -.It -The file creation mask as set by -.Ic umask . -.It -Resource limits as set by -.Ic ulimit . -.It -References to open files. -.It -Traps as set by -.Ic trap . -.It -Known jobs. -.It -Positional parameters and variables. -.It -Shell options. -.It -Shell functions. -.It -Shell aliases. -.El -. -.Pp -These are copied from the parent shell environment, -except that trapped (but not ignored) signals are reset to the default action -and known jobs are cleared. -Any changes do not affect the parent shell environment. -. -.Pp -A subshell environment may be implemented as a child process or differently. -If job control is enabled in an interactive shell, -commands grouped in parentheses can be suspended and continued as a unit. -. -.Pp -For compatibility with other shells, -two open parentheses in sequence should be separated by whitespace. -. -.Pp -The second form never forks another shell, -so it is slightly more efficient. -Grouping commands together this way allows the user to -redirect their output as though they were one program: -.Bd -literal -offset indent -{ echo -n "hello"; echo " world"; } > greeting -.Ed -. -.Ss Functions -The syntax of a function definition is -.Pp -.D1 Ar name Li \&( \&) Ar command -. -.Pp -A function definition is an executable statement; when -executed it installs a function named -.Ar name -and returns an -exit status of zero. -The -.Ar command -is normally a list -enclosed between -.Ql { -and -.Ql } . -. -.Pp -Variables may be declared to be local to a function by -using the -.Ic local -command. -This should appear as the first statement of a function, -and the syntax is: -.Pp -.D1 Ic local Oo Ar variable ... Oc Op Fl -. -.Pp -The -.Ic local -command is implemented as a built-in command. -The exit status is zero -unless the command is not in a function or a variable name is invalid. -. -.Pp -When a variable is made local, it inherits the initial -value and exported and readonly flags from the variable -with the same name in the surrounding scope, if there is -one. -Otherwise, the variable is initially unset. -The shell -uses dynamic scoping, so that if the variable -.Va x -is made local to function -.Em f , -which then calls function -.Em g , -references to the variable -.Va x -made inside -.Em g -will refer to the variable -.Va x -declared inside -.Em f , -not to the global variable named -.Va x . -. -.Pp -The only special parameter that can be made local is -.Ql - . -Making -.Ql - -local causes any shell options -(including those that only have long names) -that are -changed via the -.Ic set -command inside the function to be -restored to their original values when the function -returns. -. -.Pp -The syntax of the -.Ic return -command is -.Pp -.D1 Ic return Op Ar exitstatus -. -.Pp -It terminates the current executional scope, returning from the closest -nested function or sourced script; -if no function or sourced script is being executed, -it exits the shell instance. -The -.Ic return -command is implemented as a special built-in command. -. -.Ss Variables and Parameters -The shell maintains a set of parameters. -A parameter -denoted by a name -(consisting solely -of alphabetics, numerics, and underscores, -and starting with an alphabetic or an underscore) -is called a variable. -When starting up, -the shell turns all environment variables with valid names into shell -variables. -New variables can be set using the form -.Pp -.D1 Ar name Ns = Ns Ar value -. -.Pp -A parameter can also be denoted by a number -or a special character as explained below. -. -.Pp -Assignments are expanded differently from other words: -tilde expansion is also performed after the equals sign and after any colon -and usernames are also terminated by colons, -and field splitting and pathname expansion are not performed. -. -.Pp -This special expansion applies not only to assignments that form a simple -command by themselves or precede a command word, -but also to words passed to the -.Ic export , -.Ic local -or -.Ic readonly -built-in commands that have this form. -For this, the builtin's name must be literal -(not the result of an expansion) -and may optionally be preceded by one or more literal instances of -.Ic command -without options. -. -.Ss Positional Parameters -A positional parameter is a parameter denoted by a number greater than zero. -The shell sets these initially to the values of its command line -arguments that follow the name of the shell script. -The -.Ic set -built-in command can also be used to set or reset them. -. -.Ss Special Parameters -Special parameters are parameters denoted by a single special character -or the digit zero. -They are shown in the following list, exactly as they would appear in input -typed by the user or in the source of a shell script. -. -.Bl -hang -.It Li $* -Expands to the positional parameters, starting from one. -When -the expansion occurs within a double-quoted string -it expands to a single field with the value of each parameter -separated by the first character of the -.Va IFS -variable, -or by a space if -.Va IFS -is unset. -. -.It Li $@ -Expands to the positional parameters, starting from one. -When -the expansion occurs within double-quotes, each positional -parameter expands as a separate argument. -If there are no positional parameters, the -expansion of -.Li @ -generates zero arguments, even when -.Li @ -is double-quoted. -What this basically means, for example, is -if -.Li $1 -is -.Dq Li abc -and -.Li $2 -is -.Dq Li "def ghi" , -then -.Li \&"$@\&" -expands to -the two arguments: -.Bd -literal -offset indent -"abc" "def ghi" -.Ed -. -.It Li $# -Expands to the number of positional parameters. -. -.It Li $? -Expands to the exit status of the most recent pipeline. -. -.It Li $- -(hyphen) Expands to the current option flags (the single-letter -option names concatenated into a string) as specified on -invocation, by the -.Ic set -built-in command, or implicitly -by the shell. -. -.It Li $$ -Expands to the process ID of the invoked shell. -A subshell -retains the same value of -.Va $ -as its parent. -. -.It Li $! -Expands to the process ID of the most recent background -command executed from the current shell. -For a -pipeline, the process ID is that of the last command in the -pipeline. -If this parameter is referenced, the shell will remember -the process ID and its exit status until the -.Ic wait -built-in command reports completion of the process. -. -.It Li $0 -(zero) Expands to the name of the shell script if passed on the command line, -the -.Ar name -operand if given (with -.Fl c ) -or otherwise argument 0 passed to the shell. -.El -. -.Ss Special Variables -The following variables are set by the shell or -have special meaning to it: -. -.Bl -tag -width ".Va HISTSIZE" -.It Va CDPATH -The search path used with the -.Ic cd -built-in. -. -.It Va EDITOR -The fallback editor used with the -.Ic fc -built-in. -If not set, the default editor is -.Xr ed 1 . -. -.It Va FCEDIT -The default editor used with the -.Ic fc -built-in. -. -.It Va HISTSIZE -The number of previous commands that are accessible. -. -.It Va HOME -The user's home directory, -used in tilde expansion and as a default directory for the -.Ic cd -built-in. -. -.It Va IFS -Input Field Separators. -This is initialized at startup to -.Aq space , -.Aq tab , -and -.Aq newline -in that order. -This value also applies if -.Va IFS -is unset, but not if it is set to the empty string. -See the -.Sx White Space Splitting -section for more details. -. -.It Va LINENO -The current line number in the script or function. -. -.It Va MAIL -The name of a mail file, that will be checked for the arrival of new -mail. -Overridden by -.Va MAILPATH . -. -.It Va MAILPATH -A colon -.Pq Ql \&: -separated list of file names, for the shell to check for incoming -mail. -This variable overrides the -.Va MAIL -setting. -There is a maximum of 10 mailboxes that can be monitored at once. -. -.It Va OPTIND -The index of the next argument to be processed by -.Ic getopts . -This is initialized to 1 at startup. -. -.It Va PATH -The default search path for executables. -See the -.Sx Path Search -section for details. -. -.It Va PPID -The parent process ID of the invoked shell. -This is set at startup -unless this variable is in the environment. -A later change of parent process ID is not reflected. -A subshell retains the same value of -.Va PPID . -. -.It Va PS0 -The pre-prompt string, -which is printed before each new prompt. -.Va PS0 -may include any of the formatting sequences from -.Va PS1 . -. -.It Va PS1 -The primary prompt string, which defaults to -.Dq Li "\e$ " . -.Va PS1 -may include any of the following formatting sequences, -which are replaced by the given information: -.Bl -tag -width indent -.It Li \eH -This system's fully-qualified hostname (FQDN). -.It Li \eh -This system's hostname. -.It Li \eW -The final component of the current working directory. -.It Li \ew -The entire path of the current working directory. -.It Li \e$ -Superuser status. -.Dq Li "$ " -for normal users and -.Dq Li "# " -for superusers. -.It Li \e\e -A literal backslash. -.El -. -.It Va PS2 -The secondary prompt string, which defaults to -.Dq Li "> " . -.Va PS2 -may include any of the formatting sequences from -.Va PS1 . -. -.It Va PS4 -The prefix for the trace output (if -.Fl x -is active). -The default is -.Dq Li "+ " . -. -.It Va PSlit -Defines the character which may be embedded in pairs, in -.Va PS1 , -.Va PS2 , -.Va RPS1 -or -.Va RPS2 -to indicate to -.Xr editline 7 -that the characters between each pair of occurrences of the -.Va PSlit -character will not appear in the visible prompt, and will not -cause the terminal's cursor to change position, but rather set terminal -attributes for the following prompt character(s) at least one of -which must be present. -. -.It Va RPS1 -The primary right prompt string. -.Va RPS1 -may include any of the formatting sequences from -.Va PS1 . -. -.It Va RPS2 -The secondary right prompt string. -.Va RPS2 -may include any of the formatting sequences from -.Va PS1 . -.El -. -.Ss Word Expansions -This clause describes the various expansions that are -performed on words. -Not all expansions are performed on -every word, as explained later. -. -.Pp -Tilde expansions, parameter expansions, command substitutions, -arithmetic expansions, and quote removals that occur within -a single word expand to a single field. -It is only field -splitting or pathname expansion that can create multiple -fields from a single word. -The single exception to this rule is -the expansion of the special parameter -.Va @ -within double-quotes, -as was described above. -. -.Pp -The order of word expansion is: -.Bl -enum -.It -Tilde Expansion, Parameter Expansion, Command Substitution, -Arithmetic Expansion (these all occur at the same time). -.It -Field Splitting is performed on fields generated by step (1) -unless the -.Va IFS -variable is null. -.It -Pathname Expansion (unless the -.Fl f -option is in effect). -.It -Quote Removal. -.El -. -.Pp -The -.Ql $ -character is used to introduce parameter expansion, command -substitution, or arithmetic expansion. -. -.Ss Tilde Expansion (substituting a user's home directory) -A word beginning with an unquoted tilde character -.Pq Ql ~ -is -subjected to tilde expansion. -All the characters up to a slash -.Pq Ql / -or the end of the word are treated as a username -and are replaced with the user's home directory. -If the -username is missing (as in -.Pa ~/foobar ) , -the tilde is replaced with the value of the -.Va HOME -variable (the current user's home directory). -. -.Ss Parameter Expansion -The format for parameter expansion is as follows: -.Pp -.D1 Li ${ Ns Ar expression Ns Li } -.Pp -where -.Ar expression -consists of all characters until the matching -.Ql } . -Any -.Ql } -escaped by a backslash or within a single-quoted or double-quoted -string, and characters in -embedded arithmetic expansions, command substitutions, and variable -expansions, are not examined in determining the matching -.Ql } . -If the variants with -.Ql + , -.Ql - , -.Ql = -or -.Ql ?\& -occur within a double-quoted string, -as an extension there may be unquoted parts -(via double-quotes inside the expansion); -.Ql } -within such parts are also not examined in determining the matching -.Ql } . -. -.Pp -The simplest form for parameter expansion is: -.Pp -.D1 Li ${ Ns Ar parameter Ns Li } -.Pp -The value, if any, of -.Ar parameter -is substituted. -. -.Pp -The parameter name or symbol can be enclosed in braces, which are -optional except for positional parameters with more than one digit or -when parameter is followed by a character that could be interpreted as -part of the name. -If a parameter expansion occurs inside double-quotes: -.Bl -enum -.It -Field splitting is not performed on the results of the -expansion, with the exception of the special parameter -.Va @ . -.It -Pathname expansion is not performed on the results of the -expansion. -.El -. -.Pp -In addition, a parameter expansion can be modified by using one of the -following formats. -. -.Bl -tag -width indent -.It Li ${ Ns Ar parameter Ns Li :- Ns Ar word Ns Li } -Use Default Values. -If -.Ar parameter -is unset or null, the expansion of -.Ar word -is substituted; otherwise, the value of -.Ar parameter -is substituted. -. -.It Li ${ Ns Ar parameter Ns Li := Ns Ar word Ns Li } -Assign Default Values. -If -.Ar parameter -is unset or null, the expansion of -.Ar word -is assigned to -.Ar parameter . -In all cases, the -final value of -.Ar parameter -is substituted. -Quoting inside -.Ar word -does not prevent field splitting or pathname expansion. -Only variables, not positional -parameters or special parameters, can be -assigned in this way. -. -.It Li ${ Ns Ar parameter Ns Li :? Ns Oo Ar word Oc Ns Li } -Indicate Error if Null or Unset. -If -.Ar parameter -is unset or null, the expansion of -.Ar word -(or a message indicating it is unset if -.Ar word -is omitted) is written to standard -error and the shell exits with a nonzero -exit status. -Otherwise, the value of -.Ar parameter -is substituted. -An -interactive shell need not exit. -. -.It Li ${ Ns Ar parameter Ns Li :+ Ns Ar word Ns Li } -Use Alternate Value. -If -.Ar parameter -is unset or null, null is substituted; -otherwise, the expansion of -.Ar word -is substituted. -.El -. -.Pp -In the parameter expansions shown previously, use of the colon in the -format results in a test for a parameter that is unset or null; omission -of the colon results in a test for a parameter that is only unset. -. -.Pp -The -.Ar word -inherits the type of quoting -(unquoted, double-quoted or here-document) -from the surroundings, -with the exception that a backslash that quotes a closing brace is removed -during quote removal. -.Bl -tag -width indent -.It Li ${# Ns Ar parameter Ns Li } -String Length. -The length in characters of -the value of -.Ar parameter . -.El -. -.Pp -The following four varieties of parameter expansion provide for substring -processing. -In each case, pattern matching notation -(see -.Sx Shell Patterns ) , -rather than regular expression notation, -is used to evaluate the patterns. -If parameter is one of the special parameters -.Va * -or -.Va @ , -the result of the expansion is unspecified. -Enclosing the full parameter expansion string in double-quotes does not -cause the following four varieties of pattern characters to be quoted, -whereas quoting characters within the braces has this effect. -. -.Bl -tag -width indent -.It Li ${ Ns Ar parameter Ns Li % Ns Ar word Ns Li } -Remove Smallest Suffix Pattern. -The -.Ar word -is expanded to produce a pattern. -The -parameter expansion then results in -.Ar parameter , -with the smallest portion of the -suffix matched by the pattern deleted. -. -.It Li ${ Ns Ar parameter Ns Li %% Ns Ar word Ns Li } -Remove Largest Suffix Pattern. -The -.Ar word -is expanded to produce a pattern. -The -parameter expansion then results in -.Ar parameter , -with the largest portion of the -suffix matched by the pattern deleted. -. -.It Li ${ Ns Ar parameter Ns Li # Ns Ar word Ns Li } -Remove Smallest Prefix Pattern. -The -.Ar word -is expanded to produce a pattern. -The -parameter expansion then results in -.Ar parameter , -with the smallest portion of the -prefix matched by the pattern deleted. -. -.It Li ${ Ns Ar parameter Ns Li ## Ns Ar word Ns Li } -Remove Largest Prefix Pattern. -The -.Ar word -is expanded to produce a pattern. -The -parameter expansion then results in -.Ar parameter , -with the largest portion of the -prefix matched by the pattern deleted. -.El -. -.Ss Command Substitution -Command substitution allows the output of a command to be substituted in -place of the command name itself. -Command substitution occurs when -the command is enclosed as follows: -.Pp -.D1 Li $( Ns Ar command Ns Li )\& -.Pp -or the backquoted version: -.Pp -.D1 Li ` Ns Ar command Ns Li ` -. -.Pp -The shell expands the command substitution by executing command -and replacing the command substitution -with the standard output of the command, -removing sequences of one or more newlines at the end of the substitution. -Embedded newlines before the end of the output are not removed; -however, during field splitting, they may be translated into spaces -depending on the value of -.Va IFS -and the quoting that is in effect. -The command is executed in a subshell environment, -except that the built-in commands -.Ic jobid , -.Ic jobs , -and -.Ic trap -return information about the parent shell environment -and -.Ic times -returns information about the same process -if they are the only command in a command substitution. -. -.Pp -If a command substitution of the -.Li $( -form begins with a subshell, -the -.Li $( -and -.Li (\& -must be separated by whitespace -to avoid ambiguity with arithmetic expansion. -. -.Ss Arithmetic Expansion -Arithmetic expansion provides a mechanism for evaluating an arithmetic -expression and substituting its value. -The format for arithmetic expansion is as follows: -.Pp -.D1 Li $(( Ns Ar expression Ns Li )) -. -.Pp -The -.Ar expression -is treated as if it were in double-quotes, except -that a double-quote inside the expression is not treated specially. -The -shell expands all tokens in the -.Ar expression -for parameter expansion, -command substitution, -arithmetic expansion -and quote removal. -. -.Pp -The allowed expressions are a subset of C expressions, -summarized below. -. -.Bl -tag -width "Variables" -offset indent -.It Values -All values are of type -.Ft intmax_t . -. -.It Constants -Decimal, octal (starting with -.Li 0 ) -and hexadecimal (starting with -.Li 0x ) -integer constants. -. -.It Variables -Shell variables can be read and written -and contain integer constants. -. -.It Unary operators -.Li "! ~ + -" -. -.It Binary operators -.Li "* / % + - << >> < <= > >= == != & ^ | && ||"\& -. -.It Assignment operators -.Li "= += -= *= /= %= <<= >>= &= ^= |=" -. -.It Conditional operator -.Li "? :"\& -.El -. -.Pp -The result of the expression is substituted in decimal. -. -.Ss White Space Splitting (Field Splitting) -In certain contexts, -after parameter expansion, command substitution, and -arithmetic expansion the shell scans the results of -expansions and substitutions that did not occur in double-quotes for -field splitting and multiple fields can result. -. -.Pp -Characters in -.Va IFS -that are whitespace -.Po -.Aq space , -.Aq tab , -and -.Aq newline -.Pc -are treated differently from other characters in -.Va IFS . -. -.Pp -Whitespace in -.Va IFS -at the beginning or end of a word is discarded. -. -.Pp -Subsequently, a field is delimited by either -.Bl -enum -.It -a non-whitespace character in -.Va IFS -with any whitespace in -.Va IFS -surrounding it, or -.It -one or more whitespace characters in -.Va IFS . -.El -. -.Pp -If a word ends with a non-whitespace character in -.Va IFS , -there is no empty field after this character. -. -.Pp -If no field is delimited, the word is discarded. -In particular, if a word consists solely of an unquoted substitution -and the result of the substitution is null, -it is removed by field splitting even if -.Va IFS -is null. -. -.Ss Pathname Expansion (File Name Generation) -Unless the -.Fl f -option is set, -file name generation is performed -after word splitting is complete. -Each word is -viewed as a series of patterns, separated by slashes. -The -process of expansion replaces the word with the names of -all existing files whose names can be formed by replacing -each pattern with a string that matches the specified pattern. -There are two restrictions on this: first, a pattern cannot match -a string containing a slash, and second, -a pattern cannot match a string starting with a period -unless the first character of the pattern is a period. -The next section describes the patterns used for -Pathname Expansion, -the four varieties of parameter expansion for substring processing and the -.Ic case -command. -. -.Ss Shell Patterns -A pattern consists of normal characters, which match themselves, -and meta-characters. -The meta-characters are -.Ql * , -.Ql \&? , -and -.Ql \&[ . -These characters lose their special meanings if they are quoted. -When command or variable substitution is performed and the dollar sign -or back quotes are not double-quoted, the value of the -variable or the output of the command is scanned for these -characters and they are turned into meta-characters. -. -.Pp -An asterisk -.Pq Ql * -matches any string of characters. -A question mark -.Pq Ql \&? -matches any single character. -A left bracket -.Pq Ql \&[ -introduces a character class. -The end of the character class is indicated by a -.Ql \&] ; -if the -.Ql \&] -is missing then the -.Ql \&[ -matches a -.Ql \&[ -rather than introducing a character class. -A character class matches any of the characters between the square brackets. -A locale-dependent range of characters may be specified using a minus sign. -A named class of characters (see -.Xr wctype 3 ) -may be specified by surrounding the name with -.Ql \&[:\& -and -.Ql :\&] . -For example, -.Ql \&[\&[:alpha:\&]\&] -is a shell pattern that matches a single letter. -The character class may be complemented by making an exclamation point -.Pq Ql !\& -the first character of the character class. -A caret -.Pq Ql ^ -has the same effect but is non-standard. -. -.Pp -To include a -.Ql \&] -in a character class, make it the first character listed -(after the -.Ql \&! -or -.Ql ^ , -if any). -To include a -.Ql - , -make it the first or last character listed. -. -.Ss Built-in Commands -This section lists the built-in commands. -.Bl -tag -width indent -.It Ic \&: -A null command that returns a 0 (true) exit value. -. -.It Ic \&. Ar file -The commands in the specified file are read and executed by the shell. -The -.Ic return -command may be used to return to the -.Ic \&. -command's caller. -If -.Ar file -contains any -.Ql / -characters, it is used as is. -Otherwise, the shell searches the -.Va PATH -for the file. -If it is not found in the -.Va PATH , -it is sought in the current working directory. -. -.It Ic \&[ -A built-in equivalent of -.Xr test 1 . -This version is documented in -.Xr catsh-test 1 . -. -.It Ic alias Oo Ar name Ns Oo = Ns Ar string Oc ... Oc -If -.Ar name Ns = Ns Ar string -is specified, the shell defines the alias -.Ar name -with value -.Ar string . -If just -.Ar name -is specified, the value of the alias -.Ar name -is printed. -With no arguments, the -.Ic alias -built-in command prints the names and values of all defined aliases -(see -.Ic unalias ) . -Alias values are written with appropriate quoting so that they are -suitable for re-input to the shell. -Also see the -.Sx Aliases -subsection. -. -.It Ic bg Op Ar job ... -Continue the specified jobs -(or the current job if no jobs are given) -in the background. -. -.It Ic bind Oo Fl aeklrsv Oc Oo Ar key Oo Ar command Oc Oc -List or alter key bindings for the line editor. -This command is documented in -.Xr editrc 5 . -. -.It Ic break Op Ar num -See the -.Sx Flow-Control Constructs -subsection. -. -.It Ic builtin Ar cmd Op Ar arg ... -Execute the specified built-in command, -.Ar cmd . -This is useful when the user wishes to override a shell function -with the same name as a built-in command. -. -.It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory -.It Ic cd Fl -Switch to the specified -.Ar directory , -to the directory specified in the -.Va HOME -environment variable if no -.Ar directory -is specified or -to the directory specified in the -.Va OLDPWD -environment variable if -.Ar directory -is -.Fl . -If -.Ar directory -does not begin with -.Pa / , \&. , -or -.Pa .. , -then the directories listed in the -.Va CDPATH -variable will be -searched for the specified -.Ar directory . -If -.Va CDPATH -is unset, the current directory is searched. -The format of -.Va CDPATH -is the same as that of -.Va PATH . -In an interactive shell, -the -.Ic cd -command will print out the name of the directory -that it actually switched to -if the -.Va CDPATH -mechanism was used or if -.Ar directory -was -.Fl . -. -.Pp -If the -.Fl P -option is specified, -.Pa .. -is handled physically and symbolic links are resolved before -.Pa .. -components are processed. -If the -.Fl L -option is specified, -.Pa .. -is handled logically. -This is the default. -. -.Pp -The -.Fl e -option causes -.Ic cd -to return exit status 1 if the full pathname of the new directory -cannot be determined reliably or at all. -Normally this is not considered an error, -although a warning is printed. -. -.Pp -If changing the directory fails, the exit status is greater than 1. -If the directory is changed, the exit status is 0, or also 1 if -.Fl e -was given. -. -.It Ic chdir -A synonym for the -.Ic cd -built-in command. -. -.It Ic command Oo Fl p Oc Op Ar utility Op Ar argument ... -.It Ic command Oo Fl p Oc Fl v Ar utility -.It Ic command Oo Fl p Oc Fl V Ar utility -The first form of invocation executes the specified -.Ar utility , -ignoring shell functions in the search. -If -.Ar utility -is a special builtin, -it is executed as if it were a regular builtin. -. -.Pp -If the -.Fl p -option is specified, the command search is performed using a -default value of -.Va PATH -that is guaranteed to find all of the standard utilities. -. -.Pp -If the -.Fl v -option is specified, -.Ar utility -is not executed but a description of its interpretation by the shell is -printed. -For ordinary commands the output is the path name; for shell built-in -commands, shell functions and keywords only the name is written. -Aliases are printed as -.Dq Ic alias Ar name Ns = Ns Ar value . -. -.Pp -The -.Fl V -option is identical to -.Fl v -except for the output. -It prints -.Dq Ar utility Ic is Ar description -where -.Ar description -is either -the path name to -.Ar utility , -a special shell builtin, -a shell builtin, -a shell function, -a shell keyword -or -an alias for -.Ar value . -. -.It Ic continue Op Ar num -See the -.Sx Flow-Control Constructs -subsection. -. -.It Ic echo Oo Fl e | n Oc Op Ar string ... -Print a space-separated list of the arguments to the standard output -and append a newline character. -.Bl -tag -width indent -.It Fl n -Suppress the output of the trailing newline. -.It Fl e -Process C-style backslash escape sequences. -The -.Ic echo -command understands the following character escapes: -.Bl -tag -width indent -.It \ea -Alert (ring the terminal bell) -.It \eb -Backspace -.It \ec -Suppress the trailing newline (this has the side-effect of truncating the -line if it is not the last character) -.It \ee -The ESC character (ASCII 0x1b) -.It \ef -Formfeed -.It \en -Newline -.It \er -Carriage return -.It \et -Horizontal tab -.It \ev -Vertical tab -.It \e\e -Literal backslash -.It \e0nnn -(Zero) The character whose octal value is -.Ar nnn -.El -. -.Pp -If -.Ar string -is not enclosed in quotes then the backslash itself must be escaped -with a backslash to protect it from the shell. -For example -.Bd -literal -offset indent -$ echo -e "a\evb" -a - b -$ echo -e a\e\evb -a - b -$ echo -e "a\e\eb" -a\eb -$ echo -e a\e\e\e\eb -a\eb -.Ed -.El -. -.Pp -Only one of the -.Fl e -and -.Fl n -options may be specified. -. -.It Ic eval Ar string ... -Concatenate all the arguments with spaces. -Then re-parse and execute the command. -. -.It Ic exec Op Ar command Op arg ... -Unless -.Ar command -is omitted, -the shell process is replaced with the specified program -(which must be a real program, not a shell built-in command or function). -Any redirections on the -.Ic exec -command are marked as permanent, -so that they are not undone when the -.Ic exec -command finishes. -. -.It Ic exit Op Ar exitstatus -Terminate the shell process. -If -.Ar exitstatus -is given -it is used as the exit status of the shell. -Otherwise, if the shell is executing an -.Cm EXIT -trap, the exit status of the last command before the trap is used; -if the shell is executing a trap for a signal, -the shell exits by resending the signal to itself. -Otherwise, the exit status of the preceding command is used. -The exit status should be an integer between 0 and 255. -. -.It Ic export Ar name ... -.It Ic export Op Fl p -The specified names are exported so that they will -appear in the environment of subsequent commands. -The only way to un-export a variable is to -.Ic unset -it. -The shell allows the value of a variable to be set -at the same time as it is exported by writing -.Pp -.D1 Ic export Ar name Ns = Ns Ar value -.Pp -With no arguments the -.Ic export -command lists the names -of all exported variables. -If the -.Fl p -option is specified, the exported variables are printed as -.Dq Ic export Ar name Ns = Ns Ar value -lines, suitable for re-input to the shell. -. -.It Ic false -A null command that returns a non-zero (false) exit value. -. -.It Ic fc Oo Fl e Ar editor Oc Op Ar first Op Ar last -.It Ic fc Fl l Oo Fl nr Oc Op Ar first Op Ar last -.It Ic fc Fl s Oo Ar old Ns = Ns Ar new Oc Op Ar first -The -.Ic fc -built-in command lists, or edits and re-executes, -commands previously entered to an interactive shell. -. -.Bl -tag -width indent -.It Fl e Ar editor -Use the editor named by -.Ar editor -to edit the commands. -The -.Ar editor -string is a command name, -subject to search via the -.Va PATH -variable. -The value in the -.Va FCEDIT -variable is used as a default when -.Fl e -is not specified. -If -.Va FCEDIT -is null or unset, the value of the -.Va EDITOR -variable is used. -If -.Va EDITOR -is null or unset, -.Xr ed 1 -is used as the editor. -. -.It Fl l No (ell) -List the commands rather than invoking -an editor on them. -The commands are written in the -sequence indicated by the -.Ar first -and -.Ar last -operands, as affected by -.Fl r , -with each command preceded by the command number. -. -.It Fl n -Suppress command numbers when listing with -.Fl l . -. -.It Fl r -Reverse the order of the commands listed -(with -.Fl l ) -or edited -(with neither -.Fl l -nor -.Fl s ) . -. -.It Fl s -Re-execute the command without invoking an editor. -. -.It Ar old Ns = Ns Ar new -Replace the first occurrence of -.Ar old -in the command with -.Ar new . -If -.Ar old -is the empty string, -the command is prefixed with -.Ar new . -. -.It Ar first -.It Ar last -Select the commands to list or edit. -The number of previous commands that can be accessed -are determined by the value of the -.Va HISTSIZE -variable. -The value of -.Ar first -or -.Ar last -or both are one of the following: -. -.Bl -tag -width indent -.It Oo Cm + Oc Ns Ar num -A positive number representing a command number; -command numbers can be displayed with the -.Fl l -option. -. -.It Fl Ar num -A negative decimal number representing the -command that was executed -.Ar num -of -commands previously. -For example, \-1 is the immediately previous command. -. -.It Ar string -A string indicating the most recently entered command -that begins with that string. -If the -.Ar old Ns = Ns Ar new -operand is not also specified with -.Fl s , -the string form of the first operand cannot contain an embedded equal sign. -.El -.El -. -.Pp -The following variables affect the execution of -.Ic fc : -.Bl -tag -width ".Va HISTSIZE" -.It Va FCEDIT -Name of the editor to use for history editing. -.It Va HISTSIZE -The number of previous commands that are accessible. -.El -. -.It Ic fg Op Ar job -Move the specified -.Ar job -or the current job to the foreground. -. -.It Ic getopts Ar optstring var -The POSIX -.Ic getopts -command. -The -.Ic getopts -command deprecates the older -.Xr getopt 1 -command. -The first argument should be a series of letters, each possibly -followed by a colon which indicates that the option takes an argument. -The specified variable is set to the parsed option. -The index of -the next argument is placed into the shell variable -.Va OPTIND . -If an option takes an argument, it is placed into the shell variable -.Va OPTARG . -If an invalid option is encountered, -.Ar var -is set to -.Ql \&? . -It returns a false value (1) when it encounters the end of the options. -A new set of arguments may be parsed by assigning -.Li OPTIND=1 . -. -.It Ic hash Oo Fl rv Oc Op Ar command ... -The shell maintains a hash table which remembers the locations of commands. -With no arguments whatsoever, the -.Ic hash -command prints out the contents of this table. -. -.Pp -With arguments, the -.Ic hash -command removes each specified -.Ar command -from the hash table (unless they are functions) and then locates it. -With the -.Fl v -option, -.Ic hash -prints the locations of the commands as it finds them. -The -.Fl r -option causes the -.Ic hash -command to delete all the entries in the hash table except for functions. -. -.It Ic jobid Op Ar job -Print the process IDs of the processes in the specified -.Ar job . -If the -.Ar job -argument is omitted, use the current job. -. -.It Ic jobs Oo Fl lps Oc Op Ar job ... -Print information about the specified jobs, or all jobs if no -.Ar job -argument is given. -The information printed includes job ID, status and command name. -. -.Pp -If the -.Fl l -option is specified, the PID of each job is also printed. -If the -.Fl p -option is specified, only the process IDs for the process group leaders -are printed, one per line. -If the -.Fl s -option is specified, only the PIDs of the job commands are printed, one per -line. -. -.It Ic kill -A built-in equivalent of -.Xr kill 1 -that additionally supports sending signals to jobs. -This version is documented in -.Xr catsh-kill 1 . -. -.It Ic local Oo Ar variable ... Oc Op Fl -See the -.Sx Functions -subsection. -. -.It Ic printf -A built-in equivalent of -.Xr printf 1 . -This version is documented in -.Xr catsh-printf 1 . -. -.It Ic pwd Op Fl L | P -Print the path of the current directory. -The built-in command may -differ from the program of the same name because the -built-in command remembers what the current directory -is rather than recomputing it each time. -This makes -it faster. -However, if the current directory is -renamed, -the built-in version of -.Xr pwd 1 -will continue to print the old name for the directory. -. -.Pp -If the -.Fl P -option is specified, symbolic links are resolved. -If the -.Fl L -option is specified, the shell's notion of the current directory -is printed (symbolic links are not resolved). -This is the default. -. -.It Ic read Oo Fl p Ar prompt Oc Oo -.Fl t Ar timeout Oc Oo Fl er Oc Ar variable ... -The -.Ar prompt -is printed if the -.Fl p -option is specified -and the standard input is a terminal. -Then a line is -read from the standard input. -The trailing newline -is deleted from the line and the line is split as -described in the section on -.Sx White Space Splitting (Field Splitting)\& -above, and -the pieces are assigned to the variables in order. -If there are more pieces than variables, the remaining -pieces (along with the characters in -.Va IFS -that separated them) -are assigned to the last variable. -If there are more variables than pieces, the remaining -variables are assigned the null string. -. -.Pp -Backslashes are treated specially, unless the -.Fl r -option is -specified. -If a backslash is followed by -a newline, the backslash and the newline will be -deleted. -If a backslash is followed by any other -character, the backslash will be deleted and the following -character will be treated as though it were not in -.Va IFS , -even if it is. -. -.Pp -If the -.Fl t -option is specified and the -.Ar timeout -elapses before a complete line of input is supplied, -the -.Ic read -command will return an exit status as if terminated by -.Dv SIGALRM -without assigning any values. -The -.Ar timeout -value may optionally be followed by one of -.Ql s , -.Ql m -or -.Ql h -to explicitly specify seconds, minutes or hours. -If none is supplied, -.Ql s -is assumed. -. -.Pp -The -.Fl e -option exists only for backward compatibility with older scripts. -. -.Pp -The exit status is 0 on success, 1 on end of file, -between 2 and 128 if an error occurs -and greater than 128 if a trapped signal interrupts -.Ic read . -. -.It Ic readonly Oo Fl p Oc Op Ar name ... -Each specified -.Ar name -is marked as read only, -so that it cannot be subsequently modified or unset. -The shell allows the value of a variable to be set -at the same time as it is marked read only -by using the following form: -.Pp -.D1 Ic readonly Ar name Ns = Ns Ar value -.Pp -With no arguments the -.Ic readonly -command lists the names of all read only variables. -If the -.Fl p -option is specified, the read-only variables are printed as -.Dq Ic readonly Ar name Ns = Ns Ar value -lines, suitable for re-input to the shell. -. -.It Ic return Op Ar exitstatus -See the -.Sx Functions -subsection. -. -.It Ic set Oo Fl /+abCEefIimnpTuVvx Oc Oo Fl /+o Ar longname Oc Oo -.Fl c Ar string Oc Op Fl - Ar arg ... -The -.Ic set -command performs three different functions: -. -.Bl -item -.It -With no arguments, it lists the values of all shell variables. -. -.It -If options are given, -either in short form or using the long -.Dq Fl /+o Ar longname -form, -it sets or clears the specified options as described in the section called -.Sx Argument List Processing . -. -.It -If the -.Dq Fl - -option is specified, -.Ic set -will replace the shell's positional parameters with the subsequent -arguments. -If no arguments follow the -.Dq Fl - -option, -all the positional parameters will be cleared, -which is equivalent to executing the command -.Dq Li "shift $#" . -The -.Dq Fl - -flag may be omitted when specifying arguments to be used -as positional replacement parameters. -This is not recommended, -because the first argument may begin with a dash -.Pq Ql - -or a plus -.Pq Ql + , -which the -.Ic set -command will interpret as a request to enable or disable options. -.El -. -.It Ic setvar Ar variable value -Assigns the specified -.Ar value -to the specified -.Ar variable . -The -.Ic setvar -command is intended to be used in functions that -assign values to variables whose names are passed as parameters. -In general it is better to write -.Dq Ar variable Ns = Ns Ar value -rather than using -.Ic setvar . -. -.It Ic shift Op Ar n -Shift the positional parameters -.Ar n -times, or once if -.Ar n -is not specified. -A shift sets the value of -.Li $1 -to the value of -.Li $2 , -the value of -.Li $2 -to the value of -.Li $3 , -and so on, -decreasing the value of -.Li $# -by one. -For portability, shifting if there are zero positional parameters -should be avoided, since the shell may abort. -. -.It Ic test -A built-in equivalent of -.Xr test 1 . -This version is documented in -.Xr catsh-test 1 . -. -.It Ic times -Print the amount of time spent executing the shell process and its children. -The first output line shows the user and system times for the shell process -itself, the second one contains the user and system times for the -children. -. -.It Ic trap Oo Ar action Oc Ar signal ... -.It Ic trap Fl l -Cause the shell to parse and execute -.Ar action -when any specified -.Ar signal -is received. -The signals are specified by name or number. -In addition, the pseudo-signal -.Cm EXIT -may be used to specify an -.Ar action -that is performed when the shell terminates. -The -.Ar action -may be an empty string or a dash -.Pq Ql - ; -the former causes the specified signal to be ignored -and the latter causes the default action to be taken. -Omitting the -.Ar action -and using only signal numbers is another way to request the default action. -In a subshell or utility environment, -the shell resets trapped (but not ignored) signals to the default action. -The -.Ic trap -command has no effect on signals that were ignored on entry to the shell. -. -.Pp -Option -.Fl l -causes the -.Ic trap -command to display a list of valid signal names. -. -.It Ic true -A null command that returns a 0 (true) exit value. -. -.It Ic type Op Ar name ... -Interpret each -.Ar name -as a command and print the resolution of the command search. -Possible resolutions are: -shell keyword, alias, special shell builtin, shell builtin, command, -tracked alias -and not found. -For aliases the alias expansion is printed; -for commands and tracked aliases -the complete pathname of the command is printed. -. -.It Ic ulimit Oo Fl HSabcdfklmnopstuvw Oc Op Ar limit -Set or display resource limits (see -.Xr getrlimit 2 ) . -If -.Ar limit -is specified, the named resource will be set; -otherwise the current resource value will be displayed. -. -.Pp -If -.Fl H -is specified, the hard limits will be set or displayed. -While everybody is allowed to reduce a hard limit, -only the superuser can increase it. -The -.Fl S -option -specifies the soft limits instead. -When displaying limits, -only one of -.Fl S -or -.Fl H -can be given. -The default is to display the soft limits, -and to set both the hard and the soft limits. -. -.Pp -Option -.Fl a -causes the -.Ic ulimit -command to display all resources. -The parameter -.Ar limit -is not acceptable in this mode. -. -.Pp -The remaining options specify which resource value is to be -displayed or modified. -They are mutually exclusive. -.Bl -tag -width indent -.It Fl b Ar sbsize -The maximum size of socket buffer usage, in bytes. -.It Fl c Ar coredumpsize -The maximal size of core dump files, in 512-byte blocks. -Setting -.Ar coredumpsize -to 0 prevents core dump files from being created. -.It Fl d Ar datasize -The maximal size of the data segment of a process, in kilobytes. -.It Fl f Ar filesize -The maximal size of a file, in 512-byte blocks. -.It Fl k Ar kqueues -The maximal number of kqueues -(see -.Xr kqueue 2 ) -for this user ID. -.It Fl l Ar lockedmem -The maximal size of memory that can be locked by a process, in -kilobytes. -.It Fl m Ar memoryuse -The maximal resident set size of a process, in kilobytes. -.It Fl n Ar nofiles -The maximal number of descriptors that could be opened by a process. -.It Fl o Ar umtxp -The maximal number of process-shared locks -(see -.Xr pthread 3 ) -for this user ID. -.It Fl p Ar pseudoterminals -The maximal number of pseudo-terminals for this user ID. -.It Fl s Ar stacksize -The maximal size of the stack segment, in kilobytes. -.It Fl t Ar time -The maximal amount of CPU time to be used by each process, in seconds. -.It Fl u Ar userproc -The maximal number of simultaneous processes for this user ID. -.It Fl v Ar virtualmem -The maximal virtual size of a process, in kilobytes. -.It Fl w Ar swapuse -The maximum amount of swap space reserved or used for this user ID, -in kilobytes. -.El -. -.It Ic umask Oo Fl S Oc Op Ar mask -Set the file creation mask (see -.Xr umask 2 ) -to the octal or symbolic (see -.Xr chmod 1 ) -value specified by -.Ar mask . -If the argument is omitted, the current mask value is printed. -If the -.Fl S -option is specified, the output is symbolic, otherwise the output is octal. -. -.It Ic unalias Oo Fl a Oc Op Ar name ... -The specified alias names are removed. -If -.Fl a -is specified, all aliases are removed. -. -.It Ic unset Oo Fl fv Oc Ar name ... -The specified variables or functions are unset and unexported. -If the -.Fl v -option is specified or no options are given, the -.Ar name -arguments are treated as variable names. -If the -.Fl f -option is specified, the -.Ar name -arguments are treated as function names. -. -.It Ic wait Op Ar job ... -Wait for each specified -.Ar job -to complete and return the exit status of the last process in the -last specified -.Ar job . -If any -.Ar job -specified is unknown to the shell, it is treated as if it -were a known job that exited with exit status 127. -If no operands are given, wait for all jobs to complete -and return an exit status of zero. -.El -. -.Ss Command Line Editing -When -.Nm -is being used interactively from a terminal, the current command -and the command history -(see -.Ic fc -in -.Sx Built-in Commands ) -can be edited using -.Nm vi Ns -mode -command line editing. -This mode uses commands similar -to a subset of those described in the -.Xr vi 1 -man page. -The command -.Dq Li "set -o vi" -(or -.Dq Li "set -V" ) -enables -.Nm vi Ns -mode -editing and places -.Nm -into -.Nm vi -insert mode. -With -.Nm vi Ns -mode -enabled, -.Nm -can be switched between insert mode and command mode by typing -.Aq ESC . -Hitting -.Aq return -while in command mode will pass the line to the shell. -. -.Pp -Similarly, the -.Dq Li "set -o emacs" -(or -.Dq Li "set -E" ) -command can be used to enable a subset of -.Nm emacs Ns -style -command line editing features. -. -.Sh ENVIRONMENT -The following environment variables affect the execution of -.Nm : -. -.Bl -tag -width ".Ev LANGXXXXXX" -.It Ev ENV -Initialization file for interactive shells. -. -.It Ev LANG , Ev LC_* -Locale settings. -These are inherited by children of the shell, -and is used in a limited manner by the shell itself. -. -.It Ev OLDPWD -The previous current directory. -This is used and updated by -.Ic cd . -. -.It Ev PWD -An absolute pathname for the current directory, -possibly containing symbolic links. -This is used and updated by the shell. -. -.It Ev TERM -The default terminal setting for the shell. -This is inherited by children of the shell, and is used in the history -editing modes. -.El -. -.Pp -Additionally, environment variables are turned into shell variables -at startup, -which may affect the shell as described under -.Sx Special Variables . -. -.Sh FILES -.Bl -tag -width "/etc/suid_profileXX" -compact -.It Pa ~/.profile -User's login profile. -.It Pa /etc/profile -System login profile. -.It Pa /etc/shells -Shell database. -.It Pa /etc/suid_profile -Privileged shell profile. -.El -. -.Sh EXIT STATUS -Errors that are detected by the shell, such as a syntax error, will -cause the shell to exit with a non-zero exit status. -If the shell is not an interactive shell, the execution of the shell -file will be aborted. -Otherwise the shell will return the exit status of the last command -executed, or if the -.Ic exit -builtin is used with a numeric argument, it -will return the argument. -. -.Sh SEE ALSO -.Xr builtin 1 , -.Xr catsh-kill 1 , -.Xr catsh-printf 1 , -.Xr catsh-test 1 , -.Xr chsh 1 , -.Xr echo 1 , -.Xr ed 1 , -.Xr emacs 1 , -.Xr pwd 1 , -.Xr vi 1 , -.Xr execve 2 , -.Xr getrlimit 2 , -.Xr umask 2 , -.Xr wctype 3 , -.Xr editrc 5 , -.Xr shells 5 -. -.Sh HISTORY -A -.Xr sh 1 -command, the Thompson shell, appeared in -.At v1 . -It was superseded in -.At v7 -by the Bourne shell, which inherited the name -.Xr sh 1 . -. -.Pp -The -.Fx -version of -.Xr sh 1 -was rewritten in 1989 under the -.Bx -license after the Bourne shell from -.At V.4 . -. -.Pp -The -.Nm -sources were imported from -.Fx 12.0 -.Xr sh 1 . -Bundled -.Xr editline 3 -sources were imported from -.Nx 8.0 . -. -.Ss Differences from sh -.Bl -bullet -compact -.It -.Va ENV -has a default value. -.It -Further prompt customization with -.Va PS0 , -.Va RPS1 , -.Va RPS2 , -.Va PSlit . -.It -.Va HOME -is shortened to -.Sq ~ -in prompt expansion. -.It -.Ic fc Fl s Ar = Ns Ar new -prefixes commands. -.El -. -.Sh AUTHORS -.An -nosplit -The -.Fx -version of -.Xr sh 1 -was originally written by -.An Kenneth Almquist . -. -.Pp -The -.Nm -utility is developed by -.An June McEnroe Aq Mt june@causal.agency . -. -.Sh BUGS -The -.Nm -utility does not recognize multibyte characters other than UTF-8. -Splitting using -.Va IFS -does not recognize multibyte characters. diff --git a/bin/catsh/cd.c b/bin/catsh/cd.c deleted file mode 100644 index d1780b64..00000000 --- a/bin/catsh/cd.c +++ /dev/null @@ -1,430 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/cd.c 336320 2018-07-15 21:55:17Z jilles $"); - -#include <sys/types.h> -#include <sys/stat.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <limits.h> - -/* - * The cd and pwd commands. - */ - -#include "shell.h" -#include "var.h" -#include "nodes.h" /* for jobs.h */ -#include "jobs.h" -#include "options.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "exec.h" -#include "redir.h" -#include "mystring.h" -#include "show.h" -#include "cd.h" -#include "builtins.h" - -static int cdlogical(char *); -static int cdphysical(char *); -static int docd(char *, int, int); -static char *getcomponent(char **); -static char *findcwd(char *); -static void updatepwd(char *); -static char *getpwd(void); -static char *getpwd2(void); - -static char *curdir = NULL; /* current working directory */ - -int -cdcmd(int argc __unused, char **argv __unused) -{ - const char *dest; - const char *path; - char *p; - struct stat statb; - int ch, phys, print = 0, getcwderr = 0; - int rc; - int errno1 = ENOENT; - - phys = Pflag; - while ((ch = nextopt("eLP")) != '\0') { - switch (ch) { - case 'e': - getcwderr = 1; - break; - case 'L': - phys = 0; - break; - case 'P': - phys = 1; - break; - } - } - - if (*argptr != NULL && argptr[1] != NULL) - error("too many arguments"); - - if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL) - error("HOME not set"); - if (*dest == '\0') - dest = "."; - if (dest[0] == '-' && dest[1] == '\0') { - dest = bltinlookup("OLDPWD", 1); - if (dest == NULL) - error("OLDPWD not set"); - print = 1; - } - if (dest[0] == '/' || - (dest[0] == '.' && (dest[1] == '/' || dest[1] == '\0')) || - (dest[0] == '.' && dest[1] == '.' && (dest[2] == '/' || dest[2] == '\0')) || - (path = bltinlookup("CDPATH", 1)) == NULL) - path = ""; - while ((p = padvance(&path, NULL, dest)) != NULL) { - if (stat(p, &statb) < 0) { - if (errno != ENOENT) - errno1 = errno; - } else if (!S_ISDIR(statb.st_mode)) - errno1 = ENOTDIR; - else { - if (!print) { - /* - * XXX - rethink - */ - if (p[0] == '.' && p[1] == '/' && p[2] != '\0') - print = strcmp(p + 2, dest); - else - print = strcmp(p, dest); - } - rc = docd(p, print, phys); - if (rc >= 0) - return getcwderr ? rc : 0; - if (errno != ENOENT) - errno1 = errno; - } - } - error("%s: %s", dest, strerror(errno1)); - /*NOTREACHED*/ - return 0; -} - - -/* - * Actually change the directory. In an interactive shell, print the - * directory name if "print" is nonzero. - */ -static int -docd(char *dest, int print, int phys) -{ - int rc; - - TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys)); - - /* If logical cd fails, fall back to physical. */ - if ((phys || (rc = cdlogical(dest)) < 0) && (rc = cdphysical(dest)) < 0) - return (-1); - - if (print && iflag && curdir) { - out1fmt("%s\n", curdir); - /* - * Ignore write errors to preserve the invariant that the - * current directory is changed iff the exit status is 0 - * (or 1 if -e was given and the full pathname could not be - * determined). - */ - flushout(out1); - outclearerror(out1); - } - - return (rc); -} - -static int -cdlogical(char *dest) -{ - char *p; - char *q; - char *component; - char *path; - struct stat statb; - int first; - int badstat; - - /* - * Check each component of the path. If we find a symlink or - * something we can't stat, clear curdir to force a getcwd() - * next time we get the value of the current directory. - */ - badstat = 0; - path = stsavestr(dest); - STARTSTACKSTR(p); - if (*dest == '/') { - STPUTC('/', p); - path++; - } - first = 1; - while ((q = getcomponent(&path)) != NULL) { - if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) - continue; - if (! first) - STPUTC('/', p); - first = 0; - component = q; - STPUTS(q, p); - if (equal(component, "..")) - continue; - STACKSTRNUL(p); - if (lstat(stackblock(), &statb) < 0) { - badstat = 1; - break; - } - } - - INTOFF; - if ((p = findcwd(badstat ? NULL : dest)) == NULL || chdir(p) < 0) { - INTON; - return (-1); - } - updatepwd(p); - INTON; - return (0); -} - -static int -cdphysical(char *dest) -{ - char *p; - int rc = 0; - - INTOFF; - if (chdir(dest) < 0) { - INTON; - return (-1); - } - p = findcwd(NULL); - if (p == NULL) { - warning("warning: failed to get name of current directory"); - rc = 1; - } - updatepwd(p); - INTON; - return (rc); -} - -/* - * Get the next component of the path name pointed to by *path. - * This routine overwrites *path and the string pointed to by it. - */ -static char * -getcomponent(char **path) -{ - char *p; - char *start; - - if ((p = *path) == NULL) - return NULL; - start = *path; - while (*p != '/' && *p != '\0') - p++; - if (*p == '\0') { - *path = NULL; - } else { - *p++ = '\0'; - *path = p; - } - return start; -} - - -static char * -findcwd(char *dir) -{ - char *new; - char *p; - char *path; - - /* - * If our argument is NULL, we don't know the current directory - * any more because we traversed a symbolic link or something - * we couldn't stat(). - */ - if (dir == NULL || curdir == NULL) - return getpwd2(); - path = stsavestr(dir); - STARTSTACKSTR(new); - if (*dir != '/') { - STPUTS(curdir, new); - if (STTOPC(new) == '/') - STUNPUTC(new); - } - while ((p = getcomponent(&path)) != NULL) { - if (equal(p, "..")) { - while (new > stackblock() && (STUNPUTC(new), *new) != '/'); - } else if (*p != '\0' && ! equal(p, ".")) { - STPUTC('/', new); - STPUTS(p, new); - } - } - if (new == stackblock()) - STPUTC('/', new); - STACKSTRNUL(new); - return stackblock(); -} - -/* - * Update curdir (the name of the current directory) in response to a - * cd command. We also call hashcd to let the routines in exec.c know - * that the current directory has changed. - */ -static void -updatepwd(char *dir) -{ - char *prevdir; - - hashcd(); /* update command hash table */ - - setvar("PWD", dir, VEXPORT); - setvar("OLDPWD", curdir, VEXPORT); - prevdir = curdir; - curdir = dir ? savestr(dir) : NULL; - ckfree(prevdir); -} - -int -pwdcmd(int argc __unused, char **argv __unused) -{ - char *p; - int ch, phys; - - phys = Pflag; - while ((ch = nextopt("LP")) != '\0') { - switch (ch) { - case 'L': - phys = 0; - break; - case 'P': - phys = 1; - break; - } - } - - if (*argptr != NULL) - error("too many arguments"); - - if (!phys && getpwd()) { - out1str(curdir); - out1c('\n'); - } else { - if ((p = getpwd2()) == NULL) - error(".: %s", strerror(errno)); - out1str(p); - out1c('\n'); - } - - return 0; -} - -/* - * Get the current directory and cache the result in curdir. - */ -static char * -getpwd(void) -{ - char *p; - - if (curdir) - return curdir; - - p = getpwd2(); - if (p != NULL) - curdir = savestr(p); - - return curdir; -} - -#define MAXPWD 256 - -/* - * Return the current directory. - */ -static char * -getpwd2(void) -{ - char *pwd; - int i; - - for (i = MAXPWD;; i *= 2) { - pwd = stalloc(i); - if (getcwd(pwd, i) != NULL) - return pwd; - stunalloc(pwd); - if (errno != ERANGE) - break; - } - - return NULL; -} - -/* - * Initialize PWD in a new shell. - * If the shell is interactive, we need to warn if this fails. - */ -void -pwd_init(int warn) -{ - char *pwd; - struct stat stdot, stpwd; - - pwd = lookupvar("PWD"); - if (pwd && *pwd == '/' && stat(".", &stdot) != -1 && - stat(pwd, &stpwd) != -1 && - stdot.st_dev == stpwd.st_dev && - stdot.st_ino == stpwd.st_ino) { - if (curdir) - ckfree(curdir); - curdir = savestr(pwd); - } - if (getpwd() == NULL && warn) - out2fmt_flush("sh: cannot determine working directory\n"); - setvar("PWD", curdir, VEXPORT); -} diff --git a/bin/catsh/cd.h b/bin/catsh/cd.h deleted file mode 100644 index 11de2228..00000000 --- a/bin/catsh/cd.h +++ /dev/null @@ -1,32 +0,0 @@ -/*- - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: releng/12.0/bin/sh/cd.h 314436 2017-02-28 23:42:47Z imp $ - */ - -void pwd_init(int); diff --git a/bin/catsh/echo.c b/bin/catsh/echo.c deleted file mode 100644 index 78c146e9..00000000 --- a/bin/catsh/echo.c +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)echo.c 8.2 (Berkeley) 5/4/95 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/bltin/echo.c 326025 2017-11-20 19:49:47Z pfg $"); - -/* - * Echo command. - */ - -#define main echocmd - -#include "bltin.h" - -/* #define eflag 1 */ - -int -main(int argc, char *argv[]) -{ - char **ap; - char *p; - char c; - int count; - int nflag = 0; -#ifndef eflag - int eflag = 0; -#endif - - ap = argv; - if (argc) - ap++; - if ((p = *ap) != NULL) { - if (equal(p, "-n")) { - nflag++; - ap++; - } else if (equal(p, "-e")) { -#ifndef eflag - eflag++; -#endif - ap++; - } - } - while ((p = *ap++) != NULL) { - while ((c = *p++) != '\0') { - if (c == '\\' && eflag) { - switch (*p++) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'c': return 0; /* exit */ - case 'e': c = '\033'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\\': break; /* c = '\\' */ - case '0': - c = 0; - count = 3; - while (--count >= 0 && (unsigned)(*p - '0') < 8) - c = (c << 3) + (*p++ - '0'); - break; - default: - p--; - break; - } - } - putchar(c); - } - if (*ap) - putchar(' '); - } - if (! nflag) - putchar('\n'); - return 0; -} diff --git a/bin/catsh/error.c b/bin/catsh/error.c deleted file mode 100644 index 02680718..00000000 --- a/bin/catsh/error.c +++ /dev/null @@ -1,199 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/error.c 314436 2017-02-28 23:42:47Z imp $"); - -/* - * Errors and exceptions. - */ - -#include "shell.h" -#include "eval.h" -#include "main.h" -#include "options.h" -#include "output.h" -#include "error.h" -#include "nodes.h" /* show.h needs nodes.h */ -#include "show.h" -#include "trap.h" -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> - - -/* - * Code to handle exceptions in C. - */ - -struct jmploc *handler; -volatile sig_atomic_t exception; -volatile sig_atomic_t suppressint; -volatile sig_atomic_t intpending; - - -static void exverror(int, const char *, va_list) __printf0like(2, 0) __dead2; - -/* - * Called to raise an exception. Since C doesn't include exceptions, we - * just do a longjmp to the exception handler. The type of exception is - * stored in the global variable "exception". - * - * Interrupts are disabled; they should be reenabled when the exception is - * caught. - */ - -void -exraise(int e) -{ - INTOFF; - if (handler == NULL) - abort(); - exception = e; - longjmp(handler->loc, 1); -} - - -/* - * Called from trap.c when a SIGINT is received and not suppressed, or when - * an interrupt is pending and interrupts are re-enabled using INTON. - * (If the user specifies that SIGINT is to be trapped or ignored using the - * trap builtin, then this routine is not called.) Suppressint is nonzero - * when interrupts are held using the INTOFF macro. If SIGINTs are not - * suppressed and the shell is not a root shell, then we want to be - * terminated if we get here, as if we were terminated directly by a SIGINT. - * Arrange for this here. - */ - -void -onint(void) -{ - sigset_t sigs; - - intpending = 0; - sigemptyset(&sigs); - sigprocmask(SIG_SETMASK, &sigs, NULL); - - /* - * This doesn't seem to be needed, since main() emits a newline. - */ -#if 0 - if (tcgetpgrp(0) == getpid()) - write(STDERR_FILENO, "\n", 1); -#endif - if (rootshell && iflag) - exraise(EXINT); - else { - signal(SIGINT, SIG_DFL); - kill(getpid(), SIGINT); - _exit(128 + SIGINT); - } -} - - -static void -vwarning(const char *msg, va_list ap) -{ - if (commandname) - outfmt(out2, "%s: ", commandname); - else if (arg0) - outfmt(out2, "%s: ", arg0); - doformat(out2, msg, ap); - out2fmt_flush("\n"); -} - - -void -warning(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - vwarning(msg, ap); - va_end(ap); -} - - -/* - * Exverror is called to raise the error exception. If the first argument - * is not NULL then error prints an error message using printf style - * formatting. It then raises the error exception. - */ -static void -exverror(int cond, const char *msg, va_list ap) -{ - /* - * An interrupt trumps an error. Certain places catch error - * exceptions or transform them to a plain nonzero exit code - * in child processes, and if an error exception can be handled, - * an interrupt can be handled as well. - * - * exraise() will disable interrupts for the exception handler. - */ - FORCEINTON; - -#ifdef DEBUG - if (msg) - TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); - else - TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); -#endif - if (msg) - vwarning(msg, ap); - flushall(); - exraise(cond); -} - - -void -error(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - exverror(EXERROR, msg, ap); - va_end(ap); -} - - -void -exerror(int cond, const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - exverror(cond, msg, ap); - va_end(ap); -} diff --git a/bin/catsh/error.h b/bin/catsh/error.h deleted file mode 100644 index 8efd5b38..00000000 --- a/bin/catsh/error.h +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)error.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/error.h 319591 2017-06-04 21:58:02Z jilles $ - */ - -/* - * We enclose jmp_buf in a structure so that we can declare pointers to - * jump locations. The global variable handler contains the location to - * jump to when an exception occurs, and the global variable exception - * contains a code identifying the exception. To implement nested - * exception handlers, the user should save the value of handler on entry - * to an inner scope, set handler to point to a jmploc structure for the - * inner scope, and restore handler on exit from the scope. - */ - -#include <setjmp.h> -#include <signal.h> - -struct jmploc { - jmp_buf loc; -}; - -extern struct jmploc *handler; -extern volatile sig_atomic_t exception; - -/* exceptions */ -#define EXINT 0 /* SIGINT received */ -#define EXERROR 1 /* a generic error */ -#define EXEXEC 2 /* command execution failed */ -#define EXEXIT 3 /* call exitshell(exitstatus) */ - - -/* - * These macros allow the user to suspend the handling of interrupt signals - * over a period of time. This is similar to SIGHOLD to or sigblock, but - * much more efficient and portable. (But hacking the kernel is so much - * more fun than worrying about efficiency and portability. :-)) - */ - -extern volatile sig_atomic_t suppressint; -extern volatile sig_atomic_t intpending; - -#define INTOFF suppressint++ -#define INTON { if (--suppressint == 0 && intpending) onint(); } -#define is_int_on() suppressint -#define SETINTON(s) do { suppressint = (s); if (suppressint == 0 && intpending) onint(); } while (0) -#define FORCEINTON {suppressint = 0; if (intpending) onint();} -#define SET_PENDING_INT intpending = 1 -#define CLEAR_PENDING_INT intpending = 0 -#define int_pending() intpending - -void exraise(int) __dead2; -void onint(void) __dead2; -void warning(const char *, ...) __printflike(1, 2); -void error(const char *, ...) __printf0like(1, 2) __dead2; -void exerror(int, const char *, ...) __printf0like(2, 3) __dead2; - - -/* - * BSD setjmp saves the signal mask, which violates ANSI C and takes time, - * so we use _setjmp instead. - */ - -#define setjmp(jmploc) _setjmp(jmploc) -#define longjmp(jmploc, val) _longjmp(jmploc, val) diff --git a/bin/catsh/eval.c b/bin/catsh/eval.c deleted file mode 100644 index 5a5289e1..00000000 --- a/bin/catsh/eval.c +++ /dev/null @@ -1,1381 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/eval.c 327212 2017-12-26 16:23:18Z jilles $"); - -#include <paths.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/resource.h> -#include <errno.h> - -/* - * Evaluate a command. - */ - -#include "shell.h" -#include "nodes.h" -#include "syntax.h" -#include "expand.h" -#include "parser.h" -#include "jobs.h" -#include "eval.h" -#include "builtins.h" -#include "options.h" -#include "exec.h" -#include "redir.h" -#include "input.h" -#include "output.h" -#include "trap.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "show.h" -#include "mystring.h" -#ifndef NO_HISTORY -#include "myhistedit.h" -#endif - - -int evalskip; /* set if we are skipping commands */ -int skipcount; /* number of levels to skip */ -static int loopnest; /* current loop nesting level */ -int funcnest; /* depth of function calls */ -static int builtin_flags; /* evalcommand flags for builtins */ - - -char *commandname; -struct arglist *cmdenviron; -int exitstatus; /* exit status of last command */ -int oexitstatus; /* saved exit status */ - - -static void evalloop(union node *, int); -static void evalfor(union node *, int); -static union node *evalcase(union node *); -static void evalsubshell(union node *, int); -static void evalredir(union node *, int); -static void exphere(union node *, struct arglist *); -static void expredir(union node *); -static void evalpipe(union node *); -static int is_valid_fast_cmdsubst(union node *n); -static void evalcommand(union node *, int, struct backcmd *); -static void prehash(union node *); - - -/* - * Called to reset things after an exception. - */ - -void -reseteval(void) -{ - evalskip = 0; - loopnest = 0; -} - - -/* - * The eval command. - */ - -int -evalcmd(int argc, char **argv) -{ - char *p; - char *concat; - char **ap; - - if (argc > 1) { - p = argv[1]; - if (argc > 2) { - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { - STPUTS(p, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); - } - STPUTC('\0', concat); - p = grabstackstr(concat); - } - evalstring(p, builtin_flags); - } else - exitstatus = 0; - return exitstatus; -} - - -/* - * Execute a command or commands contained in a string. - */ - -void -evalstring(const char *s, int flags) -{ - union node *n; - struct stackmark smark; - int flags_exit; - int any; - - flags_exit = flags & EV_EXIT; - flags &= ~EV_EXIT; - any = 0; - setstackmark(&smark); - setinputstring(s, 1); - while ((n = parsecmd(0)) != NEOF) { - if (n != NULL && !nflag) { - if (flags_exit && preadateof()) - evaltree(n, flags | EV_EXIT); - else - evaltree(n, flags); - any = 1; - if (evalskip) - break; - } - popstackmark(&smark); - setstackmark(&smark); - } - popfile(); - popstackmark(&smark); - if (!any) - exitstatus = 0; - if (flags_exit) - exraise(EXEXIT); -} - - -/* - * Evaluate a parse tree. The value is left in the global variable - * exitstatus. - */ - -void -evaltree(union node *n, int flags) -{ - int do_etest; - union node *next; - struct stackmark smark; - - setstackmark(&smark); - do_etest = 0; - if (n == NULL) { - TRACE(("evaltree(NULL) called\n")); - exitstatus = 0; - goto out; - } - do { - next = NULL; -#ifndef NO_HISTORY - displayhist = 1; /* show history substitutions done with fc */ -#endif - TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type)); - switch (n->type) { - case NSEMI: - evaltree(n->nbinary.ch1, flags & ~EV_EXIT); - if (evalskip) - goto out; - next = n->nbinary.ch2; - break; - case NAND: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus != 0) { - goto out; - } - next = n->nbinary.ch2; - break; - case NOR: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus == 0) - goto out; - next = n->nbinary.ch2; - break; - case NREDIR: - evalredir(n, flags); - break; - case NSUBSHELL: - evalsubshell(n, flags); - do_etest = !(flags & EV_TESTED); - break; - case NBACKGND: - evalsubshell(n, flags); - break; - case NIF: { - evaltree(n->nif.test, EV_TESTED); - if (evalskip) - goto out; - if (exitstatus == 0) - next = n->nif.ifpart; - else if (n->nif.elsepart) - next = n->nif.elsepart; - else - exitstatus = 0; - break; - } - case NWHILE: - case NUNTIL: - evalloop(n, flags & ~EV_EXIT); - break; - case NFOR: - evalfor(n, flags & ~EV_EXIT); - break; - case NCASE: - next = evalcase(n); - break; - case NCLIST: - next = n->nclist.body; - break; - case NCLISTFALLTHRU: - if (n->nclist.body) { - evaltree(n->nclist.body, flags & ~EV_EXIT); - if (evalskip) - goto out; - } - next = n->nclist.next; - break; - case NDEFUN: - defun(n->narg.text, n->narg.next); - exitstatus = 0; - break; - case NNOT: - evaltree(n->nnot.com, EV_TESTED); - if (evalskip) - goto out; - exitstatus = !exitstatus; - break; - - case NPIPE: - evalpipe(n); - do_etest = !(flags & EV_TESTED); - break; - case NCMD: - evalcommand(n, flags, (struct backcmd *)NULL); - do_etest = !(flags & EV_TESTED); - break; - default: - out1fmt("Node type = %d\n", n->type); - flushout(&output); - break; - } - n = next; - popstackmark(&smark); - setstackmark(&smark); - } while (n != NULL); -out: - popstackmark(&smark); - if (pendingsig) - dotrap(); - if (eflag && exitstatus != 0 && do_etest) - exitshell(exitstatus); - if (flags & EV_EXIT) - exraise(EXEXIT); -} - - -static void -evalloop(union node *n, int flags) -{ - int status; - - loopnest++; - status = 0; - for (;;) { - if (!evalskip) - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip) { - if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = 0; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = 0; - if (evalskip == SKIPRETURN) - status = exitstatus; - break; - } - if (n->type == NWHILE) { - if (exitstatus != 0) - break; - } else { - if (exitstatus == 0) - break; - } - evaltree(n->nbinary.ch2, flags); - status = exitstatus; - } - loopnest--; - exitstatus = status; -} - - - -static void -evalfor(union node *n, int flags) -{ - struct arglist arglist; - union node *argp; - int i; - int status; - - emptyarglist(&arglist); - for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { - oexitstatus = exitstatus; - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - } - - loopnest++; - status = 0; - for (i = 0; i < arglist.count; i++) { - setvar(n->nfor.var, arglist.args[i], 0); - evaltree(n->nfor.body, flags); - status = exitstatus; - if (evalskip) { - if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = 0; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = 0; - break; - } - } - loopnest--; - exitstatus = status; -} - - -/* - * Evaluate a case statement, returning the selected tree. - * - * The exit status needs care to get right. - */ - -static union node * -evalcase(union node *n) -{ - union node *cp; - union node *patp; - struct arglist arglist; - - emptyarglist(&arglist); - oexitstatus = exitstatus; - expandarg(n->ncase.expr, &arglist, EXP_TILDE); - for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) { - for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { - if (casematch(patp, arglist.args[0])) { - while (cp->nclist.next && - cp->type == NCLISTFALLTHRU && - cp->nclist.body == NULL) - cp = cp->nclist.next; - if (cp->nclist.next && - cp->type == NCLISTFALLTHRU) - return (cp); - if (cp->nclist.body == NULL) - exitstatus = 0; - return (cp->nclist.body); - } - } - } - exitstatus = 0; - return (NULL); -} - - - -/* - * Kick off a subshell to evaluate a tree. - */ - -static void -evalsubshell(union node *n, int flags) -{ - struct job *jp; - int backgnd = (n->type == NBACKGND); - - oexitstatus = exitstatus; - expredir(n->nredir.redirect); - if ((!backgnd && flags & EV_EXIT && !have_traps()) || - forkshell(jp = makejob(n, 1), n, backgnd) == 0) { - if (backgnd) - flags &=~ EV_TESTED; - redirect(n->nredir.redirect, 0); - evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ - } else if (! backgnd) { - INTOFF; - exitstatus = waitforjob(jp, (int *)NULL); - INTON; - } else - exitstatus = 0; -} - - -/* - * Evaluate a redirected compound command. - */ - -static void -evalredir(union node *n, int flags) -{ - struct jmploc jmploc; - struct jmploc *savehandler; - volatile int in_redirect = 1; - - oexitstatus = exitstatus; - expredir(n->nredir.redirect); - savehandler = handler; - if (setjmp(jmploc.loc)) { - int e; - - handler = savehandler; - e = exception; - popredir(); - if (e == EXERROR || e == EXEXEC) { - if (in_redirect) { - exitstatus = 2; - FORCEINTON; - return; - } - } - longjmp(handler->loc, 1); - } else { - INTOFF; - handler = &jmploc; - redirect(n->nredir.redirect, REDIR_PUSH); - in_redirect = 0; - INTON; - evaltree(n->nredir.n, flags); - } - INTOFF; - handler = savehandler; - popredir(); - INTON; -} - - -static void -exphere(union node *redir, struct arglist *fn) -{ - struct jmploc jmploc; - struct jmploc *savehandler; - struct localvar *savelocalvars; - int need_longjmp = 0; - unsigned char saveoptreset; - - redir->nhere.expdoc = ""; - savelocalvars = localvars; - localvars = NULL; - saveoptreset = shellparam.reset; - forcelocal++; - savehandler = handler; - if (setjmp(jmploc.loc)) - need_longjmp = exception != EXERROR && exception != EXEXEC; - else { - handler = &jmploc; - expandarg(redir->nhere.doc, fn, 0); - redir->nhere.expdoc = fn->args[0]; - INTOFF; - } - handler = savehandler; - forcelocal--; - poplocalvars(); - localvars = savelocalvars; - shellparam.reset = saveoptreset; - if (need_longjmp) - longjmp(handler->loc, 1); - INTON; -} - - -/* - * Compute the names of the files in a redirection list. - */ - -static void -expredir(union node *n) -{ - union node *redir; - - for (redir = n ; redir ; redir = redir->nfile.next) { - struct arglist fn; - emptyarglist(&fn); - switch (redir->type) { - case NFROM: - case NTO: - case NFROMTO: - case NAPPEND: - case NCLOBBER: - expandarg(redir->nfile.fname, &fn, EXP_TILDE); - redir->nfile.expfname = fn.args[0]; - break; - case NFROMFD: - case NTOFD: - if (redir->ndup.vname) { - expandarg(redir->ndup.vname, &fn, EXP_TILDE); - fixredir(redir, fn.args[0], 1); - } - break; - case NXHERE: - exphere(redir, &fn); - break; - } - } -} - - - -/* - * Evaluate a pipeline. All the processes in the pipeline are children - * of the process creating the pipeline. (This differs from some versions - * of the shell, which make the last process in a pipeline the parent - * of all the rest.) - */ - -static void -evalpipe(union node *n) -{ - struct job *jp; - struct nodelist *lp; - int pipelen; - int prevfd; - int pip[2]; - - TRACE(("evalpipe(%p) called\n", (void *)n)); - pipelen = 0; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) - pipelen++; - INTOFF; - jp = makejob(n, pipelen); - prevfd = -1; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - prehash(lp->n); - pip[1] = -1; - if (lp->next) { - if (pipe(pip) < 0) { - if (prevfd >= 0) - close(prevfd); - error("Pipe call failed: %s", strerror(errno)); - } - } - if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { - INTON; - if (prevfd > 0) { - dup2(prevfd, 0); - close(prevfd); - } - if (pip[1] >= 0) { - if (!(prevfd >= 0 && pip[0] == 0)) - close(pip[0]); - if (pip[1] != 1) { - dup2(pip[1], 1); - close(pip[1]); - } - } - evaltree(lp->n, EV_EXIT); - } - if (prevfd >= 0) - close(prevfd); - prevfd = pip[0]; - if (pip[1] != -1) - close(pip[1]); - } - INTON; - if (n->npipe.backgnd == 0) { - INTOFF; - exitstatus = waitforjob(jp, (int *)NULL); - TRACE(("evalpipe: job done exit status %d\n", exitstatus)); - INTON; - } else - exitstatus = 0; -} - - - -static int -is_valid_fast_cmdsubst(union node *n) -{ - - return (n->type == NCMD); -} - -/* - * Execute a command inside back quotes. If it's a builtin command, we - * want to save its output in a block obtained from malloc. Otherwise - * we fork off a subprocess and get the output of the command via a pipe. - * Should be called with interrupts off. - */ - -void -evalbackcmd(union node *n, struct backcmd *result) -{ - int pip[2]; - struct job *jp; - struct stackmark smark; - struct jmploc jmploc; - struct jmploc *savehandler; - struct localvar *savelocalvars; - unsigned char saveoptreset; - - result->fd = -1; - result->buf = NULL; - result->nleft = 0; - result->jp = NULL; - if (n == NULL) { - exitstatus = 0; - return; - } - setstackmark(&smark); - exitstatus = oexitstatus; - if (is_valid_fast_cmdsubst(n)) { - savelocalvars = localvars; - localvars = NULL; - saveoptreset = shellparam.reset; - forcelocal++; - savehandler = handler; - if (setjmp(jmploc.loc)) { - if (exception == EXERROR || exception == EXEXEC) - exitstatus = 2; - else if (exception != 0) { - handler = savehandler; - forcelocal--; - poplocalvars(); - localvars = savelocalvars; - shellparam.reset = saveoptreset; - longjmp(handler->loc, 1); - } - } else { - handler = &jmploc; - evalcommand(n, EV_BACKCMD, result); - } - handler = savehandler; - forcelocal--; - poplocalvars(); - localvars = savelocalvars; - shellparam.reset = saveoptreset; - } else { - if (pipe(pip) < 0) - error("Pipe call failed: %s", strerror(errno)); - jp = makejob(n, 1); - if (forkshell(jp, n, FORK_NOJOB) == 0) { - FORCEINTON; - close(pip[0]); - if (pip[1] != 1) { - dup2(pip[1], 1); - close(pip[1]); - } - evaltree(n, EV_EXIT); - } - close(pip[1]); - result->fd = pip[0]; - result->jp = jp; - } - popstackmark(&smark); - TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n", - result->fd, result->buf, result->nleft, result->jp)); -} - -static int -mustexpandto(const char *argtext, const char *mask) -{ - for (;;) { - if (*argtext == CTLQUOTEMARK || *argtext == CTLQUOTEEND) { - argtext++; - continue; - } - if (*argtext == CTLESC) - argtext++; - else if (BASESYNTAX[(int)*argtext] == CCTL) - return (0); - if (*argtext != *mask) - return (0); - if (*argtext == '\0') - return (1); - argtext++; - mask++; - } -} - -static int -isdeclarationcmd(struct narg *arg) -{ - int have_command = 0; - - if (arg == NULL) - return (0); - while (mustexpandto(arg->text, "command")) { - have_command = 1; - arg = &arg->next->narg; - if (arg == NULL) - return (0); - /* - * To also allow "command -p" and "command --" as part of - * a declaration command, add code here. - * We do not do this, as ksh does not do it either and it - * is not required by POSIX. - */ - } - return (mustexpandto(arg->text, "export") || - mustexpandto(arg->text, "readonly") || - (mustexpandto(arg->text, "local") && - (have_command || !isfunc("local")))); -} - -static void -xtracecommand(struct arglist *varlist, int argc, char **argv) -{ - char sep = 0; - const char *text, *p, *ps4; - int i; - - ps4 = expandstr(ps4val()); - out2str(ps4 != NULL ? ps4 : ps4val()); - for (i = 0; i < varlist->count; i++) { - text = varlist->args[i]; - if (sep != 0) - out2c(' '); - p = strchr(text, '='); - if (p != NULL) { - p++; - outbin(text, p - text, out2); - out2qstr(p); - } else - out2qstr(text); - sep = ' '; - } - for (i = 0; i < argc; i++) { - text = argv[i]; - if (sep != 0) - out2c(' '); - out2qstr(text); - sep = ' '; - } - out2c('\n'); - flushout(&errout); -} - -/* - * Check if a builtin can safely be executed in the same process, - * even though it should be in a subshell (command substitution). - * Note that jobid, jobs, times and trap can show information not - * available in a child process; this is deliberate. - * The arguments should already have been expanded. - */ -static int -safe_builtin(int idx, int argc, char **argv) -{ - /* Generated from builtins.def. */ - if (safe_builtin_always(idx)) - return (1); - if (idx == EXPORTCMD || idx == TRAPCMD || idx == ULIMITCMD || - idx == UMASKCMD) - return (argc <= 1 || (argc == 2 && argv[1][0] == '-')); - if (idx == SETCMD) - return (argc <= 1 || (argc == 2 && (argv[1][0] == '-' || - argv[1][0] == '+') && argv[1][1] == 'o' && - argv[1][2] == '\0')); - return (0); -} - -/* - * Execute a simple command. - * Note: This may or may not return if (flags & EV_EXIT). - */ - -static void -evalcommand(union node *cmd, int flags, struct backcmd *backcmd) -{ - union node *argp; - struct arglist arglist; - struct arglist varlist; - char **argv; - int argc; - char **envp; - int varflag; - int mode; - int pip[2]; - struct cmdentry cmdentry; - struct job *jp; - struct jmploc jmploc; - struct jmploc *savehandler; - char *savecmdname; - struct shparam saveparam; - struct localvar *savelocalvars; - struct parsefile *savetopfile; - volatile int e; - char *lastarg; - int signaled; - int do_clearcmdentry; - const char *path = pathval(); - int i; - - /* First expand the arguments. */ - TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); - emptyarglist(&arglist); - emptyarglist(&varlist); - varflag = 1; - jp = NULL; - do_clearcmdentry = 0; - oexitstatus = exitstatus; - exitstatus = 0; - /* Add one slot at the beginning for tryexec(). */ - appendarglist(&arglist, nullstr); - for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - if (varflag && isassignment(argp->narg.text)) { - expandarg(argp, varflag == 1 ? &varlist : &arglist, - EXP_VARTILDE); - continue; - } else if (varflag == 1) - varflag = isdeclarationcmd(&argp->narg) ? 2 : 0; - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - } - appendarglist(&arglist, nullstr); - expredir(cmd->ncmd.redirect); - argc = arglist.count - 2; - argv = &arglist.args[1]; - - argv[argc] = NULL; - lastarg = NULL; - if (iflag && funcnest == 0 && argc > 0) - lastarg = argv[argc - 1]; - - /* Print the command if xflag is set. */ - if (xflag) - xtracecommand(&varlist, argc, argv); - - /* Now locate the command. */ - if (argc == 0) { - /* Variable assignment(s) without command */ - cmdentry.cmdtype = CMDBUILTIN; - cmdentry.u.index = BLTINCMD; - cmdentry.special = 0; - } else { - static const char PATH[] = "PATH="; - int cmd_flags = 0, bltinonly = 0; - - /* - * Modify the command lookup path, if a PATH= assignment - * is present - */ - for (i = 0; i < varlist.count; i++) - if (strncmp(varlist.args[i], PATH, sizeof(PATH) - 1) == 0) { - path = varlist.args[i] + sizeof(PATH) - 1; - /* - * On `PATH=... command`, we need to make - * sure that the command isn't using the - * non-updated hash table of the outer PATH - * setting and we need to make sure that - * the hash table isn't filled with items - * from the temporary setting. - * - * It would be better to forbit using and - * updating the table while this command - * runs, by the command finding mechanism - * is heavily integrated with hash handling, - * so we just delete the hash before and after - * the command runs. Partly deleting like - * changepatch() does doesn't seem worth the - * bookinging effort, since most such runs add - * directories in front of the new PATH. - */ - clearcmdentry(); - do_clearcmdentry = 1; - } - - for (;;) { - if (bltinonly) { - cmdentry.u.index = find_builtin(*argv, &cmdentry.special); - if (cmdentry.u.index < 0) { - cmdentry.u.index = BLTINCMD; - argv--; - argc++; - break; - } - } else - find_command(argv[0], &cmdentry, cmd_flags, path); - /* implement the bltin and command builtins here */ - if (cmdentry.cmdtype != CMDBUILTIN) - break; - if (cmdentry.u.index == BLTINCMD) { - if (argc == 1) - break; - argv++; - argc--; - bltinonly = 1; - } else if (cmdentry.u.index == COMMANDCMD) { - if (argc == 1) - break; - if (!strcmp(argv[1], "-p")) { - if (argc == 2) - break; - if (argv[2][0] == '-') { - if (strcmp(argv[2], "--")) - break; - if (argc == 3) - break; - argv += 3; - argc -= 3; - } else { - argv += 2; - argc -= 2; - } - path = _PATH_STDPATH; - clearcmdentry(); - do_clearcmdentry = 1; - } else if (!strcmp(argv[1], "--")) { - if (argc == 2) - break; - argv += 2; - argc -= 2; - } else if (argv[1][0] == '-') - break; - else { - argv++; - argc--; - } - cmd_flags |= DO_NOFUNC; - bltinonly = 0; - } else - break; - } - /* - * Special builtins lose their special properties when - * called via 'command'. - */ - if (cmd_flags & DO_NOFUNC) - cmdentry.special = 0; - } - - /* Fork off a child process if necessary. */ - if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) - && ((flags & EV_EXIT) == 0 || have_traps())) - || ((flags & EV_BACKCMD) != 0 - && (cmdentry.cmdtype != CMDBUILTIN || - !safe_builtin(cmdentry.u.index, argc, argv)))) { - jp = makejob(cmd, 1); - mode = FORK_FG; - if (flags & EV_BACKCMD) { - mode = FORK_NOJOB; - if (pipe(pip) < 0) - error("Pipe call failed: %s", strerror(errno)); - } - if (cmdentry.cmdtype == CMDNORMAL && - cmd->ncmd.redirect == NULL && - varlist.count == 0 && - (mode == FORK_FG || mode == FORK_NOJOB) && - !disvforkset() && !iflag && !mflag) { - vforkexecshell(jp, argv, environment(), path, - cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); - goto parent; - } - if (forkshell(jp, cmd, mode) != 0) - goto parent; /* at end of routine */ - if (flags & EV_BACKCMD) { - FORCEINTON; - close(pip[0]); - if (pip[1] != 1) { - dup2(pip[1], 1); - close(pip[1]); - } - flags &= ~EV_BACKCMD; - } - flags |= EV_EXIT; - } - - /* This is the child process if a fork occurred. */ - /* Execute the command. */ - if (cmdentry.cmdtype == CMDFUNCTION) { -#ifdef DEBUG - trputs("Shell function: "); trargs(argv); -#endif - saveparam = shellparam; - shellparam.malloc = 0; - shellparam.reset = 1; - shellparam.nparam = argc - 1; - shellparam.p = argv + 1; - shellparam.optp = NULL; - shellparam.optnext = NULL; - INTOFF; - savelocalvars = localvars; - localvars = NULL; - reffunc(cmdentry.u.func); - savehandler = handler; - if (setjmp(jmploc.loc)) { - popredir(); - unreffunc(cmdentry.u.func); - poplocalvars(); - localvars = savelocalvars; - freeparam(&shellparam); - shellparam = saveparam; - funcnest--; - handler = savehandler; - longjmp(handler->loc, 1); - } - handler = &jmploc; - funcnest++; - redirect(cmd->ncmd.redirect, REDIR_PUSH); - INTON; - for (i = 0; i < varlist.count; i++) - mklocal(varlist.args[i]); - exitstatus = oexitstatus; - evaltree(getfuncnode(cmdentry.u.func), - flags & (EV_TESTED | EV_EXIT)); - INTOFF; - unreffunc(cmdentry.u.func); - poplocalvars(); - localvars = savelocalvars; - freeparam(&shellparam); - shellparam = saveparam; - handler = savehandler; - funcnest--; - popredir(); - INTON; - if (evalskip == SKIPRETURN) { - evalskip = 0; - skipcount = 0; - } - if (jp) - exitshell(exitstatus); - } else if (cmdentry.cmdtype == CMDBUILTIN) { -#ifdef DEBUG - trputs("builtin command: "); trargs(argv); -#endif - mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; - if (flags == EV_BACKCMD) { - memout.nextc = memout.buf; - mode |= REDIR_BACKQ; - } - savecmdname = commandname; - savetopfile = getcurrentfile(); - cmdenviron = &varlist; - e = -1; - savehandler = handler; - if (setjmp(jmploc.loc)) { - e = exception; - if (e == EXINT) - exitstatus = SIGINT+128; - else if (e != EXEXIT) - exitstatus = 2; - goto cmddone; - } - handler = &jmploc; - redirect(cmd->ncmd.redirect, mode); - outclearerror(out1); - /* - * If there is no command word, redirection errors should - * not be fatal but assignment errors should. - */ - if (argc == 0) - cmdentry.special = 1; - listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET); - if (argc > 0) - bltinsetlocale(); - commandname = argv[0]; - argptr = argv + 1; - nextopt_optptr = NULL; /* initialize nextopt */ - builtin_flags = flags; - exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); - flushall(); - if (outiserror(out1)) { - warning("write error on stdout"); - if (exitstatus == 0 || exitstatus == 1) - exitstatus = 2; - } -cmddone: - if (argc > 0) - bltinunsetlocale(); - cmdenviron = NULL; - out1 = &output; - out2 = &errout; - freestdout(); - handler = savehandler; - commandname = savecmdname; - if (jp) - exitshell(exitstatus); - if (flags == EV_BACKCMD) { - backcmd->buf = memout.buf; - backcmd->nleft = memout.buf != NULL ? - memout.nextc - memout.buf : 0; - memout.buf = NULL; - memout.nextc = NULL; - memout.bufend = NULL; - memout.bufsize = 64; - } - if (cmdentry.u.index != EXECCMD) - popredir(); - if (e != -1) { - if ((e != EXERROR && e != EXEXEC) - || cmdentry.special) - exraise(e); - popfilesupto(savetopfile); - if (flags != EV_BACKCMD) - FORCEINTON; - } - } else { -#ifdef DEBUG - trputs("normal command: "); trargs(argv); -#endif - redirect(cmd->ncmd.redirect, 0); - for (i = 0; i < varlist.count; i++) - setvareq(varlist.args[i], VEXPORT|VSTACK); - envp = environment(); - shellexec(argv, envp, path, cmdentry.u.index); - /*NOTREACHED*/ - } - goto out; - -parent: /* parent process gets here (if we forked) */ - if (mode == FORK_FG) { /* argument to fork */ - INTOFF; - exitstatus = waitforjob(jp, &signaled); - INTON; - if (iflag && loopnest > 0 && signaled) { - evalskip = SKIPBREAK; - skipcount = loopnest; - } - } else if (mode == FORK_NOJOB) { - backcmd->fd = pip[0]; - close(pip[1]); - backcmd->jp = jp; - } - -out: - if (lastarg) - setvar("_", lastarg, 0); - if (do_clearcmdentry) - clearcmdentry(); -} - - - -/* - * Search for a command. This is called before we fork so that the - * location of the command will be available in the parent as well as - * the child. The check for "goodname" is an overly conservative - * check that the name will not be subject to expansion. - */ - -static void -prehash(union node *n) -{ - struct cmdentry entry; - - if (n && n->type == NCMD && n->ncmd.args) - if (goodname(n->ncmd.args->narg.text)) - find_command(n->ncmd.args->narg.text, &entry, 0, - pathval()); -} - - - -/* - * Builtin commands. Builtin commands whose functions are closely - * tied to evaluation are implemented here. - */ - -/* - * No command given, a bltin command with no arguments, or a bltin command - * with an invalid name. - */ - -int -bltincmd(int argc, char **argv) -{ - if (argc > 1) { - out2fmt_flush("%s: not found\n", argv[1]); - return 127; - } - /* - * Preserve exitstatus of a previous possible command substitution - * as POSIX mandates - */ - return exitstatus; -} - - -/* - * Handle break and continue commands. Break, continue, and return are - * all handled by setting the evalskip flag. The evaluation routines - * above all check this flag, and if it is set they start skipping - * commands rather than executing them. The variable skipcount is - * the number of loops to break/continue, or the number of function - * levels to return. (The latter is always 1.) It should probably - * be an error to break out of more loops than exist, but it isn't - * in the standard shell so we don't make it one here. - */ - -int -breakcmd(int argc, char **argv) -{ - long n; - char *end; - - if (argc > 1) { - /* Allow arbitrarily large numbers. */ - n = strtol(argv[1], &end, 10); - if (!is_digit(argv[1][0]) || *end != '\0') - error("Illegal number: %s", argv[1]); - } else - n = 1; - if (n > loopnest) - n = loopnest; - if (n > 0) { - evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; - skipcount = n; - } - return 0; -} - -/* - * The `command' command. - */ -int -commandcmd(int argc __unused, char **argv __unused) -{ - const char *path; - int ch; - int cmd = -1; - - path = bltinlookup("PATH", 1); - - while ((ch = nextopt("pvV")) != '\0') { - switch (ch) { - case 'p': - path = _PATH_STDPATH; - break; - case 'v': - cmd = TYPECMD_SMALLV; - break; - case 'V': - cmd = TYPECMD_BIGV; - break; - } - } - - if (cmd != -1) { - if (*argptr == NULL || argptr[1] != NULL) - error("wrong number of arguments"); - return typecmd_impl(2, argptr - 1, cmd, path); - } - if (*argptr != NULL) - error("commandcmd bad call"); - - /* - * Do nothing successfully if no command was specified; - * ksh also does this. - */ - return 0; -} - - -/* - * The return command. - */ - -int -returncmd(int argc, char **argv) -{ - int ret = argc > 1 ? number(argv[1]) : oexitstatus; - - evalskip = SKIPRETURN; - skipcount = 1; - return ret; -} - - -int -falsecmd(int argc __unused, char **argv __unused) -{ - return 1; -} - - -int -truecmd(int argc __unused, char **argv __unused) -{ - return 0; -} - - -int -execcmd(int argc, char **argv) -{ - int i; - - /* - * Because we have historically not supported any options, - * only treat "--" specially. - */ - if (argc > 1 && strcmp(argv[1], "--") == 0) - argc--, argv++; - if (argc > 1) { - iflag = 0; /* exit on error */ - mflag = 0; - optschanged(); - for (i = 0; i < cmdenviron->count; i++) - setvareq(cmdenviron->args[i], VEXPORT|VSTACK); - shellexec(argv + 1, environment(), pathval(), 0); - - } - return 0; -} - - -int -timescmd(int argc __unused, char **argv __unused) -{ - struct rusage ru; - long shumins, shsmins, chumins, chsmins; - double shusecs, shssecs, chusecs, chssecs; - - if (getrusage(RUSAGE_SELF, &ru) < 0) - return 1; - shumins = ru.ru_utime.tv_sec / 60; - shusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; - shsmins = ru.ru_stime.tv_sec / 60; - shssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; - if (getrusage(RUSAGE_CHILDREN, &ru) < 0) - return 1; - chumins = ru.ru_utime.tv_sec / 60; - chusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; - chsmins = ru.ru_stime.tv_sec / 60; - chssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; - out1fmt("%ldm%.3fs %ldm%.3fs\n%ldm%.3fs %ldm%.3fs\n", shumins, - shusecs, shsmins, shssecs, chumins, chusecs, chsmins, chssecs); - return 0; -} diff --git a/bin/catsh/eval.h b/bin/catsh/eval.h deleted file mode 100644 index 7bfa0216..00000000 --- a/bin/catsh/eval.h +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)eval.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/eval.h 314436 2017-02-28 23:42:47Z imp $ - */ - -extern char *commandname; /* currently executing command */ -extern int exitstatus; /* exit status of last command */ -extern int oexitstatus; /* saved exit status */ -extern struct arglist *cmdenviron; /* environment for builtin command */ - - -struct backcmd { /* result of evalbackcmd */ - int fd; /* file descriptor to read from */ - char *buf; /* buffer */ - int nleft; /* number of chars in buffer */ - struct job *jp; /* job structure for command */ -}; - -void reseteval(void); - -/* flags in argument to evaltree/evalstring */ -#define EV_EXIT 01 /* exit after evaluating tree */ -#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ -#define EV_BACKCMD 04 /* command executing within back quotes */ - -void evalstring(const char *, int); -union node; /* BLETCH for ansi C */ -void evaltree(union node *, int); -void evalbackcmd(union node *, struct backcmd *); - -/* in_function returns nonzero if we are currently evaluating a function */ -#define in_function() funcnest -extern int funcnest; -extern int evalskip; -extern int skipcount; - -/* reasons for skipping commands (see comment on breakcmd routine) */ -#define SKIPBREAK 1 -#define SKIPCONT 2 -#define SKIPRETURN 3 diff --git a/bin/catsh/exec.c b/bin/catsh/exec.c deleted file mode 100644 index 5026e644..00000000 --- a/bin/catsh/exec.c +++ /dev/null @@ -1,784 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/exec.c 336320 2018-07-15 21:55:17Z jilles $"); - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <paths.h> -#include <stdlib.h> - -/* - * When commands are first encountered, they are entered in a hash table. - * This ensures that a full path search will not have to be done for them - * on each invocation. - * - * We should investigate converting to a linear search, even though that - * would make the command name "hash" a misnomer. - */ - -#include "shell.h" -#include "main.h" -#include "nodes.h" -#include "parser.h" -#include "redir.h" -#include "eval.h" -#include "exec.h" -#include "builtins.h" -#include "var.h" -#include "options.h" -#include "input.h" -#include "output.h" -#include "syntax.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "show.h" -#include "jobs.h" -#include "alias.h" - - -#define CMDTABLESIZE 31 /* should be prime */ - - - -struct tblentry { - struct tblentry *next; /* next entry in hash chain */ - union param param; /* definition of builtin function */ - int special; /* flag for special builtin commands */ - signed char cmdtype; /* index identifying command */ - char cmdname[]; /* name of command */ -}; - - -static struct tblentry *cmdtable[CMDTABLESIZE]; -static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */ -int exerrno = 0; /* Last exec error */ - - -static void tryexec(char *, char **, char **); -static void printentry(struct tblentry *, int); -static struct tblentry *cmdlookup(const char *, int); -static void delete_cmd_entry(void); -static void addcmdentry(const char *, struct cmdentry *); - - - -/* - * Exec a program. Never returns. If you change this routine, you may - * have to change the find_command routine as well. - * - * The argv array may be changed and element argv[-1] should be writable. - */ - -void -shellexec(char **argv, char **envp, const char *path, int idx) -{ - char *cmdname; - const char *opt; - int e; - - if (strchr(argv[0], '/') != NULL) { - tryexec(argv[0], argv, envp); - e = errno; - } else { - e = ENOENT; - while ((cmdname = padvance(&path, &opt, argv[0])) != NULL) { - if (--idx < 0 && opt == NULL) { - tryexec(cmdname, argv, envp); - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - if (e == ENOEXEC) - break; - } - stunalloc(cmdname); - } - } - - /* Map to POSIX errors */ - if (e == ENOENT || e == ENOTDIR) { - exerrno = 127; - exerror(EXEXEC, "%s: not found", argv[0]); - } else { - exerrno = 126; - exerror(EXEXEC, "%s: %s", argv[0], strerror(e)); - } -} - - -static void -tryexec(char *cmd, char **argv, char **envp) -{ - int e, in; - ssize_t n; - char buf[256]; - - execve(cmd, argv, envp); - e = errno; - if (e == ENOEXEC) { - INTOFF; - in = open(cmd, O_RDONLY | O_NONBLOCK); - if (in != -1) { - n = pread(in, buf, sizeof buf, 0); - close(in); - if (n > 0 && memchr(buf, '\0', n) != NULL) { - errno = ENOEXEC; - return; - } - } - *argv = cmd; - *--argv = __DECONST(char *, _PATH_BSHELL); - execve(_PATH_BSHELL, argv, envp); - } - errno = e; -} - -/* - * Do a path search. The variable path (passed by reference) should be - * set to the start of the path before the first call; padvance will update - * this value as it proceeds. Successive calls to padvance will return - * the possible path expansions in sequence. If popt is not NULL, options - * are processed: if an option (indicated by a percent sign) appears in - * the path entry then *popt will be set to point to it; else *popt will be - * set to NULL. If popt is NULL, percent signs are not special. - */ - -char * -padvance(const char **path, const char **popt, const char *name) -{ - const char *p, *start; - char *q; - size_t len, namelen; - - if (*path == NULL) - return NULL; - start = *path; - if (popt != NULL) - for (p = start; *p && *p != ':' && *p != '%'; p++) - ; /* nothing */ - else - for (p = start; *p && *p != ':'; p++) - ; /* nothing */ - namelen = strlen(name); - len = p - start + namelen + 2; /* "2" is for '/' and '\0' */ - STARTSTACKSTR(q); - CHECKSTRSPACE(len, q); - if (p != start) { - memcpy(q, start, p - start); - q += p - start; - *q++ = '/'; - } - memcpy(q, name, namelen + 1); - if (popt != NULL) { - if (*p == '%') { - *popt = ++p; - while (*p && *p != ':') p++; - } else - *popt = NULL; - } - if (*p == ':') - *path = p + 1; - else - *path = NULL; - return stalloc(len); -} - - - -/*** Command hashing code ***/ - - -int -hashcmd(int argc __unused, char **argv __unused) -{ - struct tblentry **pp; - struct tblentry *cmdp; - int c; - int verbose; - struct cmdentry entry; - char *name; - int errors; - - errors = 0; - verbose = 0; - while ((c = nextopt("rv")) != '\0') { - if (c == 'r') { - clearcmdentry(); - } else if (c == 'v') { - verbose++; - } - } - if (*argptr == NULL) { - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype == CMDNORMAL) - printentry(cmdp, verbose); - } - } - return 0; - } - while ((name = *argptr) != NULL) { - if ((cmdp = cmdlookup(name, 0)) != NULL - && cmdp->cmdtype == CMDNORMAL) - delete_cmd_entry(); - find_command(name, &entry, DO_ERR, pathval()); - if (entry.cmdtype == CMDUNKNOWN) - errors = 1; - else if (verbose) { - cmdp = cmdlookup(name, 0); - if (cmdp != NULL) - printentry(cmdp, verbose); - else { - outfmt(out2, "%s: not found\n", name); - errors = 1; - } - flushall(); - } - argptr++; - } - return errors; -} - - -static void -printentry(struct tblentry *cmdp, int verbose) -{ - int idx; - const char *path, *opt; - char *name; - - if (cmdp->cmdtype == CMDNORMAL) { - idx = cmdp->param.index; - path = pathval(); - do { - name = padvance(&path, &opt, cmdp->cmdname); - stunalloc(name); - } while (--idx >= 0); - out1str(name); - } else if (cmdp->cmdtype == CMDBUILTIN) { - out1fmt("builtin %s", cmdp->cmdname); - } else if (cmdp->cmdtype == CMDFUNCTION) { - out1fmt("function %s", cmdp->cmdname); - if (verbose) { - INTOFF; - name = commandtext(getfuncnode(cmdp->param.func)); - out1c(' '); - out1str(name); - ckfree(name); - INTON; - } -#ifdef DEBUG - } else { - error("internal error: cmdtype %d", cmdp->cmdtype); -#endif - } - out1c('\n'); -} - - - -/* - * Resolve a command name. If you change this routine, you may have to - * change the shellexec routine as well. - */ - -void -find_command(const char *name, struct cmdentry *entry, int act, - const char *path) -{ - struct tblentry *cmdp, loc_cmd; - int idx; - const char *opt; - char *fullname; - struct stat statb; - int e; - int i; - int spec; - int cd; - - /* If name contains a slash, don't use the hash table */ - if (strchr(name, '/') != NULL) { - entry->cmdtype = CMDNORMAL; - entry->u.index = 0; - entry->special = 0; - return; - } - - cd = 0; - - /* If name is in the table, we're done */ - if ((cmdp = cmdlookup(name, 0)) != NULL) { - if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC) - cmdp = NULL; - else - goto success; - } - - /* Check for builtin next */ - if ((i = find_builtin(name, &spec)) >= 0) { - INTOFF; - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) - cmdp = &loc_cmd; - cmdp->cmdtype = CMDBUILTIN; - cmdp->param.index = i; - cmdp->special = spec; - INTON; - goto success; - } - - /* We have to search path. */ - - e = ENOENT; - idx = -1; - for (;(fullname = padvance(&path, &opt, name)) != NULL; - stunalloc(fullname)) { - idx++; - if (opt) { - if (strncmp(opt, "func", 4) == 0) { - /* handled below */ - } else { - continue; /* ignore unimplemented options */ - } - } - if (fullname[0] != '/') - cd = 1; - if (stat(fullname, &statb) < 0) { - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - continue; - } - e = EACCES; /* if we fail, this will be the error */ - if (!S_ISREG(statb.st_mode)) - continue; - if (opt) { /* this is a %func directory */ - readcmdfile(fullname); - if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) - error("%s not defined in %s", name, fullname); - stunalloc(fullname); - goto success; - } -#ifdef notdef - if (statb.st_uid == geteuid()) { - if ((statb.st_mode & 0100) == 0) - goto loop; - } else if (statb.st_gid == getegid()) { - if ((statb.st_mode & 010) == 0) - goto loop; - } else { - if ((statb.st_mode & 01) == 0) - goto loop; - } -#endif - TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); - INTOFF; - stunalloc(fullname); - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) - cmdp = &loc_cmd; - cmdp->cmdtype = CMDNORMAL; - cmdp->param.index = idx; - cmdp->special = 0; - INTON; - goto success; - } - - if (act & DO_ERR) { - if (e == ENOENT || e == ENOTDIR) - outfmt(out2, "%s: not found\n", name); - else - outfmt(out2, "%s: %s\n", name, strerror(e)); - } - entry->cmdtype = CMDUNKNOWN; - entry->u.index = 0; - entry->special = 0; - return; - -success: - if (cd) - cmdtable_cd = 1; - entry->cmdtype = cmdp->cmdtype; - entry->u = cmdp->param; - entry->special = cmdp->special; -} - - - -/* - * Search the table of builtin commands. - */ - -int -find_builtin(const char *name, int *special) -{ - const unsigned char *bp; - size_t len; - - len = strlen(name); - for (bp = builtincmd ; *bp ; bp += 2 + bp[0]) { - if (bp[0] == len && memcmp(bp + 2, name, len) == 0) { - *special = (bp[1] & BUILTIN_SPECIAL) != 0; - return bp[1] & ~BUILTIN_SPECIAL; - } - } - return -1; -} - - - -/* - * Called when a cd is done. If any entry in cmdtable depends on the current - * directory, simply clear cmdtable completely. - */ - -void -hashcd(void) -{ - if (cmdtable_cd) - clearcmdentry(); -} - - - -/* - * Called before PATH is changed. The argument is the new value of PATH; - * pathval() still returns the old value at this point. Called with - * interrupts off. - */ - -void -changepath(const char *newval __unused) -{ - clearcmdentry(); -} - - -/* - * Clear out cached utility locations. - */ - -void -clearcmdentry(void) -{ - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if (cmdp->cmdtype == CMDNORMAL) { - *pp = cmdp->next; - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - cmdtable_cd = 0; - INTON; -} - - -/* - * Locate a command in the command hash table. If "add" is nonzero, - * add the command to the table if it is not already present. The - * variable "lastcmdentry" is set to point to the address of the link - * pointing to the entry, so that delete_cmd_entry can delete the - * entry. - */ - -static struct tblentry **lastcmdentry; - - -static struct tblentry * -cmdlookup(const char *name, int add) -{ - unsigned int hashval; - const char *p; - struct tblentry *cmdp; - struct tblentry **pp; - size_t len; - - p = name; - hashval = (unsigned char)*p << 4; - while (*p) - hashval += *p++; - pp = &cmdtable[hashval % CMDTABLESIZE]; - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (equal(cmdp->cmdname, name)) - break; - pp = &cmdp->next; - } - if (add && cmdp == NULL) { - INTOFF; - len = strlen(name); - cmdp = *pp = ckmalloc(sizeof (struct tblentry) + len + 1); - cmdp->next = NULL; - cmdp->cmdtype = CMDUNKNOWN; - memcpy(cmdp->cmdname, name, len + 1); - INTON; - } - lastcmdentry = pp; - return cmdp; -} - -/* - * Delete the command entry returned on the last lookup. - */ - -static void -delete_cmd_entry(void) -{ - struct tblentry *cmdp; - - INTOFF; - cmdp = *lastcmdentry; - *lastcmdentry = cmdp->next; - ckfree(cmdp); - INTON; -} - - - -/* - * Add a new command entry, replacing any existing command entry for - * the same name. - */ - -static void -addcmdentry(const char *name, struct cmdentry *entry) -{ - struct tblentry *cmdp; - - INTOFF; - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) { - unreffunc(cmdp->param.func); - } - cmdp->cmdtype = entry->cmdtype; - cmdp->param = entry->u; - cmdp->special = entry->special; - INTON; -} - - -/* - * Define a shell function. - */ - -void -defun(const char *name, union node *func) -{ - struct cmdentry entry; - - INTOFF; - entry.cmdtype = CMDFUNCTION; - entry.u.func = copyfunc(func); - entry.special = 0; - addcmdentry(name, &entry); - INTON; -} - - -/* - * Delete a function if it exists. - * Called with interrupts off. - */ - -int -unsetfunc(const char *name) -{ - struct tblentry *cmdp; - - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { - unreffunc(cmdp->param.func); - delete_cmd_entry(); - return (0); - } - return (0); -} - - -/* - * Check if a function by a certain name exists. - */ -int -isfunc(const char *name) -{ - struct tblentry *cmdp; - cmdp = cmdlookup(name, 0); - return (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION); -} - - -/* - * Shared code for the following builtin commands: - * type, command -v, command -V - */ - -int -typecmd_impl(int argc, char **argv, int cmd, const char *path) -{ - struct cmdentry entry; - struct tblentry *cmdp; - const char *const *pp; - struct alias *ap; - int i; - int error1 = 0; - - if (path != pathval()) - clearcmdentry(); - - for (i = 1; i < argc; i++) { - /* First look at the keywords */ - for (pp = parsekwd; *pp; pp++) - if (**pp == *argv[i] && equal(*pp, argv[i])) - break; - - if (*pp) { - if (cmd == TYPECMD_SMALLV) - out1fmt("%s\n", argv[i]); - else - out1fmt("%s is a shell keyword\n", argv[i]); - continue; - } - - /* Then look at the aliases */ - if ((ap = lookupalias(argv[i], 1)) != NULL) { - if (cmd == TYPECMD_SMALLV) { - out1fmt("alias %s=", argv[i]); - out1qstr(ap->val); - outcslow('\n', out1); - } else - out1fmt("%s is an alias for %s\n", argv[i], - ap->val); - continue; - } - - /* Then check if it is a tracked alias */ - if ((cmdp = cmdlookup(argv[i], 0)) != NULL) { - entry.cmdtype = cmdp->cmdtype; - entry.u = cmdp->param; - entry.special = cmdp->special; - } - else { - /* Finally use brute force */ - find_command(argv[i], &entry, 0, path); - } - - switch (entry.cmdtype) { - case CMDNORMAL: { - if (strchr(argv[i], '/') == NULL) { - const char *path2 = path; - const char *opt2; - char *name; - int j = entry.u.index; - do { - name = padvance(&path2, &opt2, argv[i]); - stunalloc(name); - } while (--j >= 0); - if (cmd == TYPECMD_SMALLV) - out1fmt("%s\n", name); - else - out1fmt("%s is%s %s\n", argv[i], - (cmdp && cmd == TYPECMD_TYPE) ? - " a tracked alias for" : "", - name); - } else { - if (faccessat(AT_FDCWD, argv[i], X_OK, AT_EACCESS) == 0) { - if (cmd == TYPECMD_SMALLV) - out1fmt("%s\n", argv[i]); - else - out1fmt("%s is %s\n", argv[i], - argv[i]); - } else { - if (cmd != TYPECMD_SMALLV) - outfmt(out2, "%s: %s\n", - argv[i], strerror(errno)); - error1 |= 127; - } - } - break; - } - case CMDFUNCTION: - if (cmd == TYPECMD_SMALLV) - out1fmt("%s\n", argv[i]); - else - out1fmt("%s is a shell function\n", argv[i]); - break; - - case CMDBUILTIN: - if (cmd == TYPECMD_SMALLV) - out1fmt("%s\n", argv[i]); - else if (entry.special) - out1fmt("%s is a special shell builtin\n", - argv[i]); - else - out1fmt("%s is a shell builtin\n", argv[i]); - break; - - default: - if (cmd != TYPECMD_SMALLV) - outfmt(out2, "%s: not found\n", argv[i]); - error1 |= 127; - break; - } - } - - if (path != pathval()) - clearcmdentry(); - - return error1; -} - -/* - * Locate and print what a word is... - */ - -int -typecmd(int argc, char **argv) -{ - if (argc > 2 && strcmp(argv[1], "--") == 0) - argc--, argv++; - return typecmd_impl(argc, argv, TYPECMD_TYPE, bltinlookup("PATH", 1)); -} diff --git a/bin/catsh/exec.h b/bin/catsh/exec.h deleted file mode 100644 index 3b3a5b77..00000000 --- a/bin/catsh/exec.h +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)exec.h 8.3 (Berkeley) 6/8/95 - * $FreeBSD: releng/12.0/bin/sh/exec.h 336320 2018-07-15 21:55:17Z jilles $ - */ - -/* values of cmdtype */ -#define CMDUNKNOWN -1 /* no entry in table for command */ -#define CMDNORMAL 0 /* command is an executable program */ -#define CMDBUILTIN 1 /* command is a shell builtin */ -#define CMDFUNCTION 2 /* command is a shell function */ - -/* values for typecmd_impl's third parameter */ -enum { - TYPECMD_SMALLV, /* command -v */ - TYPECMD_BIGV, /* command -V */ - TYPECMD_TYPE /* type */ -}; - -union node; -struct cmdentry { - int cmdtype; - union param { - int index; - struct funcdef *func; - } u; - int special; -}; - - -/* action to find_command() */ -#define DO_ERR 0x01 /* prints errors */ -#define DO_NOFUNC 0x02 /* don't return shell functions, for command */ - -extern int exerrno; /* last exec error */ - -void shellexec(char **, char **, const char *, int) __dead2; -char *padvance(const char **, const char **, const char *); -void find_command(const char *, struct cmdentry *, int, const char *); -int find_builtin(const char *, int *); -void hashcd(void); -void changepath(const char *); -void defun(const char *, union node *); -int unsetfunc(const char *); -int isfunc(const char *); -int typecmd_impl(int, char **, int, const char *); -void clearcmdentry(void); diff --git a/bin/catsh/expand.c b/bin/catsh/expand.c deleted file mode 100644 index 7c419b80..00000000 --- a/bin/catsh/expand.c +++ /dev/null @@ -1,1552 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1997-2005 - * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. - * Copyright (c) 2010-2015 - * Jilles Tjoelker <jilles@stack.nl>. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/expand.c 338473 2018-09-05 19:16:09Z jilles $"); - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <dirent.h> -#include <errno.h> -#include <inttypes.h> -#include <limits.h> -#include <pwd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <wchar.h> -#include <wctype.h> - -/* - * Routines to expand arguments to commands. We have to deal with - * backquotes, shell variables, and file metacharacters. - */ - -#include "shell.h" -#include "main.h" -#include "nodes.h" -#include "eval.h" -#include "expand.h" -#include "syntax.h" -#include "parser.h" -#include "jobs.h" -#include "options.h" -#include "var.h" -#include "input.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "arith.h" -#include "show.h" -#include "builtins.h" - -enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK }; - -struct worddest { - struct arglist *list; - enum wordstate state; -}; - -static char *expdest; /* output of current string */ - -static const char *argstr(const char *, struct nodelist **restrict, int, - struct worddest *); -static const char *exptilde(const char *, int); -static const char *expari(const char *, struct nodelist **restrict, int, - struct worddest *); -static void expbackq(union node *, int, int, struct worddest *); -static const char *subevalvar_trim(const char *, struct nodelist **restrict, - int, int, int); -static const char *subevalvar_misc(const char *, struct nodelist **restrict, - const char *, int, int, int); -static const char *evalvar(const char *, struct nodelist **restrict, int, - struct worddest *); -static int varisset(const char *, int); -static void strtodest(const char *, int, int, int, struct worddest *); -static void reprocess(int, int, int, int, struct worddest *); -static void varvalue(const char *, int, int, int, struct worddest *); -static void expandmeta(char *, struct arglist *); -static void expmeta(char *, char *, struct arglist *); -static int expsortcmp(const void *, const void *); -static int patmatch(const char *, const char *); -static void cvtnum(int, char *); -static int collate_range_cmp(wchar_t, wchar_t); - -void -emptyarglist(struct arglist *list) -{ - - list->args = list->smallarg; - list->count = 0; - list->capacity = sizeof(list->smallarg) / sizeof(list->smallarg[0]); -} - -void -appendarglist(struct arglist *list, char *str) -{ - char **newargs; - int newcapacity; - - if (list->count >= list->capacity) { - newcapacity = list->capacity * 2; - if (newcapacity < 16) - newcapacity = 16; - if (newcapacity > INT_MAX / (int)sizeof(newargs[0])) - error("Too many entries in arglist"); - newargs = stalloc(newcapacity * sizeof(newargs[0])); - memcpy(newargs, list->args, list->count * sizeof(newargs[0])); - list->args = newargs; - list->capacity = newcapacity; - } - list->args[list->count++] = str; -} - -static int -collate_range_cmp(wchar_t c1, wchar_t c2) -{ - wchar_t s1[2], s2[2]; - - s1[0] = c1; - s1[1] = L'\0'; - s2[0] = c2; - s2[1] = L'\0'; - return (wcscoll(s1, s2)); -} - -static char * -stputs_quotes(const char *data, const char *syntax, char *p) -{ - while (*data) { - CHECKSTRSPACE(2, p); - if (syntax[(int)*data] == CCTL) - USTPUTC(CTLESC, p); - USTPUTC(*data++, p); - } - return (p); -} -#define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p) - -static char * -nextword(char c, int flag, char *p, struct worddest *dst) -{ - int is_ws; - - is_ws = c == '\t' || c == '\n' || c == ' '; - if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK : - dst->state != WORD_WS_DELIMITED) || c == '\0') { - STPUTC('\0', p); - if (flag & EXP_GLOB) - expandmeta(grabstackstr(p), dst->list); - else - appendarglist(dst->list, grabstackstr(p)); - dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE; - } else if (!is_ws && dst->state == WORD_WS_DELIMITED) - dst->state = WORD_IDLE; - /* Reserve space while the stack string is empty. */ - appendarglist(dst->list, NULL); - dst->list->count--; - STARTSTACKSTR(p); - return p; -} -#define NEXTWORD(c, flag, p, dstlist) p = nextword(c, flag, p, dstlist) - -static char * -stputs_split(const char *data, const char *syntax, int flag, char *p, - struct worddest *dst) -{ - const char *ifs; - char c; - - ifs = ifsset() ? ifsval() : " \t\n"; - while (*data) { - CHECKSTRSPACE(2, p); - c = *data++; - if (strchr(ifs, c) != NULL) { - NEXTWORD(c, flag, p, dst); - continue; - } - if (flag & EXP_GLOB && syntax[(int)c] == CCTL) - USTPUTC(CTLESC, p); - USTPUTC(c, p); - } - return (p); -} -#define STPUTS_SPLIT(data, syntax, flag, p, dst) p = stputs_split((data), syntax, flag, p, dst) - -/* - * Perform expansions on an argument, placing the resulting list of arguments - * in arglist. Parameter expansion, command substitution and arithmetic - * expansion are always performed; additional expansions can be requested - * via flag (EXP_*). - * The result is left in the stack string. - * When arglist is NULL, perform here document expansion. - * - * When doing something that may cause this to be re-entered, make sure - * the stack string is empty via grabstackstr() and do not assume expdest - * remains valid. - */ -void -expandarg(union node *arg, struct arglist *arglist, int flag) -{ - struct worddest exparg; - struct nodelist *argbackq; - - if (fflag) - flag &= ~EXP_GLOB; - argbackq = arg->narg.backquote; - exparg.list = arglist; - exparg.state = WORD_IDLE; - STARTSTACKSTR(expdest); - argstr(arg->narg.text, &argbackq, flag, &exparg); - if (arglist == NULL) { - STACKSTRNUL(expdest); - return; /* here document expanded */ - } - if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() || - exparg.state == WORD_QUOTEMARK) { - STPUTC('\0', expdest); - if (flag & EXP_SPLIT) { - if (flag & EXP_GLOB) - expandmeta(grabstackstr(expdest), exparg.list); - else - appendarglist(exparg.list, grabstackstr(expdest)); - } - } - if ((flag & EXP_SPLIT) == 0) - appendarglist(arglist, grabstackstr(expdest)); -} - - - -/* - * Perform parameter expansion, command substitution and arithmetic - * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE. - * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'. - * This is used to expand word in ${var+word} etc. - * If EXP_GLOB or EXP_CASE are set, keep and/or generate CTLESC - * characters to allow for further processing. - * - * If EXP_SPLIT is set, dst receives any complete words produced. - */ -static const char * -argstr(const char *p, struct nodelist **restrict argbackq, int flag, - struct worddest *dst) -{ - char c; - int quotes = flag & (EXP_GLOB | EXP_CASE); /* do CTLESC */ - int firsteq = 1; - int split_lit; - int lit_quoted; - - split_lit = flag & EXP_SPLIT_LIT; - lit_quoted = flag & EXP_LIT_QUOTED; - flag &= ~(EXP_SPLIT_LIT | EXP_LIT_QUOTED); - if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) - p = exptilde(p, flag); - for (;;) { - CHECKSTRSPACE(2, expdest); - switch (c = *p++) { - case '\0': - return (p - 1); - case CTLENDVAR: - case CTLENDARI: - return (p); - case CTLQUOTEMARK: - lit_quoted = 1; - /* "$@" syntax adherence hack */ - if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 && - p[2] == '@' && p[3] == '=') - break; - if ((flag & EXP_SPLIT) != 0 && expdest == stackblock()) - dst->state = WORD_QUOTEMARK; - break; - case CTLQUOTEEND: - lit_quoted = 0; - break; - case CTLESC: - c = *p++; - if (split_lit && !lit_quoted && - strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, flag, expdest, dst); - break; - } - if (quotes) - USTPUTC(CTLESC, expdest); - USTPUTC(c, expdest); - break; - case CTLVAR: - p = evalvar(p, argbackq, flag, dst); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - expbackq((*argbackq)->n, c & CTLQUOTE, flag, dst); - *argbackq = (*argbackq)->next; - break; - case CTLARI: - p = expari(p, argbackq, flag, dst); - break; - case ':': - case '=': - /* - * sort of a hack - expand tildes in variable - * assignments (after the first '=' and after ':'s). - */ - if (split_lit && !lit_quoted && - strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, flag, expdest, dst); - break; - } - USTPUTC(c, expdest); - if (flag & EXP_VARTILDE && *p == '~' && - (c != '=' || firsteq)) { - if (c == '=') - firsteq = 0; - p = exptilde(p, flag); - } - break; - default: - if (split_lit && !lit_quoted && - strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, flag, expdest, dst); - break; - } - USTPUTC(c, expdest); - } - } -} - -/* - * Perform tilde expansion, placing the result in the stack string and - * returning the next position in the input string to process. - */ -static const char * -exptilde(const char *p, int flag) -{ - char c; - const char *startp = p; - const char *user; - struct passwd *pw; - char *home; - int len; - - for (;;) { - c = *p; - switch(c) { - case CTLESC: /* This means CTL* are always considered quoted. */ - case CTLVAR: - case CTLBACKQ: - case CTLBACKQ | CTLQUOTE: - case CTLARI: - case CTLENDARI: - case CTLQUOTEMARK: - return (startp); - case ':': - if ((flag & EXP_VARTILDE) == 0) - break; - /* FALLTHROUGH */ - case '\0': - case '/': - case CTLENDVAR: - len = p - startp - 1; - STPUTBIN(startp + 1, len, expdest); - STACKSTRNUL(expdest); - user = expdest - len; - if (*user == '\0') { - home = lookupvar("HOME"); - } else { - pw = getpwnam(user); - home = pw != NULL ? pw->pw_dir : NULL; - } - STADJUST(-len, expdest); - if (home == NULL || *home == '\0') - return (startp); - strtodest(home, flag, VSNORMAL, 1, NULL); - return (p); - } - p++; - } -} - - -/* - * Expand arithmetic expression. - */ -static const char * -expari(const char *p, struct nodelist **restrict argbackq, int flag, - struct worddest *dst) -{ - char *q, *start; - arith_t result; - int begoff; - int quoted; - int adj; - - quoted = *p++ == '"'; - begoff = expdest - stackblock(); - p = argstr(p, argbackq, 0, NULL); - STPUTC('\0', expdest); - start = stackblock() + begoff; - - q = grabstackstr(expdest); - result = arith(start); - ungrabstackstr(q, expdest); - - start = stackblock() + begoff; - adj = start - expdest; - STADJUST(adj, expdest); - - CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); - fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); - adj = strlen(expdest); - STADJUST(adj, expdest); - /* - * If this is quoted, a '-' must not indicate a range in [...]. - * If this is not quoted, splitting may occur. - */ - if (quoted ? - result < 0 && begoff > 1 && flag & (EXP_GLOB | EXP_CASE) : - flag & EXP_SPLIT) - reprocess(expdest - adj - stackblock(), flag, VSNORMAL, quoted, - dst); - return p; -} - - -/* - * Perform command substitution. - */ -static void -expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) -{ - struct backcmd in; - int i; - char buf[128]; - char *p; - char *dest = expdest; - char lastc; - char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int quotes = flag & (EXP_GLOB | EXP_CASE); - size_t nnl; - const char *ifs; - int startloc; - - INTOFF; - p = grabstackstr(dest); - evalbackcmd(cmd, &in); - ungrabstackstr(p, dest); - - p = in.buf; - startloc = dest - stackblock(); - nnl = 0; - if (!quoted && flag & EXP_SPLIT) - ifs = ifsset() ? ifsval() : " \t\n"; - else - ifs = ""; - /* Remove trailing newlines */ - for (;;) { - if (--in.nleft < 0) { - if (in.fd < 0) - break; - while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR) - ; - TRACE(("expbackq: read returns %d\n", i)); - if (i <= 0) - break; - p = buf; - in.nleft = i - 1; - } - lastc = *p++; - if (lastc == '\0') - continue; - if (nnl > 0 && lastc != '\n') { - NEXTWORD('\n', flag, dest, dst); - nnl = 0; - } - if (strchr(ifs, lastc) != NULL) { - if (lastc == '\n') - nnl++; - else - NEXTWORD(lastc, flag, dest, dst); - } else { - CHECKSTRSPACE(2, dest); - if (quotes && syntax[(int)lastc] == CCTL) - USTPUTC(CTLESC, dest); - USTPUTC(lastc, dest); - } - } - while (dest > stackblock() + startloc && STTOPC(dest) == '\n') - STUNPUTC(dest); - - if (in.fd >= 0) - close(in.fd); - if (in.buf) - ckfree(in.buf); - if (in.jp) { - p = grabstackstr(dest); - exitstatus = waitforjob(in.jp, (int *)NULL); - ungrabstackstr(p, dest); - } - TRACE(("expbackq: done\n")); - expdest = dest; - INTON; -} - - - -static void -recordleft(const char *str, const char *loc, char *startp) -{ - int amount; - - amount = ((str - 1) - (loc - startp)) - expdest; - STADJUST(amount, expdest); - while (loc != str - 1) - *startp++ = *loc++; -} - -static const char * -subevalvar_trim(const char *p, struct nodelist **restrict argbackq, int strloc, - int subtype, int startloc) -{ - char *startp; - char *loc = NULL; - char *str; - int c = 0; - int amount; - - p = argstr(p, argbackq, EXP_CASE | EXP_TILDE, NULL); - STACKSTRNUL(expdest); - startp = stackblock() + startloc; - str = stackblock() + strloc; - - switch (subtype) { - case VSTRIMLEFT: - for (loc = startp; loc < str; loc++) { - c = *loc; - *loc = '\0'; - if (patmatch(str, startp)) { - *loc = c; - recordleft(str, loc, startp); - return p; - } - *loc = c; - } - break; - - case VSTRIMLEFTMAX: - for (loc = str - 1; loc >= startp;) { - c = *loc; - *loc = '\0'; - if (patmatch(str, startp)) { - *loc = c; - recordleft(str, loc, startp); - return p; - } - *loc = c; - loc--; - } - break; - - case VSTRIMRIGHT: - for (loc = str - 1; loc >= startp;) { - if (patmatch(str, loc)) { - amount = loc - expdest; - STADJUST(amount, expdest); - return p; - } - loc--; - } - break; - - case VSTRIMRIGHTMAX: - for (loc = startp; loc < str - 1; loc++) { - if (patmatch(str, loc)) { - amount = loc - expdest; - STADJUST(amount, expdest); - return p; - } - } - break; - - - default: - abort(); - } - amount = (expdest - stackblock() - strloc) + 1; - STADJUST(-amount, expdest); - return p; -} - - -static const char * -subevalvar_misc(const char *p, struct nodelist **restrict argbackq, - const char *var, int subtype, int startloc, int varflags) -{ - char *startp; - int amount; - - p = argstr(p, argbackq, EXP_TILDE, NULL); - STACKSTRNUL(expdest); - startp = stackblock() + startloc; - - switch (subtype) { - case VSASSIGN: - setvar(var, startp, 0); - amount = startp - expdest; - STADJUST(amount, expdest); - return p; - - case VSQUESTION: - if (*p != CTLENDVAR) { - outfmt(out2, "%s\n", startp); - error((char *)NULL); - } - error("%.*s: parameter %snot set", (int)(p - var - 1), - var, (varflags & VSNUL) ? "null or " : ""); - - default: - abort(); - } -} - - -/* - * Expand a variable, and return a pointer to the next character in the - * input string. - */ - -static const char * -evalvar(const char *p, struct nodelist **restrict argbackq, int flag, - struct worddest *dst) -{ - int subtype; - int varflags; - const char *var; - const char *val; - int patloc; - int c; - int set; - int special; - int startloc; - int varlen; - int varlenb; - char buf[21]; - - varflags = (unsigned char)*p++; - subtype = varflags & VSTYPE; - var = p; - special = 0; - if (! is_name(*p)) - special = 1; - p = strchr(p, '=') + 1; - if (varflags & VSLINENO) { - set = 1; - special = 1; - val = NULL; - } else if (special) { - set = varisset(var, varflags & VSNUL); - val = NULL; - } else { - val = bltinlookup(var, 1); - if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { - val = NULL; - set = 0; - } else - set = 1; - } - varlen = 0; - startloc = expdest - stackblock(); - if (!set && uflag && *var != '@' && *var != '*') { - switch (subtype) { - case VSNORMAL: - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - case VSLENGTH: - error("%.*s: parameter not set", (int)(p - var - 1), - var); - } - } - if (set && subtype != VSPLUS) { - /* insert the value of the variable */ - if (special) { - if (varflags & VSLINENO) { - if (p - var > (ptrdiff_t)sizeof(buf)) - abort(); - memcpy(buf, var, p - var - 1); - buf[p - var - 1] = '\0'; - strtodest(buf, flag, subtype, - varflags & VSQUOTE, dst); - } else - varvalue(var, varflags & VSQUOTE, subtype, flag, - dst); - if (subtype == VSLENGTH) { - varlenb = expdest - stackblock() - startloc; - varlen = varlenb; - if (localeisutf8) { - val = stackblock() + startloc; - for (;val != expdest; val++) - if ((*val & 0xC0) == 0x80) - varlen--; - } - STADJUST(-varlenb, expdest); - } - } else { - if (subtype == VSLENGTH) { - for (;*val; val++) - if (!localeisutf8 || - (*val & 0xC0) != 0x80) - varlen++; - } - else - strtodest(val, flag, subtype, - varflags & VSQUOTE, dst); - } - } - - if (subtype == VSPLUS) - set = ! set; - - switch (subtype) { - case VSLENGTH: - cvtnum(varlen, buf); - strtodest(buf, flag, VSNORMAL, varflags & VSQUOTE, dst); - break; - - case VSNORMAL: - return p; - - case VSPLUS: - case VSMINUS: - if (!set) { - return argstr(p, argbackq, - flag | (flag & EXP_SPLIT ? EXP_SPLIT_LIT : 0) | - (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst); - } - break; - - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - if (!set) - break; - /* - * Terminate the string and start recording the pattern - * right after it - */ - STPUTC('\0', expdest); - patloc = expdest - stackblock(); - p = subevalvar_trim(p, argbackq, patloc, subtype, startloc); - reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst); - if (flag & EXP_SPLIT && *var == '@' && varflags & VSQUOTE) - dst->state = WORD_QUOTEMARK; - return p; - - case VSASSIGN: - case VSQUESTION: - if (!set) { - p = subevalvar_misc(p, argbackq, var, subtype, - startloc, varflags); - /* assert(subtype == VSASSIGN); */ - val = lookupvar(var); - strtodest(val, flag, subtype, varflags & VSQUOTE, dst); - return p; - } - break; - - case VSERROR: - c = p - var - 1; - error("${%.*s%s}: Bad substitution", c, var, - (c > 0 && *p != CTLENDVAR) ? "..." : ""); - - default: - abort(); - } - - { /* skip to end of alternative */ - int nesting = 1; - for (;;) { - if ((c = *p++) == CTLESC) - p++; - else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) - *argbackq = (*argbackq)->next; - else if (c == CTLVAR) { - if ((*p++ & VSTYPE) != VSNORMAL) - nesting++; - } else if (c == CTLENDVAR) { - if (--nesting == 0) - break; - } - } - } - return p; -} - - - -/* - * Test whether a special or positional parameter is set. - */ - -static int -varisset(const char *name, int nulok) -{ - - if (*name == '!') - return backgndpidset(); - else if (*name == '@' || *name == '*') { - if (*shellparam.p == NULL) - return 0; - - if (nulok) { - char **av; - - for (av = shellparam.p; *av; av++) - if (**av != '\0') - return 1; - return 0; - } - } else if (is_digit(*name)) { - char *ap; - long num; - - errno = 0; - num = strtol(name, NULL, 10); - if (errno != 0 || num > shellparam.nparam) - return 0; - - if (num == 0) - ap = arg0; - else - ap = shellparam.p[num - 1]; - - if (nulok && (ap == NULL || *ap == '\0')) - return 0; - } - return 1; -} - -static void -strtodest(const char *p, int flag, int subtype, int quoted, - struct worddest *dst) -{ - if (subtype == VSLENGTH || subtype == VSTRIMLEFT || - subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT || - subtype == VSTRIMRIGHTMAX) - STPUTS(p, expdest); - else if (flag & EXP_SPLIT && !quoted && dst != NULL) - STPUTS_SPLIT(p, BASESYNTAX, flag, expdest, dst); - else if (flag & (EXP_GLOB | EXP_CASE)) - STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest); - else - STPUTS(p, expdest); -} - -static void -reprocess(int startloc, int flag, int subtype, int quoted, - struct worddest *dst) -{ - static char *buf = NULL; - static size_t buflen = 0; - char *startp; - size_t len, zpos, zlen; - - startp = stackblock() + startloc; - len = expdest - startp; - if (len >= SIZE_MAX / 2 || len > PTRDIFF_MAX) - abort(); - INTOFF; - if (len >= buflen) { - ckfree(buf); - buf = NULL; - } - if (buflen < 128) - buflen = 128; - while (len >= buflen) - buflen <<= 1; - if (buf == NULL) - buf = ckmalloc(buflen); - INTON; - memcpy(buf, startp, len); - buf[len] = '\0'; - STADJUST(-(ptrdiff_t)len, expdest); - for (zpos = 0;;) { - zlen = strlen(buf + zpos); - strtodest(buf + zpos, flag, subtype, quoted, dst); - zpos += zlen + 1; - if (zpos == len + 1) - break; - if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len))) - NEXTWORD('\0', flag, expdest, dst); - } -} - -/* - * Add the value of a special or positional parameter to the stack string. - */ - -static void -varvalue(const char *name, int quoted, int subtype, int flag, - struct worddest *dst) -{ - int num; - char *p; - int i; - int splitlater; - char sep[2]; - char **ap; - char buf[(NSHORTOPTS > 10 ? NSHORTOPTS : 10) + 1]; - - if (subtype == VSLENGTH) - flag &= ~EXP_FULL; - splitlater = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX || - subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX; - - switch (*name) { - case '$': - num = rootpid; - break; - case '?': - num = oexitstatus; - break; - case '#': - num = shellparam.nparam; - break; - case '!': - num = backgndpidval(); - break; - case '-': - p = buf; - for (i = 0 ; i < NSHORTOPTS ; i++) { - if (optval[i]) - *p++ = optletter[i]; - } - *p = '\0'; - strtodest(buf, flag, subtype, quoted, dst); - return; - case '@': - if (flag & EXP_SPLIT && quoted) { - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - strtodest(p, flag, subtype, quoted, dst); - if (*ap) { - if (splitlater) - STPUTC('\0', expdest); - else - NEXTWORD('\0', flag, expdest, - dst); - } - } - if (shellparam.nparam > 0) - dst->state = WORD_QUOTEMARK; - return; - } - /* FALLTHROUGH */ - case '*': - if (ifsset()) - sep[0] = ifsval()[0]; - else - sep[0] = ' '; - sep[1] = '\0'; - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - strtodest(p, flag, subtype, quoted, dst); - if (!*ap) - break; - if (sep[0]) - strtodest(sep, flag, subtype, quoted, dst); - else if (flag & EXP_SPLIT && !quoted && **ap != '\0') { - if (splitlater) - STPUTC('\0', expdest); - else - NEXTWORD('\0', flag, expdest, dst); - } - } - return; - default: - if (is_digit(*name)) { - num = atoi(name); - if (num == 0) - p = arg0; - else if (num > 0 && num <= shellparam.nparam) - p = shellparam.p[num - 1]; - else - return; - strtodest(p, flag, subtype, quoted, dst); - } - return; - } - cvtnum(num, buf); - strtodest(buf, flag, subtype, quoted, dst); -} - - - -static char expdir[PATH_MAX]; -#define expdir_end (expdir + sizeof(expdir)) - -/* - * Perform pathname generation and remove control characters. - * At this point, the only control characters should be CTLESC. - * The results are stored in the list dstlist. - */ -static void -expandmeta(char *pattern, struct arglist *dstlist) -{ - char *p; - int firstmatch; - char c; - - firstmatch = dstlist->count; - p = pattern; - for (; (c = *p) != '\0'; p++) { - /* fast check for meta chars */ - if (c == '*' || c == '?' || c == '[') { - INTOFF; - expmeta(expdir, pattern, dstlist); - INTON; - break; - } - } - if (dstlist->count == firstmatch) { - /* - * no matches - */ - rmescapes(pattern); - appendarglist(dstlist, pattern); - } else { - qsort(&dstlist->args[firstmatch], - dstlist->count - firstmatch, - sizeof(dstlist->args[0]), expsortcmp); - } -} - - -/* - * Do metacharacter (i.e. *, ?, [...]) expansion. - */ - -static void -expmeta(char *enddir, char *name, struct arglist *arglist) -{ - const char *p; - const char *q; - const char *start; - char *endname; - int metaflag; - struct stat statb; - DIR *dirp; - struct dirent *dp; - int atend; - int matchdot; - int esc; - int namlen; - - metaflag = 0; - start = name; - for (p = name; esc = 0, *p; p += esc + 1) { - if (*p == '*' || *p == '?') - metaflag = 1; - else if (*p == '[') { - q = p + 1; - if (*q == '!' || *q == '^') - q++; - for (;;) { - if (*q == CTLESC) - q++; - if (*q == '/' || *q == '\0') - break; - if (*++q == ']') { - metaflag = 1; - break; - } - } - } else if (*p == '\0') - break; - else { - if (*p == CTLESC) - esc++; - if (p[esc] == '/') { - if (metaflag) - break; - start = p + esc + 1; - } - } - } - if (metaflag == 0) { /* we've reached the end of the file name */ - if (enddir != expdir) - metaflag++; - for (p = name ; ; p++) { - if (*p == CTLESC) - p++; - *enddir++ = *p; - if (*p == '\0') - break; - if (enddir == expdir_end) - return; - } - if (metaflag == 0 || lstat(expdir, &statb) >= 0) - appendarglist(arglist, stsavestr(expdir)); - return; - } - endname = name + (p - name); - if (start != name) { - p = name; - while (p < start) { - if (*p == CTLESC) - p++; - *enddir++ = *p++; - if (enddir == expdir_end) - return; - } - } - if (enddir == expdir) { - p = "."; - } else if (enddir == expdir + 1 && *expdir == '/') { - p = "/"; - } else { - p = expdir; - enddir[-1] = '\0'; - } - if ((dirp = opendir(p)) == NULL) - return; - if (enddir != expdir) - enddir[-1] = '/'; - if (*endname == 0) { - atend = 1; - } else { - atend = 0; - *endname = '\0'; - endname += esc + 1; - } - matchdot = 0; - p = start; - if (*p == CTLESC) - p++; - if (*p == '.') - matchdot++; - while (! int_pending() && (dp = readdir(dirp)) != NULL) { - if (dp->d_name[0] == '.' && ! matchdot) - continue; - if (patmatch(start, dp->d_name)) { - namlen = dp->d_namlen; - if (enddir + namlen + 1 > expdir_end) - continue; - memcpy(enddir, dp->d_name, namlen + 1); - if (atend) - appendarglist(arglist, stsavestr(expdir)); - else { - if (dp->d_type != DT_UNKNOWN && - dp->d_type != DT_DIR && - dp->d_type != DT_LNK) - continue; - if (enddir + namlen + 2 > expdir_end) - continue; - enddir[namlen] = '/'; - enddir[namlen + 1] = '\0'; - expmeta(enddir + namlen + 1, endname, arglist); - } - } - } - closedir(dirp); - if (! atend) - endname[-esc - 1] = esc ? CTLESC : '/'; -} - - -static int -expsortcmp(const void *p1, const void *p2) -{ - const char *s1 = *(const char * const *)p1; - const char *s2 = *(const char * const *)p2; - - return (strcoll(s1, s2)); -} - - - -static wchar_t -get_wc(const char **p) -{ - wchar_t c; - int chrlen; - - chrlen = mbtowc(&c, *p, 4); - if (chrlen == 0) - return 0; - else if (chrlen == -1) - c = 0; - else - *p += chrlen; - return c; -} - - -/* - * See if a character matches a character class, starting at the first colon - * of "[:class:]". - * If a valid character class is recognized, a pointer to the next character - * after the final closing bracket is stored into *end, otherwise a null - * pointer is stored into *end. - */ -static int -match_charclass(const char *p, wchar_t chr, const char **end) -{ - char name[20]; - const char *nameend; - wctype_t cclass; - - *end = NULL; - p++; - nameend = strstr(p, ":]"); - if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) || - nameend == p) - return 0; - memcpy(name, p, nameend - p); - name[nameend - p] = '\0'; - *end = nameend + 2; - cclass = wctype(name); - /* An unknown class matches nothing but is valid nevertheless. */ - if (cclass == 0) - return 0; - return iswctype(chr, cclass); -} - - -/* - * Returns true if the pattern matches the string. - */ - -static int -patmatch(const char *pattern, const char *string) -{ - const char *p, *q, *end; - const char *bt_p, *bt_q; - char c; - wchar_t wc, wc2; - - p = pattern; - q = string; - bt_p = NULL; - bt_q = NULL; - for (;;) { - switch (c = *p++) { - case '\0': - if (*q != '\0') - goto backtrack; - return 1; - case CTLESC: - if (*q++ != *p++) - goto backtrack; - break; - case '?': - if (*q == '\0') - return 0; - if (localeisutf8) { - wc = get_wc(&q); - /* - * A '?' does not match invalid UTF-8 but a - * '*' does, so backtrack. - */ - if (wc == 0) - goto backtrack; - } else - q++; - break; - case '*': - c = *p; - while (c == '*') - c = *++p; - /* - * If the pattern ends here, we know the string - * matches without needing to look at the rest of it. - */ - if (c == '\0') - return 1; - /* - * First try the shortest match for the '*' that - * could work. We can forget any earlier '*' since - * there is no way having it match more characters - * can help us, given that we are already here. - */ - bt_p = p; - bt_q = q; - break; - case '[': { - const char *savep, *saveq; - int invert, found; - wchar_t chr; - - savep = p, saveq = q; - invert = 0; - if (*p == '!' || *p == '^') { - invert++; - p++; - } - found = 0; - if (*q == '\0') - return 0; - if (localeisutf8) { - chr = get_wc(&q); - if (chr == 0) - goto backtrack; - } else - chr = (unsigned char)*q++; - c = *p++; - do { - if (c == '\0') { - p = savep, q = saveq; - c = '['; - goto dft; - } - if (c == '[' && *p == ':') { - found |= match_charclass(p, chr, &end); - if (end != NULL) { - p = end; - continue; - } - } - if (c == CTLESC) - c = *p++; - if (localeisutf8 && c & 0x80) { - p--; - wc = get_wc(&p); - if (wc == 0) /* bad utf-8 */ - return 0; - } else - wc = (unsigned char)c; - if (*p == '-' && p[1] != ']') { - p++; - if (*p == CTLESC) - p++; - if (localeisutf8) { - wc2 = get_wc(&p); - if (wc2 == 0) /* bad utf-8 */ - return 0; - } else - wc2 = (unsigned char)*p++; - if ( collate_range_cmp(chr, wc) >= 0 - && collate_range_cmp(chr, wc2) <= 0 - ) - found = 1; - } else { - if (chr == wc) - found = 1; - } - } while ((c = *p++) != ']'); - if (found == invert) - goto backtrack; - break; - } -dft: default: - if (*q == '\0') - return 0; - if (*q++ == c) - break; -backtrack: - /* - * If we have a mismatch (other than hitting the end - * of the string), go back to the last '*' seen and - * have it match one additional character. - */ - if (bt_p == NULL) - return 0; - if (*bt_q == '\0') - return 0; - bt_q++; - p = bt_p; - q = bt_q; - break; - } - } -} - - - -/* - * Remove any CTLESC and CTLQUOTEMARK characters from a string. - */ - -void -rmescapes(char *str) -{ - char *p, *q; - - p = str; - while (*p != CTLESC && *p != CTLQUOTEMARK && *p != CTLQUOTEEND) { - if (*p++ == '\0') - return; - } - q = p; - while (*p) { - if (*p == CTLQUOTEMARK || *p == CTLQUOTEEND) { - p++; - continue; - } - if (*p == CTLESC) - p++; - *q++ = *p++; - } - *q = '\0'; -} - - - -/* - * See if a pattern matches in a case statement. - */ - -int -casematch(union node *pattern, const char *val) -{ - struct stackmark smark; - struct nodelist *argbackq; - int result; - char *p; - - setstackmark(&smark); - argbackq = pattern->narg.backquote; - STARTSTACKSTR(expdest); - argstr(pattern->narg.text, &argbackq, EXP_TILDE | EXP_CASE, NULL); - STPUTC('\0', expdest); - p = grabstackstr(expdest); - result = patmatch(p, val); - popstackmark(&smark); - return result; -} - -/* - * Our own itoa(). - */ - -static void -cvtnum(int num, char *buf) -{ - char temp[32]; - int neg = num < 0; - char *p = temp + 31; - - temp[31] = '\0'; - - do { - *--p = num % 10 + '0'; - } while ((num /= 10) != 0); - - if (neg) - *--p = '-'; - - memcpy(buf, p, temp + 32 - p); -} - -/* - * Do most of the work for wordexp(3). - */ - -int -wordexpcmd(int argc, char **argv) -{ - size_t len; - int i; - - out1fmt("%08x", argc - 1); - for (i = 1, len = 0; i < argc; i++) - len += strlen(argv[i]); - out1fmt("%08x", (int)len); - for (i = 1; i < argc; i++) - outbin(argv[i], strlen(argv[i]) + 1, out1); - return (0); -} - -/* - * Do most of the work for wordexp(3), new version. - */ - -int -freebsd_wordexpcmd(int argc __unused, char **argv __unused) -{ - struct arglist arglist; - union node *args, *n; - size_t len; - int ch; - int protected = 0; - int fd = -1; - int i; - - while ((ch = nextopt("f:p")) != '\0') { - switch (ch) { - case 'f': - fd = number(shoptarg); - break; - case 'p': - protected = 1; - break; - } - } - if (*argptr != NULL) - error("wrong number of arguments"); - if (fd < 0) - error("missing fd"); - INTOFF; - setinputfd(fd, 1); - INTON; - args = parsewordexp(); - popfile(); /* will also close fd */ - if (protected) - for (n = args; n != NULL; n = n->narg.next) { - if (n->narg.backquote != NULL) { - outcslow('C', out1); - error("command substitution disabled"); - } - } - outcslow(' ', out1); - emptyarglist(&arglist); - for (n = args; n != NULL; n = n->narg.next) - expandarg(n, &arglist, EXP_FULL | EXP_TILDE); - for (i = 0, len = 0; i < arglist.count; i++) - len += strlen(arglist.args[i]); - out1fmt("%016x %016zx", arglist.count, len); - for (i = 0; i < arglist.count; i++) - outbin(arglist.args[i], strlen(arglist.args[i]) + 1, out1); - return (0); -} diff --git a/bin/catsh/expand.h b/bin/catsh/expand.h deleted file mode 100644 index 92e344d9..00000000 --- a/bin/catsh/expand.h +++ /dev/null @@ -1,62 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)expand.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/expand.h 314436 2017-02-28 23:42:47Z imp $ - */ - -struct arglist { - char **args; - int count; - int capacity; - char *smallarg[1]; -}; - -/* - * expandarg() flags - */ -#define EXP_SPLIT 0x1 /* perform word splitting */ -#define EXP_TILDE 0x2 /* do normal tilde expansion */ -#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ -#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ -#define EXP_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */ -#define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */ -#define EXP_GLOB 0x80 /* perform file globbing */ - -#define EXP_FULL (EXP_SPLIT | EXP_GLOB) - - -void emptyarglist(struct arglist *); -void appendarglist(struct arglist *, char *); -union node; -void expandarg(union node *, struct arglist *, int); -void rmescapes(char *); -int casematch(union node *, const char *); diff --git a/bin/catsh/histedit.c b/bin/catsh/histedit.c deleted file mode 100644 index 08339a00..00000000 --- a/bin/catsh/histedit.c +++ /dev/null @@ -1,575 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/histedit.c 319635 2017-06-06 21:08:05Z jilles $"); - -#include <sys/param.h> -#include <limits.h> -#include <paths.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -/* - * Editline and history functions (and glue). - */ -#include "shell.h" -#include "parser.h" -#include "var.h" -#include "options.h" -#include "main.h" -#include "output.h" -#include "mystring.h" -#ifndef NO_HISTORY -#include "myhistedit.h" -#include "error.h" -#include "eval.h" -#include "memalloc.h" -#include "builtins.h" - -#define MAXHISTLOOPS 4 /* max recursions through fc */ -#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ - -History *hist; /* history cookie */ -EditLine *el; /* editline cookie */ -int displayhist; -static FILE *el_in, *el_out, *el_err; -static HistEvent he_saved; - -static void history_load(const char *hf); -static void history_save(const char *hf); - -static char *fc_replace(const char *, char *, char *); -static int not_fcnumber(const char *); -static int str_to_event(const char *, int); - -/* - * Set history and editing status. Called whenever the status may - * have changed (figures out what to do). - */ -void -histedit(void) -{ - -#define editing (Eflag || Vflag) - - if (iflag) { - if (!hist) { - /* - * turn history on - */ - INTOFF; - hist = history_init(); - INTON; - - if (hist != NULL) { - sethistsize(histsizeval()); - sethistfile(histfileval()); - } else - out2fmt_flush("sh: can't initialize history\n"); - } - if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ - /* - * turn editing on - */ - char *term; - - INTOFF; - if (el_in == NULL) - el_in = fdopen(0, "r"); - if (el_err == NULL) - el_err = fdopen(1, "w"); - if (el_out == NULL) - el_out = fdopen(2, "w"); - if (el_in == NULL || el_err == NULL || el_out == NULL) - goto bad; - term = lookupvar("TERM"); - if (term) - setenv("TERM", term, 1); - else - unsetenv("TERM"); - el = el_init(arg0, el_in, el_out, el_err); - if (el != NULL) { - if (hist) - el_set(el, EL_HIST, history, hist); - el_set(el, EL_PROMPT, getprompt); - el_set(el, EL_RPROMPT, getrprompt); - el_set(el, EL_ADDFN, "sh-complete", - "Filename completion", - _el_fn_complete); - } else { -bad: - out2fmt_flush("sh: can't initialize editing\n"); - } - INTON; - } else if (!editing && el) { - INTOFF; - el_end(el); - el = NULL; - INTON; - } - if (el) { - if (Vflag) - el_set(el, EL_EDITOR, "vi"); - else if (Eflag) - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_BIND, "^I", "sh-complete", NULL); - el_source(el, NULL); - } - } else { - INTOFF; - if (el) { /* no editing if not interactive */ - el_end(el); - el = NULL; - } - if (hist) { - if (*histfileval() != '\0') - history_save(histfileval()); - history_end(hist); - hist = NULL; - } - INTON; - } -} - - -void -sethistfile(const char *hf) -{ - if (hist != NULL && hf != NULL && *hf != '\0') - history_load(hf); -} - - -static void -history_load(const char *hf) { - HistEvent he; - const char *ehf; - - ehf = expandstr(hf); - if (ehf == NULL) - return; - if (history(hist, &he, H_LOAD, ehf) == -1) - warning("%s: %s", he.str, ehf); - else - history(hist, &he_saved, H_FIRST); -} - - -static void -history_save(const char *hf) { - HistEvent he; - const char *ehf; - - ehf = expandstr(hf); - if (ehf == NULL) - return; - if (he_saved.num == 0) - history(hist, &he_saved, H_LAST); - else - history(hist, &he_saved, H_NEXT_EVENT, he_saved.num + 1); - if (history(hist, &he, H_SAVE_INCR, ehf, he_saved.num) == -1) - warning("%s: %s", he.str, ehf); -} - - -void -sethistsize(const char *hs) -{ - int histsize; - HistEvent he; - - if (hist != NULL) { - if (hs == NULL || !is_number(hs)) - histsize = 100; - else - histsize = atoi(hs); - history(hist, &he, H_SETSIZE, histsize); - history(hist, &he, H_SETUNIQUE, 1); - } -} - -void -setpslit(const char *lit_ch) { - wchar_t wc; - - if (!(iflag && editing && el)) - return; - - if (lit_ch == NULL) { - el_set(el, EL_PROMPT, getprompt); - el_set(el, EL_RPROMPT, getrprompt); - return; - } - - mbtowc(&wc, NULL, 1); /* state init */ - - if (mbtowc(&wc, lit_ch, strlen(lit_ch)) <= 0) { - el_set(el, EL_PROMPT, getprompt); - el_set(el, EL_RPROMPT, getrprompt); - } else { - el_set(el, EL_PROMPT_ESC, getprompt, (int)wc); - el_set(el, EL_RPROMPT_ESC, getrprompt, (int)wc); - } -} - -void -setterm(const char *term) -{ - if (rootshell && el != NULL && term != NULL) - el_set(el, EL_TERMINAL, term); -} - -int -histcmd(int argc, char **argv __unused) -{ - int ch; - const char *editor = NULL; - HistEvent he; - int lflg = 0, nflg = 0, rflg = 0, sflg = 0; - int i, retval; - const char *firststr, *laststr; - int first, last, direction; - char *pat = NULL, *repl = NULL; - static int active = 0; - struct jmploc jmploc; - struct jmploc *savehandler; - char editfilestr[PATH_MAX]; - char *volatile editfile; - FILE *efp = NULL; - int oldhistnum; - - if (hist == NULL) - error("history not active"); - - if (argc == 1) - error("missing history argument"); - - while (not_fcnumber(*argptr) && (ch = nextopt("e:lnrs")) != '\0') - switch ((char)ch) { - case 'e': - editor = shoptarg; - break; - case 'l': - lflg = 1; - break; - case 'n': - nflg = 1; - break; - case 'r': - rflg = 1; - break; - case 's': - sflg = 1; - break; - } - - savehandler = handler; - /* - * If executing... - */ - if (lflg == 0 || editor || sflg) { - lflg = 0; /* ignore */ - editfile = NULL; - /* - * Catch interrupts to reset active counter and - * cleanup temp files. - */ - if (setjmp(jmploc.loc)) { - active = 0; - if (editfile) - unlink(editfile); - handler = savehandler; - longjmp(handler->loc, 1); - } - handler = &jmploc; - if (++active > MAXHISTLOOPS) { - active = 0; - displayhist = 0; - error("called recursively too many times"); - } - /* - * Set editor. - */ - if (sflg == 0) { - if (editor == NULL && - (editor = bltinlookup("FCEDIT", 1)) == NULL && - (editor = bltinlookup("EDITOR", 1)) == NULL) - editor = DEFEDITOR; - if (editor[0] == '-' && editor[1] == '\0') { - sflg = 1; /* no edit */ - editor = NULL; - } - } - } - - /* - * If executing, parse [old=new] now - */ - if (lflg == 0 && *argptr != NULL && - ((repl = strchr(*argptr, '=')) != NULL)) { - pat = *argptr; - *repl++ = '\0'; - argptr++; - } - /* - * determine [first] and [last] - */ - if (*argptr == NULL) { - firststr = lflg ? "-16" : "-1"; - laststr = "-1"; - } else if (argptr[1] == NULL) { - firststr = argptr[0]; - laststr = lflg ? "-1" : argptr[0]; - } else if (argptr[2] == NULL) { - firststr = argptr[0]; - laststr = argptr[1]; - } else - error("too many arguments"); - /* - * Turn into event numbers. - */ - first = str_to_event(firststr, 0); - last = str_to_event(laststr, 1); - - if (rflg) { - i = last; - last = first; - first = i; - } - /* - * XXX - this should not depend on the event numbers - * always increasing. Add sequence numbers or offset - * to the history element in next (diskbased) release. - */ - direction = first < last ? H_PREV : H_NEXT; - - /* - * If editing, grab a temp file. - */ - if (editor) { - int fd; - INTOFF; /* easier */ - sprintf(editfilestr, "%s/_shXXXXXX", _PATH_TMP); - if ((fd = mkstemp(editfilestr)) < 0) - error("can't create temporary file %s", editfile); - editfile = editfilestr; - if ((efp = fdopen(fd, "w")) == NULL) { - close(fd); - error("Out of space"); - } - } - - /* - * Loop through selected history events. If listing or executing, - * do it now. Otherwise, put into temp file and call the editor - * after. - * - * The history interface needs rethinking, as the following - * convolutions will demonstrate. - */ - history(hist, &he, H_FIRST); - retval = history(hist, &he, H_NEXT_EVENT, first); - for (;retval != -1; retval = history(hist, &he, direction)) { - if (lflg) { - if (!nflg) - out1fmt("%5d ", he.num); - out1str(he.str); - } else { - const char *s = pat ? - fc_replace(he.str, pat, repl) : he.str; - - if (sflg) { - if (displayhist) { - out2str(s); - flushout(out2); - } - evalstring(s, 0); - if (displayhist && hist) { - /* - * XXX what about recursive and - * relative histnums. - */ - oldhistnum = he.num; - history(hist, &he, H_ENTER, s); - /* - * XXX H_ENTER moves the internal - * cursor, set it back to the current - * entry. - */ - history(hist, &he, - H_NEXT_EVENT, oldhistnum); - } - } else - fputs(s, efp); - } - /* - * At end? (if we were to lose last, we'd sure be - * messed up). - */ - if (he.num == last) - break; - } - if (editor) { - char *editcmd; - - fclose(efp); - INTON; - editcmd = stalloc(strlen(editor) + strlen(editfile) + 2); - sprintf(editcmd, "%s %s", editor, editfile); - evalstring(editcmd, 0); /* XXX - should use no JC command */ - readcmdfile(editfile); /* XXX - should read back - quick tst */ - unlink(editfile); - } - - if (lflg == 0 && active > 0) - --active; - if (displayhist) - displayhist = 0; - handler = savehandler; - return 0; -} - -static char * -fc_replace(const char *s, char *p, char *r) -{ - char *dest; - int plen = strlen(p); - - STARTSTACKSTR(dest); - while (*s) { - if (strncmp(s, p, plen) == 0) { - STPUTS(r, dest); - s += plen; - break; - } - STPUTC(*s++, dest); - } - STPUTS(s, dest); - STPUTC('\0', dest); - dest = grabstackstr(dest); - - return (dest); -} - -static int -not_fcnumber(const char *s) -{ - if (s == NULL) - return (0); - if (*s == '-') - s++; - return (!is_number(s)); -} - -static int -str_to_event(const char *str, int last) -{ - HistEvent he; - const char *s = str; - int relative = 0; - int i, retval; - - retval = history(hist, &he, H_FIRST); - switch (*s) { - case '-': - relative = 1; - /*FALLTHROUGH*/ - case '+': - s++; - } - if (is_number(s)) { - i = atoi(s); - if (relative) { - while (retval != -1 && i--) { - retval = history(hist, &he, H_NEXT); - } - if (retval == -1) - retval = history(hist, &he, H_LAST); - } else { - retval = history(hist, &he, H_NEXT_EVENT, i); - if (retval == -1) { - /* - * the notion of first and last is - * backwards to that of the history package - */ - retval = history(hist, &he, last ? H_FIRST : H_LAST); - } - } - if (retval == -1) - error("history number %s not found (internal error)", - str); - } else { - /* - * pattern - */ - retval = history(hist, &he, H_PREV_STR, str); - if (retval == -1) - error("history pattern not found: %s", str); - } - return (he.num); -} - -int -bindcmd(int argc, char **argv) -{ - - if (el == NULL) - error("line editing is disabled"); - return (el_parse(el, argc, __DECONST(const char **, argv))); -} - -#else -#include "error.h" - -int -histcmd(int argc, char **argv) -{ - - error("not compiled with history support"); - /*NOTREACHED*/ - return (0); -} - -int -bindcmd(int argc, char **argv) -{ - - error("not compiled with line editing support"); - return (0); -} -#endif diff --git a/bin/catsh/input.c b/bin/catsh/input.c deleted file mode 100644 index 24ba73b5..00000000 --- a/bin/catsh/input.c +++ /dev/null @@ -1,520 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/input.c 314436 2017-02-28 23:42:47Z imp $"); - -#include <stdio.h> /* defines BUFSIZ */ -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -/* - * This file implements the input routines used by the parser. - */ - -#include "shell.h" -#include "redir.h" -#include "syntax.h" -#include "input.h" -#include "output.h" -#include "options.h" -#include "memalloc.h" -#include "error.h" -#include "alias.h" -#include "parser.h" -#include "myhistedit.h" -#include "trap.h" - -#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ - -struct strpush { - struct strpush *prev; /* preceding string on stack */ - const char *prevstring; - int prevnleft; - int prevlleft; - struct alias *ap; /* if push was associated with an alias */ -}; - -/* - * The parsefile structure pointed to by the global variable parsefile - * contains information about the current file being read. - */ - -struct parsefile { - struct parsefile *prev; /* preceding file on stack */ - int linno; /* current line */ - int fd; /* file descriptor (or -1 if string) */ - int nleft; /* number of chars left in this line */ - int lleft; /* number of lines left in this buffer */ - const char *nextc; /* next char in buffer */ - char *buf; /* input buffer */ - struct strpush *strpush; /* for pushing strings at this level */ - struct strpush basestrpush; /* so pushing one is fast */ -}; - - -int plinno = 1; /* input line number */ -int parsenleft; /* copy of parsefile->nleft */ -static int parselleft; /* copy of parsefile->lleft */ -const char *parsenextc; /* copy of parsefile->nextc */ -static char basebuf[BUFSIZ + 1];/* buffer for top level input file */ -static struct parsefile basepf = { /* top level input file */ - .nextc = basebuf, - .buf = basebuf -}; -static struct parsefile *parsefile = &basepf; /* current input file */ -int whichprompt; /* 1 == PS1, 2 == PS2 */ - -EditLine *el; /* cookie for editline package */ - -static void pushfile(void); -static int preadfd(void); -static void popstring(void); - -void -resetinput(void) -{ - popallfiles(); - parselleft = parsenleft = 0; /* clear input buffer */ -} - - - -/* - * Read a character from the script, returning PEOF on end of file. - * Nul characters in the input are silently discarded. - */ - -int -pgetc(void) -{ - return pgetc_macro(); -} - - -static int -preadfd(void) -{ - int nr; - parsenextc = parsefile->buf; - -retry: -#ifndef NO_HISTORY - if (parsefile->fd == 0 && el) { - static const char *rl_cp; - static int el_len; - - if (rl_cp == NULL) { - el_resize(el); - rl_cp = el_gets(el, &el_len); - } - if (rl_cp == NULL) - nr = el_len == 0 ? 0 : -1; - else { - nr = el_len; - if (nr > BUFSIZ) - nr = BUFSIZ; - memcpy(parsefile->buf, rl_cp, nr); - if (nr != el_len) { - el_len -= nr; - rl_cp += nr; - } else - rl_cp = NULL; - } - } else -#endif - nr = read(parsefile->fd, parsefile->buf, BUFSIZ); - - if (nr <= 0) { - if (nr < 0) { - if (errno == EINTR) - goto retry; - if (parsefile->fd == 0 && errno == EWOULDBLOCK) { - int flags = fcntl(0, F_GETFL, 0); - if (flags >= 0 && flags & O_NONBLOCK) { - flags &=~ O_NONBLOCK; - if (fcntl(0, F_SETFL, flags) >= 0) { - out2fmt_flush("sh: turning off NDELAY mode\n"); - goto retry; - } - } - } - } - nr = -1; - } - return nr; -} - -/* - * Refill the input buffer and return the next input character: - * - * 1) If a string was pushed back on the input, pop it; - * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading - * from a string so we can't refill the buffer, return EOF. - * 3) If there is more in this buffer, use it else call read to fill it. - * 4) Process input up to the next newline, deleting nul characters. - */ - -int -preadbuffer(void) -{ - char *p, *q, *r, *end; - char savec; - - while (parsefile->strpush) { - /* - * Add a space to the end of an alias to ensure that the - * alias remains in use while parsing its last word. - * This avoids alias recursions. - */ - if (parsenleft == -1 && parsefile->strpush->ap != NULL) - return ' '; - popstring(); - if (--parsenleft >= 0) - return (*parsenextc++); - } - if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) - return PEOF; - -again: - if (parselleft <= 0) { - if ((parselleft = preadfd()) == -1) { - parselleft = parsenleft = EOF_NLEFT; - return PEOF; - } - } - - p = parsefile->buf + (parsenextc - parsefile->buf); - end = p + parselleft; - *end = '\0'; - q = strchr(p, '\n'); - if (!q) q = strchr(p, '\0'); - if (q != end && *q == '\0') { - /* delete nul characters */ - for (r = q; q != end; q++) { - if (*q != '\0') - *r++ = *q; - } - parselleft -= end - r; - if (parselleft == 0) - goto again; - end = p + parselleft; - *end = '\0'; - q = strchr(p, '\n'); - if (!q) q = strchr(p, '\0'); - } - if (q == end) { - parsenleft = parselleft; - parselleft = 0; - } else /* *q == '\n' */ { - q++; - parsenleft = q - parsenextc; - parselleft -= parsenleft; - } - parsenleft--; - - savec = *q; - *q = '\0'; - -#ifndef NO_HISTORY - if (parsefile->fd == 0 && hist && - parsenextc[strspn(parsenextc, " \t\n")] != '\0') { - HistEvent he; - INTOFF; - history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD, - parsenextc); - INTON; - } -#endif - - if (vflag) { - out2str(parsenextc); - flushout(out2); - } - - *q = savec; - - return *parsenextc++; -} - -/* - * Returns if we are certain we are at EOF. Does not cause any more input - * to be read from the outside world. - */ - -int -preadateof(void) -{ - if (parsenleft > 0) - return 0; - if (parsefile->strpush) - return 0; - if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) - return 1; - return 0; -} - -/* - * Undo the last call to pgetc. Only one character may be pushed back. - * PEOF may be pushed back. - */ - -void -pungetc(void) -{ - parsenleft++; - parsenextc--; -} - -/* - * Push a string back onto the input at this current parsefile level. - * We handle aliases this way. - */ -void -pushstring(const char *s, int len, struct alias *ap) -{ - struct strpush *sp; - - INTOFF; -/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ - if (parsefile->strpush) { - sp = ckmalloc(sizeof (struct strpush)); - sp->prev = parsefile->strpush; - parsefile->strpush = sp; - } else - sp = parsefile->strpush = &(parsefile->basestrpush); - sp->prevstring = parsenextc; - sp->prevnleft = parsenleft; - sp->prevlleft = parselleft; - sp->ap = ap; - if (ap) - ap->flag |= ALIASINUSE; - parsenextc = s; - parsenleft = len; - INTON; -} - -static void -popstring(void) -{ - struct strpush *sp = parsefile->strpush; - - INTOFF; - if (sp->ap) { - if (parsenextc != sp->ap->val && - (parsenextc[-1] == ' ' || parsenextc[-1] == '\t')) - forcealias(); - sp->ap->flag &= ~ALIASINUSE; - } - parsenextc = sp->prevstring; - parsenleft = sp->prevnleft; - parselleft = sp->prevlleft; -/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/ - parsefile->strpush = sp->prev; - if (sp != &(parsefile->basestrpush)) - ckfree(sp); - INTON; -} - -/* - * Set the input to take input from a file. If push is set, push the - * old input onto the stack first. - */ - -void -setinputfile(const char *fname, int push) -{ - int fd; - int fd2; - - INTOFF; - if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0) - error("cannot open %s: %s", fname, strerror(errno)); - if (fd < 10) { - fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10); - close(fd); - if (fd2 < 0) - error("Out of file descriptors"); - fd = fd2; - } - setinputfd(fd, push); - INTON; -} - - -/* - * Like setinputfile, but takes an open file descriptor (which should have - * its FD_CLOEXEC flag already set). Call this with interrupts off. - */ - -void -setinputfd(int fd, int push) -{ - if (push) { - pushfile(); - parsefile->buf = ckmalloc(BUFSIZ + 1); - } - if (parsefile->fd > 0) - close(parsefile->fd); - parsefile->fd = fd; - if (parsefile->buf == NULL) - parsefile->buf = ckmalloc(BUFSIZ + 1); - parselleft = parsenleft = 0; - plinno = 1; -} - - -/* - * Like setinputfile, but takes input from a string. - */ - -void -setinputstring(const char *string, int push) -{ - INTOFF; - if (push) - pushfile(); - parsenextc = string; - parselleft = parsenleft = strlen(string); - parsefile->buf = NULL; - plinno = 1; - INTON; -} - - - -/* - * To handle the "." command, a stack of input files is used. Pushfile - * adds a new entry to the stack and popfile restores the previous level. - */ - -static void -pushfile(void) -{ - struct parsefile *pf; - - parsefile->nleft = parsenleft; - parsefile->lleft = parselleft; - parsefile->nextc = parsenextc; - parsefile->linno = plinno; - pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); - pf->prev = parsefile; - pf->fd = -1; - pf->strpush = NULL; - pf->basestrpush.prev = NULL; - parsefile = pf; -} - - -void -popfile(void) -{ - struct parsefile *pf = parsefile; - - INTOFF; - if (pf->fd >= 0) - close(pf->fd); - if (pf->buf) - ckfree(pf->buf); - while (pf->strpush) - popstring(); - parsefile = pf->prev; - ckfree(pf); - parsenleft = parsefile->nleft; - parselleft = parsefile->lleft; - parsenextc = parsefile->nextc; - plinno = parsefile->linno; - INTON; -} - - -/* - * Return current file (to go back to it later using popfilesupto()). - */ - -struct parsefile * -getcurrentfile(void) -{ - return parsefile; -} - - -/* - * Pop files until the given file is on top again. Useful for regular - * builtins that read shell commands from files or strings. - * If the given file is not an active file, an error is raised. - */ - -void -popfilesupto(struct parsefile *file) -{ - while (parsefile != file && parsefile != &basepf) - popfile(); - if (parsefile != file) - error("popfilesupto() misused"); -} - -/* - * Return to top level. - */ - -void -popallfiles(void) -{ - while (parsefile != &basepf) - popfile(); -} - - - -/* - * Close the file(s) that the shell is reading commands from. Called - * after a fork is done. - */ - -void -closescript(void) -{ - popallfiles(); - if (parsefile->fd > 0) { - close(parsefile->fd); - parsefile->fd = 0; - } -} diff --git a/bin/catsh/input.h b/bin/catsh/input.h deleted file mode 100644 index 2a04921d..00000000 --- a/bin/catsh/input.h +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)input.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/input.h 314436 2017-02-28 23:42:47Z imp $ - */ - -/* PEOF (the end of file marker) is defined in syntax.h */ - -/* - * The input line number. Input.c just defines this variable, and saves - * and restores it when files are pushed and popped. The user of this - * package must set its value. - */ -extern int plinno; -extern int parsenleft; /* number of characters left in input buffer */ -extern const char *parsenextc; /* next character in input buffer */ - -struct alias; -struct parsefile; - -void resetinput(void); -int pgetc(void); -int preadbuffer(void); -int preadateof(void); -void pungetc(void); -void pushstring(const char *, int, struct alias *); -void setinputfile(const char *, int); -void setinputfd(int, int); -void setinputstring(const char *, int); -void popfile(void); -struct parsefile *getcurrentfile(void); -void popfilesupto(struct parsefile *); -void popallfiles(void); -void closescript(void); - -#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer()) diff --git a/bin/catsh/jobs.c b/bin/catsh/jobs.c deleted file mode 100644 index 88703edd..00000000 --- a/bin/catsh/jobs.c +++ /dev/null @@ -1,1552 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/jobs.c 328818 2018-02-02 22:53:58Z jilles $"); - -#include <sys/ioctl.h> -#include <sys/param.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <paths.h> -#include <signal.h> -#include <stddef.h> -#include <stdlib.h> -#include <unistd.h> - -#include "shell.h" -#if JOBS -#include <termios.h> -#undef CEOF /* syntax.h redefines this */ -#endif -#include "redir.h" -#include "exec.h" -#include "show.h" -#include "main.h" -#include "parser.h" -#include "nodes.h" -#include "jobs.h" -#include "options.h" -#include "trap.h" -#include "syntax.h" -#include "input.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "var.h" -#include "builtins.h" - - -/* - * A job structure contains information about a job. A job is either a - * single process or a set of processes contained in a pipeline. In the - * latter case, pidlist will be non-NULL, and will point to a -1 terminated - * array of pids. - */ - -struct procstat { - pid_t pid; /* process id */ - int status; /* status flags (defined above) */ - char *cmd; /* text of command being run */ -}; - - -/* states */ -#define JOBSTOPPED 1 /* all procs are stopped */ -#define JOBDONE 2 /* all procs are completed */ - - -struct job { - struct procstat ps0; /* status of process */ - struct procstat *ps; /* status or processes when more than one */ - short nprocs; /* number of processes */ - pid_t pgrp; /* process group of this job */ - char state; /* true if job is finished */ - char used; /* true if this entry is in used */ - char changed; /* true if status has changed */ - char foreground; /* true if running in the foreground */ - char remembered; /* true if $! referenced */ -#if JOBS - char jobctl; /* job running under job control */ - struct job *next; /* job used after this one */ -#endif -}; - - -static struct job *jobtab; /* array of jobs */ -static int njobs; /* size of array */ -static pid_t backgndpid = -1; /* pid of last background process */ -static struct job *bgjob = NULL; /* last background process */ -#if JOBS -static struct job *jobmru; /* most recently used job list */ -static pid_t initialpgrp; /* pgrp of shell on invocation */ -#endif -static int ttyfd = -1; - -/* mode flags for dowait */ -#define DOWAIT_BLOCK 0x1 /* wait until a child exits */ -#define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on signal */ -#define DOWAIT_SIG_TRAP 0x4 /* if DOWAIT_SIG, abort on trapped signal only */ - -#if JOBS -static void restartjob(struct job *); -#endif -static void freejob(struct job *); -static int waitcmdloop(struct job *); -static struct job *getjob_nonotfound(const char *); -static struct job *getjob(const char *); -pid_t killjob(const char *, int); -static pid_t dowait(int, struct job *); -static void checkzombies(void); -static void cmdtxt(union node *); -static void cmdputs(const char *); -#if JOBS -static void setcurjob(struct job *); -static void deljob(struct job *); -static struct job *getcurjob(struct job *); -#endif -static void printjobcmd(struct job *); -static void showjob(struct job *, int); - - -/* - * Turn job control on and off. - */ - -static int jobctl; - -#if JOBS -static void -jobctl_notty(void) -{ - if (ttyfd >= 0) { - close(ttyfd); - ttyfd = -1; - } - if (!iflag) { - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); - jobctl = 1; - return; - } - out2fmt_flush("sh: can't access tty; job control turned off\n"); - mflag = 0; -} - -void -setjobctl(int on) -{ - int i; - - if (on == jobctl || rootshell == 0) - return; - if (on) { - if (ttyfd != -1) - close(ttyfd); - if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) { - i = 0; - while (i <= 2 && !isatty(i)) - i++; - if (i > 2 || - (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) { - jobctl_notty(); - return; - } - } - if (ttyfd < 10) { - /* - * Keep our TTY file descriptor out of the way of - * the user's redirections. - */ - if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) { - jobctl_notty(); - return; - } - close(ttyfd); - ttyfd = i; - } - do { /* while we are in the background */ - initialpgrp = tcgetpgrp(ttyfd); - if (initialpgrp < 0) { - jobctl_notty(); - return; - } - if (initialpgrp != getpgrp()) { - if (!iflag) { - initialpgrp = -1; - jobctl_notty(); - return; - } - kill(0, SIGTTIN); - continue; - } - } while (0); - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); - setpgid(0, rootpid); - tcsetpgrp(ttyfd, rootpid); - } else { /* turning job control off */ - setpgid(0, initialpgrp); - if (ttyfd >= 0) { - tcsetpgrp(ttyfd, initialpgrp); - close(ttyfd); - ttyfd = -1; - } - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); - } - jobctl = on; -} -#endif - - -#if JOBS -int -fgcmd(int argc __unused, char **argv __unused) -{ - struct job *jp; - pid_t pgrp; - int status; - - nextopt(""); - jp = getjob(*argptr); - if (jp->jobctl == 0) - error("job not created under job control"); - printjobcmd(jp); - flushout(&output); - pgrp = jp->ps[0].pid; - if (ttyfd >= 0) - tcsetpgrp(ttyfd, pgrp); - restartjob(jp); - jp->foreground = 1; - INTOFF; - status = waitforjob(jp, (int *)NULL); - INTON; - return status; -} - - -int -bgcmd(int argc __unused, char **argv __unused) -{ - struct job *jp; - - nextopt(""); - do { - jp = getjob(*argptr); - if (jp->jobctl == 0) - error("job not created under job control"); - if (jp->state == JOBDONE) - continue; - restartjob(jp); - jp->foreground = 0; - out1fmt("[%td] ", jp - jobtab + 1); - printjobcmd(jp); - } while (*argptr != NULL && *++argptr != NULL); - return 0; -} - - -static void -restartjob(struct job *jp) -{ - struct procstat *ps; - int i; - - if (jp->state == JOBDONE) - return; - setcurjob(jp); - INTOFF; - kill(-jp->ps[0].pid, SIGCONT); - for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { - if (WIFSTOPPED(ps->status)) { - ps->status = -1; - jp->state = 0; - } - } - INTON; -} -#endif - - -int -jobscmd(int argc __unused, char *argv[] __unused) -{ - char *id; - int ch, mode; - - mode = SHOWJOBS_DEFAULT; - while ((ch = nextopt("lps")) != '\0') { - switch (ch) { - case 'l': - mode = SHOWJOBS_VERBOSE; - break; - case 'p': - mode = SHOWJOBS_PGIDS; - break; - case 's': - mode = SHOWJOBS_PIDS; - break; - } - } - - if (*argptr == NULL) - showjobs(0, mode); - else - while ((id = *argptr++) != NULL) - showjob(getjob(id), mode); - - return (0); -} - -static void -printjobcmd(struct job *jp) -{ - struct procstat *ps; - int i; - - for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { - out1str(ps->cmd); - if (i > 0) - out1str(" | "); - } - out1c('\n'); -} - -static void -showjob(struct job *jp, int mode) -{ - char s[64]; - char statebuf[16]; - const char *statestr, *coredump; - struct procstat *ps; - struct job *j; - int col, curr, i, jobno, prev, procno, status; - char c; - - procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs; - jobno = jp - jobtab + 1; - curr = prev = 0; -#if JOBS - if ((j = getcurjob(NULL)) != NULL) { - curr = j - jobtab + 1; - if ((j = getcurjob(j)) != NULL) - prev = j - jobtab + 1; - } -#endif - coredump = ""; - status = jp->ps[jp->nprocs - 1].status; - if (jp->state == 0) { - statestr = "Running"; -#if JOBS - } else if (jp->state == JOBSTOPPED) { - ps = jp->ps + jp->nprocs - 1; - while (!WIFSTOPPED(ps->status) && ps > jp->ps) - ps--; - if (WIFSTOPPED(ps->status)) - i = WSTOPSIG(ps->status); - else - i = -1; - statestr = strsignal(i); - if (statestr == NULL) - statestr = "Suspended"; -#endif - } else if (WIFEXITED(status)) { - if (WEXITSTATUS(status) == 0) - statestr = "Done"; - else { - fmtstr(statebuf, sizeof(statebuf), "Done(%d)", - WEXITSTATUS(status)); - statestr = statebuf; - } - } else { - i = WTERMSIG(status); - statestr = strsignal(i); - if (statestr == NULL) - statestr = "Unknown signal"; - if (WCOREDUMP(status)) - coredump = " (core dumped)"; - } - - for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */ - if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) { - out1fmt("%d\n", (int)ps->pid); - continue; - } - if (mode != SHOWJOBS_VERBOSE && ps != jp->ps) - continue; - if (jobno == curr && ps == jp->ps) - c = '+'; - else if (jobno == prev && ps == jp->ps) - c = '-'; - else - c = ' '; - if (ps == jp->ps) - fmtstr(s, 64, "[%d] %c ", jobno, c); - else - fmtstr(s, 64, " %c ", c); - out1str(s); - col = strlen(s); - if (mode == SHOWJOBS_VERBOSE) { - fmtstr(s, 64, "%d ", (int)ps->pid); - out1str(s); - col += strlen(s); - } - if (ps == jp->ps) { - out1str(statestr); - out1str(coredump); - col += strlen(statestr) + strlen(coredump); - } - do { - out1c(' '); - col++; - } while (col < 30); - if (mode == SHOWJOBS_VERBOSE) { - out1str(ps->cmd); - out1c('\n'); - } else - printjobcmd(jp); - } -} - -/* - * Print a list of jobs. If "change" is nonzero, only print jobs whose - * statuses have changed since the last call to showjobs. - * - * If the shell is interrupted in the process of creating a job, the - * result may be a job structure containing zero processes. Such structures - * will be freed here. - */ - -void -showjobs(int change, int mode) -{ - int jobno; - struct job *jp; - - TRACE(("showjobs(%d) called\n", change)); - checkzombies(); - for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { - if (! jp->used) - continue; - if (jp->nprocs == 0) { - freejob(jp); - continue; - } - if (change && ! jp->changed) - continue; - showjob(jp, mode); - if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) { - jp->changed = 0; - /* Hack: discard jobs for which $! has not been - * referenced in interactive mode when they terminate. - */ - if (jp->state == JOBDONE && !jp->remembered && - (iflag || jp != bgjob)) { - freejob(jp); - } - } - } -} - - -/* - * Mark a job structure as unused. - */ - -static void -freejob(struct job *jp) -{ - struct procstat *ps; - int i; - - INTOFF; - if (bgjob == jp) - bgjob = NULL; - for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) { - if (ps->cmd != nullstr) - ckfree(ps->cmd); - } - if (jp->ps != &jp->ps0) - ckfree(jp->ps); - jp->used = 0; -#if JOBS - deljob(jp); -#endif - INTON; -} - - - -int -waitcmd(int argc __unused, char **argv __unused) -{ - struct job *job; - int retval; - - nextopt(""); - if (*argptr == NULL) - return (waitcmdloop(NULL)); - - do { - job = getjob_nonotfound(*argptr); - if (job == NULL) - retval = 127; - else - retval = waitcmdloop(job); - argptr++; - } while (*argptr != NULL); - - return (retval); -} - -static int -waitcmdloop(struct job *job) -{ - int status, retval, sig; - struct job *jp; - - /* - * Loop until a process is terminated or stopped, or a SIGINT is - * received. - */ - - do { - if (job != NULL) { - if (job->state == JOBDONE) { - status = job->ps[job->nprocs - 1].status; - if (WIFEXITED(status)) - retval = WEXITSTATUS(status); - else - retval = WTERMSIG(status) + 128; - if (! iflag || ! job->changed) - freejob(job); - else { - job->remembered = 0; - if (job == bgjob) - bgjob = NULL; - } - return retval; - } - } else { - for (jp = jobtab ; jp < jobtab + njobs; jp++) - if (jp->used && jp->state == JOBDONE) { - if (! iflag || ! jp->changed) - freejob(jp); - else { - jp->remembered = 0; - if (jp == bgjob) - bgjob = NULL; - } - } - for (jp = jobtab ; ; jp++) { - if (jp >= jobtab + njobs) { /* no running procs */ - return 0; - } - if (jp->used && jp->state == 0) - break; - } - } - } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1); - - sig = pendingsig_waitcmd; - pendingsig_waitcmd = 0; - return sig + 128; -} - - - -int -jobidcmd(int argc __unused, char **argv __unused) -{ - struct job *jp; - int i; - - nextopt(""); - jp = getjob(*argptr); - for (i = 0 ; i < jp->nprocs ; ) { - out1fmt("%d", (int)jp->ps[i].pid); - out1c(++i < jp->nprocs? ' ' : '\n'); - } - return 0; -} - - - -/* - * Convert a job name to a job structure. - */ - -static struct job * -getjob_nonotfound(const char *name) -{ - int jobno; - struct job *found, *jp; - size_t namelen; - pid_t pid; - int i; - - if (name == NULL) { -#if JOBS - name = "%+"; -#else - error("No current job"); -#endif - } - if (name[0] == '%') { - if (is_digit(name[1])) { - jobno = number(name + 1); - if (jobno > 0 && jobno <= njobs - && jobtab[jobno - 1].used != 0) - return &jobtab[jobno - 1]; -#if JOBS - } else if ((name[1] == '%' || name[1] == '+') && - name[2] == '\0') { - if ((jp = getcurjob(NULL)) == NULL) - error("No current job"); - return (jp); - } else if (name[1] == '-' && name[2] == '\0') { - if ((jp = getcurjob(NULL)) == NULL || - (jp = getcurjob(jp)) == NULL) - error("No previous job"); - return (jp); -#endif - } else if (name[1] == '?') { - found = NULL; - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && strstr(jp->ps[0].cmd, name + 2) != NULL) { - if (found) - error("%s: ambiguous", name); - found = jp; - } - } - if (found != NULL) - return (found); - } else { - namelen = strlen(name); - found = NULL; - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && strncmp(jp->ps[0].cmd, name + 1, - namelen - 1) == 0) { - if (found) - error("%s: ambiguous", name); - found = jp; - } - } - if (found) - return found; - } - } else if (is_number(name)) { - pid = (pid_t)number(name); - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && jp->ps[jp->nprocs - 1].pid == pid) - return jp; - } - } - return NULL; -} - - -static struct job * -getjob(const char *name) -{ - struct job *jp; - - jp = getjob_nonotfound(name); - if (jp == NULL) - error("No such job: %s", name); - return (jp); -} - - -int -killjob(const char *name, int sig) -{ - struct job *jp; - int i, ret; - - jp = getjob(name); - if (jp->state == JOBDONE) - return 0; - if (jp->jobctl) - return kill(-jp->ps[0].pid, sig); - ret = -1; - errno = ESRCH; - for (i = 0; i < jp->nprocs; i++) - if (jp->ps[i].status == -1 || WIFSTOPPED(jp->ps[i].status)) { - if (kill(jp->ps[i].pid, sig) == 0) - ret = 0; - } else - ret = 0; - return ret; -} - -/* - * Return a new job structure, - */ - -struct job * -makejob(union node *node __unused, int nprocs) -{ - int i; - struct job *jp; - - for (i = njobs, jp = jobtab ; ; jp++) { - if (--i < 0) { - INTOFF; - if (njobs == 0) { - jobtab = ckmalloc(4 * sizeof jobtab[0]); -#if JOBS - jobmru = NULL; -#endif - } else { - jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); - memcpy(jp, jobtab, njobs * sizeof jp[0]); -#if JOBS - /* Relocate `next' pointers and list head */ - if (jobmru != NULL) - jobmru = &jp[jobmru - jobtab]; - for (i = 0; i < njobs; i++) - if (jp[i].next != NULL) - jp[i].next = &jp[jp[i].next - - jobtab]; -#endif - if (bgjob != NULL) - bgjob = &jp[bgjob - jobtab]; - /* Relocate `ps' pointers */ - for (i = 0; i < njobs; i++) - if (jp[i].ps == &jobtab[i].ps0) - jp[i].ps = &jp[i].ps0; - ckfree(jobtab); - jobtab = jp; - } - jp = jobtab + njobs; - for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0) - ; - INTON; - break; - } - if (jp->used == 0) - break; - } - INTOFF; - jp->state = 0; - jp->used = 1; - jp->changed = 0; - jp->nprocs = 0; - jp->foreground = 0; - jp->remembered = 0; -#if JOBS - jp->jobctl = jobctl; - jp->next = NULL; -#endif - if (nprocs > 1) { - jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); - } else { - jp->ps = &jp->ps0; - } - INTON; - TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs, - jp - jobtab + 1)); - return jp; -} - -#if JOBS -static void -setcurjob(struct job *cj) -{ - struct job *jp, *prev; - - for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) { - if (jp == cj) { - if (prev != NULL) - prev->next = jp->next; - else - jobmru = jp->next; - jp->next = jobmru; - jobmru = cj; - return; - } - } - cj->next = jobmru; - jobmru = cj; -} - -static void -deljob(struct job *j) -{ - struct job *jp, *prev; - - for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) { - if (jp == j) { - if (prev != NULL) - prev->next = jp->next; - else - jobmru = jp->next; - return; - } - } -} - -/* - * Return the most recently used job that isn't `nj', and preferably one - * that is stopped. - */ -static struct job * -getcurjob(struct job *nj) -{ - struct job *jp; - - /* Try to find a stopped one.. */ - for (jp = jobmru; jp != NULL; jp = jp->next) - if (jp->used && jp != nj && jp->state == JOBSTOPPED) - return (jp); - /* Otherwise the most recently used job that isn't `nj' */ - for (jp = jobmru; jp != NULL; jp = jp->next) - if (jp->used && jp != nj) - return (jp); - - return (NULL); -} - -#endif - -/* - * Fork of a subshell. If we are doing job control, give the subshell its - * own process group. Jp is a job structure that the job is to be added to. - * N is the command that will be evaluated by the child. Both jp and n may - * be NULL. The mode parameter can be one of the following: - * FORK_FG - Fork off a foreground process. - * FORK_BG - Fork off a background process. - * FORK_NOJOB - Like FORK_FG, but don't give the process its own - * process group even if job control is on. - * - * When job control is turned off, background processes have their standard - * input redirected to /dev/null (except for the second and later processes - * in a pipeline). - */ - -pid_t -forkshell(struct job *jp, union node *n, int mode) -{ - pid_t pid; - pid_t pgrp; - - TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n, - mode)); - INTOFF; - if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0)) - checkzombies(); - flushall(); - pid = fork(); - if (pid == -1) { - TRACE(("Fork failed, errno=%d\n", errno)); - INTON; - error("Cannot fork: %s", strerror(errno)); - } - if (pid == 0) { - struct job *p; - int wasroot; - int i; - - TRACE(("Child shell %d\n", (int)getpid())); - wasroot = rootshell; - rootshell = 0; - handler = &main_handler; - closescript(); - INTON; - forcelocal = 0; - clear_traps(); -#if JOBS - jobctl = 0; /* do job control only in root shell */ - if (wasroot && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = getpid(); - else - pgrp = jp->ps[0].pid; - if (setpgid(0, pgrp) == 0 && mode == FORK_FG && - ttyfd >= 0) { - /*** this causes superfluous TIOCSPGRPS ***/ - if (tcsetpgrp(ttyfd, pgrp) < 0) - error("tcsetpgrp failed, errno=%d", errno); - } - setsignal(SIGTSTP); - setsignal(SIGTTOU); - } else if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(_PATH_DEVNULL, O_RDONLY) != 0) - error("cannot open %s: %s", - _PATH_DEVNULL, strerror(errno)); - } - } -#else - if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(_PATH_DEVNULL, O_RDONLY) != 0) - error("cannot open %s: %s", - _PATH_DEVNULL, strerror(errno)); - } - } -#endif - INTOFF; - for (i = njobs, p = jobtab ; --i >= 0 ; p++) - if (p->used) - freejob(p); - INTON; - if (wasroot && iflag) { - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); - } - return pid; - } - if (rootshell && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = pid; - else - pgrp = jp->ps[0].pid; - setpgid(pid, pgrp); - } - if (mode == FORK_BG) { - if (bgjob != NULL && bgjob->state == JOBDONE && - !bgjob->remembered && !iflag) - freejob(bgjob); - backgndpid = pid; /* set $! */ - bgjob = jp; - } - if (jp) { - struct procstat *ps = &jp->ps[jp->nprocs++]; - ps->pid = pid; - ps->status = -1; - ps->cmd = nullstr; - if (iflag && rootshell && n) - ps->cmd = commandtext(n); - jp->foreground = mode == FORK_FG; -#if JOBS - setcurjob(jp); -#endif - } - INTON; - TRACE(("In parent shell: child = %d\n", (int)pid)); - return pid; -} - - -pid_t -vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2]) -{ - pid_t pid; - struct jmploc jmploc; - struct jmploc *savehandler; - - TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp - jobtab, argv[0], - (void *)pip)); - INTOFF; - flushall(); - savehandler = handler; - pid = vfork(); - if (pid == -1) { - TRACE(("Vfork failed, errno=%d\n", errno)); - INTON; - error("Cannot fork: %s", strerror(errno)); - } - if (pid == 0) { - TRACE(("Child shell %d\n", (int)getpid())); - if (setjmp(jmploc.loc)) - _exit(exception == EXEXEC ? exerrno : 2); - if (pip != NULL) { - close(pip[0]); - if (pip[1] != 1) { - dup2(pip[1], 1); - close(pip[1]); - } - } - handler = &jmploc; - shellexec(argv, envp, path, idx); - } - handler = savehandler; - if (jp) { - struct procstat *ps = &jp->ps[jp->nprocs++]; - ps->pid = pid; - ps->status = -1; - ps->cmd = nullstr; - jp->foreground = 1; -#if JOBS - setcurjob(jp); -#endif - } - INTON; - TRACE(("In parent shell: child = %d\n", (int)pid)); - return pid; -} - - -/* - * Wait for job to finish. - * - * Under job control we have the problem that while a child process is - * running interrupts generated by the user are sent to the child but not - * to the shell. This means that an infinite loop started by an inter- - * active user may be hard to kill. With job control turned off, an - * interactive user may place an interactive program inside a loop. If - * the interactive program catches interrupts, the user doesn't want - * these interrupts to also abort the loop. The approach we take here - * is to have the shell ignore interrupt signals while waiting for a - * foreground process to terminate, and then send itself an interrupt - * signal if the child process was terminated by an interrupt signal. - * Unfortunately, some programs want to do a bit of cleanup and then - * exit on interrupt; unless these processes terminate themselves by - * sending a signal to themselves (instead of calling exit) they will - * confuse this approach. - */ - -int -waitforjob(struct job *jp, int *signaled) -{ -#if JOBS - int propagate_int = jp->jobctl && jp->foreground; -#endif - int status; - int st; - - INTOFF; - TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1)); - while (jp->state == 0) - if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG | - DOWAIT_SIG_TRAP : 0), jp) == -1) - dotrap(); -#if JOBS - if (jp->jobctl) { - if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0) - error("tcsetpgrp failed, errno=%d\n", errno); - } - if (jp->state == JOBSTOPPED) - setcurjob(jp); -#endif - status = jp->ps[jp->nprocs - 1].status; - if (signaled != NULL) - *signaled = WIFSIGNALED(status); - /* convert to 8 bits */ - if (WIFEXITED(status)) - st = WEXITSTATUS(status); -#if JOBS - else if (WIFSTOPPED(status)) - st = WSTOPSIG(status) + 128; -#endif - else - st = WTERMSIG(status) + 128; - if (! JOBS || jp->state == JOBDONE) - freejob(jp); - if (int_pending()) { - if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT) - CLEAR_PENDING_INT; - } -#if JOBS - else if (rootshell && propagate_int && - WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) - kill(getpid(), SIGINT); -#endif - INTON; - return st; -} - - -static void -dummy_handler(int sig __unused) -{ -} - -/* - * Wait for a process to terminate. - */ - -static pid_t -dowait(int mode, struct job *job) -{ - struct sigaction sa, osa; - sigset_t mask, omask; - pid_t pid; - int status; - struct procstat *sp; - struct job *jp; - struct job *thisjob; - const char *sigstr; - int done; - int stopped; - int sig; - int coredump; - int wflags; - int restore_sigchld; - - TRACE(("dowait(%d, %p) called\n", mode, job)); - restore_sigchld = 0; - if ((mode & DOWAIT_SIG) != 0) { - sigfillset(&mask); - sigprocmask(SIG_BLOCK, &mask, &omask); - INTOFF; - if (!issigchldtrapped()) { - restore_sigchld = 1; - sa.sa_handler = dummy_handler; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(SIGCHLD, &sa, &osa); - } - } - do { -#if JOBS - if (iflag) - wflags = WUNTRACED | WCONTINUED; - else -#endif - wflags = 0; - if ((mode & (DOWAIT_BLOCK | DOWAIT_SIG)) != DOWAIT_BLOCK) - wflags |= WNOHANG; - pid = wait3(&status, wflags, (struct rusage *)NULL); - TRACE(("wait returns %d, status=%d\n", (int)pid, status)); - if (pid == 0 && (mode & DOWAIT_SIG) != 0) { - pid = -1; - if (((mode & DOWAIT_SIG_TRAP) != 0 ? - pendingsig : pendingsig_waitcmd) != 0) { - errno = EINTR; - break; - } - sigsuspend(&omask); - if (int_pending()) - break; - } - } while (pid == -1 && errno == EINTR); - if (pid == -1 && errno == ECHILD && job != NULL) - job->state = JOBDONE; - if ((mode & DOWAIT_SIG) != 0) { - if (restore_sigchld) - sigaction(SIGCHLD, &osa, NULL); - sigprocmask(SIG_SETMASK, &omask, NULL); - INTON; - } - if (pid <= 0) - return pid; - INTOFF; - thisjob = NULL; - for (jp = jobtab ; jp < jobtab + njobs ; jp++) { - if (jp->used && jp->nprocs > 0) { - done = 1; - stopped = 1; - for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { - if (sp->pid == -1) - continue; - if (sp->pid == pid && (sp->status == -1 || - WIFSTOPPED(sp->status))) { - TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", - (int)pid, sp->status, - status)); - if (WIFCONTINUED(status)) { - sp->status = -1; - jp->state = 0; - } else - sp->status = status; - thisjob = jp; - } - if (sp->status == -1) - stopped = 0; - else if (WIFSTOPPED(sp->status)) - done = 0; - } - if (stopped) { /* stopped or done */ - int state = done? JOBDONE : JOBSTOPPED; - if (jp->state != state) { - TRACE(("Job %td: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); - jp->state = state; - if (jp != job) { - if (done && !jp->remembered && - !iflag && jp != bgjob) - freejob(jp); -#if JOBS - else if (done) - deljob(jp); -#endif - } - } - } - } - } - INTON; - if (!thisjob || thisjob->state == 0) - ; - else if ((!rootshell || !iflag || thisjob == job) && - thisjob->foreground && thisjob->state != JOBSTOPPED) { - sig = 0; - coredump = 0; - for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++) - if (WIFSIGNALED(sp->status)) { - sig = WTERMSIG(sp->status); - coredump = WCOREDUMP(sp->status); - } - if (sig > 0 && sig != SIGINT && sig != SIGPIPE) { - sigstr = strsignal(sig); - if (sigstr != NULL) - out2str(sigstr); - else - out2str("Unknown signal"); - if (coredump) - out2str(" (core dumped)"); - out2c('\n'); - flushout(out2); - } - } else { - TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job)); - thisjob->changed = 1; - } - return pid; -} - - - -/* - * return 1 if there are stopped jobs, otherwise 0 - */ -int job_warning = 0; -int -stoppedjobs(void) -{ - int jobno; - struct job *jp; - - if (job_warning) - return (0); - for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { - if (jp->used == 0) - continue; - if (jp->state == JOBSTOPPED) { - out2fmt_flush("You have stopped jobs.\n"); - job_warning = 2; - return (1); - } - } - - return (0); -} - - -static void -checkzombies(void) -{ - while (njobs > 0 && dowait(0, NULL) > 0) - ; -} - - -int -backgndpidset(void) -{ - return backgndpid != -1; -} - - -pid_t -backgndpidval(void) -{ - if (bgjob != NULL && !forcelocal) - bgjob->remembered = 1; - return backgndpid; -} - -/* - * Return a string identifying a command (to be printed by the - * jobs command. - */ - -static char *cmdnextc; -static int cmdnleft; -#define MAXCMDTEXT 200 - -char * -commandtext(union node *n) -{ - char *name; - - cmdnextc = name = ckmalloc(MAXCMDTEXT); - cmdnleft = MAXCMDTEXT - 4; - cmdtxt(n); - *cmdnextc = '\0'; - return name; -} - - -static void -cmdtxtdogroup(union node *n) -{ - cmdputs("; do "); - cmdtxt(n); - cmdputs("; done"); -} - - -static void -cmdtxtredir(union node *n, const char *op, int deffd) -{ - char s[2]; - - if (n->nfile.fd != deffd) { - s[0] = n->nfile.fd + '0'; - s[1] = '\0'; - cmdputs(s); - } - cmdputs(op); - if (n->type == NTOFD || n->type == NFROMFD) { - if (n->ndup.dupfd >= 0) - s[0] = n->ndup.dupfd + '0'; - else - s[0] = '-'; - s[1] = '\0'; - cmdputs(s); - } else { - cmdtxt(n->nfile.fname); - } -} - - -static void -cmdtxt(union node *n) -{ - union node *np; - struct nodelist *lp; - - if (n == NULL) - return; - switch (n->type) { - case NSEMI: - cmdtxt(n->nbinary.ch1); - cmdputs("; "); - cmdtxt(n->nbinary.ch2); - break; - case NAND: - cmdtxt(n->nbinary.ch1); - cmdputs(" && "); - cmdtxt(n->nbinary.ch2); - break; - case NOR: - cmdtxt(n->nbinary.ch1); - cmdputs(" || "); - cmdtxt(n->nbinary.ch2); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - cmdtxt(lp->n); - if (lp->next) - cmdputs(" | "); - } - break; - case NSUBSHELL: - cmdputs("("); - cmdtxt(n->nredir.n); - cmdputs(")"); - break; - case NREDIR: - case NBACKGND: - cmdtxt(n->nredir.n); - break; - case NIF: - cmdputs("if "); - cmdtxt(n->nif.test); - cmdputs("; then "); - cmdtxt(n->nif.ifpart); - cmdputs("..."); - break; - case NWHILE: - cmdputs("while "); - cmdtxt(n->nbinary.ch1); - cmdtxtdogroup(n->nbinary.ch2); - break; - case NUNTIL: - cmdputs("until "); - cmdtxt(n->nbinary.ch1); - cmdtxtdogroup(n->nbinary.ch2); - break; - case NFOR: - cmdputs("for "); - cmdputs(n->nfor.var); - cmdputs(" in ..."); - break; - case NCASE: - cmdputs("case "); - cmdputs(n->ncase.expr->narg.text); - cmdputs(" in ..."); - break; - case NDEFUN: - cmdputs(n->narg.text); - cmdputs("() ..."); - break; - case NNOT: - cmdputs("! "); - cmdtxt(n->nnot.com); - break; - case NCMD: - for (np = n->ncmd.args ; np ; np = np->narg.next) { - cmdtxt(np); - if (np->narg.next) - cmdputs(" "); - } - for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { - cmdputs(" "); - cmdtxt(np); - } - break; - case NARG: - cmdputs(n->narg.text); - break; - case NTO: - cmdtxtredir(n, ">", 1); - break; - case NAPPEND: - cmdtxtredir(n, ">>", 1); - break; - case NTOFD: - cmdtxtredir(n, ">&", 1); - break; - case NCLOBBER: - cmdtxtredir(n, ">|", 1); - break; - case NFROM: - cmdtxtredir(n, "<", 0); - break; - case NFROMTO: - cmdtxtredir(n, "<>", 0); - break; - case NFROMFD: - cmdtxtredir(n, "<&", 0); - break; - case NHERE: - case NXHERE: - cmdputs("<<..."); - break; - default: - cmdputs("???"); - break; - } -} - - - -static void -cmdputs(const char *s) -{ - const char *p; - char *q; - char c; - int subtype = 0; - - if (cmdnleft <= 0) - return; - p = s; - q = cmdnextc; - while ((c = *p++) != '\0') { - if (c == CTLESC) - *q++ = *p++; - else if (c == CTLVAR) { - *q++ = '$'; - if (--cmdnleft > 0) - *q++ = '{'; - subtype = *p++; - if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0) - *q++ = '#'; - } else if (c == '=' && subtype != 0) { - *q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL]; - if (*q) - q++; - else - cmdnleft++; - if (((subtype & VSTYPE) == VSTRIMLEFTMAX || - (subtype & VSTYPE) == VSTRIMRIGHTMAX) && - --cmdnleft > 0) - *q = q[-1], q++; - subtype = 0; - } else if (c == CTLENDVAR) { - *q++ = '}'; - } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) { - cmdnleft -= 5; - if (cmdnleft > 0) { - *q++ = '$'; - *q++ = '('; - *q++ = '.'; - *q++ = '.'; - *q++ = '.'; - *q++ = ')'; - } - } else if (c == CTLARI) { - cmdnleft -= 2; - if (cmdnleft > 0) { - *q++ = '$'; - *q++ = '('; - *q++ = '('; - } - p++; - } else if (c == CTLENDARI) { - if (--cmdnleft > 0) { - *q++ = ')'; - *q++ = ')'; - } - } else if (c == CTLQUOTEMARK || c == CTLQUOTEEND) - cmdnleft++; /* ignore */ - else - *q++ = c; - if (--cmdnleft <= 0) { - *q++ = '.'; - *q++ = '.'; - *q++ = '.'; - break; - } - } - cmdnextc = q; -} diff --git a/bin/catsh/jobs.h b/bin/catsh/jobs.h deleted file mode 100644 index 52c3abe1..00000000 --- a/bin/catsh/jobs.h +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)jobs.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/jobs.h 327475 2018-01-01 22:31:52Z jilles $ - */ - -/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ -#define FORK_FG 0 -#define FORK_BG 1 -#define FORK_NOJOB 2 - -#include <signal.h> /* for sig_atomic_t */ - -struct job; - -enum { - SHOWJOBS_DEFAULT, /* job number, status, command */ - SHOWJOBS_VERBOSE, /* job number, PID, status, command */ - SHOWJOBS_PIDS, /* PID only */ - SHOWJOBS_PGIDS /* PID of the group leader only */ -}; - -extern int job_warning; /* user was warned about stopped jobs */ - -void setjobctl(int); -void showjobs(int, int); -struct job *makejob(union node *, int); -pid_t forkshell(struct job *, union node *, int); -pid_t vforkexecshell(struct job *, char **, char **, const char *, int, int []); -int waitforjob(struct job *, int *); -int stoppedjobs(void); -int backgndpidset(void); -pid_t backgndpidval(void); -char *commandtext(union node *); - -#if ! JOBS -#define setjobctl(on) /* do nothing */ -#endif diff --git a/bin/catsh/kill.c b/bin/catsh/kill.c deleted file mode 100644 index f58987cc..00000000 --- a/bin/catsh/kill.c +++ /dev/null @@ -1,215 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1988, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * Important: This file is used both as a standalone program /bin/kill and - * as a builtin for /bin/sh (#define SHELL). - */ - -#if 0 -#ifndef lint -static char const copyright[] = -"@(#) Copyright (c) 1988, 1993, 1994\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95"; -#endif /* not lint */ -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/kill/kill.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef SHELL -#define main killcmd -#include "bltin.h" -#endif - -static void nosig(const char *); -static void printsignals(FILE *); -static int signame_to_signum(const char *); -static void usage(void); - -int -main(int argc, char *argv[]) -{ - long pidl; - pid_t pid; - int errors, numsig, ret; - char *ep; - - if (argc < 2) - usage(); - - numsig = SIGTERM; - - argc--, argv++; - if (!strcmp(*argv, "-l")) { - argc--, argv++; - if (argc > 1) - usage(); - if (argc == 1) { - if (!isdigit(**argv)) - usage(); - numsig = strtol(*argv, &ep, 10); - if (!**argv || *ep) - errx(2, "illegal signal number: %s", *argv); - if (numsig >= 128) - numsig -= 128; - if (numsig <= 0 || numsig >= NSIG) - nosig(*argv); - printf("%s\n", sys_signame[numsig]); - return (0); - } - printsignals(stdout); - return (0); - } - - if (!strcmp(*argv, "-s")) { - argc--, argv++; - if (argc < 1) { - warnx("option requires an argument -- s"); - usage(); - } - if (strcmp(*argv, "0")) { - if ((numsig = signame_to_signum(*argv)) < 0) - nosig(*argv); - } else - numsig = 0; - argc--, argv++; - } else if (**argv == '-' && *(*argv + 1) != '-') { - ++*argv; - if (isalpha(**argv)) { - if ((numsig = signame_to_signum(*argv)) < 0) - nosig(*argv); - } else if (isdigit(**argv)) { - numsig = strtol(*argv, &ep, 10); - if (!**argv || *ep) - errx(2, "illegal signal number: %s", *argv); - if (numsig < 0) - nosig(*argv); - } else - nosig(*argv); - argc--, argv++; - } - - if (argc > 0 && strncmp(*argv, "--", 2) == 0) - argc--, argv++; - - if (argc == 0) - usage(); - - for (errors = 0; argc; argc--, argv++) { -#ifdef SHELL - if (**argv == '%') - ret = killjob(*argv, numsig); - else -#endif - { - pidl = strtol(*argv, &ep, 10); - /* Check for overflow of pid_t. */ - pid = (pid_t)pidl; - if (!**argv || *ep || pid != pidl) - errx(2, "illegal process id: %s", *argv); - ret = kill(pid, numsig); - } - if (ret == -1) { - warn("%s", *argv); - errors = 1; - } - } - - return (errors); -} - -static int -signame_to_signum(const char *sig) -{ - int n; - - if (strncasecmp(sig, "SIG", 3) == 0) - sig += 3; - for (n = 1; n < NSIG; n++) { - if (!strcasecmp(sys_signame[n], sig)) - return (n); - } - return (-1); -} - -static void -nosig(const char *name) -{ - - warnx("unknown signal %s; valid signals:", name); - printsignals(stderr); -#ifdef SHELL - error(NULL); -#else - exit(2); -#endif -} - -static void -printsignals(FILE *fp) -{ - int n; - - for (n = 1; n < NSIG; n++) { - (void)fprintf(fp, "%s", sys_signame[n]); - if (n == (NSIG / 2) || n == (NSIG - 1)) - (void)fprintf(fp, "\n"); - else - (void)fprintf(fp, " "); - } -} - -static void -usage(void) -{ - - (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", - "usage: kill [-s signal_name] pid ...", - " kill -l [exit_status]", - " kill -signal_name pid ...", - " kill -signal_number pid ..."); -#ifdef SHELL - error(NULL); -#else - exit(2); -#endif -} diff --git a/bin/catsh/libedit/.gitignore b/bin/catsh/libedit/.gitignore deleted file mode 100644 index eeae3b81..00000000 --- a/bin/catsh/libedit/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o -common.h -config.mk -emacs.h -fcns.h -func.h -help.h -libedit.a -vi.h diff --git a/bin/catsh/libedit/Makefile b/bin/catsh/libedit/Makefile deleted file mode 100644 index 9b13d59d..00000000 --- a/bin/catsh/libedit/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -CFLAGS += -std=c99 -Wall -Wextra - --include config.mk - -OBJS += chared.o -OBJS += chartype.o -OBJS += common.o -OBJS += el.o -OBJS += eln.o -OBJS += emacs.o -OBJS += filecomplete.o -OBJS += hist.o -OBJS += history.o -OBJS += historyn.o -OBJS += keymacro.o -OBJS += literal.o -OBJS += map.o -OBJS += parse.o -OBJS += prompt.o -OBJS += read.o -OBJS += readline.o -OBJS += refresh.o -OBJS += search.o -OBJS += sig.o -OBJS += terminal.o -OBJS += tokenizer.o -OBJS += tokenizern.o -OBJS += tty.o -OBJS += vi.o - -AHDR = common.h emacs.h vi.h -ASRC = common.c emacs.c vi.c - -libedit.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -$(OBJS): $(AHDR) fcns.h func.h help.h - -common.h: makelist common.c - sh makelist -h common.c > common.h - -emacs.h: makelist emacs.c - sh makelist -h emacs.c > emacs.h - -vi.h: makelist vi.c - sh makelist -h vi.c > vi.h - -fcns.h: makelist $(AHDR) - sh makelist -fh $(AHDR) > fcns.h - -func.h: makelist $(AHDR) - sh makelist -fc $(AHDR) > func.h - -help.h: makelist $(ASRC) - sh makelist -bh $(ASRC) > help.h - -clean: - rm -f libedit.a $(OBJS) $(AHDR) fcns.h func.h help.h diff --git a/bin/catsh/libedit/chared.c b/bin/catsh/libedit/chared.c deleted file mode 100644 index 9d46ba68..00000000 --- a/bin/catsh/libedit/chared.c +++ /dev/null @@ -1,753 +0,0 @@ -/* $NetBSD: chared.c,v 1.56 2016/05/22 19:44:26 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: chared.c,v 1.56 2016/05/22 19:44:26 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * chared.c: Character editor utilities - */ -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include "el.h" -#include "common.h" -#include "fcns.h" - -/* value to leave unused in line buffer */ -#define EL_LEAVE 2 - -/* cv_undo(): - * Handle state for the vi undo command - */ -libedit_private void -cv_undo(EditLine *el) -{ - c_undo_t *vu = &el->el_chared.c_undo; - c_redo_t *r = &el->el_chared.c_redo; - size_t size; - - /* Save entire line for undo */ - size = (size_t)(el->el_line.lastchar - el->el_line.buffer); - vu->len = (ssize_t)size; - vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); - (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); - - /* save command info for redo */ - r->count = el->el_state.doingarg ? el->el_state.argument : 0; - r->action = el->el_chared.c_vcmd.action; - r->pos = r->buf; - r->cmd = el->el_state.thiscmd; - r->ch = el->el_state.thisch; -} - -/* cv_yank(): - * Save yank/delete data for paste - */ -libedit_private void -cv_yank(EditLine *el, const wchar_t *ptr, int size) -{ - c_kill_t *k = &el->el_chared.c_kill; - - (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); - k->last = k->buf + size; -} - - -/* c_insert(): - * Insert num characters - */ -libedit_private void -c_insert(EditLine *el, int num) -{ - wchar_t *cp; - - if (el->el_line.lastchar + num >= el->el_line.limit) { - if (!ch_enlargebufs(el, (size_t)num)) - return; /* can't go past end of buffer */ - } - - if (el->el_line.cursor < el->el_line.lastchar) { - /* if I must move chars */ - for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) - cp[num] = *cp; - } - el->el_line.lastchar += num; -} - - -/* c_delafter(): - * Delete num characters after the cursor - */ -libedit_private void -c_delafter(EditLine *el, int num) -{ - - if (el->el_line.cursor + num > el->el_line.lastchar) - num = (int)(el->el_line.lastchar - el->el_line.cursor); - - if (el->el_map.current != el->el_map.emacs) { - cv_undo(el); - cv_yank(el, el->el_line.cursor, num); - } - - if (num > 0) { - wchar_t *cp; - - for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) - *cp = cp[num]; - - el->el_line.lastchar -= num; - } -} - - -/* c_delafter1(): - * Delete the character after the cursor, do not yank - */ -libedit_private void -c_delafter1(EditLine *el) -{ - wchar_t *cp; - - for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) - *cp = cp[1]; - - el->el_line.lastchar--; -} - - -/* c_delbefore(): - * Delete num characters before the cursor - */ -libedit_private void -c_delbefore(EditLine *el, int num) -{ - - if (el->el_line.cursor - num < el->el_line.buffer) - num = (int)(el->el_line.cursor - el->el_line.buffer); - - if (el->el_map.current != el->el_map.emacs) { - cv_undo(el); - cv_yank(el, el->el_line.cursor - num, num); - } - - if (num > 0) { - wchar_t *cp; - - for (cp = el->el_line.cursor - num; - cp <= el->el_line.lastchar; - cp++) - *cp = cp[num]; - - el->el_line.lastchar -= num; - } -} - - -/* c_delbefore1(): - * Delete the character before the cursor, do not yank - */ -libedit_private void -c_delbefore1(EditLine *el) -{ - wchar_t *cp; - - for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) - *cp = cp[1]; - - el->el_line.lastchar--; -} - - -/* ce__isword(): - * Return if p is part of a word according to emacs - */ -libedit_private int -ce__isword(wint_t p) -{ - return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; -} - - -/* cv__isword(): - * Return if p is part of a word according to vi - */ -libedit_private int -cv__isword(wint_t p) -{ - if (iswalnum(p) || p == L'_') - return 1; - if (iswgraph(p)) - return 2; - return 0; -} - - -/* cv__isWord(): - * Return if p is part of a big word according to vi - */ -libedit_private int -cv__isWord(wint_t p) -{ - return !iswspace(p); -} - - -/* c__prev_word(): - * Find the previous word - */ -libedit_private wchar_t * -c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) -{ - p--; - - while (n--) { - while ((p >= low) && !(*wtest)(*p)) - p--; - while ((p >= low) && (*wtest)(*p)) - p--; - } - - /* cp now points to one character before the word */ - p++; - if (p < low) - p = low; - /* cp now points where we want it */ - return p; -} - - -/* c__next_word(): - * Find the next word - */ -libedit_private wchar_t * -c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) -{ - while (n--) { - while ((p < high) && !(*wtest)(*p)) - p++; - while ((p < high) && (*wtest)(*p)) - p++; - } - if (p > high) - p = high; - /* p now points where we want it */ - return p; -} - -/* cv_next_word(): - * Find the next word vi style - */ -libedit_private wchar_t * -cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, - int (*wtest)(wint_t)) -{ - int test; - - while (n--) { - test = (*wtest)(*p); - while ((p < high) && (*wtest)(*p) == test) - p++; - /* - * vi historically deletes with cw only the word preserving the - * trailing whitespace! This is not what 'w' does.. - */ - if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) - while ((p < high) && iswspace(*p)) - p++; - } - - /* p now points where we want it */ - if (p > high) - return high; - else - return p; -} - - -/* cv_prev_word(): - * Find the previous word vi style - */ -libedit_private wchar_t * -cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) -{ - int test; - - p--; - while (n--) { - while ((p > low) && iswspace(*p)) - p--; - test = (*wtest)(*p); - while ((p >= low) && (*wtest)(*p) == test) - p--; - } - p++; - - /* p now points where we want it */ - if (p < low) - return low; - else - return p; -} - - -/* cv_delfini(): - * Finish vi delete action - */ -libedit_private void -cv_delfini(EditLine *el) -{ - int size; - int action = el->el_chared.c_vcmd.action; - - if (action & INSERT) - el->el_map.current = el->el_map.key; - - if (el->el_chared.c_vcmd.pos == 0) - /* sanity */ - return; - - size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); - if (size == 0) - size = 1; - el->el_line.cursor = el->el_chared.c_vcmd.pos; - if (action & YANK) { - if (size > 0) - cv_yank(el, el->el_line.cursor, size); - else - cv_yank(el, el->el_line.cursor + size, -size); - } else { - if (size > 0) { - c_delafter(el, size); - re_refresh_cursor(el); - } else { - c_delbefore(el, -size); - el->el_line.cursor += size; - } - } - el->el_chared.c_vcmd.action = NOP; -} - - -/* cv__endword(): - * Go to the end of this word according to vi - */ -libedit_private wchar_t * -cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t)) -{ - int test; - - p++; - - while (n--) { - while ((p < high) && iswspace(*p)) - p++; - - test = (*wtest)(*p); - while ((p < high) && (*wtest)(*p) == test) - p++; - } - p--; - return p; -} - -/* ch_init(): - * Initialize the character editor - */ -libedit_private int -ch_init(EditLine *el) -{ - el->el_line.buffer = el_malloc(EL_BUFSIZ * - sizeof(*el->el_line.buffer)); - if (el->el_line.buffer == NULL) - return -1; - - (void) memset(el->el_line.buffer, 0, EL_BUFSIZ * - sizeof(*el->el_line.buffer)); - el->el_line.cursor = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; - - el->el_chared.c_undo.buf = el_malloc(EL_BUFSIZ * - sizeof(*el->el_chared.c_undo.buf)); - if (el->el_chared.c_undo.buf == NULL) - return -1; - (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ * - sizeof(*el->el_chared.c_undo.buf)); - el->el_chared.c_undo.len = -1; - el->el_chared.c_undo.cursor = 0; - el->el_chared.c_redo.buf = el_malloc(EL_BUFSIZ * - sizeof(*el->el_chared.c_redo.buf)); - if (el->el_chared.c_redo.buf == NULL) - return -1; - el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; - el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; - el->el_chared.c_redo.cmd = ED_UNASSIGNED; - - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = el->el_line.buffer; - - el->el_chared.c_kill.buf = el_malloc(EL_BUFSIZ * - sizeof(*el->el_chared.c_kill.buf)); - if (el->el_chared.c_kill.buf == NULL) - return -1; - (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ * - sizeof(*el->el_chared.c_kill.buf)); - el->el_chared.c_kill.mark = el->el_line.buffer; - el->el_chared.c_kill.last = el->el_chared.c_kill.buf; - el->el_chared.c_resizefun = NULL; - el->el_chared.c_resizearg = NULL; - el->el_chared.c_aliasfun = NULL; - el->el_chared.c_aliasarg = NULL; - - el->el_map.current = el->el_map.key; - - el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ - el->el_state.doingarg = 0; - el->el_state.metanext = 0; - el->el_state.argument = 1; - el->el_state.lastcmd = ED_UNASSIGNED; - - return 0; -} - -/* ch_reset(): - * Reset the character editor - */ -libedit_private void -ch_reset(EditLine *el) -{ - el->el_line.cursor = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer; - - el->el_chared.c_undo.len = -1; - el->el_chared.c_undo.cursor = 0; - - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = el->el_line.buffer; - - el->el_chared.c_kill.mark = el->el_line.buffer; - - el->el_map.current = el->el_map.key; - - el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ - el->el_state.doingarg = 0; - el->el_state.metanext = 0; - el->el_state.argument = 1; - el->el_state.lastcmd = ED_UNASSIGNED; - - el->el_history.eventno = 0; -} - -/* ch_enlargebufs(): - * Enlarge line buffer to be able to hold twice as much characters. - * Returns 1 if successful, 0 if not. - */ -libedit_private int -ch_enlargebufs(EditLine *el, size_t addlen) -{ - size_t sz, newsz; - wchar_t *newbuffer, *oldbuf, *oldkbuf; - - sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); - newsz = sz * 2; - /* - * If newly required length is longer than current buffer, we need - * to make the buffer big enough to hold both old and new stuff. - */ - if (addlen > sz) { - while(newsz - sz < addlen) - newsz *= 2; - } - - /* - * Reallocate line buffer. - */ - newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); - if (!newbuffer) - return 0; - - /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); - - oldbuf = el->el_line.buffer; - - el->el_line.buffer = newbuffer; - el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); - el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); - /* don't set new size until all buffers are enlarged */ - el->el_line.limit = &newbuffer[sz - EL_LEAVE]; - - /* - * Reallocate kill buffer. - */ - newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * - sizeof(*newbuffer)); - if (!newbuffer) - return 0; - - /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); - - oldkbuf = el->el_chared.c_kill.buf; - - el->el_chared.c_kill.buf = newbuffer; - el->el_chared.c_kill.last = newbuffer + - (el->el_chared.c_kill.last - oldkbuf); - el->el_chared.c_kill.mark = el->el_line.buffer + - (el->el_chared.c_kill.mark - oldbuf); - - /* - * Reallocate undo buffer. - */ - newbuffer = el_realloc(el->el_chared.c_undo.buf, - newsz * sizeof(*newbuffer)); - if (!newbuffer) - return 0; - - /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); - el->el_chared.c_undo.buf = newbuffer; - - newbuffer = el_realloc(el->el_chared.c_redo.buf, - newsz * sizeof(*newbuffer)); - if (!newbuffer) - return 0; - el->el_chared.c_redo.pos = newbuffer + - (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); - el->el_chared.c_redo.lim = newbuffer + - (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); - el->el_chared.c_redo.buf = newbuffer; - - if (!hist_enlargebuf(el, sz, newsz)) - return 0; - - /* Safe to set enlarged buffer size */ - el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; - if (el->el_chared.c_resizefun) - (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); - return 1; -} - -/* ch_end(): - * Free the data structures used by the editor - */ -libedit_private void -ch_end(EditLine *el) -{ - el_free(el->el_line.buffer); - el->el_line.buffer = NULL; - el->el_line.limit = NULL; - el_free(el->el_chared.c_undo.buf); - el->el_chared.c_undo.buf = NULL; - el_free(el->el_chared.c_redo.buf); - el->el_chared.c_redo.buf = NULL; - el->el_chared.c_redo.pos = NULL; - el->el_chared.c_redo.lim = NULL; - el->el_chared.c_redo.cmd = ED_UNASSIGNED; - el_free(el->el_chared.c_kill.buf); - el->el_chared.c_kill.buf = NULL; - ch_reset(el); -} - - -/* el_insertstr(): - * Insert string at cursorI - */ -int -el_winsertstr(EditLine *el, const wchar_t *s) -{ - size_t len; - - if (s == NULL || (len = wcslen(s)) == 0) - return -1; - if (el->el_line.lastchar + len >= el->el_line.limit) { - if (!ch_enlargebufs(el, len)) - return -1; - } - - c_insert(el, (int)len); - while (*s) - *el->el_line.cursor++ = *s++; - return 0; -} - - -/* el_deletestr(): - * Delete num characters before the cursor - */ -void -el_deletestr(EditLine *el, int n) -{ - if (n <= 0) - return; - - if (el->el_line.cursor < &el->el_line.buffer[n]) - return; - - c_delbefore(el, n); /* delete before dot */ - el->el_line.cursor -= n; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; -} - -/* el_cursor(): - * Move the cursor to the left or the right of the current position - */ -int -el_cursor(EditLine *el, int n) -{ - if (n == 0) - goto out; - - el->el_line.cursor += n; - - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; -out: - return (int)(el->el_line.cursor - el->el_line.buffer); -} - -/* c_gets(): - * Get a string - */ -libedit_private int -c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt) -{ - ssize_t len; - wchar_t *cp = el->el_line.buffer, ch; - - if (prompt) { - len = (ssize_t)wcslen(prompt); - (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); - cp += len; - } - len = 0; - - for (;;) { - el->el_line.cursor = cp; - *cp = ' '; - el->el_line.lastchar = cp + 1; - re_refresh(el); - - if (el_wgetc(el, &ch) != 1) { - ed_end_of_file(el, 0); - len = -1; - break; - } - - switch (ch) { - - case L'\b': /* Delete and backspace */ - case 0177: - if (len == 0) { - len = -1; - break; - } - len--; - cp--; - continue; - - case 0033: /* ESC */ - case L'\r': /* Newline */ - case L'\n': - buf[len] = ch; - break; - - default: - if (len >= (ssize_t)(EL_BUFSIZ - 16)) - terminal_beep(el); - else { - buf[len++] = ch; - *cp++ = ch; - } - continue; - } - break; - } - - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - return (int)len; -} - - -/* c_hpos(): - * Return the current horizontal position of the cursor - */ -libedit_private int -c_hpos(EditLine *el) -{ - wchar_t *ptr; - - /* - * Find how many characters till the beginning of this line. - */ - if (el->el_line.cursor == el->el_line.buffer) - return 0; - else { - for (ptr = el->el_line.cursor - 1; - ptr >= el->el_line.buffer && *ptr != '\n'; - ptr--) - continue; - return (int)(el->el_line.cursor - ptr - 1); - } -} - -libedit_private int -ch_resizefun(EditLine *el, el_zfunc_t f, void *a) -{ - el->el_chared.c_resizefun = f; - el->el_chared.c_resizearg = a; - return 0; -} - -libedit_private int -ch_aliasfun(EditLine *el, el_afunc_t f, void *a) -{ - el->el_chared.c_aliasfun = f; - el->el_chared.c_aliasarg = a; - return 0; -} diff --git a/bin/catsh/libedit/chared.h b/bin/catsh/libedit/chared.h deleted file mode 100644 index 39f7d517..00000000 --- a/bin/catsh/libedit/chared.h +++ /dev/null @@ -1,155 +0,0 @@ -/* $NetBSD: chared.h,v 1.30 2016/05/22 19:44:26 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)chared.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.chared.h: Character editor interface - */ -#ifndef _h_el_chared -#define _h_el_chared - -/* - * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works - * like real vi: i.e. the transition from command<->insert modes moves - * the cursor. - * - * On the other hand we really don't want to move the cursor, because - * all the editing commands don't include the character under the cursor. - * Probably the best fix is to make all the editing commands aware of - * this fact. - */ -#define VI_MOVE - -/* - * Undo information for vi - no undo in emacs (yet) - */ -typedef struct c_undo_t { - ssize_t len; /* length of saved line */ - int cursor; /* position of saved cursor */ - wchar_t *buf; /* full saved text */ -} c_undo_t; - -/* redo for vi */ -typedef struct c_redo_t { - wchar_t *buf; /* redo insert key sequence */ - wchar_t *pos; - wchar_t *lim; - el_action_t cmd; /* command to redo */ - wchar_t ch; /* char that invoked it */ - int count; - int action; /* from cv_action() */ -} c_redo_t; - -/* - * Current action information for vi - */ -typedef struct c_vcmd_t { - int action; - wchar_t *pos; -} c_vcmd_t; - -/* - * Kill buffer for emacs - */ -typedef struct c_kill_t { - wchar_t *buf; - wchar_t *last; - wchar_t *mark; -} c_kill_t; - -typedef void (*el_zfunc_t)(EditLine *, void *); -typedef const char *(*el_afunc_t)(void *, const char *); - -/* - * Note that we use both data structures because the user can bind - * commands from both editors! - */ -typedef struct el_chared_t { - c_undo_t c_undo; - c_kill_t c_kill; - c_redo_t c_redo; - c_vcmd_t c_vcmd; - el_zfunc_t c_resizefun; - el_afunc_t c_aliasfun; - void * c_resizearg; - void * c_aliasarg; -} el_chared_t; - - -#define STRQQ "\"\"" - -#define isglob(a) (strchr("*[]?", (a)) != NULL) - -#define NOP 0x00 -#define DELETE 0x01 -#define INSERT 0x02 -#define YANK 0x04 - -#define CHAR_FWD (+1) -#define CHAR_BACK (-1) - -#define MODE_INSERT 0 -#define MODE_REPLACE 1 -#define MODE_REPLACE_1 2 - - -libedit_private int cv__isword(wint_t); -libedit_private int cv__isWord(wint_t); -libedit_private void cv_delfini(EditLine *); -libedit_private wchar_t *cv__endword(wchar_t *, wchar_t *, int, int (*)(wint_t)); -libedit_private int ce__isword(wint_t); -libedit_private void cv_undo(EditLine *); -libedit_private void cv_yank(EditLine *, const wchar_t *, int); -libedit_private wchar_t *cv_next_word(EditLine*, wchar_t *, wchar_t *, int, - int (*)(wint_t)); -libedit_private wchar_t *cv_prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); -libedit_private wchar_t *c__next_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); -libedit_private wchar_t *c__prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t)); -libedit_private void c_insert(EditLine *, int); -libedit_private void c_delbefore(EditLine *, int); -libedit_private void c_delbefore1(EditLine *); -libedit_private void c_delafter(EditLine *, int); -libedit_private void c_delafter1(EditLine *); -libedit_private int c_gets(EditLine *, wchar_t *, const wchar_t *); -libedit_private int c_hpos(EditLine *); - -libedit_private int ch_init(EditLine *); -libedit_private void ch_reset(EditLine *); -libedit_private int ch_resizefun(EditLine *, el_zfunc_t, void *); -libedit_private int ch_aliasfun(EditLine *, el_afunc_t, void *); -libedit_private int ch_enlargebufs(EditLine *, size_t); -libedit_private void ch_end(EditLine *); - -#endif /* _h_el_chared */ diff --git a/bin/catsh/libedit/chartype.c b/bin/catsh/libedit/chartype.c deleted file mode 100644 index 9288e6b7..00000000 --- a/bin/catsh/libedit/chartype.c +++ /dev/null @@ -1,341 +0,0 @@ -/* $NetBSD: chartype.c,v 1.31 2017/01/09 02:54:18 christos Exp $ */ - -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * chartype.c: character classification and meta information - */ -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: chartype.c,v 1.31 2017/01/09 02:54:18 christos Exp $"); -#endif /* not lint && not SCCSID */ - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include "el.h" - -#define CT_BUFSIZ ((size_t)1024) - -static int ct_conv_cbuff_resize(ct_buffer_t *, size_t); -static int ct_conv_wbuff_resize(ct_buffer_t *, size_t); - -static int -ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize) -{ - void *p; - - if (csize <= conv->csize) - return 0; - - conv->csize = csize; - - p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff)); - if (p == NULL) { - conv->csize = 0; - el_free(conv->cbuff); - conv->cbuff = NULL; - return -1; - } - conv->cbuff = p; - return 0; -} - -static int -ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize) -{ - void *p; - - if (wsize <= conv->wsize) - return 0; - - conv->wsize = wsize; - - p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff)); - if (p == NULL) { - conv->wsize = 0; - el_free(conv->wbuff); - conv->wbuff = NULL; - return -1; - } - conv->wbuff = p; - return 0; -} - - -char * -ct_encode_string(const wchar_t *s, ct_buffer_t *conv) -{ - char *dst; - ssize_t used; - - if (!s) - return NULL; - - dst = conv->cbuff; - for (;;) { - used = (ssize_t)(dst - conv->cbuff); - if ((conv->csize - (size_t)used) < 5) { - if (ct_conv_cbuff_resize(conv, - conv->csize + CT_BUFSIZ) == -1) - return NULL; - dst = conv->cbuff + used; - } - if (!*s) - break; - used = ct_encode_char(dst, (size_t)5, *s); - if (used == -1) /* failed to encode, need more buffer space */ - abort(); - ++s; - dst += used; - } - *dst = '\0'; - return conv->cbuff; -} - -wchar_t * -ct_decode_string(const char *s, ct_buffer_t *conv) -{ - size_t len; - - if (!s) - return NULL; - - len = mbstowcs(NULL, s, (size_t)0); - if (len == (size_t)-1) - return NULL; - - if (conv->wsize < ++len) - if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1) - return NULL; - - mbstowcs(conv->wbuff, s, conv->wsize); - return conv->wbuff; -} - - -libedit_private wchar_t ** -ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv) -{ - size_t bufspace; - int i; - wchar_t *p; - wchar_t **wargv; - ssize_t bytes; - - /* Make sure we have enough space in the conversion buffer to store all - * the argv strings. */ - for (i = 0, bufspace = 0; i < argc; ++i) - bufspace += argv[i] ? strlen(argv[i]) + 1 : 0; - if (conv->wsize < ++bufspace) - if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1) - return NULL; - - wargv = el_malloc((size_t)(argc + 1) * sizeof(*wargv)); - - for (i = 0, p = conv->wbuff; i < argc; ++i) { - if (!argv[i]) { /* don't pass null pointers to mbstowcs */ - wargv[i] = NULL; - continue; - } else { - wargv[i] = p; - bytes = (ssize_t)mbstowcs(p, argv[i], bufspace); - } - if (bytes == -1) { - el_free(wargv); - return NULL; - } else - bytes++; /* include '\0' in the count */ - bufspace -= (size_t)bytes; - p += bytes; - } - wargv[i] = NULL; - - return wargv; -} - - -libedit_private size_t -ct_enc_width(wchar_t c) -{ - /* UTF-8 encoding specific values */ - if (c < 0x80) - return 1; - else if (c < 0x0800) - return 2; - else if (c < 0x10000) - return 3; - else if (c < 0x110000) - return 4; - else - return 0; /* not a valid codepoint */ -} - -libedit_private ssize_t -ct_encode_char(char *dst, size_t len, wchar_t c) -{ - ssize_t l = 0; - if (len < ct_enc_width(c)) - return -1; - l = wctomb(dst, c); - - if (l < 0) { - wctomb(NULL, L'\0'); - l = 0; - } - return l; -} - -libedit_private const wchar_t * -ct_visual_string(const wchar_t *s, ct_buffer_t *conv) -{ - wchar_t *dst; - ssize_t used; - - if (!s) - return NULL; - - if (ct_conv_wbuff_resize(conv, CT_BUFSIZ) == -1) - return NULL; - - used = 0; - dst = conv->wbuff; - while (*s) { - used = ct_visual_char(dst, - conv->wsize - (size_t)(dst - conv->wbuff), *s); - if (used != -1) { - ++s; - dst += used; - continue; - } - - /* failed to encode, need more buffer space */ - used = dst - conv->wbuff; - if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1) - return NULL; - dst = conv->wbuff + used; - } - - if (dst >= (conv->wbuff + conv->wsize)) { /* sigh */ - used = dst - conv->wbuff; - if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1) - return NULL; - dst = conv->wbuff + used; - } - - *dst = L'\0'; - return conv->wbuff; -} - - - -libedit_private int -ct_visual_width(wchar_t c) -{ - int t = ct_chr_class(c); - switch (t) { - case CHTYPE_ASCIICTL: - return 2; /* ^@ ^? etc. */ - case CHTYPE_TAB: - return 1; /* Hmm, this really need to be handled outside! */ - case CHTYPE_NL: - return 0; /* Should this be 1 instead? */ - case CHTYPE_PRINT: - return wcwidth(c); - case CHTYPE_NONPRINT: - if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ - return 8; /* \U+12345 */ - else - return 7; /* \U+1234 */ - default: - return 0; /* should not happen */ - } -} - - -libedit_private ssize_t -ct_visual_char(wchar_t *dst, size_t len, wchar_t c) -{ - int t = ct_chr_class(c); - switch (t) { - case CHTYPE_TAB: - case CHTYPE_NL: - case CHTYPE_ASCIICTL: - if (len < 2) - return -1; /* insufficient space */ - *dst++ = '^'; - if (c == '\177') - *dst = '?'; /* DEL -> ^? */ - else - *dst = c | 0100; /* uncontrolify it */ - return 2; - case CHTYPE_PRINT: - if (len < 1) - return -1; /* insufficient space */ - *dst = c; - return 1; - case CHTYPE_NONPRINT: - /* we only use single-width glyphs for display, - * so this is right */ - if ((ssize_t)len < ct_visual_width(c)) - return -1; /* insufficient space */ - *dst++ = '\\'; - *dst++ = 'U'; - *dst++ = '+'; -#define tohexdigit(v) "0123456789ABCDEF"[v] - if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ - *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf); - *dst = tohexdigit(((unsigned int) c ) & 0xf); - return c > 0xffff ? 8 : 7; - /*FALLTHROUGH*/ - /* these two should be handled outside this function */ - default: /* we should never hit the default */ - return 0; - } -} - - - - -libedit_private int -ct_chr_class(wchar_t c) -{ - if (c == '\t') - return CHTYPE_TAB; - else if (c == '\n') - return CHTYPE_NL; - else if (c < 0x100 && iswcntrl(c)) - return CHTYPE_ASCIICTL; - else if (iswprint(c)) - return CHTYPE_PRINT; - else - return CHTYPE_NONPRINT; -} diff --git a/bin/catsh/libedit/chartype.h b/bin/catsh/libedit/chartype.h deleted file mode 100644 index 4cdd981d..00000000 --- a/bin/catsh/libedit/chartype.h +++ /dev/null @@ -1,119 +0,0 @@ -/* $NetBSD: chartype.h,v 1.35 2017/05/22 19:16:25 christos Exp $ */ - -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _h_chartype_f -#define _h_chartype_f - -/* Ideally we should also test the value of the define to see if it - * supports non-BMP code points without requiring UTF-16, but nothing - * seems to actually advertise this properly, despite Unicode 3.1 having - * been around since 2001... */ -#if !defined(__NetBSD__) && \ - !defined(__sun) && \ - !(defined(__APPLE__) && defined(__MACH__)) && \ - !defined(__OpenBSD__) && \ - !defined(__FreeBSD__) && \ - !defined(__DragonFly__) -#ifndef __STDC_ISO_10646__ -/* In many places it is assumed that the first 127 code points are ASCII - * compatible, so ensure wchar_t indeed does ISO 10646 and not some other - * funky encoding that could break us in weird and wonderful ways. */ - #error wchar_t must store ISO 10646 characters -#endif -#endif - -/* Oh for a <uchar.h> with char32_t and __STDC_UTF_32__ in it... - * ref: ISO/IEC DTR 19769 - */ -#if WCHAR_MAX < INT32_MAX -#warning Build environment does not support non-BMP characters -#endif - -/* - * Conversion buffer - */ -typedef struct ct_buffer_t { - char *cbuff; - size_t csize; - wchar_t *wbuff; - size_t wsize; -} ct_buffer_t; - -/* Encode a wide-character string and return the UTF-8 encoded result. */ -char *ct_encode_string(const wchar_t *, ct_buffer_t *); - -/* Decode a (multi)?byte string and return the wide-character string result. */ -wchar_t *ct_decode_string(const char *, ct_buffer_t *); - -/* Decode a (multi)?byte argv string array. - * The pointer returned must be free()d when done. */ -libedit_private wchar_t **ct_decode_argv(int, const char *[], ct_buffer_t *); - -/* Encode a character into the destination buffer, provided there is sufficient - * buffer space available. Returns the number of bytes used up (zero if the - * character cannot be encoded, -1 if there was not enough space available). */ -libedit_private ssize_t ct_encode_char(char *, size_t, wchar_t); -libedit_private size_t ct_enc_width(wchar_t); - -/* The maximum buffer size to hold the most unwieldy visual representation, - * in this case \U+nnnnn. */ -#define VISUAL_WIDTH_MAX ((size_t)8) - -/* The terminal is thought of in terms of X columns by Y lines. In the cases - * where a wide character takes up more than one column, the adjacent - * occupied column entries will contain this faux character. */ -#define MB_FILL_CHAR ((wchar_t)-1) - -/* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn - * style visual expansions. */ -libedit_private int ct_visual_width(wchar_t); - -/* Turn the given character into the appropriate visual format, matching - * the width given by ct_visual_width(). Returns the number of characters used - * up, or -1 if insufficient space. Buffer length is in count of wchar_t's. */ -libedit_private ssize_t ct_visual_char(wchar_t *, size_t, wchar_t); - -/* Convert the given string into visual format, using the ct_visual_char() - * function. Uses a static buffer, so not threadsafe. */ -libedit_private const wchar_t *ct_visual_string(const wchar_t *, ct_buffer_t *); - - -/* printable character, use ct_visual_width() to find out display width */ -#define CHTYPE_PRINT ( 0) -/* control character found inside the ASCII portion of the charset */ -#define CHTYPE_ASCIICTL (-1) -/* a \t */ -#define CHTYPE_TAB (-2) -/* a \n */ -#define CHTYPE_NL (-3) -/* non-printable character */ -#define CHTYPE_NONPRINT (-4) -/* classification of character c, as one of the above defines */ -libedit_private int ct_chr_class(wchar_t c); - -#endif /* _chartype_f */ diff --git a/bin/catsh/libedit/common.c b/bin/catsh/libedit/common.c deleted file mode 100644 index 27086051..00000000 --- a/bin/catsh/libedit/common.c +++ /dev/null @@ -1,835 +0,0 @@ -/* $NetBSD: common.c,v 1.47 2016/05/22 19:44:26 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: common.c,v 1.47 2016/05/22 19:44:26 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * common.c: Common Editor functions - */ -#include <ctype.h> -#include <string.h> - -#include "el.h" -#include "common.h" -#include "fcns.h" -#include "parse.h" -#include "vi.h" - -/* ed_end_of_file(): - * Indicate end of file - * [^D] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - re_goto_bottom(el); - *el->el_line.lastchar = '\0'; - return CC_EOF; -} - - -/* ed_insert(): - * Add character to the line - * Insert a character [bound to all insert keys] - */ -libedit_private el_action_t -ed_insert(EditLine *el, wint_t c) -{ - int count = el->el_state.argument; - - if (c == '\0') - return CC_ERROR; - - if (el->el_line.lastchar + el->el_state.argument >= - el->el_line.limit) { - /* end of buffer space, try to allocate more */ - if (!ch_enlargebufs(el, (size_t) count)) - return CC_ERROR; /* error allocating more */ - } - - if (count == 1) { - if (el->el_state.inputmode == MODE_INSERT - || el->el_line.cursor >= el->el_line.lastchar) - c_insert(el, 1); - - *el->el_line.cursor++ = c; - re_fastaddc(el); /* fast refresh for one char. */ - } else { - if (el->el_state.inputmode != MODE_REPLACE_1) - c_insert(el, el->el_state.argument); - - while (count-- && el->el_line.cursor < el->el_line.lastchar) - *el->el_line.cursor++ = c; - re_refresh(el); - } - - if (el->el_state.inputmode == MODE_REPLACE_1) - return vi_command_mode(el, 0); - - return CC_NORM; -} - - -/* ed_delete_prev_word(): - * Delete from beginning of current word to cursor - * [M-^?] [^W] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *p, *kp; - - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - - cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, - el->el_state.argument, ce__isword); - - for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) - *kp++ = *p; - el->el_chared.c_kill.last = kp; - - c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ - el->el_line.cursor = cp; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; /* bounds check */ - return CC_REFRESH; -} - - -/* ed_delete_next_char(): - * Delete character under cursor - * [^D] [x] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ -#ifdef DEBUG_EDIT -#define EL el->el_line - (void) fprintf(el->el_errfile, - "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n", - EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, - EL.lastchar, EL.limit, EL.limit); -#endif - if (el->el_line.cursor == el->el_line.lastchar) { - /* if I'm at the end */ - if (el->el_map.type == MAP_VI) { - if (el->el_line.cursor == el->el_line.buffer) { - /* if I'm also at the beginning */ -#ifdef KSHVI - return CC_ERROR; -#else - /* then do an EOF */ - terminal_writec(el, c); - return CC_EOF; -#endif - } else { -#ifdef KSHVI - el->el_line.cursor--; -#else - return CC_ERROR; -#endif - } - } else - return CC_ERROR; - } - c_delafter(el, el->el_state.argument); /* delete after dot */ - if (el->el_map.type == MAP_VI && - el->el_line.cursor >= el->el_line.lastchar && - el->el_line.cursor > el->el_line.buffer) - /* bounds check */ - el->el_line.cursor = el->el_line.lastchar - 1; - return CC_REFRESH; -} - - -/* ed_kill_line(): - * Cut to the end of line - * [^K] [^K] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.lastchar) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - /* zap! -- delete to end */ - el->el_line.lastchar = el->el_line.cursor; - return CC_REFRESH; -} - - -/* ed_move_to_end(): - * Move cursor to the end of line - * [^E] [^E] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_line.cursor = el->el_line.lastchar; - if (el->el_map.type == MAP_VI) { - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } -#ifdef VI_MOVE - el->el_line.cursor--; -#endif - } - return CC_CURSOR; -} - - -/* ed_move_to_beg(): - * Move cursor to the beginning of line - * [^A] [^A] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_line.cursor = el->el_line.buffer; - - if (el->el_map.type == MAP_VI) { - /* We want FIRST non space character */ - while (iswspace(*el->el_line.cursor)) - el->el_line.cursor++; - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - } - return CC_CURSOR; -} - - -/* ed_transpose_chars(): - * Exchange the character to the left of the cursor with the one under it - * [^T] [^T] - */ -libedit_private el_action_t -ed_transpose_chars(EditLine *el, wint_t c) -{ - - if (el->el_line.cursor < el->el_line.lastchar) { - if (el->el_line.lastchar <= &el->el_line.buffer[1]) - return CC_ERROR; - else - el->el_line.cursor++; - } - if (el->el_line.cursor > &el->el_line.buffer[1]) { - /* must have at least two chars entered */ - c = el->el_line.cursor[-2]; - el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = c; - return CC_REFRESH; - } else - return CC_ERROR; -} - - -/* ed_next_char(): - * Move to the right one character - * [^F] [^F] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *lim = el->el_line.lastchar; - - if (el->el_line.cursor >= lim || - (el->el_line.cursor == lim - 1 && - el->el_map.type == MAP_VI && - el->el_chared.c_vcmd.action == NOP)) - return CC_ERROR; - - el->el_line.cursor += el->el_state.argument; - if (el->el_line.cursor > lim) - el->el_line.cursor = lim; - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* ed_prev_word(): - * Move to the beginning of the current word - * [M-b] [b] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - - el->el_line.cursor = c__prev_word(el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - ce__isword); - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* ed_prev_char(): - * Move to the left one character - * [^B] [^B] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor > el->el_line.buffer) { - el->el_line.cursor -= el->el_state.argument; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; - } else - return CC_ERROR; -} - - -/* ed_quoted_insert(): - * Add the next character typed verbatim - * [^V] [^V] - */ -libedit_private el_action_t -ed_quoted_insert(EditLine *el, wint_t c) -{ - int num; - - tty_quotemode(el); - num = el_wgetc(el, &c); - tty_noquotemode(el); - if (num == 1) - return ed_insert(el, c); - else - return ed_end_of_file(el, 0); -} - - -/* ed_digit(): - * Adds to argument or enters a digit - */ -libedit_private el_action_t -ed_digit(EditLine *el, wint_t c) -{ - - if (!iswdigit(c)) - return CC_ERROR; - - if (el->el_state.doingarg) { - /* if doing an arg, add this in... */ - if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) - el->el_state.argument = c - '0'; - else { - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); - } - return CC_ARGHACK; - } - - return ed_insert(el, c); -} - - -/* ed_argument_digit(): - * Digit that starts argument - * For ESC-n - */ -libedit_private el_action_t -ed_argument_digit(EditLine *el, wint_t c) -{ - - if (!iswdigit(c)) - return CC_ERROR; - - if (el->el_state.doingarg) { - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.argument = (el->el_state.argument * 10) + - (c - '0'); - } else { /* else starting an argument */ - el->el_state.argument = c - '0'; - el->el_state.doingarg = 1; - } - return CC_ARGHACK; -} - - -/* ed_unassigned(): - * Indicates unbound character - * Bound to keys that are not assigned - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_unassigned(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_ERROR; -} - - -/* ed_ignore(): - * Input characters that have no effect - * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_ignore(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_newline(): - * Execute command - * [^J] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - re_goto_bottom(el); - *el->el_line.lastchar++ = '\n'; - *el->el_line.lastchar = '\0'; - return CC_NEWLINE; -} - - -/* ed_delete_prev_char(): - * Delete the character to the left of the cursor - * [^?] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor <= el->el_line.buffer) - return CC_ERROR; - - c_delbefore(el, el->el_state.argument); - el->el_line.cursor -= el->el_state.argument; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; - return CC_REFRESH; -} - - -/* ed_clear_screen(): - * Clear screen leaving current line at the top - * [^L] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - terminal_clear_screen(el); /* clear the whole real screen */ - re_clear_display(el); /* reset everything */ - return CC_REFRESH; -} - - -/* ed_redisplay(): - * Redisplay everything - * ^R - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_redisplay(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_REDISPLAY; -} - - -/* ed_start_over(): - * Erase current line and start from scratch - * [^G] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - ch_reset(el); - return CC_REFRESH; -} - - -/* ed_sequence_lead_in(): - * First character in a bound sequence - * Placeholder for external keys - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), - wint_t c __attribute__((__unused__))) -{ - - return CC_NORM; -} - - -/* ed_prev_history(): - * Move to the previous history line - * [^P] [k] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) -{ - char beep = 0; - int sv_event = el->el_history.eventno; - - el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ - - if (el->el_history.eventno == 0) { /* save the current buffer - * away */ - (void) wcsncpy(el->el_history.buf, el->el_line.buffer, - EL_BUFSIZ); - el->el_history.last = el->el_history.buf + - (el->el_line.lastchar - el->el_line.buffer); - } - el->el_history.eventno += el->el_state.argument; - - if (hist_get(el) == CC_ERROR) { - if (el->el_map.type == MAP_VI) { - el->el_history.eventno = sv_event; - } - beep = 1; - /* el->el_history.eventno was fixed by first call */ - (void) hist_get(el); - } - if (beep) - return CC_REFRESH_BEEP; - return CC_REFRESH; -} - - -/* ed_next_history(): - * Move to the next history line - * [^N] [j] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) -{ - el_action_t beep = CC_REFRESH, rval; - - el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ - - el->el_history.eventno -= el->el_state.argument; - - if (el->el_history.eventno < 0) { - el->el_history.eventno = 0; - beep = CC_REFRESH_BEEP; - } - rval = hist_get(el); - if (rval == CC_REFRESH) - return beep; - return rval; - -} - - -/* ed_search_prev_history(): - * Search previous in history for a line matching the current - * next search history [M-P] [K] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) -{ - const wchar_t *hp; - int h; - int found = 0; - - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ - if (el->el_history.eventno < 0) { -#ifdef DEBUG_EDIT - (void) fprintf(el->el_errfile, - "e_prev_search_hist(): eventno < 0;\n"); -#endif - el->el_history.eventno = 0; - return CC_ERROR; - } - if (el->el_history.eventno == 0) { - (void) wcsncpy(el->el_history.buf, el->el_line.buffer, - EL_BUFSIZ); - el->el_history.last = el->el_history.buf + - (el->el_line.lastchar - el->el_line.buffer); - } - if (el->el_history.ref == NULL) - return CC_ERROR; - - hp = HIST_FIRST(el); - if (hp == NULL) - return CC_ERROR; - - c_setpat(el); /* Set search pattern !! */ - - for (h = 1; h <= el->el_history.eventno; h++) - hp = HIST_NEXT(el); - - while (hp != NULL) { -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); -#endif - if ((wcsncmp(hp, el->el_line.buffer, (size_t) - (el->el_line.lastchar - el->el_line.buffer)) || - hp[el->el_line.lastchar - el->el_line.buffer]) && - c_hmatch(el, hp)) { - found = 1; - break; - } - h++; - hp = HIST_NEXT(el); - } - - if (!found) { -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "not found\n"); -#endif - return CC_ERROR; - } - el->el_history.eventno = h; - - return hist_get(el); -} - - -/* ed_search_next_history(): - * Search next in history for a line matching the current - * [M-N] [J] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) -{ - const wchar_t *hp; - int h; - int found = 0; - - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ - - if (el->el_history.eventno == 0) - return CC_ERROR; - - if (el->el_history.ref == NULL) - return CC_ERROR; - - hp = HIST_FIRST(el); - if (hp == NULL) - return CC_ERROR; - - c_setpat(el); /* Set search pattern !! */ - - for (h = 1; h < el->el_history.eventno && hp; h++) { -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); -#endif - if ((wcsncmp(hp, el->el_line.buffer, (size_t) - (el->el_line.lastchar - el->el_line.buffer)) || - hp[el->el_line.lastchar - el->el_line.buffer]) && - c_hmatch(el, hp)) - found = h; - hp = HIST_NEXT(el); - } - - if (!found) { /* is it the current history number? */ - if (!c_hmatch(el, el->el_history.buf)) { -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "not found\n"); -#endif - return CC_ERROR; - } - } - el->el_history.eventno = found; - - return hist_get(el); -} - - -/* ed_prev_line(): - * Move up one line - * Could be [k] [^p] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *ptr; - int nchars = c_hpos(el); - - /* - * Move to the line requested - */ - if (*(ptr = el->el_line.cursor) == '\n') - ptr--; - - for (; ptr >= el->el_line.buffer; ptr--) - if (*ptr == '\n' && --el->el_state.argument <= 0) - break; - - if (el->el_state.argument > 0) - return CC_ERROR; - - /* - * Move to the beginning of the line - */ - for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) - continue; - - /* - * Move to the character requested - */ - for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; - ptr++) - continue; - - el->el_line.cursor = ptr; - return CC_CURSOR; -} - - -/* ed_next_line(): - * Move down one line - * Could be [j] [^n] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *ptr; - int nchars = c_hpos(el); - - /* - * Move to the line requested - */ - for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) - if (*ptr == '\n' && --el->el_state.argument <= 0) - break; - - if (el->el_state.argument > 0) - return CC_ERROR; - - /* - * Move to the character requested - */ - for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; - ptr++) - continue; - - el->el_line.cursor = ptr; - return CC_CURSOR; -} - - -/* ed_command(): - * Editline extended command - * [M-X] [:] - */ -libedit_private el_action_t -/*ARGSUSED*/ -ed_command(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t tmpbuf[EL_BUFSIZ]; - int tmplen; - - tmplen = c_gets(el, tmpbuf, L"\n: "); - terminal__putc(el, '\n'); - - if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) - terminal_beep(el); - - el->el_map.current = el->el_map.key; - re_clear_display(el); - return CC_REFRESH; -} diff --git a/bin/catsh/libedit/config.h b/bin/catsh/libedit/config.h deleted file mode 100644 index 3eb35d17..00000000 --- a/bin/catsh/libedit/config.h +++ /dev/null @@ -1,286 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if the `closedir' function returns void instead of `int'. */ -/* #undef CLOSEDIR_VOID */ - -/* Define to 1 if you have the <curses.h> header file. */ -#define HAVE_CURSES_H 1 - -/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. - */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `endpwent' function. */ -#define HAVE_ENDPWENT 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `getline' function. */ -#define HAVE_GETLINE 1 - -/* Define to 1 if you have the `fork' function. */ -#define HAVE_FORK 1 - -/* Define to 1 if you have getpwnam_r and getpwuid_r that are draft POSIX.1 - versions. */ -/* #undef HAVE_GETPW_R_DRAFT */ - -/* Define to 1 if you have getpwnam_r and getpwuid_r that are POSIX.1 - compatible. */ -#define HAVE_GETPW_R_POSIX 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `isascii' function. */ -#define HAVE_ISASCII 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `curses' library (-lcurses). */ -/* #undef HAVE_LIBCURSES */ - -/* Define to 1 if you have the `ncurses' library (-lncurses). */ -/* #undef HAVE_LIBNCURSES */ - -/* Define to 1 if you have the `termcap' library (-ltermcap). */ -/* #undef HAVE_LIBTERMCAP */ - -/* Define to 1 if you have the `terminfo' library (-lterminfo). */ -#define HAVE_LIBTERMINFO 1 - -/* Define to 1 if you have the `termlib' library (-ltermlib). */ -/* #undef HAVE_LIBTERMLIB */ - -/* Define to 1 if you have the <limits.h> header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the <malloc.h> header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the `memchr' function. */ -#define HAVE_MEMCHR 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -#define HAVE_MEMSET 1 - -/* Define to 1 if you have the <ncurses.h> header file. */ -/* #undef HAVE_NCURSES_H */ - -/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the `regcomp' function. */ -#define HAVE_REGCOMP 1 - -/* Define to 1 if you have the `re_comp' function. */ -/* #undef HAVE_RE_COMP */ - -/* Define to 1 if `stat' has the bug that it succeeds when given the - zero-length file name argument. */ -/* #undef HAVE_STAT_EMPTY_STRING_BUG */ - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasecmp' function. */ -#define HAVE_STRCASECMP 1 - -/* Define to 1 if you have the `strchr' function. */ -#define HAVE_STRCHR 1 - -/* Define to 1 if you have the `strcspn' function. */ -#define HAVE_STRCSPN 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcat' function. */ -#define HAVE_STRLCAT 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strrchr' function. */ -#define HAVE_STRRCHR 1 - -/* Define to 1 if you have the `strstr' function. */ -#define HAVE_STRSTR 1 - -/* Define to 1 if you have the `strtol' function. */ -#define HAVE_STRTOL 1 - -/* Define to 1 if struct dirent has member d_namlen */ -#define HAVE_STRUCT_DIRENT_D_NAMLEN 1 - -/* Define to 1 if you have the `strunvis' function. */ -#define HAVE_STRUNVIS 1 - -/* Define to 1 if you have the `strvis' function. */ -#define HAVE_STRVIS 1 - -/* Define to 1 if you have the <sys/cdefs.h> header file. */ -#define HAVE_SYS_CDEFS_H 1 - -/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the <termcap.h> header file. */ -#define HAVE_TERMCAP_H 1 - -/* Define to 1 if you have the <term.h> header file. */ -#define HAVE_TERM_H 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if the system has the type `u_int32_t'. */ -#define HAVE_U_INT32_T 1 - -/* Define to 1 if you have the `vfork' function. */ -#define HAVE_VFORK 1 - -/* Define to 1 if you have the <vfork.h> header file. */ -/* #undef HAVE_VFORK_H */ - -/* Define to 1 if you have the `vis' function. */ -#define HAVE_VIS 1 - -/* Define to 1 if `fork' works. */ -#define HAVE_WORKING_FORK 1 - -/* Define to 1 if `vfork' works. */ -#define HAVE_WORKING_VFORK 1 - -/* Define to 1 if `lstat' dereferences a symlink specified with a trailing - slash. */ -#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Name of package */ -#define PACKAGE "libedit-20110729" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libedit" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libedit 3.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libedit-20110729" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "3.0" - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# define _ALL_SOURCE 1 -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# define _TANDEM_SOURCE 1 -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 -#endif - - -/* Version number of package */ -#define VERSION "3.0" - -/* Define to 1 if the system provides the SIZE_MAX constant */ -#define HAVE_SIZE_MAX 1 - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define as `fork' if `vfork' does not work. */ -/* #undef vfork */ - - -#include "sys.h" -/* #undef SCCSID */ -/* #undef LIBC_SCCS */ -/* #undef lint */ - diff --git a/bin/catsh/libedit/editline.3 b/bin/catsh/libedit/editline.3 deleted file mode 100644 index a27e24ce..00000000 --- a/bin/catsh/libedit/editline.3 +++ /dev/null @@ -1,1013 +0,0 @@ -.\" $NetBSD: editline.3,v 1.93.4.1 2017/07/23 14:41:26 snj Exp $ -.\" -.\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd June 27, 2017 -.Dt EDITLINE 3 -.Os -.Sh NAME -.Nm editline , -.Nm el_init , -.Nm el_init_fd , -.Nm el_end , -.Nm el_reset , -.Nm el_gets , -.Nm el_wgets , -.Nm el_getc , -.Nm el_wgetc , -.Nm el_push , -.Nm el_wpush , -.Nm el_parse , -.Nm el_wparse , -.Nm el_set , -.Nm el_wset , -.Nm el_get , -.Nm el_wget , -.Nm el_source , -.Nm el_resize , -.Nm el_cursor , -.Nm el_line , -.Nm el_wline , -.Nm el_insertstr , -.Nm el_winsertstr , -.Nm el_deletestr , -.Nm el_wdeletestr , -.Nm history_init , -.Nm history_winit , -.Nm history_end , -.Nm history_wend , -.Nm history , -.Nm history_w , -.Nm tok_init , -.Nm tok_winit , -.Nm tok_end , -.Nm tok_wend , -.Nm tok_reset , -.Nm tok_wreset , -.Nm tok_line , -.Nm tok_wline , -.Nm tok_str , -.Nm tok_wstr -.Nd line editor, history and tokenization functions -.Sh LIBRARY -.Lb libedit -.Sh SYNOPSIS -.In histedit.h -.Ft EditLine * -.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" -.Ft EditLine * -.Fn el_init_fd "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" "int fdin" "int fdout" "int fderr" -.Ft void -.Fn el_end "EditLine *e" -.Ft void -.Fn el_reset "EditLine *e" -.Ft const char * -.Fn el_gets "EditLine *e" "int *count" -.Ft const wchar_t * -.Fn el_wgets "EditLine *e" "int *count" -.Ft int -.Fn el_getc "EditLine *e" "char *ch" -.Ft int -.Fn el_wgetc "EditLine *e" "wchar_t *wc" -.Ft void -.Fn el_push "EditLine *e" "const char *mbs" -.Ft void -.Fn el_wpush "EditLine *e" "const wchar_t *wcs" -.Ft int -.Fn el_parse "EditLine *e" "int argc" "const char *argv[]" -.Ft int -.Fn el_wparse "EditLine *e" "int argc" "const wchar_t *argv[]" -.Ft int -.Fn el_set "EditLine *e" "int op" "..." -.Ft int -.Fn el_wset "EditLine *e" "int op" "..." -.Ft int -.Fn el_get "EditLine *e" "int op" "..." -.Ft int -.Fn el_wget "EditLine *e" "int op" "..." -.Ft int -.Fn el_source "EditLine *e" "const char *file" -.Ft void -.Fn el_resize "EditLine *e" -.Ft int -.Fn el_cursor "EditLine *e" "int count" -.Ft const LineInfo * -.Fn el_line "EditLine *e" -.Ft const LineInfoW * -.Fn el_wline "EditLine *e" -.Ft int -.Fn el_insertstr "EditLine *e" "const char *str" -.Ft int -.Fn el_winsertstr "EditLine *e" "const wchar_t *str" -.Ft void -.Fn el_deletestr "EditLine *e" "int count" -.Ft void -.Fn el_wdeletestr "EditLine *e" "int count" -.Ft History * -.Fn history_init void -.Ft HistoryW * -.Fn history_winit void -.Ft void -.Fn history_end "History *h" -.Ft void -.Fn history_wend "HistoryW *h" -.Ft int -.Fn history "History *h" "HistEvent *ev" "int op" "..." -.Ft int -.Fn history_w "HistoryW *h" "HistEventW *ev" "int op" "..." -.Ft Tokenizer * -.Fn tok_init "const char *IFS" -.Ft TokenizerW * -.Fn tok_winit "const wchar_t *IFS" -.Ft void -.Fn tok_end "Tokenizer *t" -.Ft void -.Fn tok_wend "TokenizerW *t" -.Ft void -.Fn tok_reset "Tokenizer *t" -.Ft void -.Fn tok_wreset "TokenizerW *t" -.Ft int -.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro" -.Ft int -.Fn tok_wline "TokenizerW *t" "const LineInfoW *li" "int *argc" "const wchar_t **argv[]" "int *cursorc" "int *cursoro" -.Ft int -.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]" -.Ft int -.Fn tok_wstr "TokenizerW *t" "const wchar_t *str" "int *argc" "const wchar_t **argv[]" -.Sh DESCRIPTION -The -.Nm -library provides generic line editing, history and tokenization functions, -similar to those found in -.Xr sh 1 . -.Pp -These functions are available in the -.Nm libedit -library (which needs the -.Nm libtermcap -library). -Programs should be linked with -.Fl ledit ltermcap . -.Pp -The -.Nm -library respects the -.Ev LC_CTYPE -locale set by the application program and never uses -.Xr setlocale 3 -to change the locale. -The only locales supported are UTF-8 and the default C or POSIX locale. -If any other locale is set, behaviour is undefined. -.Sh LINE EDITING FUNCTIONS -The line editing functions use a common data structure, -.Fa EditLine , -which is created by -.Fn el_init -or -.Fn el_init_fd -and freed by -.Fn el_end . -.Pp -The wide-character functions behave the same way as their narrow -counterparts. -.Pp -The following functions are available: -.Bl -tag -width 4n -.It Fn el_init -Initialize the line editor, and return a data structure -to be used by all other line editing functions, or -.Dv NULL -on failure. -.Fa prog -is the name of the invoking program, used when reading the -.Xr editrc 5 -file to determine which settings to use. -.Fa fin , -.Fa fout -and -.Fa ferr -are the input, output, and error streams (respectively) to use. -In this documentation, references to -.Dq the tty -are actually to this input/output stream combination. -.It Fn el_init_fd -Like -.Fn el_init -but allows specifying file descriptors for the -.Xr stdio 3 -corresponding streams, in case those were created with -.Xr funopen 3 . -.It Fn el_end -Clean up and finish with -.Fa e , -assumed to have been created with -.Fn el_init -or -.Fn el_init_fd . -.It Fn el_reset -Reset the tty and the parser. -This should be called after an error which may have upset the tty's -state. -.It Fn el_gets -Read a line from the tty. -.Fa count -is modified to contain the number of characters read. -Returns the line read if successful, or -.Dv NULL -if no characters were read or if an error occurred. -If an error occurred, -.Fa count -is set to \-1 and -.Dv errno -contains the error code that caused it. -The return value may not remain valid across calls to -.Fn el_gets -and must be copied if the data is to be retained. -.It Fn el_wgetc -Read a wide character from the tty, respecting the current locale, -or from the input queue described in -.Xr editline 7 -if that is not empty, and store it in -.Fa wc . -If an invalid or incomplete character is found, it is discarded, -.Va errno -is set to -.Er EILSEQ , -and the next character is read and stored in -.Fa wc . -Returns 1 if a valid character was read, 0 on end of file, or \-1 on -.Xr read 2 -failure. -In the latter case, -.Va errno -is set to indicate the error. -.It Fn el_getc -Read a wide character as described for -.Fn el_wgetc -and return 0 on end of file or \-1 on failure. -If the wide character can be represented as a single-byte character, -convert it with -.Xr wctob 3 , -store the result in -.Fa ch , -and return 1; otherwise, set -.Va errno -to -.Er ERANGE -and return \-1. -In the C or POSIX locale, this simply reads a byte, but for any other -locale, including UTF-8, this is rarely useful. -.It Fn el_wpush -Push the wide character string -.Fa wcs -back onto the input queue described in -.Xr editline 7 . -If the queue overflows, for example due to a recursive macro, -or if an error occurs, for example because -.Fa wcs -is -.Dv NULL -or memory allocation fails, the function beeps at the user, -but does not report the problem to the caller. -.It Fn el_push -Use the current locale to convert the multibyte string -.Fa mbs -to a wide character string, and pass the result to -.Fn el_wpush . -.It Fn el_parse -Parses the -.Fa argv -array (which is -.Fa argc -elements in size) -to execute builtin -.Nm -commands. -If the command is prefixed with -.Dq prog : -then -.Fn el_parse -will only execute the command if -.Dq prog -matches the -.Fa prog -argument supplied to -.Fn el_init . -The return value is -\-1 if the command is unknown, -0 if there was no error or -.Dq prog -didn't match, or -1 if the command returned an error. -Refer to -.Xr editrc 5 -for more information. -.It Fn el_set -Set -.Nm -parameters. -.Fa op -determines which parameter to set, and each operation has its -own parameter list. -Returns 0 on success, \-1 on failure. -.Pp -The following values for -.Fa op -are supported, along with the required argument list: -.Bl -tag -width 4n -.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" -Define prompt printing function as -.Fa f , -which is to return a string that contains the prompt. -.It Dv EL_PROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c" -Same as -.Dv EL_PROMPT , -but the -.Fa c -argument indicates the start/stop literal prompt character. -.Pp -If a start/stop literal character is found in the prompt, the -character itself -is not printed, but characters after it are printed directly to the -terminal without affecting the state of the current line. -A subsequent second start/stop literal character ends this behavior. -This is typically used to embed literal escape sequences that change the -color/style of the terminal in the prompt. -Note that the literal escape character cannot be the last character in the -prompt, as the escape sequence is attached to the next character in the prompt. -.Dv 0 -unsets it. -.It Dv EL_REFRESH -Re-display the current line on the next terminal line. -.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" -Define right side prompt printing function as -.Fa f , -which is to return a string that contains the prompt. -.It Dv EL_RPROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c" -Define the right prompt printing function but with a literal escape character. -.It Dv EL_TERMINAL , Fa "const char *type" -Define terminal type of the tty to be -.Fa type , -or to -.Ev TERM -if -.Fa type -is -.Dv NULL . -.It Dv EL_EDITOR , Fa "const char *mode" -Set editing mode to -.Fa mode , -which must be one of -.Dq emacs -or -.Dq vi . -.It Dv EL_SIGNAL , Fa "int flag" -If -.Fa flag -is non-zero, -.Nm -will install its own signal handler for the following signals when -reading command input: -.Dv SIGCONT , -.Dv SIGHUP , -.Dv SIGINT , -.Dv SIGQUIT , -.Dv SIGSTOP , -.Dv SIGTERM , -.Dv SIGTSTP , -and -.Dv SIGWINCH . -Otherwise, the current signal handlers will be used. -.It Dv EL_BIND , Fa "const char *" , Fa "..." , Dv NULL -Perform the -.Ic bind -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_ECHOTC , Fa "const char *" , Fa "..." , Dv NULL -Perform the -.Ic echotc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_SETTC , Fa "const char *" , Fa "..." , Dv NULL -Perform the -.Ic settc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_SETTY , Fa "const char *" , Fa "..." , Dv NULL -Perform the -.Ic setty -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_TELLTC , Fa "const char *" , Fa "..." , Dv NULL -Perform the -.Ic telltc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_ADDFN , Fa "const char *name" , Fa "const char *help" , \ -Fa "unsigned char (*func)(EditLine *e, int ch)" -Add a user defined function, -.Fn func , -referred to as -.Fa name -which is invoked when a key which is bound to -.Fa name -is entered. -.Fa help -is a description of -.Fa name . -At invocation time, -.Fa ch -is the key which caused the invocation. -The return value of -.Fn func -should be one of: -.Bl -tag -width "CC_REDISPLAY" -.It Dv CC_NORM -Add a normal character. -.It Dv CC_NEWLINE -End of line was entered. -.It Dv CC_EOF -EOF was entered. -.It Dv CC_ARGHACK -Expecting further command input as arguments, do nothing visually. -.It Dv CC_REFRESH -Refresh display. -.It Dv CC_REFRESH_BEEP -Refresh display, and beep. -.It Dv CC_CURSOR -Cursor moved, so update and perform -.Dv CC_REFRESH . -.It Dv CC_REDISPLAY -Redisplay entire input line. -This is useful if a key binding outputs extra information. -.It Dv CC_ERROR -An error occurred. -Beep, and flush tty. -.It Dv CC_FATAL -Fatal error, reset tty to known state. -.El -.It Dv EL_HIST , Fa "History *(*func)(History *, int op, ...)" , \ -Fa "const char *ptr" -Defines which history function to use, which is usually -.Fn history . -.Fa ptr -should be the value returned by -.Fn history_init . -.It Dv EL_EDITMODE , Fa "int flag" -If -.Fa flag -is non-zero, -editing is enabled (the default). -Note that this is only an indication, and does not -affect the operation of -.Nm . -At this time, it is the caller's responsibility to -check this -(using -.Fn el_get ) -to determine if editing should be enabled or not. -.It Dv EL_UNBUFFERED , Fa "int flag" -If -.Fa flag -is zero, -unbuffered mode is disabled (the default). -In unbuffered mode, -.Fn el_gets -will return immediately after processing a single character. -.It Dv EL_GETCFN , Fa "el_rfunc_t f" -Whenever reading a character, use the function -.Bd -ragged -offset indent -compact -.Ft int -.Fo f -.Fa "EditLine *e" -.Fa "wchar_t *wc" -.Fc -.Ed -which stores the character in -.Fa wc -and returns 1 on success, 0 on end of file, or \-1 on I/O or encoding -errors. -Functions internally using it include -.Fn el_wgets , -.Fn el_wgetc , -.Fn el_gets , -and -.Fn el_getc . -Initially, a builtin function is installed, and replacing it -is discouraged because writing such a function is very error prone. -The builtin function can be restored at any time by passing the -special value -.Dv EL_BUILTIN_GETCFN -instead of a function pointer. -.It Dv EL_CLIENTDATA , Fa "void *data" -Register -.Fa data -to be associated with this EditLine structure. -It can be retrieved with the corresponding -.Fn el_get -call. -.It Dv EL_SETFP , Fa "int fd" , Fa "FILE *fp" -Set the current -.Nm editline -file pointer for -.Dq input -.Fa fd -= -.Dv 0 , -.Dq output -.Fa fd -= -.Dv 1 , -or -.Dq error -.Fa fd -= -.Dv 2 -from -.Fa fp . -.El -.It Fn el_get -Get -.Nm -parameters. -.Fa op -determines which parameter to retrieve into -.Fa result . -Returns 0 if successful, \-1 otherwise. -.Pp -The following values for -.Fa op -are supported, along with actual type of -.Fa result : -.Bl -tag -width 4n -.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Set -.Fa f -to a pointer to the function that displays the prompt. -If -.Fa c -is not -.Dv NULL , -set it to the start/stop literal prompt character. -.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Set -.Fa f -to a pointer to the function that displays the prompt. -If -.Fa c -is not -.Dv NULL , -set it to the start/stop literal prompt character. -.It Dv EL_EDITOR , Fa "const char **n" -Set the name of the editor in -.Fa n , -which will be one of -.Dq emacs -or -.Dq vi . -.It Dv EL_GETTC , Fa "const char *name" , Fa "void *value" -If -.Fa name -is a valid -.Xr termcap 5 -capability set -.Fa value -to the current value of that capability. -.It Dv EL_SIGNAL , Fa "int *s" -Set -.Fa s -to non-zero if -.Nm -has installed private signal handlers (see -.Fn el_get -above). -.It Dv EL_EDITMODE , Fa "int *c" -Set -.Fa c -to non-zero if editing is enabled. -.It Dv EL_GETCFN , Fa "el_rfunc_t *f" -Set -.Fa f -to a pointer to the function that reads characters, or to -.Dv EL_BUILTIN_GETCFN -if the builtin function is in use. -.It Dv EL_CLIENTDATA , Fa "void **data" -Set -.Fa data -to the previously registered client data set by an -.Fn el_set -call. -.It Dv EL_UNBUFFERED , Fa "int *c" -Set -.Fa c -to non-zero if unbuffered mode is enabled. -.It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp" -Set -.Fa fp -to the current -.Nm editline -file pointer for -.Dq input -.Fa fd -= -.Dv 0 , -.Dq output -.Fa fd -= -.Dv 1 , -or -.Dq error -.Fa fd -= -.Dv 2 . -.El -.It Fn el_source -Initialize -.Nm -by reading the contents of -.Fa file . -.Fn el_parse -is called for each line in -.Fa file . -If -.Fa file -is -.Dv NULL , -try -.Pa $EDITRC -and if that is not set -.Pa $HOME/.editrc . -Refer to -.Xr editrc 5 -for details on the format of -.Fa file . -.Fn el_source -returns 0 on success and \-1 on error. -.It Fn el_resize -Must be called if the terminal size changes. -If -.Dv EL_SIGNAL -has been set with -.Fn el_set , -then this is done automatically. -Otherwise, it's the responsibility of the application to call -.Fn el_resize -on the appropriate occasions. -.It Fn el_cursor -Move the cursor to the right (if positive) or to the left (if negative) -.Fa count -characters. -Returns the resulting offset of the cursor from the beginning of the line. -.It Fn el_line -Return the editing information for the current line in a -.Fa LineInfo -structure, which is defined as follows: -.Bd -literal -typedef struct lineinfo { - const char *buffer; /* address of buffer */ - const char *cursor; /* address of cursor */ - const char *lastchar; /* address of last character */ -} LineInfo; -.Ed -.Pp -.Fa buffer -is not NUL terminated. -This function may be called after -.Fn el_gets -to obtain the -.Fa LineInfo -structure pertaining to line returned by that function, -and from within user defined functions added with -.Dv EL_ADDFN . -.It Fn el_insertstr -Insert -.Fa str -into the line at the cursor. -Returns \-1 if -.Fa str -is empty or won't fit, and 0 otherwise. -.It Fn el_deletestr -Delete -.Fa count -characters before the cursor. -.El -.Sh HISTORY LIST FUNCTIONS -The history functions use a common data structure, -.Fa History , -which is created by -.Fn history_init -and freed by -.Fn history_end . -.Pp -The following functions are available: -.Bl -tag -width 4n -.It Fn history_init -Initialize the history list, and return a data structure -to be used by all other history list functions, or -.Dv NULL -on failure. -.It Fn history_end -Clean up and finish with -.Fa h , -assumed to have been created with -.Fn history_init . -.It Fn history -Perform operation -.Fa op -on the history list, with optional arguments as needed by the -operation. -.Fa ev -is changed accordingly to operation. -The following values for -.Fa op -are supported, along with the required argument list: -.Bl -tag -width 4n -.It Dv H_SETSIZE , Fa "int size" -Set size of history to -.Fa size -elements. -.It Dv H_GETSIZE -Get number of events currently in history. -.It Dv H_END -Cleans up and finishes with -.Fa h , -assumed to be created with -.Fn history_init . -.It Dv H_CLEAR -Clear the history. -.It Dv H_FUNC , Fa "void *ptr" , Fa "history_gfun_t first" , \ -Fa "history_gfun_t next" , Fa "history_gfun_t last" , \ -Fa "history_gfun_t prev" , Fa "history_gfun_t curr" , \ -Fa "history_sfun_t set" , Fa "history_vfun_t clear" , \ -Fa "history_efun_t enter" , Fa "history_efun_t add" -Define functions to perform various history operations. -.Fa ptr -is the argument given to a function when it's invoked. -.It Dv H_FIRST -Return the first element in the history. -.It Dv H_LAST -Return the last element in the history. -.It Dv H_PREV -Return the previous element in the history. -It is newer than the current one. -.It Dv H_NEXT -Return the next element in the history. -It is older than the current one. -.It Dv H_CURR -Return the current element in the history. -.It Dv H_SET , Fa "int position" -Set the cursor to point to the requested element. -.It Dv H_ADD , Fa "const char *str" -Append -.Fa str -to the current element of the history, or perform the -.Dv H_ENTER -operation with argument -.Fa str -if there is no current element. -.It Dv H_APPEND , Fa "const char *str" -Append -.Fa str -to the last new element of the history. -.It Dv H_ENTER , Fa "const char *str" -Add -.Fa str -as a new element to the history and, if necessary, -removing the oldest entry to keep the list to the created size. -If -.Dv H_SETUNIQUE -has been called with a non-zero argument, the element -will not be entered into the history if its contents match -the ones of the current history element. -If the element is entered -.Fn history -returns 1; if it is ignored as a duplicate returns 0. -Finally -.Fn history -returns \-1 if an error occurred. -.It Dv H_PREV_STR , Fa "const char *str" -Return the closest previous event that starts with -.Fa str . -.It Dv H_NEXT_STR , Fa "const char *str" -Return the closest next event that starts with -.Fa str . -.It Dv H_PREV_EVENT , Fa "int e" -Return the previous event numbered -.Fa e . -.It Dv H_NEXT_EVENT , Fa "int e" -Return the next event numbered -.Fa e . -.It Dv H_LOAD , Fa "const char *file" -Load the history list stored in -.Fa file . -.It Dv H_SAVE , Fa "const char *file" -Save the history list to -.Fa file . -.It Dv H_SAVE_INCR , Fa "const char *file" , Fa "int e" -Append the history list since the event numbered -.Fa e -to -.Fa file . -.It Dv H_SAVE_FP , Fa "FILE *fp" -Save the history list to the opened -.Ft FILE -pointer -.Fa fp . -.It Dv H_SAVE_FP_INCR , Fa "FILE *fp" , Fa "int e" -Append the history list since the event numbered -.Fa e -to the opened -.Ft FILE -pointer -.Fa fp . -.It Dv H_SETUNIQUE , Fa "int unique" -Set flag that adjacent identical event strings should not be entered -into the history. -.It Dv H_GETUNIQUE -Retrieve the current setting if adjacent identical elements should -be entered into the history. -.It Dv H_DEL , Fa "int e" -Delete the event numbered -.Fa e . -This function is only provided for -.Xr readline 3 -compatibility. -The caller is responsible for free'ing the string in the returned -.Fa HistEvent . -.El -.Pp -.Fn history -returns >= 0 if the operation -.Fa op -succeeds. -Otherwise, \-1 is returned and -.Fa ev -is updated to contain more details about the error. -.El -.Sh TOKENIZATION FUNCTIONS -The tokenization functions use a common data structure, -.Fa Tokenizer , -which is created by -.Fn tok_init -and freed by -.Fn tok_end . -.Pp -The following functions are available: -.Bl -tag -width 4n -.It Fn tok_init -Initialize the tokenizer, and return a data structure -to be used by all other tokenizer functions. -.Fa IFS -contains the Input Field Separators, which defaults to -.Aq space , -.Aq tab , -and -.Aq newline -if -.Dv NULL . -.It Fn tok_end -Clean up and finish with -.Fa t , -assumed to have been created with -.Fn tok_init . -.It Fn tok_reset -Reset the tokenizer state. -Use after a line has been successfully tokenized -by -.Fn tok_line -or -.Fn tok_str -and before a new line is to be tokenized. -.It Fn tok_line -Tokenize -.Fa li , -If successful, modify: -.Fa argv -to contain the words, -.Fa argc -to contain the number of words, -.Fa cursorc -(if not -.Dv NULL ) -to contain the index of the word containing the cursor, -and -.Fa cursoro -(if not -.Dv NULL ) -to contain the offset within -.Fa argv[cursorc] -of the cursor. -.Pp -Returns -0 if successful, -\-1 for an internal error, -1 for an unmatched single quote, -2 for an unmatched double quote, -and -3 for a backslash quoted -.Aq newline . -A positive exit code indicates that another line should be read -and tokenization attempted again. -. -.It Fn tok_str -A simpler form of -.Fn tok_line ; -.Fa str -is a NUL terminated string to tokenize. -.El -. -.\"XXX.Sh EXAMPLES -.\"XXX: provide some examples -.Sh SEE ALSO -.Xr sh 1 , -.Xr signal 3 , -.Xr termcap 3 , -.Xr editrc 5 , -.Xr termcap 5 , -.Xr editline 7 -.Sh HISTORY -The -.Nm -library first appeared in -.Bx 4.4 . -.Dv CC_REDISPLAY -appeared in -.Nx 1.3 . -.Dv CC_REFRESH_BEEP , -.Dv EL_EDITMODE -and the readline emulation appeared in -.Nx 1.4 . -.Dv EL_RPROMPT -appeared in -.Nx 1.5 . -.Sh AUTHORS -.An -nosplit -The -.Nm -library was written by -.An Christos Zoulas . -.An Luke Mewburn -wrote this manual and implemented -.Dv CC_REDISPLAY , -.Dv CC_REFRESH_BEEP , -.Dv EL_EDITMODE , -and -.Dv EL_RPROMPT . -.An Jaromir Dolecek -implemented the readline emulation. -.An Johny Mattsson -implemented wide-character support. -.Sh BUGS -At this time, it is the responsibility of the caller to -check the result of the -.Dv EL_EDITMODE -operation of -.Fn el_get -(after an -.Fn el_source -or -.Fn el_parse ) -to determine if -.Nm -should be used for further input. -I.e., -.Dv EL_EDITMODE -is purely an indication of the result of the most recent -.Xr editrc 5 -.Ic edit -command. diff --git a/bin/catsh/libedit/editline.7 b/bin/catsh/libedit/editline.7 deleted file mode 100644 index 863bab96..00000000 --- a/bin/catsh/libedit/editline.7 +++ /dev/null @@ -1,935 +0,0 @@ -.\" $NetBSD: editline.7,v 1.5 2016/05/09 21:27:55 christos Exp $ -.\" $OpenBSD: editline.7,v 1.1 2016/04/20 01:11:45 schwarze Exp $ -.\" -.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd May 7, 2016 -.Dt EDITLINE 7 -.Os -.Sh NAME -.Nm editline -.Nd line editing user interface -.Sh DESCRIPTION -When a program using the -.Xr editline 3 -library prompts for an input string using the function -.Xr el_wgets 3 , -it reads characters from the terminal. -Invalid input bytes that do not form characters are silently -discarded. -For each character read, one editor command is executed. -The mapping of input characters to editor commands depends on the -editing mode. -There are three editing modes: vi insert mode, vi command mode, -and emacs mode. -The default is vi insert mode. -The program can switch the default to emacs mode by using the -.Xr el_set 3 -or -.Xr el_parse 3 -functions, and the user can switch to emacs mode either in the -.Xr editrc 5 -configuration file or interactively with the -.Ic ed-command -editor command, in all three cases executing the -.Ic bind Fl e -builtin command. -.Pp -If trying to read from the terminal results in end of file or an -error, the library signals end of file to the program and does not -return a string. -.Ss Input character bindings -All default bindings described below can be overridden by individual -programs and can be changed with the -.Xr editrc 5 -.Ic bind -builtin command. -.Pp -In the following tables, -.Sq Ctrl- -indicates a character with the bit 0x40 flipped, and -.Sq Meta- -indicates a character with the bit 0x80 set. -In vi insert mode and in emacs mode, all Meta-characters considered -printable by the current -.Xr locale 1 -are bound to -.Ic ed-insert -instead of to the editor command listed below. -Consequently, in UTF-8 mode, most of the Meta-characters are not -directly accessible because their code points are occupied by -printable Unicode characters, and Meta-characters are usually input -using the -.Ic em-meta-next -editor command. -For example, to enter -.Sq Meta-B -in order to call the -.Ic ed-prev-word -editor command in emacs mode, call -.Ic em-meta-next -by pressing and releasing the escape key (or equivalently, Ctrl-[), -then press and release the -.Sq B -key. -If you have configured a Meta-key on your keyboard, for example -with -.Ql setxkbmap -option altwin:left_meta_win , -the Ctrl-Meta-characters are directly accessible. -For example, to enter -.Sq Ctrl-Meta-H -in order to call the -.Ic ed-delete-prev-word -editor command in emacs mode, hold down the keys -.Sq Ctrl , -.Sq Meta , -and -.Sq H -at the same time. -Alternatively, press and release the escape key, then press and -release -.Sq Ctrl-H . -.Pp -In vi input mode, input characters are bound to the following editor -commands by default: -.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" -.It Ctrl-D, EOF Ta Ic vi-list-or-eof -.It Ctrl-H, BS Ta Ic vi-delete-prev-char -.It Ctrl-J, LF Ta Ic ed-newline -.It Ctrl-M, CR Ta Ic ed-newline -.It Ctrl-Q Ta Ic ed-tty-start-output -.It Ctrl-S Ta Ic ed-tty-stop-output -.It Ctrl-U Ta Ic vi-kill-line-prev -.It Ctrl-V Ta Ic ed-quoted-insert -.It Ctrl-W Ta Ic ed-delete-prev-word -.It Ctrl-[, ESC Ta Ic vi-command-mode -.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit -.It Ctrl-?, DEL Ta Ic vi-delete-prev-char -.El -.Pp -All other input characters except the NUL character (Ctrl-@) are -bound to -.Ic ed-insert . -.Pp -In vi command mode, input characters are bound to the following -editor commands by default: -.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" -.It Ctrl-A Ta Ic ed-move-to-beg -.It Ctrl-C, INT Ta Ic ed-tty-sigint -.It Ctrl-E Ta Ic ed-move-to-end -.It Ctrl-H, BS Ta Ic ed-delete-prev-char -.It Ctrl-J, LF Ta Ic ed-newline -.It Ctrl-K Ta Ic ed-kill-line -.It Ctrl-L, FF Ta Ic ed-clear-screen -.It Ctrl-M, CR Ta Ic ed-newline -.It Ctrl-N Ta Ic ed-next-history -.It Ctrl-O Ta Ic ed-tty-flush-output -.It Ctrl-P Ta Ic ed-prev-history -.It Ctrl-Q Ta Ic ed-tty-start-output -.It Ctrl-R Ta Ic ed-redisplay -.It Ctrl-S Ta Ic ed-tty-stop-output -.It Ctrl-U Ta Ic vi-kill-line-prev -.It Ctrl-W Ta Ic ed-delete-prev-word -.It Ctrl-[, ESC Ta Ic em-meta-next -.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit -.It Space Ta Ic ed-next-char -.It # Ta Ic vi-comment-out -.It $ Ta Ic ed-move-to-end -.It % Ta Ic vi-match -.It + Ta Ic ed-next-history -.It \&, Ta Ic vi-repeat-prev-char -.It - Ta Ic ed-prev-history -.It \&. Ta Ic vi-redo -.It / Ta Ic vi-search-prev -.It 0 Ta Ic vi-zero -.It 1 to 9 Ta Ic ed-argument-digit -.It \&: Ta Ic ed-command -.It \&; Ta Ic vi-repeat-next-char -.It \&? Ta Ic vi-search-next -.It @ Ta Ic vi-alias -.It A Ta Ic vi-add-at-eol -.It B Ta Ic vi-prev-big-word -.It C Ta Ic vi-change-to-eol -.It D Ta Ic ed-kill-line -.It E Ta Ic vi-end-big-word -.It F Ta Ic vi-prev-char -.It G Ta Ic vi-to-history-line -.It I Ta Ic vi-insert-at-bol -.It J Ta Ic ed-search-next-history -.It K Ta Ic ed-search-prev-history -.It N Ta Ic vi-repeat-search-prev -.It O Ta Ic ed-sequence-lead-in -.It P Ta Ic vi-paste-prev -.It R Ta Ic vi-replace-mode -.It S Ta Ic vi-substitute-line -.It T Ta Ic vi-to-prev-char -.It U Ta Ic vi-undo-line -.It W Ta Ic vi-next-big-word -.It X Ta Ic ed-delete-prev-char -.It Y Ta Ic vi-yank-end -.It \&[ Ta Ic ed-sequence-lead-in -.It ^ Ta Ic ed-move-to-beg -.It _ Ta Ic vi-history-word -.It a Ta Ic vi-add -.It b Ta Ic vi-prev-word -.It c Ta Ic vi-change-meta -.It d Ta Ic vi-delete-meta -.It e Ta Ic vi-end-word -.It f Ta Ic vi-next-char -.It h Ta Ic ed-prev-char -.It i Ta Ic vi-insert -.It j Ta Ic ed-next-history -.It k Ta Ic ed-prev-history -.It l Ta Ic ed-next-char -.It n Ta Ic vi-repeat-search-next -.It p Ta Ic vi-paste-next -.It r Ta Ic vi-replace-char -.It s Ta Ic vi-substitute-char -.It t Ta Ic vi-to-next-char -.It u Ta Ic vi-undo -.It v Ta Ic vi-histedit -.It w Ta Ic vi-next-word -.It x Ta Ic ed-delete-next-char -.It y Ta Ic vi-yank -.It \&| Ta Ic vi-to-column -.It ~ Ta Ic vi-change-case -.It Ctrl-?, DEL Ta Ic ed-delete-prev-char -.It Meta-O Ta Ic ed-sequence-lead-in -.It Meta-[ Ta Ic ed-sequence-lead-in -.El -.Pp -In emacs mode, input characters are bound to the following editor -commands by default: -.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history" -.It 0 to 9 Ta Ic ed-digit -.It Ctrl-@, NUL Ta Ic em-set-mark -.It Ctrl-A Ta Ic ed-move-to-beg -.It Ctrl-B Ta Ic ed-prev-char -.It Ctrl-C, INT Ta Ic ed-tty-sigint -.It Ctrl-D, EOF Ta Ic em-delete-or-list -.It Ctrl-E Ta Ic ed-move-to-end -.It Ctrl-F Ta Ic ed-next-char -.It Ctrl-H, BS Ta Ic em-delete-prev-char -.It Ctrl-J, LF Ta Ic ed-newline -.It Ctrl-K Ta Ic ed-kill-line -.It Ctrl-L, FF Ta Ic ed-clear-screen -.It Ctrl-M, CR Ta Ic ed-newline -.It Ctrl-N Ta Ic ed-next-history -.It Ctrl-O Ta Ic ed-tty-flush-output -.It Ctrl-P Ta Ic ed-prev-history -.It Ctrl-Q Ta Ic ed-tty-start-output -.It Ctrl-R Ta Ic ed-redisplay -.It Ctrl-S Ta Ic ed-tty-stop-output -.It Ctrl-T Ta Ic ed-transpose-chars -.It Ctrl-U Ta Ic ed-kill-line -.It Ctrl-V Ta Ic ed-quoted-insert -.It Ctrl-W Ta Ic em-kill-region -.It Ctrl-X Ta Ic ed-sequence-lead-in -.It Ctrl-Y Ta Ic em-yank -.It Ctrl-Z, TSTP Ta Ic ed-tty-sigtstp -.It Ctrl-[, ESC Ta Ic em-meta-next -.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit -.It Ctrl-] Ta Ic ed-tty-dsusp -.It Ctrl-?, DEL Ta Ic em-delete-prev-char -.It Ctrl-Meta-H Ta Ic ed-delete-prev-word -.It Ctrl-Meta-L Ta Ic ed-clear-screen -.It Ctrl-Meta-_ Ta Ic em-copy-prev-word -.It Meta-0 to 9 Ta Ic ed-argument-digit -.It Meta-B Ta Ic ed-prev-word -.It Meta-C Ta Ic em-capitol-case -.It Meta-D Ta Ic em-delete-next-word -.It Meta-F Ta Ic em-next-word -.It Meta-L Ta Ic em-lower-case -.It Meta-N Ta Ic ed-search-next-history -.It Meta-O Ta Ic ed-sequence-lead-in -.It Meta-P Ta Ic ed-search-prev-history -.It Meta-U Ta Ic em-upper-case -.It Meta-W Ta Ic em-copy-region -.It Meta-X Ta Ic ed-command -.It Meta-[ Ta Ic ed-sequence-lead-in -.It Meta-b Ta Ic ed-prev-word -.It Meta-c Ta Ic em-capitol-case -.It Meta-d Ta Ic em-delete-next-word -.It Meta-f Ta Ic em-next-word -.It Meta-l Ta Ic em-lower-case -.It Meta-n Ta Ic ed-search-next-history -.It Meta-p Ta Ic ed-search-prev-history -.It Meta-u Ta Ic em-upper-case -.It Meta-w Ta Ic em-copy-region -.It Meta-x Ta Ic ed-command -.It Ctrl-Meta-? Ta Ic ed-delete-prev-word -.El -.Pp -The remaining -.Xr ascii 7 -characters in the range 0x20 to 0x7e are bound to -.Ic ed-insert . -.Pp -If standard output is not connected to a terminal device -or -.Xr el_set 3 -was used to set -.Dv EL_EDITMODE -to 0, all input character bindings are disabled and all characters -typed are appended to the edit buffer. -In that case, the edit buffer is returned to the program after a -newline or carriage return character is typed, or after the first -character typed if -.Xr el_set 3 -was used to set -.Dv EL_UNBUFFERED -to non-zero. -.Ss Editor commands -Most editor commands accept an optional argument. -The argument is entered by prefixing the editor command with one -or more of the editor commands -.Ic ed-argument-digit , -.Ic ed-digit , -.Ic em-universal-argument , -or -.Ic vi-zero . -When an argument is not provided, it defaults to 1. -For most editor commands, the effect of an argument is to repeatedly -execute the command that number of times. -.Pp -When talking about a character string from a left character to a -right character, the left character is included in the string, while -the right character is not included. -.Pp -If an editor command causes an error, the input character is discarded, -no action occurs, and the terminal bell is rung. -In case of a non-fatal error, the terminal bell is also rung, -but the editor command takes effect anyway. -.Pp -In the following list, the default key bindings are listed after -each editor command. -.Bl -tag -width 4n -.It Ic ed-argument-digit Pq vi command: 1 to 9; emacs: Meta-0 to Meta-9 -If in argument input mode, append the input digit to the argument -being read. -Otherwise, switch to argument input mode and use the input digit -as the most significant digit of the argument. -It is an error if the input character is not a digit or if the -existing argument is already greater than a million. -.It Ic ed-clear-screen Pq vi command: Ctrl-L; emacs: Ctrl-L, Ctrl-Meta-L -Clear the screen and display the edit buffer at the top. -Ignore any argument. -.It Ic ed-command Pq vi command: So \&: Sc ; emacs: Meta-X, Meta-x -Read a line from the terminal bypassing the normal line editing -functionality and execute that line as an -.Xr editrc 5 -builtin command. -If in vi command mode, also switch back to vi insert mode. -Ignore any argument. -.It Ic ed-delete-next-char Pq vi command: x -Delete the character at the cursor position. -With an argument, delete that number of characters. -In emacs mode, it is an error if the cursor is at the end of the -edit buffer. -In vi mode, the last character in the edit buffer is deleted in -that case, and it is an error if the buffer is empty. -.It Ic ed-delete-prev-char Pq vi command: X, Ctrl-H, BS, Ctrl-?, DEL -Delete the character to the left of the cursor position. -With an argument, delete that number of characters. -It is an error if the cursor is at the beginning of the edit buffer. -.It Ic ed-delete-prev-word Pq vi: Ctrl-W; emacs: Ctrl-Meta-H, Ctrl-Meta-? -Move to the left to the closest beginning of a word, delete the -string from that position to the cursor, and save it to the cut -buffer. -With an argument, delete that number of words. -It is an error if the cursor is at the beginning of the edit buffer. -.It Ic ed-digit Pq emacs: 0 to 9 -If in argument input mode, append the input digit to the argument -being read. -Otherwise, call -.Ic ed-insert . -It is an error if the input character is not a digit or if the -existing argument is already greater than a million. -.It Ic ed-end-of-file Pq not bound by default -Discard the edit buffer and indicate end of file to the program. -Ignore any argument. -.It Ic ed-ignore Pq various -Discard the input character and do nothing. -.It Ic ed-insert Pq vi input: almost all; emacs: printable characters -In insert mode, insert the input character left of the cursor -position. -In replace mode, overwrite the character at the cursor and move the -cursor to the right by one character position. -Accept an argument to do this repeatedly. -It is an error if the input character is the NUL character (Ctrl-@). -Failure to enlarge the edit buffer also results in an error. -.It Ic ed-kill-line Pq vi command: D, Ctrl-K; emacs: Ctrl-K, Ctrl-U -Delete the string from the cursor position to the end of the line -and save it to the cut buffer. -Ignore any argument. -.It Ic ed-move-to-beg Pq vi command: ^, Ctrl-A; emacs: Ctrl-A -In vi mode, move the cursor to the first non-space character in the -edit buffer. -In emacs mode, move the cursor to the beginning of the edit buffer. -Ignore any argument. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.It Ic ed-move-to-end Pq vi command: $, Ctrl-E; emacs: Ctrl-E -Move the cursor to the end of the edit buffer. -Ignore any argument. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.It Ic ed-newline Pq all modes: Ctrl-J, LF, Ctrl-M, CR -Append a newline character to the edit buffer and return the edit -buffer to the program. -Ignore any argument. -.It Ic ed-next-char Pq vi command: Space, l; emacs: Ctrl-F -Move the cursor one character position to the right. -With an argument, move by that number of characters. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer. -.It Ic ed-next-history Pq vi command: j, +, Ctrl-N; emacs: Ctrl-N -Replace the edit buffer with the next history line. -That line is older than the current line. -With an argument, go forward by that number of history lines. -It is a non-fatal error to advance by more lines than are available. -.It Ic ed-next-line Pq not bound by default -Move the cursor down one line. -With an argument, move down by that number of lines. -It is an error if the edit buffer does not contain enough newline -characters to the right of the cursor position. -.It Ic ed-prev-char Pq vi command: h; emacs: Ctrl-B -Move the cursor one character position to the left. -With an argument, move by that number of characters. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the beginning of the -edit buffer. -.It Ic ed-prev-history Pq vi command: k, -, Ctrl-P; emacs: Ctrl-P -Replace the edit buffer with the previous history line. -That line is newer than the current line. -With an argument, go back by that number of lines. -It is a non-fatal error to back up by more lines than are available. -.It Ic ed-prev-line Pq not bound by default -Move the cursor up one line. -With an argument, move up by that number of lines. -It is an error if the edit buffer does not contain enough newline -characters to the left of the cursor position. -.It Ic ed-prev-word Pq emacs: Meta-B, Meta-b -Move the cursor to the left to the closest beginning of a word. -With an argument, repeat that number of times. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the beginning of the -edit buffer. -.It Ic ed-quoted-insert Pq vi insert, emacs: Ctrl-V -Read one character from the terminal bypassing the normal line -editing functionality and call -.Ic ed-insert -on it. -If trying to read the character returns end of file or an error, -call -.Ic ed-end-of-file -instead. -.It Ic ed-redisplay Pq vi command, emacs: Ctrl-R -Redisplay everything. -Ignore any argument. -.It Ic ed-search-next-history Pq vi command: J; emacs: Meta-N, Meta-n -Replace the edit buffer with the next matching history entry. -.It Ic ed-search-prev-history Pq vi command: K; emacs: Meta-P, Meta-p -Replace the edit buffer with the previous matching history entry. -.It Ic ed-sequence-lead-in Pq vi cmd: O, \&[; emacs: Ctrl-X;\ - both: Meta-O, Meta-[ -Call a macro. -See the section about -.Sx Macros -below for details. -.It Ic ed-start-over Pq not bound by default -Discard the contents of the edit buffer and start from scratch. -Ignore any argument. -.It Ic ed-transpose-chars Pq emacs: Ctrl-T -Exchange the character at the cursor position with the one to the -left of it and move the cursor to the character to the right of the -two exchanged characters. -Ignore any argument. -It is an error if the cursor is at the beginning of the edit buffer -or if the edit buffer contains less than two characters. -.It Ic ed-unassigned Pq all characters not listed -This editor command always results in an error. -.It Ic em-capitol-case Pq emacs: Meta-C, Meta-c -Capitalize the string from the cursor to the end of the current -word. -That is, if it contains at least one alphabetic character, convert -the first alphabetic character to upper case, and convert all -characters to the right of it to lower case. -In any case, move the cursor to the next character after the end -of the current word. -.It Ic em-copy-prev-word Pq emacs: Ctrl-Meta-_ -Copy the string from the beginning of the current word to the cursor -and insert it to the left of the cursor. -Move the cursor to the character after the inserted string. -It is an error if the cursor is at the beginning of the edit buffer. -.It Ic em-copy-region Pq emacs: Meta-W, Meta-w -Copy the string from the cursor to the mark to the cut buffer. -It is an error if the mark is not set. -.It Ic em-delete-next-word Pq emacs: Meta-D, Meta-d -Delete the string from the cursor to the end of the current word -and save it to the cut buffer. -It is an error if the cursor is at the end of the edit buffer. -.It Ic em-delete-or-list Pq emacs: Ctrl-D, EOF -If the cursor is not at the end of the line, delete the character -at the cursor. -If the edit buffer is empty, indicate end of file to the program. -It is an error if the cursor is at the end of the edit buffer and -the edit buffer is not empty. -.It Ic em-delete-prev-char Pq emacs: Ctrl-H, BS, Ctrl-?, DEL -Delete the character to the left of the cursor. -It is an error if the cursor is at the beginning of the edit buffer. -.It Ic em-exchange-mark Pq not bound by default -Exchange the cursor and the mark. -.It Ic em-gosmacs-transpose Pq not bound by default -Exchange the two characters to the left of the cursor. -It is an error if the cursor is on the first or second character -of the edit buffer. -.It Ic em-inc-search-next Pq not bound by default -Emacs incremental next search. -.It Ic em-inc-search-prev Pq not bound by default -Emacs incremental reverse search. -.It Ic em-kill-line Pq not bound by default -Delete the entire contents of the edit buffer and save it to the -cut buffer. -.It Ic em-kill-region Pq emacs: Ctrl-W -Delete the string from the cursor to the mark and save it to the -cut buffer. -It is an error if the mark is not set. -.It Ic em-lower-case Pq emacs: Meta-L, Meta-l -Convert the characters from the cursor to the end of the current -word to lower case. -.It Ic em-meta-next Pq vi command, emacs: Ctrl-[, ESC -Set the bit 0x80 on the next character typed. -Unless the resulting code point is printable, holding down the -.Sq Meta- -key while typing that character is a simpler way to achieve the -same effect. -.It Ic em-next-word Pq Meta-F, Meta-f -Move the cursor to the end of the current word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer. -.It Ic em-set-mark Pq emacs: Ctrl-Q, NUL -Set the mark at the current cursor position. -.It Ic em-toggle-overwrite Pq not bound by default -Switch from insert to overwrite mode or vice versa. -.It Ic em-universal-argument Pq not bound by default -If in argument input mode, multiply the argument by 4. -Otherwise, switch to argument input mode and set the argument to 4. -It is an error if the existing argument is already greater than a -million. -.It Ic em-upper-case Pq emacs: Meta-U, Meta-u -Convert the characters from the cursor to the end of the current -word to upper case. -.It Ic em-yank Pq emacs: Ctrl-Y -Paste the cut buffer to the left of the cursor. -.It Ic vi-add Pq vi command: a -Switch to vi insert mode. -Unless the cursor is already at the end of the edit buffer, move -it one character position to the right. -.It Ic vi-add-at-eol Pq vi command: A -Switch to vi insert mode and move the cursor to the end of the edit -buffer. -.It Ic vi-alias Pq vi command: @ -If an alias function was defined by calling the -.Xr el_set 3 -or -.Xr el_wset 3 -function with the argument -.Dv EL_ALIAS_TEXT , -read one character from the terminal bypassing the normal line -editing functionality, call the alias function passing the argument that was specified with -.Dv EL_ALIAS_TEXT -as the first argument and the character read, with an underscore -prepended, as the second argument, and pass the string returned -from the alias function to -.Xr el_wpush 3 . -It is an error if no alias function is defined or if trying to read -the character results in end of file or an error. -.It Ic vi-change-case Pq vi command: ~ -Change the case of the character at the cursor and move the cursor -one character position to the right. -It is an error if the cursor is already at the end of the edit -buffer. -.It Ic vi-change-meta Pq vi command: c -Delete the string from the cursor to the position specified by the -following movement command and save a copy of it to the cut buffer. -When given twice in a row, instead delete the whole contents of the -edit buffer and save a copy of it to the cut buffer. -In either case, switch to vi insert mode after that. -.It Ic vi-change-to-eol Pq vi command: C -Delete the string from the cursor position to the end of the line -and save it to the cut buffer, then switch to vi insert mode. -.It Ic vi-command-mode Pq vi insert: Ctrl-[, ESC -Discard pending actions and arguments and switch to vi command mode. -Unless the cursor is already at the beginning of the edit buffer, -move it to the left by one character position. -.It Ic vi-comment-out Pq vi command: # -Insert a -.Sq # -character at the beginning of the edit buffer and return the edit -buffer to the program. -.It Ic vi-delete-meta Pq vi command: d -Delete the string from the cursor to the position specified by the -following movement command and save a copy of it to the cut buffer. -When given twice in a row, instead delete the whole contents of the -edit buffer and save a copy of it to the cut buffer. -.It Ic vi-delete-prev-char Pq vi insert: Ctrl-H, BS, Ctrl-?, DEL -Delete the character to the left of the cursor. -It is an error if the cursor is already at the beginning of the -edit buffer. -.It Ic vi-end-big-word Pq vi command: E -Move the cursor to the end of the current space delimited word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer. -.It Ic vi-end-word Pq vi command: e -Move the cursor to the end of the current word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer. -.It Ic vi-history-word Pq vi command: _ -Insert the first word from the most recent history entry after the -cursor, move the cursor after to the character after the inserted -word, and switch to vi insert mode. -It is an error if there is no history entry or the most recent -history entry is empty. -.It Ic vi-insert Pq vi command: i -Enter insert mode. -.It Ic vi-insert-at-bol Pq vi command: I -Move the cursor to the beginning of the edit buffer and switch to -vi insert mode. -.It Ic vi-kill-line-prev Pq vi: Ctrl-U -Delete the string from the beginning of the edit buffer to the -cursor and save it to the cut buffer. -.It Ic vi-list-or-eof Pq vi insert: Ctrl-D, EOF -If the edit buffer is empty, indicate end of file to the program. -It is an error if the edit buffer is not empty. -.It Ic vi-match Pq vi command: % -Consider opening and closing parentheses, braces, and brackets as -delimiters. -If the cursor is not at a delimiter, move it to the right until it -gets to one, then move it to the matching delimiter. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if there is no delimiter at the cursor or in the -string to the right of the cursor, or if the first such delimiter -has no matching delimiter. -.It Ic vi-next-big-word Pq vi command: W -Move the cursor to the right to the beginning of the next space -delimited word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer or on its last character. -.It Ic vi-next-char Pq vi command: f -Read one character from the terminal bypassing the normal line -editing functionality and move the cursor to the right to the next -instance of that character in the edit buffer. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -If trying to read the character results in end of file or an error, -call -.Ic ed-end-of-file -instead. -It is an error if the character is not found searching to the right -in the edit buffer. -.It Ic vi-next-word Pq vi command: w -Move the cursor to the right to the beginning of the next word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the end of the edit -buffer or on its last character. -.It Ic vi-paste-next Pq vi command: p -Insert a copy of the cut buffer to the right of the cursor. -It is an error if the cut buffer is empty. -.It Ic vi-paste-prev Pq vi command: P -Insert a copy of the cut buffer to the left of the cursor. -It is an error if the cut buffer is empty. -.It Ic vi-prev-big-word Pq vi command: B -Move the cursor to the left to the next beginning of a space delimited -word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the beginning of the -edit buffer. -.It Ic vi-prev-char Pq vi command: F -Read one character from the terminal bypassing the normal line -editing functionality and move the cursor to the left to the next -instance of that character in the edit buffer. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -If trying to read the character results in end of file or an error, -call -.Ic ed-end-of-file -instead. -It is an error if the character is not found searching to the left -in the edit buffer. -.It Ic vi-prev-word Pq vi command: b -Move the cursor to the left to the next beginning of a word. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -It is an error if the cursor is already at the beginning of the -edit buffer. -.It Ic vi-redo Pq vi command: Sq \&. -Redo the last non-motion command. -.It Ic vi-repeat-next-char Pq vi command: Sq \&; -Repeat the most recent character search in the same search direction. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.It Ic vi-repeat-prev-char Pq vi command: Sq \&, -Repeat the most recent character search in the opposite search -direction. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.It Ic vi-repeat-search-next Pq vi command: n -Repeat the most recent history search in the same search direction. -.It Ic vi-repeat-search-prev Pq vi command: N -Repeat the most recent history search in the opposite search -direction. -.It Ic vi-replace-char Pq vi command: r -Switch to vi replace mode, and automatically switch back to vi -command mode after the next character typed. -See -.Ic ed-insert -for a description of replace mode. -It is an error if the cursor is at the end of the edit buffer. -.It Ic vi-replace-mode Pq vi command: R -Switch to vi replace mode. -This is a variant of vi insert mode; see -.Ic ed-insert -for the difference. -.It Ic vi-search-next Pq vi command: \&? -Replace the edit buffer with the next matching history entry. -.It Ic vi-search-prev Pq vi command: / -Replace the edit buffer with the previous matching history entry. -.It Ic vi-substitute-char Pq vi command: s -Delete the character at the cursor and switch to vi insert mode. -.It Ic vi-substitute-line Pq vi command: S -Delete the entire contents of the edit buffer, save a copy of it -in the cut buffer, and enter vi insert mode. -.It Ic vi-to-column Pq vi command: \&| -Move the cursor to the column specified as the argument. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.It Ic vi-to-history-line Pq vi command: G -Replace the edit buffer with the specified history entry. -.It Ic vi-to-next-char Pq vi command: t -Read one character from the terminal bypassing the normal line -editing functionality and move the cursor to the right to the -character before the next instance of that character in the edit -buffer. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -If trying to read the character results in end of file or an error, -call -.Ic ed-end-of-file -instead. -It is an error if the character is not found searching to the right -in the edit buffer. -.It Ic vi-to-prev-char Pq vi command: T -Read one character from the terminal bypassing the normal line -editing functionality and move the cursor to the left to the character -after the next instance of that character in the edit buffer. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -If trying to read the character results in end of file or an error, -call -.Ic ed-end-of-file -instead. -It is an error if the character is not found searching to the left -in the edit buffer. -.It Ic vi-undo Pq vi command: u -Undo the last change. -.It Ic vi-undo-line Pq vi command: U -Undo all changes to the edit buffer. -.It Ic vi-yank Pq vi command: y -Copy the string from the cursor to the position specified by the -following movement command to the cut buffer. -When given twice in a row, instead copy the whole contents of the -edit buffer to the cut buffer. -.It Ic vi-yank-end Pq vi command: Y -Copy the string from the cursor to the end of the edit buffer to -the cut buffer. -.It Ic vi-zero Pq vi command: 0 -If in argument input mode, multiply the argument by ten. -Otherwise, move the cursor to the beginning of the edit buffer. -Can be used as a movement command after -.Ic vi_change_meta , -.Ic vi_delete_meta , -or -.Ic vi_yank . -.El -.Ss Macros -If an input character is bound to the editor command -.Ic ed-sequence-lead-in , -.Nm -attempts to call a macro. -If the input character by itself forms the name of a macro, that -macro is executed. -Otherwise, additional input characters are read until the string -read forms the name of a macro, in which case that macro is executed, -or until the string read matches the beginning of none of the existing -macro names, in which case the string including the final, mismatching -character is discarded and the terminal bell is rung. -.Pp -There are two kinds of macros. -Command macros execute a single editor command. -Keyboard macros return a string of characters that is appended -as a new line to the -.Sx Input Queue . -.Pp -The following command macros are defined by default in vi command -mode and in emacs mode: -.Bl -column -offset indent "Esc O A, Esc O A" "em-exchange-mark" -.It Esc \&[ A, Esc O A Ta Ic ed-prev-history -.It Esc \&[ B, Esc O B Ta Ic ed-next-history -.It Esc \&[ C, Esc O C Ta Ic ed-next-char -.It Esc \&[ D, Esc O D Ta Ic ed-prev-char -.It Esc \&[ F, Esc O F Ta Ic ed-move-to-end -.It Esc \&[ H, Esc O H Ta Ic ed-move-to-beg -.El -.Pp -In vi command mode, they are also defined by default without the -initial escape character. -.Pp -In addition, the -.Nm -library tries to bind the strings generated by the arrow keys -as reported by the -.Xr terminfo 5 -database to these editor commands, unless that would clobber -user settings. -.Pp -In emacs mode, the two-character string -.Dq Ctrl-X Ctrl-X -is bound to the -.Ic em-exchange-mark -editor command. -.Ss Input Queue -The -.Nm -library maintains an input queue operated in FIFO mode. -Whenever it needs an input character, it takes the first character -from the first line of the input queue. -When the queue is empty, it reads from the terminal. -.Pp -A line can be appended to the end of the input queue in several ways: -.Bl -dash -offset indent -.It -By calling one of the keyboard -.Sx Macros . -.It -By calling the editor command -.Ic vi-redo . -.It -By calling the editor command -.Ic vi-alias . -.It -By pressing a key in emacs incremental search mode that doesn't -have a special meaning in that mode but returns to normal emacs -mode. -.It -If an application program directly calls the functions -.Xr el_push 3 -or -.Xr el_wpush 3 , -it can provide additional, program-specific ways -of appending to the input queue. -.El -.Sh SEE ALSO -.Xr mg 1 , -.Xr vi 1 , -.Xr editline 3 , -.Xr el_wgets 3 , -.Xr el_wpush 3 , -.Xr el_wset 3 , -.Xr editrc 5 -.Sh HISTORY -This manual page first appeared in -.Ox 6.0 -and -.Nx 8 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Ingo Schwarze Aq Mt schwarze@openbsd.org . diff --git a/bin/catsh/libedit/editrc.5 b/bin/catsh/libedit/editrc.5 deleted file mode 100644 index 9bc94b8b..00000000 --- a/bin/catsh/libedit/editrc.5 +++ /dev/null @@ -1,325 +0,0 @@ -.\" $NetBSD: editrc.5,v 1.32.8.1 2017/07/23 14:41:26 snj Exp $ -.\" -.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd May 22, 2016 -.Dt EDITRC 5 -.Os -.Sh NAME -.Nm editrc -.Nd configuration file for editline library -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -The -.Nm -file defines various settings to be used by the -.Xr editline 3 -library. -.Pp -The format of each line is: -.Pp -.Dl [prog:]command [arg ...] -.Pp -.Ar command -is one of the -.Xr editline 3 -builtin commands. -Refer to -.Sx BUILTIN COMMANDS -for more information. -.Pp -.Ar prog -is the program name string that a program defines when it calls -.Xr el_init 3 -to set up -.Xr editline 3 , -which is usually -.Va argv[0] . -.Ar command -will be executed for any program which matches -.Ar prog . -.Pp -.Ar prog -may also be a -.Xr regex 3 -style -regular expression, in which case -.Ar command -will be executed for any program that matches the regular expression. -.Pp -If -.Ar prog -is absent, -.Ar command -is executed for all programs. -.Sh BUILTIN COMMANDS -The -.Nm editline -library has some builtin commands, which affect the way -that the line editing and history functions operate. -These are based on similar named builtins present in the -.Xr tcsh 1 -shell. -.Pp -The following builtin commands are available: -.Bl -tag -width 4n -.It Ic bind Oo Fl aeklrsv Oc Op Ar key Op Ar command -Without options and arguments, list all bound keys and macros, and -the editor command or input string to which each one is bound. -If only -.Ar key -is supplied, show the binding for that key or macro. -If -.Ar key command -is supplied, bind the editor -.Ar command -to that key or macro. -.Pp -The options are as follows: -.Bl -tag -width 4n -.It Fl a -List or change key bindings in the -.Xr vi 1 -mode alternate (command mode) key map. -.It Fl e -Bind all keys to the standard GNU Emacs-like bindings. -.It Fl k -.Ar key -is interpreted as a symbolic arrow key name, which may be one of -.Sq up , -.Sq down , -.Sq left -or -.Sq right . -.It Fl l -List all editor commands and a short description of each. -.It Fl r -Remove the binding of the key or macro -.Ar key . -.It Fl s -Define a keyboard macro rather than a key binding or command macro: -.Ar command -is taken as a literal string and appended to the input queue whenever -.Ar key -is typed. -Bound keys and macros in -.Ar command -are themselves reinterpreted, and this continues for ten levels of -interpretation. -.It Fl v -Bind all keys to the standard -.Xr vi 1 Ns -like -bindings. -.El -.Pp -The -.Xr editline 7 -manual documents all editor commands and contains more information -about macros and the input queue. -.Pp -.Ar key -and -.Ar command -can contain control characters of the form -.Sm off -.Sq No ^ Ar character -.Sm on -.Po -e.g.\& -.Sq ^A -.Pc , -and the following backslashed escape sequences: -.Pp -.Bl -tag -compact -offset indent -width 4n -.It Ic \ea -Bell -.It Ic \eb -Backspace -.It Ic \ee -Escape -.It Ic \ef -Formfeed -.It Ic \en -Newline -.It Ic \er -Carriage return -.It Ic \et -Horizontal tab -.It Ic \ev -Vertical tab -.Sm off -.It Sy \e Ar nnn -.Sm on -The ASCII character corresponding to the octal number -.Ar nnn . -.El -.Pp -.Sq \e -nullifies the special meaning of the following character, -if it has any, notably -.Sq \e -and -.Sq ^ . -.It Ic echotc Oo Fl sv Oc Ar arg Ar ... -Exercise terminal capabilities given in -.Ar arg ... . -If -.Ar arg -is -.Sq baud , -.Sq cols , -.Sq lines , -.Sq rows , -.Sq meta , -or -.Sq tabs , -the value of that capability is printed, with -.Dq yes -or -.Dq no -indicating that the terminal does or does not have that capability. -.Pp -.Fl s -returns an empty string for non-existent capabilities, rather than -causing an error. -.Fl v -causes messages to be verbose. -.It Ic edit Op Li on | Li off -Enable or disable the -.Nm editline -functionality in a program. -.It Ic history Ar list | Ar size Dv n | Ar unique Dv n -The -.Ar list -command lists all entries in the history. -The -.Ar size -command sets the history size to -.Dv n -entries. -The -.Ar unique -command controls if history should keep duplicate entries. -If -.Dv n -is non zero, only keep unique history entries. -If -.Dv n -is zero, then keep all entries (the default). -.It Ic settc Ar cap Ar val -Set the terminal capability -.Ar cap -to -.Ar val , -as defined in -.Xr termcap 5 . -No sanity checking is done. -.It Ic setty Oo Fl a Oc Oo Fl d Oc Oo Fl q Oc Oo Fl x Oc Oo Ar +mode Oc \ -Oo Ar -mode Oc Oo Ar mode Oc Oo Ar char=c Oc -Control which tty modes that -.Nm -won't allow the user to change. -.Fl d , -.Fl q -or -.Fl x -tells -.Ic setty -to act on the -.Sq edit , -.Sq quote -or -.Sq execute -set of tty modes respectively; defaulting to -.Fl x . -.Pp -Without other arguments, -.Ic setty -lists the modes in the chosen set which are fixed on -.Po -.Sq +mode -.Pc -or off -.Po -.Sq -mode -.Pc . -.Fl a -lists all tty modes in the chosen set regardless of the setting. -With -.Ar +mode , -.Ar -mode -or -.Ar mode , -fixes -.Ar mode -on or off or removes control of -.Ar mode -in the chosen set. -.Pp -.Ic Setty -can also be used to set tty characters to particular values using -.Ar char=value . -If -.Ar value -is empty -then the character is set to -.Dv _POSIX_VDISABLE . -.It Ic telltc -List the values of all the terminal capabilities (see -.Xr termcap 5 ) . -.El -.Sh ENVIRONMENT -.Bl -tag -width "~/.editrcXXX" -.It Ev EDITRC -Names the default configuration file for the -.Xr editline 3 -library. -.El -.Sh FILES -.Bl -tag -width "~/.editrcXXX" -.It Pa ~/.editrc -Last resort, if no other file is specified, -user configuration file for the -.Xr editline 3 -library. -.El -.Sh SEE ALSO -.Xr editline 3 , -.Xr regex 3 , -.Xr termcap 5 , -.Xr editline 7 -.Sh AUTHORS -.An -nosplit -The -.Nm editline -library was written by -.An Christos Zoulas , -and this manual was written by -.An Luke Mewburn , -with some sections inspired by -.Xr tcsh 1 . diff --git a/bin/catsh/libedit/el.c b/bin/catsh/libedit/el.c deleted file mode 100644 index c30f50ca..00000000 --- a/bin/catsh/libedit/el.c +++ /dev/null @@ -1,649 +0,0 @@ -/* $NetBSD: el.c,v 1.92.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; -#else -__RCSID("$NetBSD: el.c,v 1.92.8.1 2017/07/23 14:41:26 snj Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * el.c: EditLine interface functions - */ -#include <sys/types.h> -#include <sys/param.h> -#include <ctype.h> -#include <langinfo.h> -#include <locale.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -#include "el.h" -#include "parse.h" -#include "read.h" - -/* el_init(): - * Initialize editline and set default parameters. - */ -EditLine * -el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) -{ - return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout), - fileno(ferr)); -} - -EditLine * -el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr, - int fdin, int fdout, int fderr) -{ - EditLine *el = el_malloc(sizeof(*el)); - - if (el == NULL) - return NULL; - - memset(el, 0, sizeof(EditLine)); - - el->el_infile = fin; - el->el_outfile = fout; - el->el_errfile = ferr; - - el->el_infd = fdin; - el->el_outfd = fdout; - el->el_errfd = fderr; - - el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch)); - if (el->el_prog == NULL) { - el_free(el); - return NULL; - } - - /* - * Initialize all the modules. Order is important!!! - */ - el->el_flags = 0; - if (setlocale(LC_CTYPE, NULL) != NULL){ - if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) - el->el_flags |= CHARSET_IS_UTF8; - } - - if (terminal_init(el) == -1) { - el_free(el->el_prog); - el_free(el); - return NULL; - } - (void) keymacro_init(el); - (void) map_init(el); - if (tty_init(el) == -1) - el->el_flags |= NO_TTY; - (void) ch_init(el); - (void) search_init(el); - (void) hist_init(el); - (void) prompt_init(el); - (void) sig_init(el); - (void) literal_init(el); - if (read_init(el) == -1) { - el_end(el); - return NULL; - } - return el; -} - - -/* el_end(): - * Clean up. - */ -void -el_end(EditLine *el) -{ - - if (el == NULL) - return; - - el_reset(el); - - terminal_end(el); - keymacro_end(el); - map_end(el); - if (!(el->el_flags & NO_TTY)) - tty_end(el); - ch_end(el); - read_end(el->el_read); - search_end(el); - hist_end(el); - prompt_end(el); - sig_end(el); - literal_end(el); - - el_free(el->el_prog); - el_free(el->el_visual.cbuff); - el_free(el->el_visual.wbuff); - el_free(el->el_scratch.cbuff); - el_free(el->el_scratch.wbuff); - el_free(el->el_lgcyconv.cbuff); - el_free(el->el_lgcyconv.wbuff); - el_free(el); -} - - -/* el_reset(): - * Reset the tty and the parser - */ -void -el_reset(EditLine *el) -{ - - tty_cookedmode(el); - ch_reset(el); /* XXX: Do we want that? */ -} - - -/* el_set(): - * set the editline parameters - */ -int -el_wset(EditLine *el, int op, ...) -{ - va_list ap; - int rv = 0; - - if (el == NULL) - return -1; - va_start(ap, op); - - switch (op) { - case EL_PROMPT: - case EL_RPROMPT: { - el_pfunc_t p = va_arg(ap, el_pfunc_t); - - rv = prompt_set(el, p, 0, op, 1); - break; - } - - case EL_RESIZE: { - el_zfunc_t p = va_arg(ap, el_zfunc_t); - void *arg = va_arg(ap, void *); - rv = ch_resizefun(el, p, arg); - break; - } - - case EL_ALIAS_TEXT: { - el_afunc_t p = va_arg(ap, el_afunc_t); - void *arg = va_arg(ap, void *); - rv = ch_aliasfun(el, p, arg); - break; - } - - case EL_PROMPT_ESC: - case EL_RPROMPT_ESC: { - el_pfunc_t p = va_arg(ap, el_pfunc_t); - int c = va_arg(ap, int); - - rv = prompt_set(el, p, (wchar_t)c, op, 1); - break; - } - - case EL_TERMINAL: - rv = terminal_set(el, va_arg(ap, char *)); - break; - - case EL_EDITOR: - rv = map_set_editor(el, va_arg(ap, wchar_t *)); - break; - - case EL_SIGNAL: - if (va_arg(ap, int)) - el->el_flags |= HANDLE_SIGNALS; - else - el->el_flags &= ~HANDLE_SIGNALS; - break; - - case EL_BIND: - case EL_TELLTC: - case EL_SETTC: - case EL_ECHOTC: - case EL_SETTY: - { - const wchar_t *argv[20]; - int i; - - for (i = 1; i < (int)__arraycount(argv); i++) - if ((argv[i] = va_arg(ap, wchar_t *)) == NULL) - break; - - switch (op) { - case EL_BIND: - argv[0] = L"bind"; - rv = map_bind(el, i, argv); - break; - - case EL_TELLTC: - argv[0] = L"telltc"; - rv = terminal_telltc(el, i, argv); - break; - - case EL_SETTC: - argv[0] = L"settc"; - rv = terminal_settc(el, i, argv); - break; - - case EL_ECHOTC: - argv[0] = L"echotc"; - rv = terminal_echotc(el, i, argv); - break; - - case EL_SETTY: - argv[0] = L"setty"; - rv = tty_stty(el, i, argv); - break; - - default: - rv = -1; - EL_ABORT((el->el_errfile, "Bad op %d\n", op)); - break; - } - break; - } - - case EL_ADDFN: - { - wchar_t *name = va_arg(ap, wchar_t *); - wchar_t *help = va_arg(ap, wchar_t *); - el_func_t func = va_arg(ap, el_func_t); - - rv = map_addfunc(el, name, help, func); - break; - } - - case EL_HIST: - { - hist_fun_t func = va_arg(ap, hist_fun_t); - void *ptr = va_arg(ap, void *); - - rv = hist_set(el, func, ptr); - if (!(el->el_flags & CHARSET_IS_UTF8)) - el->el_flags &= ~NARROW_HISTORY; - break; - } - - case EL_EDITMODE: - if (va_arg(ap, int)) - el->el_flags &= ~EDIT_DISABLED; - else - el->el_flags |= EDIT_DISABLED; - rv = 0; - break; - - case EL_GETCFN: - { - el_rfunc_t rc = va_arg(ap, el_rfunc_t); - rv = el_read_setfn(el->el_read, rc); - break; - } - - case EL_CLIENTDATA: - el->el_data = va_arg(ap, void *); - break; - - case EL_UNBUFFERED: - rv = va_arg(ap, int); - if (rv && !(el->el_flags & UNBUFFERED)) { - el->el_flags |= UNBUFFERED; - read_prepare(el); - } else if (!rv && (el->el_flags & UNBUFFERED)) { - el->el_flags &= ~UNBUFFERED; - read_finish(el); - } - rv = 0; - break; - - case EL_PREP_TERM: - rv = va_arg(ap, int); - if (rv) - (void) tty_rawmode(el); - else - (void) tty_cookedmode(el); - rv = 0; - break; - - case EL_SETFP: - { - FILE *fp; - int what; - - what = va_arg(ap, int); - fp = va_arg(ap, FILE *); - - rv = 0; - switch (what) { - case 0: - el->el_infile = fp; - el->el_infd = fileno(fp); - break; - case 1: - el->el_outfile = fp; - el->el_outfd = fileno(fp); - break; - case 2: - el->el_errfile = fp; - el->el_errfd = fileno(fp); - break; - default: - rv = -1; - break; - } - break; - } - - case EL_REFRESH: - re_clear_display(el); - re_refresh(el); - terminal__flush(el); - break; - - default: - rv = -1; - break; - } - - va_end(ap); - return rv; -} - - -/* el_get(): - * retrieve the editline parameters - */ -int -el_wget(EditLine *el, int op, ...) -{ - va_list ap; - int rv; - - if (el == NULL) - return -1; - - va_start(ap, op); - - switch (op) { - case EL_PROMPT: - case EL_RPROMPT: { - el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - rv = prompt_get(el, p, 0, op); - break; - } - case EL_PROMPT_ESC: - case EL_RPROMPT_ESC: { - el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - wchar_t *c = va_arg(ap, wchar_t *); - - rv = prompt_get(el, p, c, op); - break; - } - - case EL_EDITOR: - rv = map_get_editor(el, va_arg(ap, const wchar_t **)); - break; - - case EL_SIGNAL: - *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS); - rv = 0; - break; - - case EL_EDITMODE: - *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED); - rv = 0; - break; - - case EL_TERMINAL: - terminal_get(el, va_arg(ap, const char **)); - rv = 0; - break; - - case EL_GETTC: - { - static char name[] = "gettc"; - char *argv[20]; - int i; - - for (i = 1; i < (int)__arraycount(argv); i++) - if ((argv[i] = va_arg(ap, char *)) == NULL) - break; - - argv[0] = name; - rv = terminal_gettc(el, i, argv); - break; - } - - case EL_GETCFN: - *va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read); - rv = 0; - break; - - case EL_CLIENTDATA: - *va_arg(ap, void **) = el->el_data; - rv = 0; - break; - - case EL_UNBUFFERED: - *va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0; - rv = 0; - break; - - case EL_GETFP: - { - int what; - FILE **fpp; - - what = va_arg(ap, int); - fpp = va_arg(ap, FILE **); - rv = 0; - switch (what) { - case 0: - *fpp = el->el_infile; - break; - case 1: - *fpp = el->el_outfile; - break; - case 2: - *fpp = el->el_errfile; - break; - default: - rv = -1; - break; - } - break; - } - default: - rv = -1; - break; - } - va_end(ap); - - return rv; -} - - -/* el_line(): - * Return editing info - */ -const LineInfoW * -el_wline(EditLine *el) -{ - - return (const LineInfoW *)(void *)&el->el_line; -} - - -/* el_source(): - * Source a file - */ -int -el_source(EditLine *el, const char *fname) -{ - FILE *fp; - size_t len; - ssize_t slen; - char *ptr; - char *path = NULL; - const wchar_t *dptr; - int error = 0; - - fp = NULL; - if (fname == NULL) { -#ifdef HAVE_ISSETUGID - if (issetugid()) - return -1; - - if ((fname = getenv("EDITRC")) == NULL) { - static const char elpath[] = "/.editrc"; - size_t plen = sizeof(elpath); - - if ((ptr = getenv("HOME")) == NULL) - return -1; - plen += strlen(ptr); - if ((path = el_malloc(plen * sizeof(*path))) == NULL) - return -1; - (void)snprintf(path, plen, "%s%s", ptr, - elpath + (*ptr == '\0')); - fname = path; - } -#else - /* - * If issetugid() is missing, always return an error, in order - * to keep from inadvertently opening up the user to a security - * hole. - */ - return -1; -#endif - } - if (fname[0] == '\0') - return -1; - - if (fp == NULL) - fp = fopen(fname, "r"); - if (fp == NULL) { - el_free(path); - return -1; - } - - ptr = NULL; - len = 0; - while ((slen = getline(&ptr, &len, fp)) != -1) { - if (*ptr == '\n') - continue; /* Empty line. */ - if (slen > 0 && ptr[--slen] == '\n') - ptr[slen] = '\0'; - - dptr = ct_decode_string(ptr, &el->el_scratch); - if (!dptr) - continue; - /* loop until first non-space char or EOL */ - while (*dptr != '\0' && iswspace(*dptr)) - dptr++; - if (*dptr == '#') - continue; /* ignore, this is a comment line */ - if ((error = parse_line(el, dptr)) == -1) - break; - } - free(ptr); - - el_free(path); - (void) fclose(fp); - return error; -} - - -/* el_resize(): - * Called from program when terminal is resized - */ -void -el_resize(EditLine *el) -{ - int lins, cols; - sigset_t oset, nset; - - (void) sigemptyset(&nset); - (void) sigaddset(&nset, SIGWINCH); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - - /* get the correct window size */ - if (terminal_get_size(el, &lins, &cols)) - terminal_change_size(el, lins, cols); - - (void) sigprocmask(SIG_SETMASK, &oset, NULL); -} - - -/* el_beep(): - * Called from the program to beep - */ -void -el_beep(EditLine *el) -{ - - terminal_beep(el); -} - - -/* el_editmode() - * Set the state of EDIT_DISABLED from the `edit' command. - */ -libedit_private int -/*ARGSUSED*/ -el_editmode(EditLine *el, int argc, const wchar_t **argv) -{ - const wchar_t *how; - - if (argv == NULL || argc != 2 || argv[1] == NULL) - return -1; - - how = argv[1]; - if (wcscmp(how, L"on") == 0) { - el->el_flags &= ~EDIT_DISABLED; - tty_rawmode(el); - } else if (wcscmp(how, L"off") == 0) { - tty_cookedmode(el); - el->el_flags |= EDIT_DISABLED; - } - else { - (void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n", - how); - return -1; - } - return 0; -} diff --git a/bin/catsh/libedit/el.h b/bin/catsh/libedit/el.h deleted file mode 100644 index 862e1976..00000000 --- a/bin/catsh/libedit/el.h +++ /dev/null @@ -1,155 +0,0 @@ -/* $NetBSD: el.h,v 1.41.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)el.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.h: Internal structures. - */ -#ifndef _h_el -#define _h_el -/* - * Local defaults - */ -#define KSHVI -#define VIDEFAULT -#define ANCHOR - -#include "histedit.h" -#include "chartype.h" - -#define EL_BUFSIZ ((size_t)1024) /* Maximum line size */ - -#define HANDLE_SIGNALS 0x01 -#define NO_TTY 0x02 -#define EDIT_DISABLED 0x04 -#define UNBUFFERED 0x08 -#define CHARSET_IS_UTF8 0x10 -#define NARROW_HISTORY 0x40 - -typedef unsigned char el_action_t; /* Index to command array */ - -typedef struct coord_t { /* Position on the screen */ - int h; - int v; -} coord_t; - -typedef struct el_line_t { - wchar_t *buffer; /* Input line */ - wchar_t *cursor; /* Cursor position */ - wchar_t *lastchar; /* Last character */ - const wchar_t *limit; /* Max position */ -} el_line_t; - -/* - * Editor state - */ -typedef struct el_state_t { - int inputmode; /* What mode are we in? */ - int doingarg; /* Are we getting an argument? */ - int argument; /* Numeric argument */ - int metanext; /* Is the next char a meta char */ - el_action_t lastcmd; /* Previous command */ - el_action_t thiscmd; /* this command */ - wchar_t thisch; /* char that generated it */ -} el_state_t; - -/* - * Until we come up with something better... - */ -#define el_malloc(a) malloc(a) -#define el_realloc(a,b) realloc(a, b) -#define el_free(a) free(a) - -#include "tty.h" -#include "prompt.h" -#include "literal.h" -#include "keymacro.h" -#include "terminal.h" -#include "refresh.h" -#include "chared.h" -#include "search.h" -#include "hist.h" -#include "map.h" -#include "sig.h" - -struct el_read_t; - -struct editline { - wchar_t *el_prog; /* the program name */ - FILE *el_infile; /* Stdio stuff */ - FILE *el_outfile; /* Stdio stuff */ - FILE *el_errfile; /* Stdio stuff */ - int el_infd; /* Input file descriptor */ - int el_outfd; /* Output file descriptor */ - int el_errfd; /* Error file descriptor */ - int el_flags; /* Various flags. */ - coord_t el_cursor; /* Cursor location */ - wint_t **el_display; /* Real screen image = what is there */ - wint_t **el_vdisplay; /* Virtual screen image = what we see */ - void *el_data; /* Client data */ - el_line_t el_line; /* The current line information */ - el_state_t el_state; /* Current editor state */ - el_terminal_t el_terminal; /* Terminal dependent stuff */ - el_tty_t el_tty; /* Tty dependent stuff */ - el_refresh_t el_refresh; /* Refresh stuff */ - el_prompt_t el_prompt; /* Prompt stuff */ - el_prompt_t el_rprompt; /* Prompt stuff */ - el_literal_t el_literal; /* prompt literal bits */ - el_chared_t el_chared; /* Characted editor stuff */ - el_map_t el_map; /* Key mapping stuff */ - el_keymacro_t el_keymacro; /* Key binding stuff */ - el_history_t el_history; /* History stuff */ - el_search_t el_search; /* Search stuff */ - el_signal_t el_signal; /* Signal handling stuff */ - struct el_read_t *el_read; /* Character reading stuff */ - ct_buffer_t el_visual; /* Buffer for displayable str */ - ct_buffer_t el_scratch; /* Scratch conversion buffer */ - ct_buffer_t el_lgcyconv; /* Buffer for legacy wrappers */ - LineInfo el_lgcylinfo; /* Legacy LineInfo buffer */ -}; - -libedit_private int el_editmode(EditLine *, int, const wchar_t **); - -#ifdef DEBUG -#define EL_ABORT(a) do { \ - fprintf(el->el_errfile, "%s, %d: ", \ - __FILE__, __LINE__); \ - fprintf a; \ - abort(); \ - } while( /*CONSTCOND*/0); -#else -#define EL_ABORT(a) abort() -#endif -#endif /* _h_el */ diff --git a/bin/catsh/libedit/eln.c b/bin/catsh/libedit/eln.c deleted file mode 100644 index aa0a5b56..00000000 --- a/bin/catsh/libedit/eln.c +++ /dev/null @@ -1,388 +0,0 @@ -/* $NetBSD: eln.c,v 1.34 2016/05/09 21:37:34 christos Exp $ */ - -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: eln.c,v 1.34 2016/05/09 21:37:34 christos Exp $"); -#endif /* not lint && not SCCSID */ - -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> - -#include "el.h" - -int -el_getc(EditLine *el, char *cp) -{ - int num_read; - wchar_t wc = 0; - - num_read = el_wgetc(el, &wc); - *cp = '\0'; - if (num_read <= 0) - return num_read; - num_read = wctob(wc); - if (num_read == EOF) { - errno = ERANGE; - return -1; - } else { - *cp = (char)num_read; - return 1; - } -} - - -void -el_push(EditLine *el, const char *str) -{ - /* Using multibyte->wide string decoding works fine under single-byte - * character sets too, and Does The Right Thing. */ - el_wpush(el, ct_decode_string(str, &el->el_lgcyconv)); -} - - -const char * -el_gets(EditLine *el, int *nread) -{ - const wchar_t *tmp; - - tmp = el_wgets(el, nread); - if (tmp != NULL) { - int i; - size_t nwread = 0; - - for (i = 0; i < *nread; i++) - nwread += ct_enc_width(tmp[i]); - *nread = (int)nwread; - } - return ct_encode_string(tmp, &el->el_lgcyconv); -} - - -int -el_parse(EditLine *el, int argc, const char *argv[]) -{ - int ret; - const wchar_t **wargv; - - wargv = (void *)ct_decode_argv(argc, argv, &el->el_lgcyconv); - if (!wargv) - return -1; - ret = el_wparse(el, argc, wargv); - el_free(wargv); - - return ret; -} - - -int -el_set(EditLine *el, int op, ...) -{ - va_list ap; - int ret; - - if (!el) - return -1; - va_start(ap, op); - - switch (op) { - case EL_PROMPT: /* el_pfunc_t */ - case EL_RPROMPT: { - el_pfunc_t p = va_arg(ap, el_pfunc_t); - ret = prompt_set(el, p, 0, op, 0); - break; - } - - case EL_RESIZE: { - el_zfunc_t p = va_arg(ap, el_zfunc_t); - void *arg = va_arg(ap, void *); - ret = ch_resizefun(el, p, arg); - break; - } - - case EL_ALIAS_TEXT: { - el_afunc_t p = va_arg(ap, el_afunc_t); - void *arg = va_arg(ap, void *); - ret = ch_aliasfun(el, p, arg); - break; - } - - case EL_PROMPT_ESC: - case EL_RPROMPT_ESC: { - el_pfunc_t p = va_arg(ap, el_pfunc_t); - int c = va_arg(ap, int); - - ret = prompt_set(el, p, c, op, 0); - break; - } - - case EL_TERMINAL: /* const char * */ - ret = el_wset(el, op, va_arg(ap, char *)); - break; - - case EL_EDITOR: /* const wchar_t * */ - ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *), - &el->el_lgcyconv)); - break; - - case EL_SIGNAL: /* int */ - case EL_EDITMODE: - case EL_UNBUFFERED: - case EL_PREP_TERM: - ret = el_wset(el, op, va_arg(ap, int)); - break; - - case EL_BIND: /* const char * list -> const wchar_t * list */ - case EL_TELLTC: - case EL_SETTC: - case EL_ECHOTC: - case EL_SETTY: { - const char *argv[20]; - int i; - const wchar_t **wargv; - for (i = 1; i < (int)__arraycount(argv) - 1; ++i) - if ((argv[i] = va_arg(ap, const char *)) == NULL) - break; - argv[0] = argv[i] = NULL; - wargv = (void *)ct_decode_argv(i + 1, argv, &el->el_lgcyconv); - if (!wargv) { - ret = -1; - goto out; - } - /* - * AFAIK we can't portably pass through our new wargv to - * el_wset(), so we have to reimplement the body of - * el_wset() for these ops. - */ - switch (op) { - case EL_BIND: - wargv[0] = L"bind"; - ret = map_bind(el, i, wargv); - break; - case EL_TELLTC: - wargv[0] = L"telltc"; - ret = terminal_telltc(el, i, wargv); - break; - case EL_SETTC: - wargv[0] = L"settc"; - ret = terminal_settc(el, i, wargv); - break; - case EL_ECHOTC: - wargv[0] = L"echotc"; - ret = terminal_echotc(el, i, wargv); - break; - case EL_SETTY: - wargv[0] = L"setty"; - ret = tty_stty(el, i, wargv); - break; - default: - ret = -1; - } - el_free(wargv); - break; - } - - /* XXX: do we need to change el_func_t too? */ - case EL_ADDFN: { /* const char *, const char *, el_func_t */ - const char *args[2]; - el_func_t func; - wchar_t **wargv; - - args[0] = va_arg(ap, const char *); - args[1] = va_arg(ap, const char *); - func = va_arg(ap, el_func_t); - - wargv = ct_decode_argv(2, args, &el->el_lgcyconv); - if (!wargv) { - ret = -1; - goto out; - } - /* XXX: The two strdup's leak */ - ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]), - func); - el_free(wargv); - break; - } - case EL_HIST: { /* hist_fun_t, const char * */ - hist_fun_t fun = va_arg(ap, hist_fun_t); - void *ptr = va_arg(ap, void *); - ret = hist_set(el, fun, ptr); - el->el_flags |= NARROW_HISTORY; - break; - } - - case EL_GETCFN: /* el_rfunc_t */ - ret = el_wset(el, op, va_arg(ap, el_rfunc_t)); - break; - - case EL_CLIENTDATA: /* void * */ - ret = el_wset(el, op, va_arg(ap, void *)); - break; - - case EL_SETFP: { /* int, FILE * */ - int what = va_arg(ap, int); - FILE *fp = va_arg(ap, FILE *); - ret = el_wset(el, op, what, fp); - break; - } - - case EL_REFRESH: - re_clear_display(el); - re_refresh(el); - terminal__flush(el); - ret = 0; - break; - - default: - ret = -1; - break; - } - -out: - va_end(ap); - return ret; -} - - -int -el_get(EditLine *el, int op, ...) -{ - va_list ap; - int ret; - - if (!el) - return -1; - - va_start(ap, op); - - switch (op) { - case EL_PROMPT: /* el_pfunc_t * */ - case EL_RPROMPT: { - el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - ret = prompt_get(el, p, 0, op); - break; - } - - case EL_PROMPT_ESC: /* el_pfunc_t *, char **/ - case EL_RPROMPT_ESC: { - el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - char *c = va_arg(ap, char *); - wchar_t wc = 0; - ret = prompt_get(el, p, &wc, op); - *c = (char)wc; - break; - } - - case EL_EDITOR: { - const char **p = va_arg(ap, const char **); - const wchar_t *pw; - ret = el_wget(el, op, &pw); - *p = ct_encode_string(pw, &el->el_lgcyconv); - if (!el->el_lgcyconv.csize) - ret = -1; - break; - } - - case EL_TERMINAL: /* const char ** */ - ret = el_wget(el, op, va_arg(ap, const char **)); - break; - - case EL_SIGNAL: /* int * */ - case EL_EDITMODE: - case EL_UNBUFFERED: - case EL_PREP_TERM: - ret = el_wget(el, op, va_arg(ap, int *)); - break; - - case EL_GETTC: { - char *argv[20]; - static char gettc[] = "gettc"; - int i; - for (i = 1; i < (int)__arraycount(argv); ++i) - if ((argv[i] = va_arg(ap, char *)) == NULL) - break; - argv[0] = gettc; - ret = terminal_gettc(el, i, argv); - break; - } - - case EL_GETCFN: /* el_rfunc_t */ - ret = el_wget(el, op, va_arg(ap, el_rfunc_t *)); - break; - - case EL_CLIENTDATA: /* void ** */ - ret = el_wget(el, op, va_arg(ap, void **)); - break; - - case EL_GETFP: { /* int, FILE ** */ - int what = va_arg(ap, int); - FILE **fpp = va_arg(ap, FILE **); - ret = el_wget(el, op, what, fpp); - break; - } - - default: - ret = -1; - break; - } - - va_end(ap); - return ret; -} - - -const LineInfo * -el_line(EditLine *el) -{ - const LineInfoW *winfo = el_wline(el); - LineInfo *info = &el->el_lgcylinfo; - size_t offset; - const wchar_t *p; - - info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv); - - offset = 0; - for (p = winfo->buffer; p < winfo->cursor; p++) - offset += ct_enc_width(*p); - info->cursor = info->buffer + offset; - - offset = 0; - for (p = winfo->buffer; p < winfo->lastchar; p++) - offset += ct_enc_width(*p); - info->lastchar = info->buffer + offset; - - return info; -} - - -int -el_insertstr(EditLine *el, const char *str) -{ - return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv)); -} diff --git a/bin/catsh/libedit/emacs.c b/bin/catsh/libedit/emacs.c deleted file mode 100644 index 0636c28b..00000000 --- a/bin/catsh/libedit/emacs.c +++ /dev/null @@ -1,512 +0,0 @@ -/* $NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * emacs.c: Emacs functions - */ -#include <ctype.h> - -#include "el.h" -#include "emacs.h" -#include "fcns.h" - -/* em_delete_or_list(): - * Delete character under cursor or list completions if at end of line - * [^D] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_delete_or_list(EditLine *el, wint_t c) -{ - - if (el->el_line.cursor == el->el_line.lastchar) { - /* if I'm at the end */ - if (el->el_line.cursor == el->el_line.buffer) { - /* and the beginning */ - terminal_writec(el, c); /* then do an EOF */ - return CC_EOF; - } else { - /* - * Here we could list completions, but it is an - * error right now - */ - terminal_beep(el); - return CC_ERROR; - } - } else { - if (el->el_state.doingarg) - c_delafter(el, el->el_state.argument); - else - c_delafter1(el); - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - /* bounds check */ - return CC_REFRESH; - } -} - - -/* em_delete_next_word(): - * Cut from cursor to end of current word - * [M-d] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_delete_next_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *p, *kp; - - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - - cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); - - for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++) - /* save the text */ - *kp++ = *p; - el->el_chared.c_kill.last = kp; - - c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */ - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - /* bounds check */ - return CC_REFRESH; -} - - -/* em_yank(): - * Paste cut buffer at cursor position - * [^Y] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_yank(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) - return CC_NORM; - - if (el->el_line.lastchar + - (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= - el->el_line.limit) - return CC_ERROR; - - el->el_chared.c_kill.mark = el->el_line.cursor; - cp = el->el_line.cursor; - - /* open the space, */ - c_insert(el, - (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf)); - /* copy the chars */ - for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) - *cp++ = *kp; - - /* if an arg, cursor at beginning else cursor at end */ - if (el->el_state.argument == 1) - el->el_line.cursor = cp; - - return CC_REFRESH; -} - - -/* em_kill_line(): - * Cut the entire line and save in cut buffer - * [^U] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - cp = el->el_line.buffer; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.lastchar) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - /* zap! -- delete all of it */ - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - return CC_REFRESH; -} - - -/* em_kill_region(): - * Cut area between mark and cursor and save in cut buffer - * [^W] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_kill_region(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - if (!el->el_chared.c_kill.mark) - return CC_ERROR; - - if (el->el_chared.c_kill.mark > el->el_line.cursor) { - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_chared.c_kill.mark) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delafter(el, (int)(cp - el->el_line.cursor)); - } else { /* mark is before cursor */ - cp = el->el_chared.c_kill.mark; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark)); - el->el_line.cursor = el->el_chared.c_kill.mark; - } - return CC_REFRESH; -} - - -/* em_copy_region(): - * Copy area between mark and cursor to cut buffer - * [M-W] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_copy_region(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - if (!el->el_chared.c_kill.mark) - return CC_ERROR; - - if (el->el_chared.c_kill.mark > el->el_line.cursor) { - cp = el->el_line.cursor; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_chared.c_kill.mark) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - } else { - cp = el->el_chared.c_kill.mark; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - } - return CC_NORM; -} - - -/* em_gosmacs_transpose(): - * Exchange the two characters before the cursor - * Gosling emacs transpose chars [^T] - */ -libedit_private el_action_t -em_gosmacs_transpose(EditLine *el, wint_t c) -{ - - if (el->el_line.cursor > &el->el_line.buffer[1]) { - /* must have at least two chars entered */ - c = el->el_line.cursor[-2]; - el->el_line.cursor[-2] = el->el_line.cursor[-1]; - el->el_line.cursor[-1] = c; - return CC_REFRESH; - } else - return CC_ERROR; -} - - -/* em_next_word(): - * Move next to end of current word - * [M-f] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_next_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - - el->el_line.cursor = c__next_word(el->el_line.cursor, - el->el_line.lastchar, - el->el_state.argument, - ce__isword); - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* em_upper_case(): - * Uppercase the characters from cursor to end of current word - * [M-u] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_upper_case(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *ep; - - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); - - for (cp = el->el_line.cursor; cp < ep; cp++) - if (iswlower(*cp)) - *cp = towupper(*cp); - - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; -} - - -/* em_capitol_case(): - * Capitalize the characters from cursor to end of current word - * [M-c] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_capitol_case(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *ep; - - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); - - for (cp = el->el_line.cursor; cp < ep; cp++) { - if (iswalpha(*cp)) { - if (iswlower(*cp)) - *cp = towupper(*cp); - cp++; - break; - } - } - for (; cp < ep; cp++) - if (iswupper(*cp)) - *cp = towlower(*cp); - - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; -} - - -/* em_lower_case(): - * Lowercase the characters from cursor to end of current word - * [M-l] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_lower_case(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *ep; - - ep = c__next_word(el->el_line.cursor, el->el_line.lastchar, - el->el_state.argument, ce__isword); - - for (cp = el->el_line.cursor; cp < ep; cp++) - if (iswupper(*cp)) - *cp = towlower(*cp); - - el->el_line.cursor = ep; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - return CC_REFRESH; -} - - -/* em_set_mark(): - * Set the mark at cursor - * [^@] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_set_mark(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_chared.c_kill.mark = el->el_line.cursor; - return CC_NORM; -} - - -/* em_exchange_mark(): - * Exchange the cursor and mark - * [^X^X] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_exchange_mark(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp; - - cp = el->el_line.cursor; - el->el_line.cursor = el->el_chared.c_kill.mark; - el->el_chared.c_kill.mark = cp; - return CC_CURSOR; -} - - -/* em_universal_argument(): - * Universal argument (argument times 4) - * [^U] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__))) -{ /* multiply current argument by 4 */ - - if (el->el_state.argument > 1000000) - return CC_ERROR; - el->el_state.doingarg = 1; - el->el_state.argument *= 4; - return CC_ARGHACK; -} - - -/* em_meta_next(): - * Add 8th bit to next character typed - * [<ESC>] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_meta_next(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_state.metanext = 1; - return CC_ARGHACK; -} - - -/* em_toggle_overwrite(): - * Switch from insert to overwrite mode or vice versa - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? - MODE_REPLACE : MODE_INSERT; - return CC_NORM; -} - - -/* em_copy_prev_word(): - * Copy current word to cursor - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_copy_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *cp, *oldc, *dp; - - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - - oldc = el->el_line.cursor; - /* does a bounds check */ - cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, - el->el_state.argument, ce__isword); - - c_insert(el, (int)(oldc - cp)); - for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) - *dp++ = *cp; - - el->el_line.cursor = dp;/* put cursor at end */ - - return CC_REFRESH; -} - - -/* em_inc_search_next(): - * Emacs incremental next search - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_search.patlen = 0; - return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY); -} - - -/* em_inc_search_prev(): - * Emacs incremental reverse search - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_search.patlen = 0; - return ce_inc_search(el, ED_SEARCH_PREV_HISTORY); -} - - -/* em_delete_prev_char(): - * Delete the character to the left of the cursor - * [^?] - */ -libedit_private el_action_t -/*ARGSUSED*/ -em_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor <= el->el_line.buffer) - return CC_ERROR; - - if (el->el_state.doingarg) - c_delbefore(el, el->el_state.argument); - else - c_delbefore1(el); - el->el_line.cursor -= el->el_state.argument; - if (el->el_line.cursor < el->el_line.buffer) - el->el_line.cursor = el->el_line.buffer; - return CC_REFRESH; -} diff --git a/bin/catsh/libedit/filecomplete.c b/bin/catsh/libedit/filecomplete.c deleted file mode 100644 index 6ccc2719..00000000 --- a/bin/catsh/libedit/filecomplete.c +++ /dev/null @@ -1,579 +0,0 @@ -/* $NetBSD: filecomplete.c,v 1.45 2017/04/21 05:38:03 abhinav Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.45 2017/04/21 05:38:03 abhinav Exp $"); -#endif /* not lint && not SCCSID */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "el.h" -#include "filecomplete.h" - -static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{("; - -/********************************/ -/* completion functions */ - -/* - * does tilde expansion of strings of type ``~user/foo'' - * if ``user'' isn't valid user name or ``txt'' doesn't start - * w/ '~', returns pointer to strdup()ed copy of ``txt'' - * - * it's the caller's responsibility to free() the returned string - */ -char * -fn_tilde_expand(const char *txt) -{ -#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) - struct passwd pwres; - char pwbuf[1024]; -#endif - struct passwd *pass; - char *temp; - size_t len = 0; - - if (txt[0] != '~') - return strdup(txt); - - temp = strchr(txt + 1, '/'); - if (temp == NULL) { - temp = strdup(txt + 1); - if (temp == NULL) - return NULL; - } else { - /* text until string after slash */ - len = (size_t)(temp - txt + 1); - temp = el_malloc(len * sizeof(*temp)); - if (temp == NULL) - return NULL; - (void)strncpy(temp, txt + 1, len - 2); - temp[len - 2] = '\0'; - } - if (temp[0] == 0) { -#ifdef HAVE_GETPW_R_POSIX - if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), - &pass) != 0) - pass = NULL; -#elif HAVE_GETPW_R_DRAFT - pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf)); -#else - pass = getpwuid(getuid()); -#endif - } else { -#ifdef HAVE_GETPW_R_POSIX - if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) - pass = NULL; -#elif HAVE_GETPW_R_DRAFT - pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf)); -#else - pass = getpwnam(temp); -#endif - } - el_free(temp); /* value no more needed */ - if (pass == NULL) - return strdup(txt); - - /* update pointer txt to point at string immedially following */ - /* first slash */ - txt += len; - - len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1; - temp = el_malloc(len * sizeof(*temp)); - if (temp == NULL) - return NULL; - (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt); - - return temp; -} - - -/* - * return first found file name starting by the ``text'' or NULL if no - * such file can be found - * value of ``state'' is ignored - * - * it's the caller's responsibility to free the returned string - */ -char * -fn_filename_completion_function(const char *text, int state) -{ - static DIR *dir = NULL; - static char *filename = NULL, *dirname = NULL, *dirpath = NULL; - static size_t filename_len = 0; - struct dirent *entry; - char *temp; - size_t len; - - if (state == 0 || dir == NULL) { - temp = strrchr(text, '/'); - if (temp) { - char *nptr; - temp++; - nptr = el_realloc(filename, (strlen(temp) + 1) * - sizeof(*nptr)); - if (nptr == NULL) { - el_free(filename); - filename = NULL; - return NULL; - } - filename = nptr; - (void)strcpy(filename, temp); - len = (size_t)(temp - text); /* including last slash */ - - nptr = el_realloc(dirname, (len + 1) * - sizeof(*nptr)); - if (nptr == NULL) { - el_free(dirname); - dirname = NULL; - return NULL; - } - dirname = nptr; - (void)strncpy(dirname, text, len); - dirname[len] = '\0'; - } else { - el_free(filename); - if (*text == 0) - filename = NULL; - else { - filename = strdup(text); - if (filename == NULL) - return NULL; - } - el_free(dirname); - dirname = NULL; - } - - if (dir != NULL) { - (void)closedir(dir); - dir = NULL; - } - - /* support for ``~user'' syntax */ - - el_free(dirpath); - dirpath = NULL; - if (dirname == NULL) { - if ((dirname = strdup("")) == NULL) - return NULL; - dirpath = strdup("./"); - } else if (*dirname == '~') - dirpath = fn_tilde_expand(dirname); - else - dirpath = strdup(dirname); - - if (dirpath == NULL) - return NULL; - - dir = opendir(dirpath); - if (!dir) - return NULL; /* cannot open the directory */ - - /* will be used in cycle */ - filename_len = filename ? strlen(filename) : 0; - } - - /* find the match */ - while ((entry = readdir(dir)) != NULL) { - /* skip . and .. */ - if (entry->d_name[0] == '.' && (!entry->d_name[1] - || (entry->d_name[1] == '.' && !entry->d_name[2]))) - continue; - if (filename_len == 0) - break; - /* otherwise, get first entry where first */ - /* filename_len characters are equal */ - if (entry->d_name[0] == filename[0] -#if HAVE_STRUCT_DIRENT_D_NAMLEN - && entry->d_namlen >= filename_len -#else - && strlen(entry->d_name) >= filename_len -#endif - && strncmp(entry->d_name, filename, - filename_len) == 0) - break; - } - - if (entry) { /* match found */ - -#if HAVE_STRUCT_DIRENT_D_NAMLEN - len = entry->d_namlen; -#else - len = strlen(entry->d_name); -#endif - - len = strlen(dirname) + len + 1; - temp = el_malloc(len * sizeof(*temp)); - if (temp == NULL) - return NULL; - (void)snprintf(temp, len, "%s%s", dirname, entry->d_name); - } else { - (void)closedir(dir); - dir = NULL; - temp = NULL; - } - - return temp; -} - - -static const char * -append_char_function(const char *name) -{ - struct stat stbuf; - char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; - const char *rs = " "; - - if (stat(expname ? expname : name, &stbuf) == -1) - goto out; - if (S_ISDIR(stbuf.st_mode)) - rs = "/"; -out: - if (expname) - el_free(expname); - return rs; -} -/* - * returns list of completions for text given - * non-static for readline. - */ -char ** completion_matches(const char *, char *(*)(const char *, int)); -char ** -completion_matches(const char *text, char *(*genfunc)(const char *, int)) -{ - char **match_list = NULL, *retstr, *prevstr; - size_t match_list_len, max_equal, which, i; - size_t matches; - - matches = 0; - match_list_len = 1; - while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { - /* allow for list terminator here */ - if (matches + 3 >= match_list_len) { - char **nmatch_list; - while (matches + 3 >= match_list_len) - match_list_len <<= 1; - nmatch_list = el_realloc(match_list, - match_list_len * sizeof(*nmatch_list)); - if (nmatch_list == NULL) { - el_free(match_list); - return NULL; - } - match_list = nmatch_list; - - } - match_list[++matches] = retstr; - } - - if (!match_list) - return NULL; /* nothing found */ - - /* find least denominator and insert it to match_list[0] */ - which = 2; - prevstr = match_list[1]; - max_equal = strlen(prevstr); - for (; which <= matches; which++) { - for (i = 0; i < max_equal && - prevstr[i] == match_list[which][i]; i++) - continue; - max_equal = i; - } - - retstr = el_malloc((max_equal + 1) * sizeof(*retstr)); - if (retstr == NULL) { - el_free(match_list); - return NULL; - } - (void)strncpy(retstr, match_list[1], max_equal); - retstr[max_equal] = '\0'; - match_list[0] = retstr; - - /* add NULL as last pointer to the array */ - match_list[matches + 1] = NULL; - - return match_list; -} - -/* - * Sort function for qsort(). Just wrapper around strcasecmp(). - */ -static int -_fn_qsort_string_compare(const void *i1, const void *i2) -{ - const char *s1 = ((const char * const *)i1)[0]; - const char *s2 = ((const char * const *)i2)[0]; - - return strcasecmp(s1, s2); -} - -/* - * Display list of strings in columnar format on readline's output stream. - * 'matches' is list of strings, 'num' is number of strings in 'matches', - * 'width' is maximum length of string in 'matches'. - * - * matches[0] is not one of the match strings, but it is counted in - * num, so the strings are matches[1] *through* matches[num-1]. - */ -void -fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width, - const char *(*app_func) (const char *)) -{ - size_t line, lines, col, cols, thisguy; - int screenwidth = el->el_terminal.t_size.h; - if (app_func == NULL) - app_func = append_char_function; - - /* Ignore matches[0]. Avoid 1-based array logic below. */ - matches++; - num--; - - /* - * Find out how many entries can be put on one line; count - * with one space between strings the same way it's printed. - */ - cols = (size_t)screenwidth / (width + 1); - if (cols == 0) - cols = 1; - - /* how many lines of output, rounded up */ - lines = (num + cols - 1) / cols; - - /* Sort the items. */ - qsort(matches, num, sizeof(char *), _fn_qsort_string_compare); - - /* - * On the ith line print elements i, i+lines, i+lines*2, etc. - */ - for (line = 0; line < lines; line++) { - for (col = 0; col < cols; col++) { - thisguy = line + col * lines; - if (thisguy >= num) - break; - (void)fprintf(el->el_outfile, "%s%s%s", - col == 0 ? "" : " ", matches[thisguy], - append_char_function(matches[thisguy])); - (void)fprintf(el->el_outfile, "%-*s", - (int) (width - strlen(matches[thisguy])), ""); - } - (void)fprintf(el->el_outfile, "\n"); - } -} - -/* - * Complete the word at or before point, - * 'what_to_do' says what to do with the completion. - * \t means do standard completion. - * `?' means list the possible completions. - * `*' means insert all of the possible completions. - * `!' means to do standard completion, and list all possible completions if - * there is more than one. - * - * Note: '*' support is not implemented - * '!' could never be invoked - */ -int -fn_complete(EditLine *el, - char *(*complet_func)(const char *, int), - char **(*attempted_completion_function)(const char *, int, int), - const wchar_t *word_break, const wchar_t *special_prefixes, - const char *(*app_func)(const char *), size_t query_items, - int *completion_type, int *over, int *point, int *end) -{ - const LineInfoW *li; - wchar_t *temp; - char **matches; - const wchar_t *ctemp; - size_t len; - int what_to_do = '\t'; - int retval = CC_NORM; - - if (el->el_state.lastcmd == el->el_state.thiscmd) - what_to_do = '?'; - - /* readline's rl_complete() has to be told what we did... */ - if (completion_type != NULL) - *completion_type = what_to_do; - - if (!complet_func) - complet_func = fn_filename_completion_function; - if (!app_func) - app_func = append_char_function; - - /* We now look backwards for the start of a filename/variable word */ - li = el_wline(el); - ctemp = li->cursor; - while (ctemp > li->buffer - && !wcschr(word_break, ctemp[-1]) - && (!special_prefixes || !wcschr(special_prefixes, ctemp[-1]) ) ) - ctemp--; - - len = (size_t)(li->cursor - ctemp); - temp = el_malloc((len + 1) * sizeof(*temp)); - (void)wcsncpy(temp, ctemp, len); - temp[len] = '\0'; - - /* these can be used by function called in completion_matches() */ - /* or (*attempted_completion_function)() */ - if (point != NULL) - *point = (int)(li->cursor - li->buffer); - if (end != NULL) - *end = (int)(li->lastchar - li->buffer); - - if (attempted_completion_function) { - int cur_off = (int)(li->cursor - li->buffer); - matches = (*attempted_completion_function)( - ct_encode_string(temp, &el->el_scratch), - cur_off - (int)len, cur_off); - } else - matches = NULL; - if (!attempted_completion_function || - (over != NULL && !*over && !matches)) - matches = completion_matches( - ct_encode_string(temp, &el->el_scratch), complet_func); - - if (over != NULL) - *over = 0; - - if (matches) { - int i; - size_t matches_num, maxlen, match_len, match_display=1; - - retval = CC_REFRESH; - /* - * Only replace the completed string with common part of - * possible matches if there is possible completion. - */ - if (matches[0][0] != '\0') { - el_deletestr(el, (int) len); - el_winsertstr(el, - ct_decode_string(matches[0], &el->el_scratch)); - } - - - if (matches[2] == NULL && - (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0)) { - /* - * We found exact match. Add a space after - * it, unless we do filename completion and the - * object is a directory. - */ - el_winsertstr(el, - ct_decode_string((*app_func)(matches[0]), - &el->el_scratch)); - } else if (what_to_do == '!' || what_to_do == '?') { - /* - * More than one match and requested to list possible - * matches. - */ - - for(i = 1, maxlen = 0; matches[i]; i++) { - match_len = strlen(matches[i]); - if (match_len > maxlen) - maxlen = match_len; - } - /* matches[1] through matches[i-1] are available */ - matches_num = (size_t)(i - 1); - - /* newline to get on next line from command line */ - (void)fprintf(el->el_outfile, "\n"); - - /* - * If there are too many items, ask user for display - * confirmation. - */ - if (matches_num > query_items) { - (void)fprintf(el->el_outfile, - "Display all %zu possibilities? (y or n) ", - matches_num); - (void)fflush(el->el_outfile); - if (getc(stdin) != 'y') - match_display = 0; - (void)fprintf(el->el_outfile, "\n"); - } - - if (match_display) { - /* - * Interface of this function requires the - * strings be matches[1..num-1] for compat. - * We have matches_num strings not counting - * the prefix in matches[0], so we need to - * add 1 to matches_num for the call. - */ - fn_display_match_list(el, matches, - matches_num+1, maxlen, app_func); - } - retval = CC_REDISPLAY; - } else if (matches[0][0]) { - /* - * There was some common match, but the name was - * not complete enough. Next tab will print possible - * completions. - */ - el_beep(el); - } else { - /* lcd is not a valid object - further specification */ - /* is needed */ - el_beep(el); - retval = CC_NORM; - } - - /* free elements of array and the array itself */ - for (i = 0; matches[i]; i++) - el_free(matches[i]); - el_free(matches); - matches = NULL; - } - el_free(temp); - return retval; -} - -/* - * el-compatible wrapper around rl_complete; needed for key binding - */ -/* ARGSUSED */ -unsigned char -_el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) -{ - return (unsigned char)fn_complete(el, NULL, NULL, - break_chars, NULL, NULL, (size_t)100, - NULL, NULL, NULL, NULL); -} diff --git a/bin/catsh/libedit/filecomplete.h b/bin/catsh/libedit/filecomplete.h deleted file mode 100644 index 61d81389..00000000 --- a/bin/catsh/libedit/filecomplete.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $NetBSD: filecomplete.h,v 1.11 2017/04/21 05:38:03 abhinav Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _FILECOMPLETE_H_ -#define _FILECOMPLETE_H_ - -int fn_complete(EditLine *, - char *(*)(const char *, int), - char **(*)(const char *, int, int), - const wchar_t *, const wchar_t *, const char *(*)(const char *), size_t, - int *, int *, int *, int *); - -void fn_display_match_list(EditLine *, char **, size_t, size_t, - const char *(*)(const char *)); -char *fn_tilde_expand(const char *); -char *fn_filename_completion_function(const char *, int); - -#endif diff --git a/bin/catsh/libedit/hist.c b/bin/catsh/libedit/hist.c deleted file mode 100644 index 3c9db7dc..00000000 --- a/bin/catsh/libedit/hist.c +++ /dev/null @@ -1,252 +0,0 @@ -/* $NetBSD: hist.c,v 1.32 2017/03/05 19:23:58 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: hist.c,v 1.32 2017/03/05 19:23:58 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * hist.c: History access functions - */ -#include <stdlib.h> -#include <string.h> -#include <vis.h> - -#include "el.h" - -/* hist_init(): - * Initialization function. - */ -libedit_private int -hist_init(EditLine *el) -{ - - el->el_history.fun = NULL; - el->el_history.ref = NULL; - el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf)); - el->el_history.sz = EL_BUFSIZ; - if (el->el_history.buf == NULL) - return -1; - el->el_history.last = el->el_history.buf; - return 0; -} - - -/* hist_end(): - * clean up history; - */ -libedit_private void -hist_end(EditLine *el) -{ - - el_free(el->el_history.buf); - el->el_history.buf = NULL; -} - - -/* hist_set(): - * Set new history interface - */ -libedit_private int -hist_set(EditLine *el, hist_fun_t fun, void *ptr) -{ - - el->el_history.ref = ptr; - el->el_history.fun = fun; - return 0; -} - - -/* hist_get(): - * Get a history line and update it in the buffer. - * eventno tells us the event to get. - */ -libedit_private el_action_t -hist_get(EditLine *el) -{ - const wchar_t *hp; - int h; - size_t blen, hlen; - - if (el->el_history.eventno == 0) { /* if really the current line */ - (void) wcsncpy(el->el_line.buffer, el->el_history.buf, - el->el_history.sz); - el->el_line.lastchar = el->el_line.buffer + - (el->el_history.last - el->el_history.buf); - -#ifdef KSHVI - if (el->el_map.type == MAP_VI) - el->el_line.cursor = el->el_line.buffer; - else -#endif /* KSHVI */ - el->el_line.cursor = el->el_line.lastchar; - - return CC_REFRESH; - } - if (el->el_history.ref == NULL) - return CC_ERROR; - - hp = HIST_FIRST(el); - - if (hp == NULL) - return CC_ERROR; - - for (h = 1; h < el->el_history.eventno; h++) - if ((hp = HIST_NEXT(el)) == NULL) - goto out; - - hlen = wcslen(hp) + 1; - blen = (size_t)(el->el_line.limit - el->el_line.buffer); - if (hlen > blen && !ch_enlargebufs(el, hlen)) - goto out; - - memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp)); - el->el_line.lastchar = el->el_line.buffer + hlen - 1; - - if (el->el_line.lastchar > el->el_line.buffer - && el->el_line.lastchar[-1] == '\n') - el->el_line.lastchar--; - if (el->el_line.lastchar > el->el_line.buffer - && el->el_line.lastchar[-1] == ' ') - el->el_line.lastchar--; -#ifdef KSHVI - if (el->el_map.type == MAP_VI) - el->el_line.cursor = el->el_line.buffer; - else -#endif /* KSHVI */ - el->el_line.cursor = el->el_line.lastchar; - - return CC_REFRESH; -out: - el->el_history.eventno = h; - return CC_ERROR; - -} - - -/* hist_command() - * process a history command - */ -libedit_private int -hist_command(EditLine *el, int argc, const wchar_t **argv) -{ - const wchar_t *str; - int num; - HistEventW ev; - - if (el->el_history.ref == NULL) - return -1; - - if (argc == 1 || wcscmp(argv[1], L"list") == 0) { - size_t maxlen = 0; - char *buf = NULL; - int hno = 1; - /* List history entries */ - - for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) { - char *ptr = - ct_encode_string(str, &el->el_scratch); - size_t len = strlen(ptr); - if (len > 0 && ptr[len - 1] == '\n') - ptr[--len] = '\0'; - len = len * 4 + 1; - if (len >= maxlen) { - maxlen = len + 1024; - char *nbuf = el_realloc(buf, maxlen); - if (nbuf == NULL) { - el_free(buf); - return -1; - } - buf = nbuf; - } - strvis(buf, ptr, VIS_NL); - (void) fprintf(el->el_outfile, "%d\t%s\n", - hno++, buf); - } - el_free(buf); - return 0; - } - - if (argc != 3) - return -1; - - num = (int)wcstol(argv[2], NULL, 0); - - if (wcscmp(argv[1], L"size") == 0) - return history_w(el->el_history.ref, &ev, H_SETSIZE, num); - - if (wcscmp(argv[1], L"unique") == 0) - return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num); - - return -1; -} - -/* hist_enlargebuf() - * Enlarge history buffer to specified value. Called from el_enlargebufs(). - * Return 0 for failure, 1 for success. - */ -libedit_private int -/*ARGSUSED*/ -hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) -{ - wchar_t *newbuf; - - newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); - if (!newbuf) - return 0; - - (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); - - el->el_history.last = newbuf + - (el->el_history.last - el->el_history.buf); - el->el_history.buf = newbuf; - el->el_history.sz = newsz; - - return 1; -} - -libedit_private wchar_t * -hist_convert(EditLine *el, int fn, void *arg) -{ - HistEventW ev; - if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1) - return NULL; - return ct_decode_string((const char *)(const void *)ev.str, - &el->el_scratch); -} diff --git a/bin/catsh/libedit/hist.h b/bin/catsh/libedit/hist.h deleted file mode 100644 index c58c5bfe..00000000 --- a/bin/catsh/libedit/hist.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $NetBSD: hist.h,v 1.22 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)hist.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.hist.c: History functions - */ -#ifndef _h_el_hist -#define _h_el_hist - -typedef int (*hist_fun_t)(void *, HistEventW *, int, ...); - -typedef struct el_history_t { - wchar_t *buf; /* The history buffer */ - size_t sz; /* Size of history buffer */ - wchar_t *last; /* The last character */ - int eventno; /* Event we are looking for */ - void *ref; /* Argument for history fcns */ - hist_fun_t fun; /* Event access */ - HistEventW ev; /* Event cookie */ -} el_history_t; - -#define HIST_FUN_INTERNAL(el, fn, arg) \ - ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \ - fn, arg)) == -1) ? NULL : (el)->el_history.ev.str) -#define HIST_FUN(el, fn, arg) \ - (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \ - HIST_FUN_INTERNAL(el, fn, arg)) - -#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL) -#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL) -#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) -#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) -#define HIST_SET(el, num) HIST_FUN(el, H_SET, num) -#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) -#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) -#define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP fp) - -libedit_private int hist_init(EditLine *); -libedit_private void hist_end(EditLine *); -libedit_private el_action_t hist_get(EditLine *); -libedit_private int hist_set(EditLine *, hist_fun_t, void *); -libedit_private int hist_command(EditLine *, int, const wchar_t **); -libedit_private int hist_enlargebuf(EditLine *, size_t, size_t); -libedit_private wchar_t *hist_convert(EditLine *, int, void *); - -#endif /* _h_el_hist */ diff --git a/bin/catsh/libedit/histedit.h b/bin/catsh/libedit/histedit.h deleted file mode 100644 index ecb42686..00000000 --- a/bin/catsh/libedit/histedit.h +++ /dev/null @@ -1,315 +0,0 @@ -/* $NetBSD: histedit.h,v 1.56 2016/04/19 19:50:53 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)histedit.h 8.2 (Berkeley) 1/3/94 - */ - -/* - * histedit.h: Line editor and history interface. - */ -#ifndef _HISTEDIT_H_ -#define _HISTEDIT_H_ - -#define LIBEDIT_MAJOR 2 -#define LIBEDIT_MINOR 11 - -#include <sys/types.h> -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * ==== Editing ==== - */ - -typedef struct editline EditLine; - -/* - * For user-defined function interface - */ -typedef struct lineinfo { - const char *buffer; - const char *cursor; - const char *lastchar; -} LineInfo; - -/* - * EditLine editor function return codes. - * For user-defined function interface - */ -#define CC_NORM 0 -#define CC_NEWLINE 1 -#define CC_EOF 2 -#define CC_ARGHACK 3 -#define CC_REFRESH 4 -#define CC_CURSOR 5 -#define CC_ERROR 6 -#define CC_FATAL 7 -#define CC_REDISPLAY 8 -#define CC_REFRESH_BEEP 9 - -/* - * Initialization, cleanup, and resetting - */ -EditLine *el_init(const char *, FILE *, FILE *, FILE *); -EditLine *el_init_fd(const char *, FILE *, FILE *, FILE *, - int, int, int); -void el_end(EditLine *); -void el_reset(EditLine *); - -/* - * Get a line, a character or push a string back in the input queue - */ -const char *el_gets(EditLine *, int *); -int el_getc(EditLine *, char *); -void el_push(EditLine *, const char *); - -/* - * Beep! - */ -void el_beep(EditLine *); - -/* - * High level function internals control - * Parses argc, argv array and executes builtin editline commands - */ -int el_parse(EditLine *, int, const char **); - -/* - * Low level editline access functions - */ -int el_set(EditLine *, int, ...); -int el_get(EditLine *, int, ...); -unsigned char _el_fn_complete(EditLine *, int); - -/* - * el_set/el_get parameters - * - * When using el_wset/el_wget (as opposed to el_set/el_get): - * Char is wchar_t, otherwise it is char. - * prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t . - - * Prompt function prototypes are: - * typedef char *(*el_pfunct_t) (EditLine *); - * typedef wchar_t *(*el_wpfunct_t) (EditLine *); - * - * For operations that support set or set/get, the argument types listed are for - * the "set" operation. For "get", each listed type must be a pointer. - * E.g. EL_EDITMODE takes an int when set, but an int* when get. - * - * Operations that only support "get" have the correct argument types listed. - */ -#define EL_PROMPT 0 /* , prompt_func); set/get */ -#define EL_TERMINAL 1 /* , const char *); set/get */ -#define EL_EDITOR 2 /* , const Char *); set/get */ -#define EL_SIGNAL 3 /* , int); set/get */ -#define EL_BIND 4 /* , const Char *, ..., NULL); set */ -#define EL_TELLTC 5 /* , const Char *, ..., NULL); set */ -#define EL_SETTC 6 /* , const Char *, ..., NULL); set */ -#define EL_ECHOTC 7 /* , const Char *, ..., NULL); set */ -#define EL_SETTY 8 /* , const Char *, ..., NULL); set */ -#define EL_ADDFN 9 /* , const Char *, const Char, set */ - /* el_func_t); */ -#define EL_HIST 10 /* , hist_fun_t, const void *); set */ -#define EL_EDITMODE 11 /* , int); set/get */ -#define EL_RPROMPT 12 /* , prompt_func); set/get */ -#define EL_GETCFN 13 /* , el_rfunc_t); set/get */ -#define EL_CLIENTDATA 14 /* , void *); set/get */ -#define EL_UNBUFFERED 15 /* , int); set/get */ -#define EL_PREP_TERM 16 /* , int); set */ -#define EL_GETTC 17 /* , const Char *, ..., NULL); get */ -#define EL_GETFP 18 /* , int, FILE **); get */ -#define EL_SETFP 19 /* , int, FILE *); set */ -#define EL_REFRESH 20 /* , void); set */ -#define EL_PROMPT_ESC 21 /* , prompt_func, Char); set/get */ -#define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */ -#define EL_RESIZE 23 /* , el_zfunc_t, void *); set */ -#define EL_ALIAS_TEXT 24 /* , el_afunc_t, void *); set */ - -#define EL_BUILTIN_GETCFN (NULL) - -/* - * Source named file or $PWD/.editrc or $HOME/.editrc - */ -int el_source(EditLine *, const char *); - -/* - * Must be called when the terminal changes size; If EL_SIGNAL - * is set this is done automatically otherwise it is the responsibility - * of the application - */ -void el_resize(EditLine *); - -/* - * User-defined function interface. - */ -const LineInfo *el_line(EditLine *); -int el_insertstr(EditLine *, const char *); -void el_deletestr(EditLine *, int); - - -/* - * ==== History ==== - */ - -typedef struct history History; - -typedef struct HistEvent { - int num; - const char *str; -} HistEvent; - -/* - * History access functions. - */ -History * history_init(void); -void history_end(History *); - -int history(History *, HistEvent *, int, ...); - -#define H_FUNC 0 /* , UTSL */ -#define H_SETSIZE 1 /* , const int); */ -#define H_GETSIZE 2 /* , void); */ -#define H_FIRST 3 /* , void); */ -#define H_LAST 4 /* , void); */ -#define H_PREV 5 /* , void); */ -#define H_NEXT 6 /* , void); */ -#define H_CURR 8 /* , const int); */ -#define H_SET 7 /* , int); */ -#define H_ADD 9 /* , const wchar_t *); */ -#define H_ENTER 10 /* , const wchar_t *); */ -#define H_APPEND 11 /* , const wchar_t *); */ -#define H_END 12 /* , void); */ -#define H_NEXT_STR 13 /* , const wchar_t *); */ -#define H_PREV_STR 14 /* , const wchar_t *); */ -#define H_NEXT_EVENT 15 /* , const int); */ -#define H_PREV_EVENT 16 /* , const int); */ -#define H_LOAD 17 /* , const char *); */ -#define H_SAVE 18 /* , const char *); */ -#define H_CLEAR 19 /* , void); */ -#define H_SETUNIQUE 20 /* , int); */ -#define H_GETUNIQUE 21 /* , void); */ -#define H_DEL 22 /* , int); */ -#define H_NEXT_EVDATA 23 /* , const int, histdata_t *); */ -#define H_DELDATA 24 /* , int, histdata_t *);*/ -#define H_REPLACE 25 /* , const char *, histdata_t); */ -#define H_SAVE_FP 26 /* , FILE *); */ -#define H_SAVE_INCR 27 /* , const char *, int); */ -#define H_SAVE_FP_INCR 28 /* , FILE *, int); */ - - - -/* - * ==== Tokenization ==== - */ - -typedef struct tokenizer Tokenizer; - -/* - * String tokenization functions, using simplified sh(1) quoting rules - */ -Tokenizer *tok_init(const char *); -void tok_end(Tokenizer *); -void tok_reset(Tokenizer *); -int tok_line(Tokenizer *, const LineInfo *, - int *, const char ***, int *, int *); -int tok_str(Tokenizer *, const char *, - int *, const char ***); - -/* - * Begin Wide Character Support - */ -#include <wchar.h> -#include <wctype.h> - -/* - * ==== Editing ==== - */ -typedef struct lineinfow { - const wchar_t *buffer; - const wchar_t *cursor; - const wchar_t *lastchar; -} LineInfoW; - -typedef int (*el_rfunc_t)(EditLine *, wchar_t *); - -const wchar_t *el_wgets(EditLine *, int *); -int el_wgetc(EditLine *, wchar_t *); -void el_wpush(EditLine *, const wchar_t *); - -int el_wparse(EditLine *, int, const wchar_t **); - -int el_wset(EditLine *, int, ...); -int el_wget(EditLine *, int, ...); - -int el_cursor(EditLine *, int); -const LineInfoW *el_wline(EditLine *); -int el_winsertstr(EditLine *, const wchar_t *); -#define el_wdeletestr el_deletestr - -/* - * ==== History ==== - */ -typedef struct histeventW { - int num; - const wchar_t *str; -} HistEventW; - -typedef struct historyW HistoryW; - -HistoryW * history_winit(void); -void history_wend(HistoryW *); - -int history_w(HistoryW *, HistEventW *, int, ...); - -/* - * ==== Tokenization ==== - */ -typedef struct tokenizerW TokenizerW; - -/* Wide character tokenizer support */ -TokenizerW *tok_winit(const wchar_t *); -void tok_wend(TokenizerW *); -void tok_wreset(TokenizerW *); -int tok_wline(TokenizerW *, const LineInfoW *, - int *, const wchar_t ***, int *, int *); -int tok_wstr(TokenizerW *, const wchar_t *, - int *, const wchar_t ***); - -#ifdef __cplusplus -} -#endif - -#endif /* _HISTEDIT_H_ */ diff --git a/bin/catsh/libedit/history.c b/bin/catsh/libedit/history.c deleted file mode 100644 index 005fe2a0..00000000 --- a/bin/catsh/libedit/history.c +++ /dev/null @@ -1,1271 +0,0 @@ -/* $NetBSD: history.c,v 1.57 2016/04/11 18:56:31 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: history.c,v 1.57 2016/04/11 18:56:31 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * hist.c: TYPE(History) access functions - */ -#include <sys/file.h> -#include <sys/stat.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <vis.h> - -static const char hist_cookie[] = "_HiStOrY_V2_\n"; - -#include "histedit.h" - - -#ifdef NARROWCHAR - -#define Char char -#define FUN(prefix, rest) prefix ## _ ## rest -#define FUNW(type) type -#define TYPE(type) type -#define STR(x) x - -#define Strlen(s) strlen(s) -#define Strdup(s) strdup(s) -#define Strcmp(d, s) strcmp(d, s) -#define Strncmp(d, s, n) strncmp(d, s, n) -#define Strncpy(d, s, n) strncpy(d, s, n) -#define Strncat(d, s, n) strncat(d, s, n) -#define ct_decode_string(s, b) (s) -#define ct_encode_string(s, b) (s) - -#else -#include "chartype.h" - -#define Char wchar_t -#define FUN(prefix, rest) prefix ## _w ## rest -#define FUNW(type) type ## _w -#define TYPE(type) type ## W -#define STR(x) L ## x - -#define Strlen(s) wcslen(s) -#define Strdup(s) wcsdup(s) -#define Strcmp(d, s) wcscmp(d, s) -#define Strncmp(d, s, n) wcsncmp(d, s, n) -#define Strncpy(d, s, n) wcsncpy(d, s, n) -#define Strncat(d, s, n) wcsncat(d, s, n) - -#endif - - -typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *); -typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *); -typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *); -typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int); - -struct TYPE(history) { - void *h_ref; /* Argument for history fcns */ - int h_ent; /* Last entry point for history */ - history_gfun_t h_first; /* Get the first element */ - history_gfun_t h_next; /* Get the next element */ - history_gfun_t h_last; /* Get the last element */ - history_gfun_t h_prev; /* Get the previous element */ - history_gfun_t h_curr; /* Get the current element */ - history_sfun_t h_set; /* Set the current element */ - history_sfun_t h_del; /* Set the given element */ - history_vfun_t h_clear; /* Clear the history list */ - history_efun_t h_enter; /* Add an element */ - history_efun_t h_add; /* Append to an element */ -}; - -#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev) -#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev) -#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev) -#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev) -#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev) -#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n) -#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev) -#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str) -#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) -#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) - -#define h_strdup(a) Strdup(a) -#define h_malloc(a) malloc(a) -#define h_realloc(a, b) realloc((a), (b)) -#define h_free(a) free(a) - -typedef struct { - int num; - Char *str; -} HistEventPrivate; - - -static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int); -static int history_getsize(TYPE(History) *, TYPE(HistEvent) *); -static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int); -static int history_getunique(TYPE(History) *, TYPE(HistEvent) *); -static int history_set_fun(TYPE(History) *, TYPE(History) *); -static int history_load(TYPE(History) *, const char *); -static int history_save(TYPE(History) *, const char *); -static int history_save_fp(TYPE(History) *, FILE *); -static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int); -static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int); -static int history_next_string(TYPE(History) *, TYPE(HistEvent) *, - const Char *); -static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, - const Char *); - - -/***********************************************************************/ - -/* - * Builtin- history implementation - */ -typedef struct hentry_t { - TYPE(HistEvent) ev; /* What we return */ - void *data; /* data */ - struct hentry_t *next; /* Next entry */ - struct hentry_t *prev; /* Previous entry */ -} hentry_t; - -typedef struct history_t { - hentry_t list; /* Fake list header element */ - hentry_t *cursor; /* Current element in the list */ - int max; /* Maximum number of events */ - int cur; /* Current number of events */ - int eventid; /* For generation of unique event id */ - int flags; /* TYPE(History) flags */ -#define H_UNIQUE 1 /* Store only unique elements */ -} history_t; - -static int history_def_next(void *, TYPE(HistEvent) *); -static int history_def_first(void *, TYPE(HistEvent) *); -static int history_def_prev(void *, TYPE(HistEvent) *); -static int history_def_last(void *, TYPE(HistEvent) *); -static int history_def_curr(void *, TYPE(HistEvent) *); -static int history_def_set(void *, TYPE(HistEvent) *, const int); -static void history_def_clear(void *, TYPE(HistEvent) *); -static int history_def_enter(void *, TYPE(HistEvent) *, const Char *); -static int history_def_add(void *, TYPE(HistEvent) *, const Char *); -static int history_def_del(void *, TYPE(HistEvent) *, const int); - -static int history_def_init(void **, TYPE(HistEvent) *, int); -static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *); -static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *); - -static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **); -static int history_set_nth(void *, TYPE(HistEvent) *, int); - -#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) -#define history_def_getsize(p) (((history_t *)p)->cur) -#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0) -#define history_def_setunique(p, uni) \ - if (uni) \ - (((history_t *)p)->flags) |= H_UNIQUE; \ - else \ - (((history_t *)p)->flags) &= ~H_UNIQUE - -#define he_strerror(code) he_errlist[code] -#define he_seterrev(evp, code) {\ - evp->num = code;\ - evp->str = he_strerror(code);\ - } - -/* error messages */ -static const Char *const he_errlist[] = { - STR("OK"), - STR("unknown error"), - STR("malloc() failed"), - STR("first event not found"), - STR("last event not found"), - STR("empty list"), - STR("no next event"), - STR("no previous event"), - STR("current event is invalid"), - STR("event not found"), - STR("can't read history from file"), - STR("can't write history"), - STR("required parameter(s) not supplied"), - STR("history size negative"), - STR("function not allowed with other history-functions-set the default"), - STR("bad parameters") -}; -/* error codes */ -#define _HE_OK 0 -#define _HE_UNKNOWN 1 -#define _HE_MALLOC_FAILED 2 -#define _HE_FIRST_NOTFOUND 3 -#define _HE_LAST_NOTFOUND 4 -#define _HE_EMPTY_LIST 5 -#define _HE_END_REACHED 6 -#define _HE_START_REACHED 7 -#define _HE_CURR_INVALID 8 -#define _HE_NOT_FOUND 9 -#define _HE_HIST_READ 10 -#define _HE_HIST_WRITE 11 -#define _HE_PARAM_MISSING 12 -#define _HE_SIZE_NEGATIVE 13 -#define _HE_NOT_ALLOWED 14 -#define _HE_BAD_PARAM 15 - -/* history_def_first(): - * Default function to return the first event in the history. - */ -static int -history_def_first(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - h->cursor = h->list.next; - if (h->cursor != &h->list) - *ev = h->cursor->ev; - else { - he_seterrev(ev, _HE_FIRST_NOTFOUND); - return -1; - } - - return 0; -} - - -/* history_def_last(): - * Default function to return the last event in the history. - */ -static int -history_def_last(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - h->cursor = h->list.prev; - if (h->cursor != &h->list) - *ev = h->cursor->ev; - else { - he_seterrev(ev, _HE_LAST_NOTFOUND); - return -1; - } - - return 0; -} - - -/* history_def_next(): - * Default function to return the next event in the history. - */ -static int -history_def_next(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - if (h->cursor == &h->list) { - he_seterrev(ev, _HE_EMPTY_LIST); - return -1; - } - - if (h->cursor->next == &h->list) { - he_seterrev(ev, _HE_END_REACHED); - return -1; - } - - h->cursor = h->cursor->next; - *ev = h->cursor->ev; - - return 0; -} - - -/* history_def_prev(): - * Default function to return the previous event in the history. - */ -static int -history_def_prev(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - if (h->cursor == &h->list) { - he_seterrev(ev, - (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); - return -1; - } - - if (h->cursor->prev == &h->list) { - he_seterrev(ev, _HE_START_REACHED); - return -1; - } - - h->cursor = h->cursor->prev; - *ev = h->cursor->ev; - - return 0; -} - - -/* history_def_curr(): - * Default function to return the current event in the history. - */ -static int -history_def_curr(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - if (h->cursor != &h->list) - *ev = h->cursor->ev; - else { - he_seterrev(ev, - (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST); - return -1; - } - - return 0; -} - - -/* history_def_set(): - * Default function to set the current event in the history to the - * given one. - */ -static int -history_def_set(void *p, TYPE(HistEvent) *ev, const int n) -{ - history_t *h = (history_t *) p; - - if (h->cur == 0) { - he_seterrev(ev, _HE_EMPTY_LIST); - return -1; - } - if (h->cursor == &h->list || h->cursor->ev.num != n) { - for (h->cursor = h->list.next; h->cursor != &h->list; - h->cursor = h->cursor->next) - if (h->cursor->ev.num == n) - break; - } - if (h->cursor == &h->list) { - he_seterrev(ev, _HE_NOT_FOUND); - return -1; - } - return 0; -} - - -/* history_set_nth(): - * Default function to set the current event in the history to the - * n-th one. - */ -static int -history_set_nth(void *p, TYPE(HistEvent) *ev, int n) -{ - history_t *h = (history_t *) p; - - if (h->cur == 0) { - he_seterrev(ev, _HE_EMPTY_LIST); - return -1; - } - for (h->cursor = h->list.prev; h->cursor != &h->list; - h->cursor = h->cursor->prev) - if (n-- <= 0) - break; - if (h->cursor == &h->list) { - he_seterrev(ev, _HE_NOT_FOUND); - return -1; - } - return 0; -} - - -/* history_def_add(): - * Append string to element - */ -static int -history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str) -{ - history_t *h = (history_t *) p; - size_t len; - Char *s; - HistEventPrivate *evp = (void *)&h->cursor->ev; - - if (h->cursor == &h->list) - return history_def_enter(p, ev, str); - len = Strlen(evp->str) + Strlen(str) + 1; - s = h_malloc(len * sizeof(*s)); - if (s == NULL) { - he_seterrev(ev, _HE_MALLOC_FAILED); - return -1; - } - (void) Strncpy(s, h->cursor->ev.str, len); - s[len - 1] = '\0'; - (void) Strncat(s, str, len - Strlen(s) - 1); - h_free(evp->str); - evp->str = s; - *ev = h->cursor->ev; - return 0; -} - - -static int -history_deldata_nth(history_t *h, TYPE(HistEvent) *ev, - int num, void **data) -{ - if (history_set_nth(h, ev, num) != 0) - return -1; - /* magic value to skip delete (just set to n-th history) */ - if (data == (void **)-1) - return 0; - ev->str = Strdup(h->cursor->ev.str); - ev->num = h->cursor->ev.num; - if (data) - *data = h->cursor->data; - history_def_delete(h, ev, h->cursor); - return 0; -} - - -/* history_def_del(): - * Delete element hp of the h list - */ -/* ARGSUSED */ -static int -history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)), - const int num) -{ - history_t *h = (history_t *) p; - if (history_def_set(h, ev, num) != 0) - return -1; - ev->str = Strdup(h->cursor->ev.str); - ev->num = h->cursor->ev.num; - history_def_delete(h, ev, h->cursor); - return 0; -} - - -/* history_def_delete(): - * Delete element hp of the h list - */ -/* ARGSUSED */ -static void -history_def_delete(history_t *h, - TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp) -{ - HistEventPrivate *evp = (void *)&hp->ev; - if (hp == &h->list) - abort(); - if (h->cursor == hp) { - h->cursor = hp->prev; - if (h->cursor == &h->list) - h->cursor = hp->next; - } - hp->prev->next = hp->next; - hp->next->prev = hp->prev; - h_free(evp->str); - h_free(hp); - h->cur--; -} - - -/* history_def_insert(): - * Insert element with string str in the h list - */ -static int -history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str) -{ - hentry_t *c; - - c = h_malloc(sizeof(*c)); - if (c == NULL) - goto oomem; - if ((c->ev.str = h_strdup(str)) == NULL) { - h_free(c); - goto oomem; - } - c->data = NULL; - c->ev.num = ++h->eventid; - c->next = h->list.next; - c->prev = &h->list; - h->list.next->prev = c; - h->list.next = c; - h->cur++; - h->cursor = c; - - *ev = c->ev; - return 0; -oomem: - he_seterrev(ev, _HE_MALLOC_FAILED); - return -1; -} - - -/* history_def_enter(): - * Default function to enter an item in the history - */ -static int -history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str) -{ - history_t *h = (history_t *) p; - - if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && - Strcmp(h->list.next->ev.str, str) == 0) - return 0; - - if (history_def_insert(h, ev, str) == -1) - return -1; /* error, keep error message */ - - /* - * Always keep at least one entry. - * This way we don't have to check for the empty list. - */ - while (h->cur > h->max && h->cur > 0) - history_def_delete(h, ev, h->list.prev); - - return 1; -} - - -/* history_def_init(): - * Default history initialization function - */ -/* ARGSUSED */ -static int -history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n) -{ - history_t *h = (history_t *) h_malloc(sizeof(*h)); - if (h == NULL) - return -1; - - if (n <= 0) - n = 0; - h->eventid = 0; - h->cur = 0; - h->max = n; - h->list.next = h->list.prev = &h->list; - h->list.ev.str = NULL; - h->list.ev.num = 0; - h->cursor = &h->list; - h->flags = 0; - *p = h; - return 0; -} - - -/* history_def_clear(): - * Default history cleanup function - */ -static void -history_def_clear(void *p, TYPE(HistEvent) *ev) -{ - history_t *h = (history_t *) p; - - while (h->list.prev != &h->list) - history_def_delete(h, ev, h->list.prev); - h->cursor = &h->list; - h->eventid = 0; - h->cur = 0; -} - - - - -/************************************************************************/ - -/* history_init(): - * Initialization function. - */ -TYPE(History) * -FUN(history,init)(void) -{ - TYPE(HistEvent) ev; - TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h)); - if (h == NULL) - return NULL; - - if (history_def_init(&h->h_ref, &ev, 0) == -1) { - h_free(h); - return NULL; - } - h->h_ent = -1; - h->h_next = history_def_next; - h->h_first = history_def_first; - h->h_last = history_def_last; - h->h_prev = history_def_prev; - h->h_curr = history_def_curr; - h->h_set = history_def_set; - h->h_clear = history_def_clear; - h->h_enter = history_def_enter; - h->h_add = history_def_add; - h->h_del = history_def_del; - - return h; -} - - -/* history_end(): - * clean up history; - */ -void -FUN(history,end)(TYPE(History) *h) -{ - TYPE(HistEvent) ev; - - if (h->h_next == history_def_next) - history_def_clear(h->h_ref, &ev); - h_free(h->h_ref); - h_free(h); -} - - - -/* history_setsize(): - * Set history number of events - */ -static int -history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num) -{ - - if (h->h_next != history_def_next) { - he_seterrev(ev, _HE_NOT_ALLOWED); - return -1; - } - if (num < 0) { - he_seterrev(ev, _HE_BAD_PARAM); - return -1; - } - history_def_setsize(h->h_ref, num); - return 0; -} - - -/* history_getsize(): - * Get number of events currently in history - */ -static int -history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev) -{ - if (h->h_next != history_def_next) { - he_seterrev(ev, _HE_NOT_ALLOWED); - return -1; - } - ev->num = history_def_getsize(h->h_ref); - if (ev->num < -1) { - he_seterrev(ev, _HE_SIZE_NEGATIVE); - return -1; - } - return 0; -} - - -/* history_setunique(): - * Set if adjacent equal events should not be entered in history. - */ -static int -history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni) -{ - - if (h->h_next != history_def_next) { - he_seterrev(ev, _HE_NOT_ALLOWED); - return -1; - } - history_def_setunique(h->h_ref, uni); - return 0; -} - - -/* history_getunique(): - * Get if adjacent equal events should not be entered in history. - */ -static int -history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev) -{ - if (h->h_next != history_def_next) { - he_seterrev(ev, _HE_NOT_ALLOWED); - return -1; - } - ev->num = history_def_getunique(h->h_ref); - return 0; -} - - -/* history_set_fun(): - * Set history functions - */ -static int -history_set_fun(TYPE(History) *h, TYPE(History) *nh) -{ - TYPE(HistEvent) ev; - - if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || - nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || - nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || - nh->h_del == NULL || nh->h_ref == NULL) { - if (h->h_next != history_def_next) { - if (history_def_init(&h->h_ref, &ev, 0) == -1) - return -1; - h->h_first = history_def_first; - h->h_next = history_def_next; - h->h_last = history_def_last; - h->h_prev = history_def_prev; - h->h_curr = history_def_curr; - h->h_set = history_def_set; - h->h_clear = history_def_clear; - h->h_enter = history_def_enter; - h->h_add = history_def_add; - h->h_del = history_def_del; - } - return -1; - } - if (h->h_next == history_def_next) - history_def_clear(h->h_ref, &ev); - - h->h_ent = -1; - h->h_first = nh->h_first; - h->h_next = nh->h_next; - h->h_last = nh->h_last; - h->h_prev = nh->h_prev; - h->h_curr = nh->h_curr; - h->h_set = nh->h_set; - h->h_clear = nh->h_clear; - h->h_enter = nh->h_enter; - h->h_add = nh->h_add; - h->h_del = nh->h_del; - - return 0; -} - - -/* history_load(): - * TYPE(History) load function - */ -static int -history_load(TYPE(History) *h, const char *fname) -{ - FILE *fp; - char *line = NULL; - size_t llen; - ssize_t sz; - size_t max_size; - char *ptr; - int i = -1; - TYPE(HistEvent) ev; -#ifndef NARROWCHAR - static ct_buffer_t conv; -#endif - - if ((fp = fopen(fname, "r")) == NULL) - return i; - - if (flock(fileno(fp), LOCK_SH) == -1) - goto done; - - llen = 0; - if ((sz = getline(&line, &llen, fp)) == -1) - goto done; - - if (strncmp(line, hist_cookie, (size_t)sz) != 0) - goto done; - - ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); - if (ptr == NULL) - goto done; - for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) { - if (sz > 0 && line[sz - 1] == '\n') - line[--sz] = '\0'; - if (max_size < (size_t)sz) { - char *nptr; - max_size = ((size_t)sz + 1024) & (size_t)~1023; - nptr = h_realloc(ptr, max_size * sizeof(*ptr)); - if (nptr == NULL) { - i = -1; - goto oomem; - } - ptr = nptr; - } - (void) strunvis(ptr, line); - if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) { - i = -1; - goto oomem; - } - } -oomem: - h_free(ptr); -done: - free(line); - (void) fclose(fp); - return i; -} - - -/* history_save_fp(): - * TYPE(History) save function - */ -static int -history_save_fp(TYPE(History) *h, FILE *fp) -{ - TYPE(HistEvent) ev; - int i = -1, retval; - size_t len, max_size; - char *ptr; - const char *str; -#ifndef NARROWCHAR - static ct_buffer_t conv; -#endif - - if (flock(fileno(fp), LOCK_EX) == -1) - goto done; - if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) - goto done; - if (fputs(hist_cookie, fp) == EOF) - goto done; - ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); - if (ptr == NULL) - goto done; - for (i = 0, retval = HLAST(h, &ev); - retval != -1; - retval = HPREV(h, &ev), i++) { - str = ct_encode_string(ev.str, &conv); - len = strlen(str) * 4 + 1; - if (len > max_size) { - char *nptr; - max_size = (len + 1024) & (size_t)~1023; - nptr = h_realloc(ptr, max_size * sizeof(*ptr)); - if (nptr == NULL) { - i = -1; - goto oomem; - } - ptr = nptr; - } - (void) strvis(ptr, str, VIS_WHITE); - (void) fprintf(fp, "%s\n", ptr); - } -oomem: - h_free(ptr); -done: - (void) flock(fileno(fp), LOCK_UN); - return i; -} - - -/* history_save(): - * History save function - */ -static int -history_save(TYPE(History) *h, const char *fname) -{ - FILE *fp; - int i; - - if ((fp = fopen(fname, "w")) == NULL) - return -1; - - i = history_save_fp(h, fp); - - (void) fclose(fp); - return i; -} - - -static int -history_save_fp_incr(TYPE(History) *h, FILE *fp, int num) -{ - TYPE(HistEvent) ev; - char *line = NULL; - char *ptr; - const char *str; - int i = -1, retval; - size_t len, max_size; - size_t llen = 0; - ssize_t sz; -#ifndef NARROWCHAR - static ct_buffer_t conv; -#endif - - for (retval = HCURR(h, &ev); retval != -1; retval = HNEXT(h, &ev)) - if (ev.num == num) - break; - if (retval == -1) - goto done; - - if (flock(fileno(fp), LOCK_EX) == -1) - goto done; - if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) - goto done; - - if (fseek(fp, 0, SEEK_SET) == -1) - goto done; - if ((sz = getline(&line, &llen, fp)) == -1) { - if (ferror(fp)) - goto done; - else - sz = 0; - } - if (strncmp(line, hist_cookie, (size_t)sz) != 0) - goto done; - if (fseek(fp, 0, SEEK_END) == -1) - goto done; - if (sz == 0) - if (fputs(hist_cookie, fp) == EOF) - goto done; - - ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); - if (ptr == NULL) - goto done; - for (i = 0, retval = 0; - retval != -1; - retval = HPREV(h, &ev), i++) { - str = ct_encode_string(ev.str, &conv); - len = strlen(str) * 4 + 1; - if (len > max_size) { - char *nptr; - max_size = (len + 1024) & (size_t)~1023; - nptr = h_realloc(ptr, max_size * sizeof(*ptr)); - if (nptr == NULL) { - i = -1; - goto oomem; - } - ptr = nptr; - } - (void) strvis(ptr, str, VIS_WHITE); - (void) fprintf(fp, "%s\n", ptr); - } -oomem: - h_free(ptr); -done: - free(line); - (void) flock(fileno(fp), LOCK_UN); - return i; -} - - -static int -history_save_incr(TYPE(History) *h, const char *fname, int num) -{ - FILE *fp; - int i; - - if ((fp = fopen(fname, "a+")) == NULL) - return -1; - - i = history_save_fp_incr(h, fp, num); - - (void) fclose(fp); - return i; -} - - -/* history_prev_event(): - * Find the previous event, with number given - */ -static int -history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) -{ - int retval; - - for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) - if (ev->num == num) - return 0; - - he_seterrev(ev, _HE_NOT_FOUND); - return -1; -} - - -static int -history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d) -{ - int retval; - - for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) - if (ev->num == num) { - if (d) - *d = ((history_t *)h->h_ref)->cursor->data; - return 0; - } - - he_seterrev(ev, _HE_NOT_FOUND); - return -1; -} - - -/* history_next_event(): - * Find the next event, with number given - */ -static int -history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) -{ - int retval; - - for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) - if (ev->num == num) - return 0; - - he_seterrev(ev, _HE_NOT_FOUND); - return -1; -} - - -/* history_prev_string(): - * Find the previous event beginning with string - */ -static int -history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) -{ - size_t len = Strlen(str); - int retval; - - for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) - if (Strncmp(str, ev->str, len) == 0) - return 0; - - he_seterrev(ev, _HE_NOT_FOUND); - return -1; -} - - -/* history_next_string(): - * Find the next event beginning with string - */ -static int -history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) -{ - size_t len = Strlen(str); - int retval; - - for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) - if (Strncmp(str, ev->str, len) == 0) - return 0; - - he_seterrev(ev, _HE_NOT_FOUND); - return -1; -} - - -/* history(): - * User interface to history functions. - */ -int -FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...) -{ - va_list va; - const Char *str; - int retval; - - va_start(va, fun); - - he_seterrev(ev, _HE_OK); - - switch (fun) { - case H_GETSIZE: - retval = history_getsize(h, ev); - break; - - case H_SETSIZE: - retval = history_setsize(h, ev, va_arg(va, int)); - break; - - case H_GETUNIQUE: - retval = history_getunique(h, ev); - break; - - case H_SETUNIQUE: - retval = history_setunique(h, ev, va_arg(va, int)); - break; - - case H_ADD: - str = va_arg(va, const Char *); - retval = HADD(h, ev, str); - break; - - case H_DEL: - retval = HDEL(h, ev, va_arg(va, const int)); - break; - - case H_ENTER: - str = va_arg(va, const Char *); - if ((retval = HENTER(h, ev, str)) != -1) - h->h_ent = ev->num; - break; - - case H_APPEND: - str = va_arg(va, const Char *); - if ((retval = HSET(h, ev, h->h_ent)) != -1) - retval = HADD(h, ev, str); - break; - - case H_FIRST: - retval = HFIRST(h, ev); - break; - - case H_NEXT: - retval = HNEXT(h, ev); - break; - - case H_LAST: - retval = HLAST(h, ev); - break; - - case H_PREV: - retval = HPREV(h, ev); - break; - - case H_CURR: - retval = HCURR(h, ev); - break; - - case H_SET: - retval = HSET(h, ev, va_arg(va, const int)); - break; - - case H_CLEAR: - HCLEAR(h, ev); - retval = 0; - break; - - case H_LOAD: - retval = history_load(h, va_arg(va, const char *)); - if (retval == -1) - he_seterrev(ev, _HE_HIST_READ); - break; - - case H_SAVE: - retval = history_save(h, va_arg(va, const char *)); - if (retval == -1) - he_seterrev(ev, _HE_HIST_WRITE); - break; - - case H_SAVE_INCR: - { - const char *fname = va_arg(va, const char *); - int num = va_arg(va, int); - retval = history_save_incr(h, fname, num); - if (retval == -1) - he_seterrev(ev, _HE_HIST_WRITE); - break; - } - - case H_SAVE_FP: - retval = history_save_fp(h, va_arg(va, FILE *)); - if (retval == -1) - he_seterrev(ev, _HE_HIST_WRITE); - break; - - case H_SAVE_FP_INCR: - { - FILE *fp = va_arg(va, FILE *); - int num = va_arg(va, int); - retval = history_save_fp_incr(h, fp, num); - if (retval == -1) - he_seterrev(ev, _HE_HIST_WRITE); - break; - } - - case H_PREV_EVENT: - retval = history_prev_event(h, ev, va_arg(va, int)); - break; - - case H_NEXT_EVENT: - retval = history_next_event(h, ev, va_arg(va, int)); - break; - - case H_PREV_STR: - retval = history_prev_string(h, ev, va_arg(va, const Char *)); - break; - - case H_NEXT_STR: - retval = history_next_string(h, ev, va_arg(va, const Char *)); - break; - - case H_FUNC: - { - TYPE(History) hf; - - hf.h_ref = va_arg(va, void *); - h->h_ent = -1; - hf.h_first = va_arg(va, history_gfun_t); - hf.h_next = va_arg(va, history_gfun_t); - hf.h_last = va_arg(va, history_gfun_t); - hf.h_prev = va_arg(va, history_gfun_t); - hf.h_curr = va_arg(va, history_gfun_t); - hf.h_set = va_arg(va, history_sfun_t); - hf.h_clear = va_arg(va, history_vfun_t); - hf.h_enter = va_arg(va, history_efun_t); - hf.h_add = va_arg(va, history_efun_t); - hf.h_del = va_arg(va, history_sfun_t); - - if ((retval = history_set_fun(h, &hf)) == -1) - he_seterrev(ev, _HE_PARAM_MISSING); - break; - } - - case H_END: - FUN(history,end)(h); - retval = 0; - break; - - case H_NEXT_EVDATA: - { - int num = va_arg(va, int); - void **d = va_arg(va, void **); - retval = history_next_evdata(h, ev, num, d); - break; - } - - case H_DELDATA: - { - int num = va_arg(va, int); - void **d = va_arg(va, void **); - retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d); - break; - } - - case H_REPLACE: /* only use after H_NEXT_EVDATA */ - { - const Char *line = va_arg(va, const Char *); - void *d = va_arg(va, void *); - const Char *s; - if(!line || !(s = Strdup(line))) { - retval = -1; - break; - } - ((history_t *)h->h_ref)->cursor->ev.str = s; - ((history_t *)h->h_ref)->cursor->data = d; - retval = 0; - break; - } - - default: - retval = -1; - he_seterrev(ev, _HE_UNKNOWN); - break; - } - va_end(va); - return retval; -} diff --git a/bin/catsh/libedit/historyn.c b/bin/catsh/libedit/historyn.c deleted file mode 100644 index 59130dea..00000000 --- a/bin/catsh/libedit/historyn.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" -#define NARROWCHAR -#include "history.c" diff --git a/bin/catsh/libedit/keymacro.c b/bin/catsh/libedit/keymacro.c deleted file mode 100644 index 13d20893..00000000 --- a/bin/catsh/libedit/keymacro.c +++ /dev/null @@ -1,669 +0,0 @@ -/* $NetBSD: keymacro.c,v 1.23 2016/05/24 15:00:45 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: keymacro.c,v 1.23 2016/05/24 15:00:45 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * keymacro.c: This module contains the procedures for maintaining - * the extended-key map. - * - * An extended-key (key) is a sequence of keystrokes introduced - * with a sequence introducer and consisting of an arbitrary - * number of characters. This module maintains a map (the - * el->el_keymacro.map) - * to convert these extended-key sequences into input strs - * (XK_STR) or editor functions (XK_CMD). - * - * Warning: - * If key is a substr of some other keys, then the longer - * keys are lost!! That is, if the keys "abcd" and "abcef" - * are in el->el_keymacro.map, adding the key "abc" will cause - * the first two definitions to be lost. - * - * Restrictions: - * ------------- - * 1) It is not possible to have one key that is a - * substr of another. - */ -#include <stdlib.h> -#include <string.h> - -#include "el.h" -#include "fcns.h" - -/* - * The Nodes of the el->el_keymacro.map. The el->el_keymacro.map is a - * linked list of these node elements - */ -struct keymacro_node_t { - wchar_t ch; /* single character of key */ - int type; /* node type */ - keymacro_value_t val; /* command code or pointer to str, */ - /* if this is a leaf */ - struct keymacro_node_t *next; /* ptr to next char of this key */ - struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/ -}; - -static int node_trav(EditLine *, keymacro_node_t *, wchar_t *, - keymacro_value_t *); -static int node__try(EditLine *, keymacro_node_t *, - const wchar_t *, keymacro_value_t *, int); -static keymacro_node_t *node__get(wint_t); -static void node__free(keymacro_node_t *); -static void node__put(EditLine *, keymacro_node_t *); -static int node__delete(EditLine *, keymacro_node_t **, - const wchar_t *); -static int node_lookup(EditLine *, const wchar_t *, - keymacro_node_t *, size_t); -static int node_enum(EditLine *, keymacro_node_t *, size_t); - -#define KEY_BUFSIZ EL_BUFSIZ - - -/* keymacro_init(): - * Initialize the key maps - */ -libedit_private int -keymacro_init(EditLine *el) -{ - - el->el_keymacro.buf = el_malloc(KEY_BUFSIZ * - sizeof(*el->el_keymacro.buf)); - if (el->el_keymacro.buf == NULL) - return -1; - el->el_keymacro.map = NULL; - keymacro_reset(el); - return 0; -} - -/* keymacro_end(): - * Free the key maps - */ -libedit_private void -keymacro_end(EditLine *el) -{ - - el_free(el->el_keymacro.buf); - el->el_keymacro.buf = NULL; - node__free(el->el_keymacro.map); -} - - -/* keymacro_map_cmd(): - * Associate cmd with a key value - */ -libedit_private keymacro_value_t * -keymacro_map_cmd(EditLine *el, int cmd) -{ - - el->el_keymacro.val.cmd = (el_action_t) cmd; - return &el->el_keymacro.val; -} - - -/* keymacro_map_str(): - * Associate str with a key value - */ -libedit_private keymacro_value_t * -keymacro_map_str(EditLine *el, wchar_t *str) -{ - - el->el_keymacro.val.str = str; - return &el->el_keymacro.val; -} - - -/* keymacro_reset(): - * Takes all nodes on el->el_keymacro.map and puts them on free list. - * Then initializes el->el_keymacro.map with arrow keys - * [Always bind the ansi arrow keys?] - */ -libedit_private void -keymacro_reset(EditLine *el) -{ - - node__put(el, el->el_keymacro.map); - el->el_keymacro.map = NULL; - return; -} - - -/* keymacro_get(): - * Calls the recursive function with entry point el->el_keymacro.map - * Looks up *ch in map and then reads characters until a - * complete match is found or a mismatch occurs. Returns the - * type of the match found (XK_STR or XK_CMD). - * Returns NULL in val.str and XK_STR for no match. - * Returns XK_NOD for end of file or read error. - * The last character read is returned in *ch. - */ -libedit_private int -keymacro_get(EditLine *el, wchar_t *ch, keymacro_value_t *val) -{ - - return node_trav(el, el->el_keymacro.map, ch, val); -} - - -/* keymacro_add(): - * Adds key to the el->el_keymacro.map and associates the value in - * val with it. If key is already is in el->el_keymacro.map, the new - * code is applied to the existing key. Ntype specifies if code is a - * command, an out str or a unix command. - */ -libedit_private void -keymacro_add(EditLine *el, const wchar_t *key, keymacro_value_t *val, - int ntype) -{ - - if (key[0] == '\0') { - (void) fprintf(el->el_errfile, - "keymacro_add: Null extended-key not allowed.\n"); - return; - } - if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) { - (void) fprintf(el->el_errfile, - "keymacro_add: sequence-lead-in command not allowed\n"); - return; - } - if (el->el_keymacro.map == NULL) - /* tree is initially empty. Set up new node to match key[0] */ - el->el_keymacro.map = node__get(key[0]); - /* it is properly initialized */ - - /* Now recurse through el->el_keymacro.map */ - (void) node__try(el, el->el_keymacro.map, key, val, ntype); - return; -} - - -/* keymacro_clear(): - * - */ -libedit_private void -keymacro_clear(EditLine *el, el_action_t *map, const wchar_t *in) -{ - if (*in > N_KEYS) /* can't be in the map */ - return; - if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && - ((map == el->el_map.key && - el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) || - (map == el->el_map.alt && - el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN))) - (void) keymacro_delete(el, in); -} - - -/* keymacro_delete(): - * Delete the key and all longer keys staring with key, if - * they exists. - */ -libedit_private int -keymacro_delete(EditLine *el, const wchar_t *key) -{ - - if (key[0] == '\0') { - (void) fprintf(el->el_errfile, - "keymacro_delete: Null extended-key not allowed.\n"); - return -1; - } - if (el->el_keymacro.map == NULL) - return 0; - - (void) node__delete(el, &el->el_keymacro.map, key); - return 0; -} - - -/* keymacro_print(): - * Print the binding associated with key key. - * Print entire el->el_keymacro.map if null - */ -libedit_private void -keymacro_print(EditLine *el, const wchar_t *key) -{ - - /* do nothing if el->el_keymacro.map is empty and null key specified */ - if (el->el_keymacro.map == NULL && *key == 0) - return; - - el->el_keymacro.buf[0] = '"'; - if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1) - /* key is not bound */ - (void) fprintf(el->el_errfile, "Unbound extended key \"%ls" - "\"\n", key); - return; -} - - -/* node_trav(): - * recursively traverses node in tree until match or mismatch is - * found. May read in more characters. - */ -static int -node_trav(EditLine *el, keymacro_node_t *ptr, wchar_t *ch, - keymacro_value_t *val) -{ - - if (ptr->ch == *ch) { - /* match found */ - if (ptr->next) { - /* key not complete so get next char */ - if (el_wgetc(el, ch) != 1) - return XK_NOD; - return node_trav(el, ptr->next, ch, val); - } else { - *val = ptr->val; - if (ptr->type != XK_CMD) - *ch = '\0'; - return ptr->type; - } - } else { - /* no match found here */ - if (ptr->sibling) { - /* try next sibling */ - return node_trav(el, ptr->sibling, ch, val); - } else { - /* no next sibling -- mismatch */ - val->str = NULL; - return XK_STR; - } - } -} - - -/* node__try(): - * Find a node that matches *str or allocate a new one - */ -static int -node__try(EditLine *el, keymacro_node_t *ptr, const wchar_t *str, - keymacro_value_t *val, int ntype) -{ - - if (ptr->ch != *str) { - keymacro_node_t *xm; - - for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) - if (xm->sibling->ch == *str) - break; - if (xm->sibling == NULL) - xm->sibling = node__get(*str); /* setup new node */ - ptr = xm->sibling; - } - if (*++str == '\0') { - /* we're there */ - if (ptr->next != NULL) { - node__put(el, ptr->next); - /* lose longer keys with this prefix */ - ptr->next = NULL; - } - switch (ptr->type) { - case XK_CMD: - case XK_NOD: - break; - case XK_STR: - if (ptr->val.str) - el_free(ptr->val.str); - break; - default: - EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", - ptr->type)); - break; - } - - switch (ptr->type = ntype) { - case XK_CMD: - ptr->val = *val; - break; - case XK_STR: - if ((ptr->val.str = wcsdup(val->str)) == NULL) - return -1; - break; - default: - EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); - break; - } - } else { - /* still more chars to go */ - if (ptr->next == NULL) - ptr->next = node__get(*str); /* setup new node */ - (void) node__try(el, ptr->next, str, val, ntype); - } - return 0; -} - - -/* node__delete(): - * Delete node that matches str - */ -static int -node__delete(EditLine *el, keymacro_node_t **inptr, const wchar_t *str) -{ - keymacro_node_t *ptr; - keymacro_node_t *prev_ptr = NULL; - - ptr = *inptr; - - if (ptr->ch != *str) { - keymacro_node_t *xm; - - for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) - if (xm->sibling->ch == *str) - break; - if (xm->sibling == NULL) - return 0; - prev_ptr = xm; - ptr = xm->sibling; - } - if (*++str == '\0') { - /* we're there */ - if (prev_ptr == NULL) - *inptr = ptr->sibling; - else - prev_ptr->sibling = ptr->sibling; - ptr->sibling = NULL; - node__put(el, ptr); - return 1; - } else if (ptr->next != NULL && - node__delete(el, &ptr->next, str) == 1) { - if (ptr->next != NULL) - return 0; - if (prev_ptr == NULL) - *inptr = ptr->sibling; - else - prev_ptr->sibling = ptr->sibling; - ptr->sibling = NULL; - node__put(el, ptr); - return 1; - } else { - return 0; - } -} - - -/* node__put(): - * Puts a tree of nodes onto free list using free(3). - */ -static void -node__put(EditLine *el, keymacro_node_t *ptr) -{ - if (ptr == NULL) - return; - - if (ptr->next != NULL) { - node__put(el, ptr->next); - ptr->next = NULL; - } - node__put(el, ptr->sibling); - - switch (ptr->type) { - case XK_CMD: - case XK_NOD: - break; - case XK_STR: - if (ptr->val.str != NULL) - el_free(ptr->val.str); - break; - default: - EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type)); - break; - } - el_free(ptr); -} - - -/* node__get(): - * Returns pointer to a keymacro_node_t for ch. - */ -static keymacro_node_t * -node__get(wint_t ch) -{ - keymacro_node_t *ptr; - - ptr = el_malloc(sizeof(*ptr)); - if (ptr == NULL) - return NULL; - ptr->ch = ch; - ptr->type = XK_NOD; - ptr->val.str = NULL; - ptr->next = NULL; - ptr->sibling = NULL; - return ptr; -} - -static void -node__free(keymacro_node_t *k) -{ - if (k == NULL) - return; - node__free(k->sibling); - node__free(k->next); - el_free(k); -} - -/* node_lookup(): - * look for the str starting at node ptr. - * Print if last node - */ -static int -node_lookup(EditLine *el, const wchar_t *str, keymacro_node_t *ptr, - size_t cnt) -{ - ssize_t used; - - if (ptr == NULL) - return -1; /* cannot have null ptr */ - - if (!str || *str == 0) { - /* no more chars in str. node_enum from here. */ - (void) node_enum(el, ptr, cnt); - return 0; - } else { - /* If match put this char into el->el_keymacro.buf. Recurse */ - if (ptr->ch == *str) { - /* match found */ - used = ct_visual_char(el->el_keymacro.buf + cnt, - KEY_BUFSIZ - cnt, ptr->ch); - if (used == -1) - return -1; /* ran out of buffer space */ - if (ptr->next != NULL) - /* not yet at leaf */ - return (node_lookup(el, str + 1, ptr->next, - (size_t)used + cnt)); - else { - /* next node is null so key should be complete */ - if (str[1] == 0) { - size_t px = cnt + (size_t)used; - el->el_keymacro.buf[px] = '"'; - el->el_keymacro.buf[px + 1] = '\0'; - keymacro_kprint(el, el->el_keymacro.buf, - &ptr->val, ptr->type); - return 0; - } else - return -1; - /* mismatch -- str still has chars */ - } - } else { - /* no match found try sibling */ - if (ptr->sibling) - return (node_lookup(el, str, ptr->sibling, - cnt)); - else - return -1; - } - } -} - - -/* node_enum(): - * Traverse the node printing the characters it is bound in buffer - */ -static int -node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt) -{ - ssize_t used; - - if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */ - el->el_keymacro.buf[++cnt] = '"'; - el->el_keymacro.buf[++cnt] = '\0'; - (void) fprintf(el->el_errfile, - "Some extended keys too long for internal print buffer"); - (void) fprintf(el->el_errfile, " \"%ls...\"\n", - el->el_keymacro.buf); - return 0; - } - if (ptr == NULL) { -#ifdef DEBUG_EDIT - (void) fprintf(el->el_errfile, - "node_enum: BUG!! Null ptr passed\n!"); -#endif - return -1; - } - /* put this char at end of str */ - used = ct_visual_char(el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt, - ptr->ch); - if (ptr->next == NULL) { - /* print this key and function */ - el->el_keymacro.buf[cnt + (size_t)used ] = '"'; - el->el_keymacro.buf[cnt + (size_t)used + 1] = '\0'; - keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type); - } else - (void) node_enum(el, ptr->next, cnt + (size_t)used); - - /* go to sibling if there is one */ - if (ptr->sibling) - (void) node_enum(el, ptr->sibling, cnt); - return 0; -} - - -/* keymacro_kprint(): - * Print the specified key and its associated - * function specified by val - */ -libedit_private void -keymacro_kprint(EditLine *el, const wchar_t *key, keymacro_value_t *val, - int ntype) -{ - el_bindings_t *fp; - char unparsbuf[EL_BUFSIZ]; - static const char fmt[] = "%-15s-> %s\n"; - - if (val != NULL) - switch (ntype) { - case XK_STR: - (void) keymacro__decode_str(val->str, unparsbuf, - sizeof(unparsbuf), - ntype == XK_STR ? "\"\"" : "[]"); - (void) fprintf(el->el_outfile, fmt, - ct_encode_string(key, &el->el_scratch), unparsbuf); - break; - case XK_CMD: - for (fp = el->el_map.help; fp->name; fp++) - if (val->cmd == fp->func) { - wcstombs(unparsbuf, fp->name, sizeof(unparsbuf)); - unparsbuf[sizeof(unparsbuf) -1] = '\0'; - (void) fprintf(el->el_outfile, fmt, - ct_encode_string(key, &el->el_scratch), unparsbuf); - break; - } -#ifdef DEBUG_KEY - if (fp->name == NULL) - (void) fprintf(el->el_outfile, - "BUG! Command not found.\n"); -#endif - - break; - default: - EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); - break; - } - else - (void) fprintf(el->el_outfile, fmt, ct_encode_string(key, - &el->el_scratch), "no input"); -} - - -#define ADDC(c) \ - if (b < eb) \ - *b++ = c; \ - else \ - b++ -/* keymacro__decode_str(): - * Make a printable version of the ey - */ -libedit_private size_t -keymacro__decode_str(const wchar_t *str, char *buf, size_t len, - const char *sep) -{ - char *b = buf, *eb = b + len; - const wchar_t *p; - - b = buf; - if (sep[0] != '\0') { - ADDC(sep[0]); - } - if (*str == '\0') { - ADDC('^'); - ADDC('@'); - goto add_endsep; - } - for (p = str; *p != 0; p++) { - wchar_t dbuf[VISUAL_WIDTH_MAX]; - wchar_t *p2 = dbuf; - ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p); - while (l-- > 0) { - ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++); - if (n == -1) /* ran out of space */ - goto add_endsep; - else - b += n; - } - } -add_endsep: - if (sep[0] != '\0' && sep[1] != '\0') { - ADDC(sep[1]); - } - ADDC('\0'); - if ((size_t)(b - buf) >= len) - buf[len - 1] = '\0'; - return (size_t)(b - buf); -} diff --git a/bin/catsh/libedit/keymacro.h b/bin/catsh/libedit/keymacro.h deleted file mode 100644 index 0653bbe3..00000000 --- a/bin/catsh/libedit/keymacro.h +++ /dev/null @@ -1,76 +0,0 @@ -/* $NetBSD: keymacro.h,v 1.6 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)key.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.keymacro.h: Key macro header - */ -#ifndef _h_el_keymacro -#define _h_el_keymacro - -typedef union keymacro_value_t { - el_action_t cmd; /* If it is a command the # */ - wchar_t *str; /* If it is a string... */ -} keymacro_value_t; - -typedef struct keymacro_node_t keymacro_node_t; - -typedef struct el_keymacro_t { - wchar_t *buf; /* Key print buffer */ - keymacro_node_t *map; /* Key map */ - keymacro_value_t val; /* Local conversion buffer */ -} el_keymacro_t; - -#define XK_CMD 0 -#define XK_STR 1 -#define XK_NOD 2 - -libedit_private int keymacro_init(EditLine *); -libedit_private void keymacro_end(EditLine *); -libedit_private keymacro_value_t *keymacro_map_cmd(EditLine *, int); -libedit_private keymacro_value_t *keymacro_map_str(EditLine *, wchar_t *); -libedit_private void keymacro_reset(EditLine *); -libedit_private int keymacro_get(EditLine *, wchar_t *, keymacro_value_t *); -libedit_private void keymacro_add(EditLine *, const wchar_t *, - keymacro_value_t *, int); -libedit_private void keymacro_clear(EditLine *, el_action_t *, const wchar_t *); -libedit_private int keymacro_delete(EditLine *, const wchar_t *); -libedit_private void keymacro_print(EditLine *, const wchar_t *); -libedit_private void keymacro_kprint(EditLine *, const wchar_t *, - keymacro_value_t *, int); -libedit_private size_t keymacro__decode_str(const wchar_t *, char *, size_t, - const char *); - -#endif /* _h_el_keymacro */ diff --git a/bin/catsh/libedit/literal.c b/bin/catsh/libedit/literal.c deleted file mode 100644 index 816dc3ce..00000000 --- a/bin/catsh/libedit/literal.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $NetBSD: literal.c,v 1.3.4.2 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 2017 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: literal.c,v 1.3.4.2 2017/07/23 14:41:26 snj Exp $"); -#endif /* not lint && not SCCSID */ - -/* - * literal.c: Literal sequences handling. - */ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "el.h" - -libedit_private void -literal_init(EditLine *el) -{ - el_literal_t *l = &el->el_literal; - - memset(l, 0, sizeof(*l)); -} - -libedit_private void -literal_end(EditLine *el) -{ - literal_clear(el); -} - -libedit_private void -literal_clear(EditLine *el) -{ - el_literal_t *l = &el->el_literal; - size_t i; - - if (l->l_len == 0) - return; - - for (i = 0; i < l->l_idx; i++) - el_free(l->l_buf[i]); - el_free(l->l_buf); - l->l_buf = NULL; - l->l_len = 0; - l->l_idx = 0; -} - -libedit_private wint_t -literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp) -{ - el_literal_t *l = &el->el_literal; - size_t i, len; - ssize_t w, n; - char *b; - - w = wcwidth(end[1]); /* column width of the visible char */ - *wp = (int)w; - - if (w <= 0) /* we require something to be printed */ - return 0; - - len = (size_t)(end - buf); - for (w = 0, i = 0; i < len; i++) - w += ct_enc_width(buf[i]); - w += ct_enc_width(end[1]); - - b = el_malloc((size_t)(w + 1)); - if (b == NULL) - return 0; - - for (n = 0, i = 0; i < len; i++) - n += ct_encode_char(b + n, w - n, buf[i]); - n += ct_encode_char(b + n, w - n, end[1]); - b[n] = '\0'; - - /* - * Then save this literal string in the list of such strings, - * and return a "magic character" to put into the terminal buffer. - * When that magic char is 'printed' the saved string (which includes - * the char that belongs in that position) gets sent instead. - */ - if (l->l_idx == l->l_len) { - char **bp; - - l->l_len += 4; - bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * l->l_len); - if (bp == NULL) { - free(b); - l->l_len -= 4; - return 0; - } - l->l_buf = bp; - } - l->l_buf[l->l_idx++] = b; - return EL_LITERAL | (wint_t)(l->l_idx - 1); -} - -libedit_private const char * -literal_get(EditLine *el, wint_t idx) -{ - el_literal_t *l = &el->el_literal; - - assert(idx & EL_LITERAL); - idx &= ~EL_LITERAL; - assert(l->l_idx > (size_t)idx); - return l->l_buf[idx]; -} diff --git a/bin/catsh/libedit/literal.h b/bin/catsh/libedit/literal.h deleted file mode 100644 index d1929505..00000000 --- a/bin/catsh/libedit/literal.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $NetBSD: literal.h,v 1.2.4.2 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 2017 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * el.literal.h: Literal character - */ -#ifndef _h_el_literal -#define _h_el_literal - -#define EL_LITERAL ((wint_t)0x80000000) - -typedef struct el_literal_t { - char **l_buf; /* array of buffers */ - size_t l_idx; /* max in use */ - size_t l_len; /* max allocated */ -} el_literal_t; - -libedit_private void literal_init(EditLine *); -libedit_private void literal_end(EditLine *); -libedit_private void literal_clear(EditLine *); -libedit_private wint_t literal_add(EditLine *, const wchar_t *, - const wchar_t *, int *); -libedit_private const char *literal_get(EditLine *, wint_t); - -#endif /* _h_el_literal */ diff --git a/bin/catsh/libedit/makelist b/bin/catsh/libedit/makelist deleted file mode 100644 index c8f92765..00000000 --- a/bin/catsh/libedit/makelist +++ /dev/null @@ -1,174 +0,0 @@ -#!/bin/sh - -# $NetBSD: makelist,v 1.29 2016/05/09 21:46:56 christos Exp $ -# -# Copyright (c) 1992, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Christos Zoulas of Cornell University. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)makelist 5.3 (Berkeley) 6/4/93 - -# makelist.sh: Automatically generate header files... - -AWK=awk -USAGE="Usage: $0 -h|-fc|-fh|-bh <filenames>" - -if [ "x$1" = "x" ] -then - echo $USAGE 1>&2 - exit 1 -fi - -FLAG="$1" -shift - -FILES="$@" - -case $FLAG in - --h) - set - `echo $FILES | sed -e 's/\\./_/g'` - hdr="_h_`basename $1`" - cat $FILES | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'"); - } - /\(\):/ { - pr = substr($2, 1, 2); - if (pr == "vi" || pr == "em" || pr == "ed") { - name = substr($2, 1, length($2) - 3); -# -# XXX: need a space between name and prototype so that -fc and -fh -# parsing is much easier -# - printf("libedit_private el_action_t\t%s (EditLine *, wint_t);\n", - name); - } - } - END { - printf("#endif /* %s */\n", "'$hdr'"); - }' - ;; - -# generate help.h from various .c files -# --bh) - cat $FILES | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("static const struct el_bindings_t el_func_help[] = {\n"); - low = "abcdefghijklmnopqrstuvwxyz_"; - high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; - for (i = 1; i <= length(low); i++) - tr[substr(low, i, 1)] = substr(high, i, 1); - } - /\(\):/ { - pr = substr($2, 1, 2); - if (pr == "vi" || pr == "em" || pr == "ed") { - name = substr($2, 1, length($2) - 3); - uname = ""; - fname = ""; - for (i = 1; i <= length(name); i++) { - s = substr(name, i, 1); - uname = uname tr[s]; - if (s == "_") - s = "-"; - fname = fname s; - } - - printf(" { %-30.30s %-30.30s\n","L\"" fname "\",", uname ","); - ok = 1; - } - } - /^ \*/ { - if (ok) { - printf(" L\""); - for (i = 2; i < NF; i++) - printf("%s ", $i); - printf("%s\" },\n", $i); - ok = 0; - } - } - END { - printf("};\n"); - }' - ;; - -# generate fcns.h from various .h files -# --fh) - cat $FILES | $AWK '/el_action_t/ { print $3 }' | \ - sort | tr '[:lower:]' '[:upper:]' | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - count = 0; - } - { - printf("#define\t%-30.30s\t%3d\n", $1, count++); - } - END { - printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count); - }' - ;; - -# generate func.h from various .h files -# --fc) - cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("static const el_func_t el_func[] = {"); - maxlen = 80; - needn = 1; - len = 0; - } - { - clen = 25 + 2; - len += clen; - if (len >= maxlen) - needn = 1; - if (needn) { - printf("\n "); - needn = 0; - len = 4 + clen; - } - s = $1 ","; - printf("%-26.26s ", s); - } - END { - printf("\n};\n"); - }' - ;; - -*) - echo $USAGE 1>&2 - exit 1 - ;; - -esac diff --git a/bin/catsh/libedit/map.c b/bin/catsh/libedit/map.c deleted file mode 100644 index f72d2724..00000000 --- a/bin/catsh/libedit/map.c +++ /dev/null @@ -1,1427 +0,0 @@ -/* $NetBSD: map.c,v 1.51 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: map.c,v 1.51 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * map.c: Editor function definitions - */ -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#include "el.h" -#include "common.h" -#include "emacs.h" -#include "vi.h" -#include "fcns.h" -#include "func.h" -#include "help.h" -#include "parse.h" - -static void map_print_key(EditLine *, el_action_t *, const wchar_t *); -static void map_print_some_keys(EditLine *, el_action_t *, wint_t, wint_t); -static void map_print_all_keys(EditLine *); -static void map_init_nls(EditLine *); -static void map_init_meta(EditLine *); - -/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */ - - -static const el_action_t el_map_emacs[] = { - /* 0 */ EM_SET_MARK, /* ^@ */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ - /* 2 */ ED_PREV_CHAR, /* ^B */ - /* 3 */ ED_IGNORE, /* ^C */ - /* 4 */ EM_DELETE_OR_LIST, /* ^D */ - /* 5 */ ED_MOVE_TO_END, /* ^E */ - /* 6 */ ED_NEXT_CHAR, /* ^F */ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ EM_DELETE_PREV_CHAR, /* ^H */ - /* 9 */ ED_UNASSIGNED, /* ^I */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_IGNORE, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_IGNORE, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_IGNORE, /* ^S */ - /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ - /* 21 */ EM_KILL_LINE, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ EM_KILL_REGION, /* ^W */ - /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */ - /* 25 */ EM_YANK, /* ^Y */ - /* 26 */ ED_IGNORE, /* ^Z */ - /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_IGNORE, /* ^\ */ - /* 29 */ ED_IGNORE, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ - /* 32 */ ED_INSERT, /* SPACE */ - /* 33 */ ED_INSERT, /* ! */ - /* 34 */ ED_INSERT, /* " */ - /* 35 */ ED_INSERT, /* # */ - /* 36 */ ED_INSERT, /* $ */ - /* 37 */ ED_INSERT, /* % */ - /* 38 */ ED_INSERT, /* & */ - /* 39 */ ED_INSERT, /* ' */ - /* 40 */ ED_INSERT, /* ( */ - /* 41 */ ED_INSERT, /* ) */ - /* 42 */ ED_INSERT, /* * */ - /* 43 */ ED_INSERT, /* + */ - /* 44 */ ED_INSERT, /* , */ - /* 45 */ ED_INSERT, /* - */ - /* 46 */ ED_INSERT, /* . */ - /* 47 */ ED_INSERT, /* / */ - /* 48 */ ED_DIGIT, /* 0 */ - /* 49 */ ED_DIGIT, /* 1 */ - /* 50 */ ED_DIGIT, /* 2 */ - /* 51 */ ED_DIGIT, /* 3 */ - /* 52 */ ED_DIGIT, /* 4 */ - /* 53 */ ED_DIGIT, /* 5 */ - /* 54 */ ED_DIGIT, /* 6 */ - /* 55 */ ED_DIGIT, /* 7 */ - /* 56 */ ED_DIGIT, /* 8 */ - /* 57 */ ED_DIGIT, /* 9 */ - /* 58 */ ED_INSERT, /* : */ - /* 59 */ ED_INSERT, /* ; */ - /* 60 */ ED_INSERT, /* < */ - /* 61 */ ED_INSERT, /* = */ - /* 62 */ ED_INSERT, /* > */ - /* 63 */ ED_INSERT, /* ? */ - /* 64 */ ED_INSERT, /* @ */ - /* 65 */ ED_INSERT, /* A */ - /* 66 */ ED_INSERT, /* B */ - /* 67 */ ED_INSERT, /* C */ - /* 68 */ ED_INSERT, /* D */ - /* 69 */ ED_INSERT, /* E */ - /* 70 */ ED_INSERT, /* F */ - /* 71 */ ED_INSERT, /* G */ - /* 72 */ ED_INSERT, /* H */ - /* 73 */ ED_INSERT, /* I */ - /* 74 */ ED_INSERT, /* J */ - /* 75 */ ED_INSERT, /* K */ - /* 76 */ ED_INSERT, /* L */ - /* 77 */ ED_INSERT, /* M */ - /* 78 */ ED_INSERT, /* N */ - /* 79 */ ED_INSERT, /* O */ - /* 80 */ ED_INSERT, /* P */ - /* 81 */ ED_INSERT, /* Q */ - /* 82 */ ED_INSERT, /* R */ - /* 83 */ ED_INSERT, /* S */ - /* 84 */ ED_INSERT, /* T */ - /* 85 */ ED_INSERT, /* U */ - /* 86 */ ED_INSERT, /* V */ - /* 87 */ ED_INSERT, /* W */ - /* 88 */ ED_INSERT, /* X */ - /* 89 */ ED_INSERT, /* Y */ - /* 90 */ ED_INSERT, /* Z */ - /* 91 */ ED_INSERT, /* [ */ - /* 92 */ ED_INSERT, /* \ */ - /* 93 */ ED_INSERT, /* ] */ - /* 94 */ ED_INSERT, /* ^ */ - /* 95 */ ED_INSERT, /* _ */ - /* 96 */ ED_INSERT, /* ` */ - /* 97 */ ED_INSERT, /* a */ - /* 98 */ ED_INSERT, /* b */ - /* 99 */ ED_INSERT, /* c */ - /* 100 */ ED_INSERT, /* d */ - /* 101 */ ED_INSERT, /* e */ - /* 102 */ ED_INSERT, /* f */ - /* 103 */ ED_INSERT, /* g */ - /* 104 */ ED_INSERT, /* h */ - /* 105 */ ED_INSERT, /* i */ - /* 106 */ ED_INSERT, /* j */ - /* 107 */ ED_INSERT, /* k */ - /* 108 */ ED_INSERT, /* l */ - /* 109 */ ED_INSERT, /* m */ - /* 110 */ ED_INSERT, /* n */ - /* 111 */ ED_INSERT, /* o */ - /* 112 */ ED_INSERT, /* p */ - /* 113 */ ED_INSERT, /* q */ - /* 114 */ ED_INSERT, /* r */ - /* 115 */ ED_INSERT, /* s */ - /* 116 */ ED_INSERT, /* t */ - /* 117 */ ED_INSERT, /* u */ - /* 118 */ ED_INSERT, /* v */ - /* 119 */ ED_INSERT, /* w */ - /* 120 */ ED_INSERT, /* x */ - /* 121 */ ED_INSERT, /* y */ - /* 122 */ ED_INSERT, /* z */ - /* 123 */ ED_INSERT, /* { */ - /* 124 */ ED_INSERT, /* | */ - /* 125 */ ED_INSERT, /* } */ - /* 126 */ ED_INSERT, /* ~ */ - /* 127 */ EM_DELETE_PREV_CHAR, /* ^? */ - /* 128 */ ED_UNASSIGNED, /* M-^@ */ - /* 129 */ ED_UNASSIGNED, /* M-^A */ - /* 130 */ ED_UNASSIGNED, /* M-^B */ - /* 131 */ ED_UNASSIGNED, /* M-^C */ - /* 132 */ ED_UNASSIGNED, /* M-^D */ - /* 133 */ ED_UNASSIGNED, /* M-^E */ - /* 134 */ ED_UNASSIGNED, /* M-^F */ - /* 135 */ ED_UNASSIGNED, /* M-^G */ - /* 136 */ ED_DELETE_PREV_WORD, /* M-^H */ - /* 137 */ ED_UNASSIGNED, /* M-^I */ - /* 138 */ ED_UNASSIGNED, /* M-^J */ - /* 139 */ ED_UNASSIGNED, /* M-^K */ - /* 140 */ ED_CLEAR_SCREEN, /* M-^L */ - /* 141 */ ED_UNASSIGNED, /* M-^M */ - /* 142 */ ED_UNASSIGNED, /* M-^N */ - /* 143 */ ED_UNASSIGNED, /* M-^O */ - /* 144 */ ED_UNASSIGNED, /* M-^P */ - /* 145 */ ED_UNASSIGNED, /* M-^Q */ - /* 146 */ ED_UNASSIGNED, /* M-^R */ - /* 147 */ ED_UNASSIGNED, /* M-^S */ - /* 148 */ ED_UNASSIGNED, /* M-^T */ - /* 149 */ ED_UNASSIGNED, /* M-^U */ - /* 150 */ ED_UNASSIGNED, /* M-^V */ - /* 151 */ ED_UNASSIGNED, /* M-^W */ - /* 152 */ ED_UNASSIGNED, /* M-^X */ - /* 153 */ ED_UNASSIGNED, /* M-^Y */ - /* 154 */ ED_UNASSIGNED, /* M-^Z */ - /* 155 */ ED_UNASSIGNED, /* M-^[ */ - /* 156 */ ED_UNASSIGNED, /* M-^\ */ - /* 157 */ ED_UNASSIGNED, /* M-^] */ - /* 158 */ ED_UNASSIGNED, /* M-^^ */ - /* 159 */ EM_COPY_PREV_WORD, /* M-^_ */ - /* 160 */ ED_UNASSIGNED, /* M-SPACE */ - /* 161 */ ED_UNASSIGNED, /* M-! */ - /* 162 */ ED_UNASSIGNED, /* M-" */ - /* 163 */ ED_UNASSIGNED, /* M-# */ - /* 164 */ ED_UNASSIGNED, /* M-$ */ - /* 165 */ ED_UNASSIGNED, /* M-% */ - /* 166 */ ED_UNASSIGNED, /* M-& */ - /* 167 */ ED_UNASSIGNED, /* M-' */ - /* 168 */ ED_UNASSIGNED, /* M-( */ - /* 169 */ ED_UNASSIGNED, /* M-) */ - /* 170 */ ED_UNASSIGNED, /* M-* */ - /* 171 */ ED_UNASSIGNED, /* M-+ */ - /* 172 */ ED_UNASSIGNED, /* M-, */ - /* 173 */ ED_UNASSIGNED, /* M-- */ - /* 174 */ ED_UNASSIGNED, /* M-. */ - /* 175 */ ED_UNASSIGNED, /* M-/ */ - /* 176 */ ED_ARGUMENT_DIGIT, /* M-0 */ - /* 177 */ ED_ARGUMENT_DIGIT, /* M-1 */ - /* 178 */ ED_ARGUMENT_DIGIT, /* M-2 */ - /* 179 */ ED_ARGUMENT_DIGIT, /* M-3 */ - /* 180 */ ED_ARGUMENT_DIGIT, /* M-4 */ - /* 181 */ ED_ARGUMENT_DIGIT, /* M-5 */ - /* 182 */ ED_ARGUMENT_DIGIT, /* M-6 */ - /* 183 */ ED_ARGUMENT_DIGIT, /* M-7 */ - /* 184 */ ED_ARGUMENT_DIGIT, /* M-8 */ - /* 185 */ ED_ARGUMENT_DIGIT, /* M-9 */ - /* 186 */ ED_UNASSIGNED, /* M-: */ - /* 187 */ ED_UNASSIGNED, /* M-; */ - /* 188 */ ED_UNASSIGNED, /* M-< */ - /* 189 */ ED_UNASSIGNED, /* M-= */ - /* 190 */ ED_UNASSIGNED, /* M-> */ - /* 191 */ ED_UNASSIGNED, /* M-? */ - /* 192 */ ED_UNASSIGNED, /* M-@ */ - /* 193 */ ED_UNASSIGNED, /* M-A */ - /* 194 */ ED_PREV_WORD, /* M-B */ - /* 195 */ EM_CAPITOL_CASE, /* M-C */ - /* 196 */ EM_DELETE_NEXT_WORD, /* M-D */ - /* 197 */ ED_UNASSIGNED, /* M-E */ - /* 198 */ EM_NEXT_WORD, /* M-F */ - /* 199 */ ED_UNASSIGNED, /* M-G */ - /* 200 */ ED_UNASSIGNED, /* M-H */ - /* 201 */ ED_UNASSIGNED, /* M-I */ - /* 202 */ ED_UNASSIGNED, /* M-J */ - /* 203 */ ED_UNASSIGNED, /* M-K */ - /* 204 */ EM_LOWER_CASE, /* M-L */ - /* 205 */ ED_UNASSIGNED, /* M-M */ - /* 206 */ ED_SEARCH_NEXT_HISTORY, /* M-N */ - /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */ - /* 208 */ ED_SEARCH_PREV_HISTORY, /* M-P */ - /* 209 */ ED_UNASSIGNED, /* M-Q */ - /* 210 */ ED_UNASSIGNED, /* M-R */ - /* 211 */ ED_UNASSIGNED, /* M-S */ - /* 212 */ ED_UNASSIGNED, /* M-T */ - /* 213 */ EM_UPPER_CASE, /* M-U */ - /* 214 */ ED_UNASSIGNED, /* M-V */ - /* 215 */ EM_COPY_REGION, /* M-W */ - /* 216 */ ED_COMMAND, /* M-X */ - /* 217 */ ED_UNASSIGNED, /* M-Y */ - /* 218 */ ED_UNASSIGNED, /* M-Z */ - /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */ - /* 220 */ ED_UNASSIGNED, /* M-\ */ - /* 221 */ ED_UNASSIGNED, /* M-] */ - /* 222 */ ED_UNASSIGNED, /* M-^ */ - /* 223 */ ED_UNASSIGNED, /* M-_ */ - /* 223 */ ED_UNASSIGNED, /* M-` */ - /* 224 */ ED_UNASSIGNED, /* M-a */ - /* 225 */ ED_PREV_WORD, /* M-b */ - /* 226 */ EM_CAPITOL_CASE, /* M-c */ - /* 227 */ EM_DELETE_NEXT_WORD, /* M-d */ - /* 228 */ ED_UNASSIGNED, /* M-e */ - /* 229 */ EM_NEXT_WORD, /* M-f */ - /* 230 */ ED_UNASSIGNED, /* M-g */ - /* 231 */ ED_UNASSIGNED, /* M-h */ - /* 232 */ ED_UNASSIGNED, /* M-i */ - /* 233 */ ED_UNASSIGNED, /* M-j */ - /* 234 */ ED_UNASSIGNED, /* M-k */ - /* 235 */ EM_LOWER_CASE, /* M-l */ - /* 236 */ ED_UNASSIGNED, /* M-m */ - /* 237 */ ED_SEARCH_NEXT_HISTORY, /* M-n */ - /* 238 */ ED_UNASSIGNED, /* M-o */ - /* 239 */ ED_SEARCH_PREV_HISTORY, /* M-p */ - /* 240 */ ED_UNASSIGNED, /* M-q */ - /* 241 */ ED_UNASSIGNED, /* M-r */ - /* 242 */ ED_UNASSIGNED, /* M-s */ - /* 243 */ ED_UNASSIGNED, /* M-t */ - /* 244 */ EM_UPPER_CASE, /* M-u */ - /* 245 */ ED_UNASSIGNED, /* M-v */ - /* 246 */ EM_COPY_REGION, /* M-w */ - /* 247 */ ED_COMMAND, /* M-x */ - /* 248 */ ED_UNASSIGNED, /* M-y */ - /* 249 */ ED_UNASSIGNED, /* M-z */ - /* 250 */ ED_UNASSIGNED, /* M-{ */ - /* 251 */ ED_UNASSIGNED, /* M-| */ - /* 252 */ ED_UNASSIGNED, /* M-} */ - /* 253 */ ED_UNASSIGNED, /* M-~ */ - /* 254 */ ED_DELETE_PREV_WORD /* M-^? */ - /* 255 */ -}; - - -/* - * keymap table for vi. Each index into above tbl; should be - * N_KEYS entries long. Vi mode uses a sticky-extend to do command mode: - * insert mode characters are in the normal keymap, and command mode - * in the extended keymap. - */ -static const el_action_t el_map_vi_insert[] = { -#ifdef KSHVI - /* 0 */ ED_UNASSIGNED, /* ^@ */ - /* 1 */ ED_INSERT, /* ^A */ - /* 2 */ ED_INSERT, /* ^B */ - /* 3 */ ED_INSERT, /* ^C */ - /* 4 */ VI_LIST_OR_EOF, /* ^D */ - /* 5 */ ED_INSERT, /* ^E */ - /* 6 */ ED_INSERT, /* ^F */ - /* 7 */ ED_INSERT, /* ^G */ - /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ - /* 9 */ ED_INSERT, /* ^I */ /* Tab Key */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_INSERT, /* ^K */ - /* 12 */ ED_INSERT, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_INSERT, /* ^N */ - /* 15 */ ED_INSERT, /* ^O */ - /* 16 */ ED_INSERT, /* ^P */ - /* 17 */ ED_IGNORE, /* ^Q */ - /* 18 */ ED_INSERT, /* ^R */ - /* 19 */ ED_IGNORE, /* ^S */ - /* 20 */ ED_INSERT, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ - /* ED_DELETE_PREV_WORD: Only until strt edit pos */ - /* 24 */ ED_INSERT, /* ^X */ - /* 25 */ ED_INSERT, /* ^Y */ - /* 26 */ ED_INSERT, /* ^Z */ - /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */ - /* 28 */ ED_IGNORE, /* ^\ */ - /* 29 */ ED_INSERT, /* ^] */ - /* 30 */ ED_INSERT, /* ^^ */ - /* 31 */ ED_INSERT, /* ^_ */ -#else /* !KSHVI */ - /* - * NOTE: These mappings do NOT Correspond well - * to the KSH VI editing assignments. - * On the other and they are convenient and - * many people have have gotten used to them. - */ - /* 0 */ ED_UNASSIGNED, /* ^@ */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ - /* 2 */ ED_PREV_CHAR, /* ^B */ - /* 3 */ ED_IGNORE, /* ^C */ - /* 4 */ VI_LIST_OR_EOF, /* ^D */ - /* 5 */ ED_MOVE_TO_END, /* ^E */ - /* 6 */ ED_NEXT_CHAR, /* ^F */ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */ - /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_IGNORE, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_IGNORE, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_IGNORE, /* ^S */ - /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ - /* 24 */ ED_UNASSIGNED, /* ^X */ - /* 25 */ ED_IGNORE, /* ^Y */ - /* 26 */ ED_IGNORE, /* ^Z */ - /* 27 */ VI_COMMAND_MODE, /* ^[ */ - /* 28 */ ED_IGNORE, /* ^\ */ - /* 29 */ ED_UNASSIGNED, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ -#endif /* KSHVI */ - /* 32 */ ED_INSERT, /* SPACE */ - /* 33 */ ED_INSERT, /* ! */ - /* 34 */ ED_INSERT, /* " */ - /* 35 */ ED_INSERT, /* # */ - /* 36 */ ED_INSERT, /* $ */ - /* 37 */ ED_INSERT, /* % */ - /* 38 */ ED_INSERT, /* & */ - /* 39 */ ED_INSERT, /* ' */ - /* 40 */ ED_INSERT, /* ( */ - /* 41 */ ED_INSERT, /* ) */ - /* 42 */ ED_INSERT, /* * */ - /* 43 */ ED_INSERT, /* + */ - /* 44 */ ED_INSERT, /* , */ - /* 45 */ ED_INSERT, /* - */ - /* 46 */ ED_INSERT, /* . */ - /* 47 */ ED_INSERT, /* / */ - /* 48 */ ED_INSERT, /* 0 */ - /* 49 */ ED_INSERT, /* 1 */ - /* 50 */ ED_INSERT, /* 2 */ - /* 51 */ ED_INSERT, /* 3 */ - /* 52 */ ED_INSERT, /* 4 */ - /* 53 */ ED_INSERT, /* 5 */ - /* 54 */ ED_INSERT, /* 6 */ - /* 55 */ ED_INSERT, /* 7 */ - /* 56 */ ED_INSERT, /* 8 */ - /* 57 */ ED_INSERT, /* 9 */ - /* 58 */ ED_INSERT, /* : */ - /* 59 */ ED_INSERT, /* ; */ - /* 60 */ ED_INSERT, /* < */ - /* 61 */ ED_INSERT, /* = */ - /* 62 */ ED_INSERT, /* > */ - /* 63 */ ED_INSERT, /* ? */ - /* 64 */ ED_INSERT, /* @ */ - /* 65 */ ED_INSERT, /* A */ - /* 66 */ ED_INSERT, /* B */ - /* 67 */ ED_INSERT, /* C */ - /* 68 */ ED_INSERT, /* D */ - /* 69 */ ED_INSERT, /* E */ - /* 70 */ ED_INSERT, /* F */ - /* 71 */ ED_INSERT, /* G */ - /* 72 */ ED_INSERT, /* H */ - /* 73 */ ED_INSERT, /* I */ - /* 74 */ ED_INSERT, /* J */ - /* 75 */ ED_INSERT, /* K */ - /* 76 */ ED_INSERT, /* L */ - /* 77 */ ED_INSERT, /* M */ - /* 78 */ ED_INSERT, /* N */ - /* 79 */ ED_INSERT, /* O */ - /* 80 */ ED_INSERT, /* P */ - /* 81 */ ED_INSERT, /* Q */ - /* 82 */ ED_INSERT, /* R */ - /* 83 */ ED_INSERT, /* S */ - /* 84 */ ED_INSERT, /* T */ - /* 85 */ ED_INSERT, /* U */ - /* 86 */ ED_INSERT, /* V */ - /* 87 */ ED_INSERT, /* W */ - /* 88 */ ED_INSERT, /* X */ - /* 89 */ ED_INSERT, /* Y */ - /* 90 */ ED_INSERT, /* Z */ - /* 91 */ ED_INSERT, /* [ */ - /* 92 */ ED_INSERT, /* \ */ - /* 93 */ ED_INSERT, /* ] */ - /* 94 */ ED_INSERT, /* ^ */ - /* 95 */ ED_INSERT, /* _ */ - /* 96 */ ED_INSERT, /* ` */ - /* 97 */ ED_INSERT, /* a */ - /* 98 */ ED_INSERT, /* b */ - /* 99 */ ED_INSERT, /* c */ - /* 100 */ ED_INSERT, /* d */ - /* 101 */ ED_INSERT, /* e */ - /* 102 */ ED_INSERT, /* f */ - /* 103 */ ED_INSERT, /* g */ - /* 104 */ ED_INSERT, /* h */ - /* 105 */ ED_INSERT, /* i */ - /* 106 */ ED_INSERT, /* j */ - /* 107 */ ED_INSERT, /* k */ - /* 108 */ ED_INSERT, /* l */ - /* 109 */ ED_INSERT, /* m */ - /* 110 */ ED_INSERT, /* n */ - /* 111 */ ED_INSERT, /* o */ - /* 112 */ ED_INSERT, /* p */ - /* 113 */ ED_INSERT, /* q */ - /* 114 */ ED_INSERT, /* r */ - /* 115 */ ED_INSERT, /* s */ - /* 116 */ ED_INSERT, /* t */ - /* 117 */ ED_INSERT, /* u */ - /* 118 */ ED_INSERT, /* v */ - /* 119 */ ED_INSERT, /* w */ - /* 120 */ ED_INSERT, /* x */ - /* 121 */ ED_INSERT, /* y */ - /* 122 */ ED_INSERT, /* z */ - /* 123 */ ED_INSERT, /* { */ - /* 124 */ ED_INSERT, /* | */ - /* 125 */ ED_INSERT, /* } */ - /* 126 */ ED_INSERT, /* ~ */ - /* 127 */ VI_DELETE_PREV_CHAR, /* ^? */ - /* 128 */ ED_INSERT, /* M-^@ */ - /* 129 */ ED_INSERT, /* M-^A */ - /* 130 */ ED_INSERT, /* M-^B */ - /* 131 */ ED_INSERT, /* M-^C */ - /* 132 */ ED_INSERT, /* M-^D */ - /* 133 */ ED_INSERT, /* M-^E */ - /* 134 */ ED_INSERT, /* M-^F */ - /* 135 */ ED_INSERT, /* M-^G */ - /* 136 */ ED_INSERT, /* M-^H */ - /* 137 */ ED_INSERT, /* M-^I */ - /* 138 */ ED_INSERT, /* M-^J */ - /* 139 */ ED_INSERT, /* M-^K */ - /* 140 */ ED_INSERT, /* M-^L */ - /* 141 */ ED_INSERT, /* M-^M */ - /* 142 */ ED_INSERT, /* M-^N */ - /* 143 */ ED_INSERT, /* M-^O */ - /* 144 */ ED_INSERT, /* M-^P */ - /* 145 */ ED_INSERT, /* M-^Q */ - /* 146 */ ED_INSERT, /* M-^R */ - /* 147 */ ED_INSERT, /* M-^S */ - /* 148 */ ED_INSERT, /* M-^T */ - /* 149 */ ED_INSERT, /* M-^U */ - /* 150 */ ED_INSERT, /* M-^V */ - /* 151 */ ED_INSERT, /* M-^W */ - /* 152 */ ED_INSERT, /* M-^X */ - /* 153 */ ED_INSERT, /* M-^Y */ - /* 154 */ ED_INSERT, /* M-^Z */ - /* 155 */ ED_INSERT, /* M-^[ */ - /* 156 */ ED_INSERT, /* M-^\ */ - /* 157 */ ED_INSERT, /* M-^] */ - /* 158 */ ED_INSERT, /* M-^^ */ - /* 159 */ ED_INSERT, /* M-^_ */ - /* 160 */ ED_INSERT, /* M-SPACE */ - /* 161 */ ED_INSERT, /* M-! */ - /* 162 */ ED_INSERT, /* M-" */ - /* 163 */ ED_INSERT, /* M-# */ - /* 164 */ ED_INSERT, /* M-$ */ - /* 165 */ ED_INSERT, /* M-% */ - /* 166 */ ED_INSERT, /* M-& */ - /* 167 */ ED_INSERT, /* M-' */ - /* 168 */ ED_INSERT, /* M-( */ - /* 169 */ ED_INSERT, /* M-) */ - /* 170 */ ED_INSERT, /* M-* */ - /* 171 */ ED_INSERT, /* M-+ */ - /* 172 */ ED_INSERT, /* M-, */ - /* 173 */ ED_INSERT, /* M-- */ - /* 174 */ ED_INSERT, /* M-. */ - /* 175 */ ED_INSERT, /* M-/ */ - /* 176 */ ED_INSERT, /* M-0 */ - /* 177 */ ED_INSERT, /* M-1 */ - /* 178 */ ED_INSERT, /* M-2 */ - /* 179 */ ED_INSERT, /* M-3 */ - /* 180 */ ED_INSERT, /* M-4 */ - /* 181 */ ED_INSERT, /* M-5 */ - /* 182 */ ED_INSERT, /* M-6 */ - /* 183 */ ED_INSERT, /* M-7 */ - /* 184 */ ED_INSERT, /* M-8 */ - /* 185 */ ED_INSERT, /* M-9 */ - /* 186 */ ED_INSERT, /* M-: */ - /* 187 */ ED_INSERT, /* M-; */ - /* 188 */ ED_INSERT, /* M-< */ - /* 189 */ ED_INSERT, /* M-= */ - /* 190 */ ED_INSERT, /* M-> */ - /* 191 */ ED_INSERT, /* M-? */ - /* 192 */ ED_INSERT, /* M-@ */ - /* 193 */ ED_INSERT, /* M-A */ - /* 194 */ ED_INSERT, /* M-B */ - /* 195 */ ED_INSERT, /* M-C */ - /* 196 */ ED_INSERT, /* M-D */ - /* 197 */ ED_INSERT, /* M-E */ - /* 198 */ ED_INSERT, /* M-F */ - /* 199 */ ED_INSERT, /* M-G */ - /* 200 */ ED_INSERT, /* M-H */ - /* 201 */ ED_INSERT, /* M-I */ - /* 202 */ ED_INSERT, /* M-J */ - /* 203 */ ED_INSERT, /* M-K */ - /* 204 */ ED_INSERT, /* M-L */ - /* 205 */ ED_INSERT, /* M-M */ - /* 206 */ ED_INSERT, /* M-N */ - /* 207 */ ED_INSERT, /* M-O */ - /* 208 */ ED_INSERT, /* M-P */ - /* 209 */ ED_INSERT, /* M-Q */ - /* 210 */ ED_INSERT, /* M-R */ - /* 211 */ ED_INSERT, /* M-S */ - /* 212 */ ED_INSERT, /* M-T */ - /* 213 */ ED_INSERT, /* M-U */ - /* 214 */ ED_INSERT, /* M-V */ - /* 215 */ ED_INSERT, /* M-W */ - /* 216 */ ED_INSERT, /* M-X */ - /* 217 */ ED_INSERT, /* M-Y */ - /* 218 */ ED_INSERT, /* M-Z */ - /* 219 */ ED_INSERT, /* M-[ */ - /* 220 */ ED_INSERT, /* M-\ */ - /* 221 */ ED_INSERT, /* M-] */ - /* 222 */ ED_INSERT, /* M-^ */ - /* 223 */ ED_INSERT, /* M-_ */ - /* 224 */ ED_INSERT, /* M-` */ - /* 225 */ ED_INSERT, /* M-a */ - /* 226 */ ED_INSERT, /* M-b */ - /* 227 */ ED_INSERT, /* M-c */ - /* 228 */ ED_INSERT, /* M-d */ - /* 229 */ ED_INSERT, /* M-e */ - /* 230 */ ED_INSERT, /* M-f */ - /* 231 */ ED_INSERT, /* M-g */ - /* 232 */ ED_INSERT, /* M-h */ - /* 233 */ ED_INSERT, /* M-i */ - /* 234 */ ED_INSERT, /* M-j */ - /* 235 */ ED_INSERT, /* M-k */ - /* 236 */ ED_INSERT, /* M-l */ - /* 237 */ ED_INSERT, /* M-m */ - /* 238 */ ED_INSERT, /* M-n */ - /* 239 */ ED_INSERT, /* M-o */ - /* 240 */ ED_INSERT, /* M-p */ - /* 241 */ ED_INSERT, /* M-q */ - /* 242 */ ED_INSERT, /* M-r */ - /* 243 */ ED_INSERT, /* M-s */ - /* 244 */ ED_INSERT, /* M-t */ - /* 245 */ ED_INSERT, /* M-u */ - /* 246 */ ED_INSERT, /* M-v */ - /* 247 */ ED_INSERT, /* M-w */ - /* 248 */ ED_INSERT, /* M-x */ - /* 249 */ ED_INSERT, /* M-y */ - /* 250 */ ED_INSERT, /* M-z */ - /* 251 */ ED_INSERT, /* M-{ */ - /* 252 */ ED_INSERT, /* M-| */ - /* 253 */ ED_INSERT, /* M-} */ - /* 254 */ ED_INSERT, /* M-~ */ - /* 255 */ ED_INSERT /* M-^? */ -}; - -static const el_action_t el_map_vi_command[] = { - /* 0 */ ED_UNASSIGNED, /* ^@ */ - /* 1 */ ED_MOVE_TO_BEG, /* ^A */ - /* 2 */ ED_UNASSIGNED, /* ^B */ - /* 3 */ ED_IGNORE, /* ^C */ - /* 4 */ ED_UNASSIGNED, /* ^D */ - /* 5 */ ED_MOVE_TO_END, /* ^E */ - /* 6 */ ED_UNASSIGNED, /* ^F */ - /* 7 */ ED_UNASSIGNED, /* ^G */ - /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ - /* 9 */ ED_UNASSIGNED, /* ^I */ - /* 10 */ ED_NEWLINE, /* ^J */ - /* 11 */ ED_KILL_LINE, /* ^K */ - /* 12 */ ED_CLEAR_SCREEN, /* ^L */ - /* 13 */ ED_NEWLINE, /* ^M */ - /* 14 */ ED_NEXT_HISTORY, /* ^N */ - /* 15 */ ED_IGNORE, /* ^O */ - /* 16 */ ED_PREV_HISTORY, /* ^P */ - /* 17 */ ED_IGNORE, /* ^Q */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_IGNORE, /* ^S */ - /* 20 */ ED_UNASSIGNED, /* ^T */ - /* 21 */ VI_KILL_LINE_PREV, /* ^U */ - /* 22 */ ED_UNASSIGNED, /* ^V */ - /* 23 */ ED_DELETE_PREV_WORD, /* ^W */ - /* 24 */ ED_UNASSIGNED, /* ^X */ - /* 25 */ ED_UNASSIGNED, /* ^Y */ - /* 26 */ ED_UNASSIGNED, /* ^Z */ - /* 27 */ EM_META_NEXT, /* ^[ */ - /* 28 */ ED_IGNORE, /* ^\ */ - /* 29 */ ED_UNASSIGNED, /* ^] */ - /* 30 */ ED_UNASSIGNED, /* ^^ */ - /* 31 */ ED_UNASSIGNED, /* ^_ */ - /* 32 */ ED_NEXT_CHAR, /* SPACE */ - /* 33 */ ED_UNASSIGNED, /* ! */ - /* 34 */ ED_UNASSIGNED, /* " */ - /* 35 */ VI_COMMENT_OUT, /* # */ - /* 36 */ ED_MOVE_TO_END, /* $ */ - /* 37 */ VI_MATCH, /* % */ - /* 38 */ ED_UNASSIGNED, /* & */ - /* 39 */ ED_UNASSIGNED, /* ' */ - /* 40 */ ED_UNASSIGNED, /* ( */ - /* 41 */ ED_UNASSIGNED, /* ) */ - /* 42 */ ED_UNASSIGNED, /* * */ - /* 43 */ ED_NEXT_HISTORY, /* + */ - /* 44 */ VI_REPEAT_PREV_CHAR, /* , */ - /* 45 */ ED_PREV_HISTORY, /* - */ - /* 46 */ VI_REDO, /* . */ - /* 47 */ VI_SEARCH_PREV, /* / */ - /* 48 */ VI_ZERO, /* 0 */ - /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */ - /* 50 */ ED_ARGUMENT_DIGIT, /* 2 */ - /* 51 */ ED_ARGUMENT_DIGIT, /* 3 */ - /* 52 */ ED_ARGUMENT_DIGIT, /* 4 */ - /* 53 */ ED_ARGUMENT_DIGIT, /* 5 */ - /* 54 */ ED_ARGUMENT_DIGIT, /* 6 */ - /* 55 */ ED_ARGUMENT_DIGIT, /* 7 */ - /* 56 */ ED_ARGUMENT_DIGIT, /* 8 */ - /* 57 */ ED_ARGUMENT_DIGIT, /* 9 */ - /* 58 */ ED_COMMAND, /* : */ - /* 59 */ VI_REPEAT_NEXT_CHAR, /* ; */ - /* 60 */ ED_UNASSIGNED, /* < */ - /* 61 */ ED_UNASSIGNED, /* = */ - /* 62 */ ED_UNASSIGNED, /* > */ - /* 63 */ VI_SEARCH_NEXT, /* ? */ - /* 64 */ VI_ALIAS, /* @ */ - /* 65 */ VI_ADD_AT_EOL, /* A */ - /* 66 */ VI_PREV_BIG_WORD, /* B */ - /* 67 */ VI_CHANGE_TO_EOL, /* C */ - /* 68 */ ED_KILL_LINE, /* D */ - /* 69 */ VI_END_BIG_WORD, /* E */ - /* 70 */ VI_PREV_CHAR, /* F */ - /* 71 */ VI_TO_HISTORY_LINE, /* G */ - /* 72 */ ED_UNASSIGNED, /* H */ - /* 73 */ VI_INSERT_AT_BOL, /* I */ - /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */ - /* 75 */ ED_SEARCH_PREV_HISTORY, /* K */ - /* 76 */ ED_UNASSIGNED, /* L */ - /* 77 */ ED_UNASSIGNED, /* M */ - /* 78 */ VI_REPEAT_SEARCH_PREV, /* N */ - /* 79 */ ED_SEQUENCE_LEAD_IN, /* O */ - /* 80 */ VI_PASTE_PREV, /* P */ - /* 81 */ ED_UNASSIGNED, /* Q */ - /* 82 */ VI_REPLACE_MODE, /* R */ - /* 83 */ VI_SUBSTITUTE_LINE, /* S */ - /* 84 */ VI_TO_PREV_CHAR, /* T */ - /* 85 */ VI_UNDO_LINE, /* U */ - /* 86 */ ED_UNASSIGNED, /* V */ - /* 87 */ VI_NEXT_BIG_WORD, /* W */ - /* 88 */ ED_DELETE_PREV_CHAR, /* X */ - /* 89 */ VI_YANK_END, /* Y */ - /* 90 */ ED_UNASSIGNED, /* Z */ - /* 91 */ ED_SEQUENCE_LEAD_IN, /* [ */ - /* 92 */ ED_UNASSIGNED, /* \ */ - /* 93 */ ED_UNASSIGNED, /* ] */ - /* 94 */ ED_MOVE_TO_BEG, /* ^ */ - /* 95 */ VI_HISTORY_WORD, /* _ */ - /* 96 */ ED_UNASSIGNED, /* ` */ - /* 97 */ VI_ADD, /* a */ - /* 98 */ VI_PREV_WORD, /* b */ - /* 99 */ VI_CHANGE_META, /* c */ - /* 100 */ VI_DELETE_META, /* d */ - /* 101 */ VI_END_WORD, /* e */ - /* 102 */ VI_NEXT_CHAR, /* f */ - /* 103 */ ED_UNASSIGNED, /* g */ - /* 104 */ ED_PREV_CHAR, /* h */ - /* 105 */ VI_INSERT, /* i */ - /* 106 */ ED_NEXT_HISTORY, /* j */ - /* 107 */ ED_PREV_HISTORY, /* k */ - /* 108 */ ED_NEXT_CHAR, /* l */ - /* 109 */ ED_UNASSIGNED, /* m */ - /* 110 */ VI_REPEAT_SEARCH_NEXT, /* n */ - /* 111 */ ED_UNASSIGNED, /* o */ - /* 112 */ VI_PASTE_NEXT, /* p */ - /* 113 */ ED_UNASSIGNED, /* q */ - /* 114 */ VI_REPLACE_CHAR, /* r */ - /* 115 */ VI_SUBSTITUTE_CHAR, /* s */ - /* 116 */ VI_TO_NEXT_CHAR, /* t */ - /* 117 */ VI_UNDO, /* u */ - /* 118 */ VI_HISTEDIT, /* v */ - /* 119 */ VI_NEXT_WORD, /* w */ - /* 120 */ ED_DELETE_NEXT_CHAR, /* x */ - /* 121 */ VI_YANK, /* y */ - /* 122 */ ED_UNASSIGNED, /* z */ - /* 123 */ ED_UNASSIGNED, /* { */ - /* 124 */ VI_TO_COLUMN, /* | */ - /* 125 */ ED_UNASSIGNED, /* } */ - /* 126 */ VI_CHANGE_CASE, /* ~ */ - /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */ - /* 128 */ ED_UNASSIGNED, /* M-^@ */ - /* 129 */ ED_UNASSIGNED, /* M-^A */ - /* 130 */ ED_UNASSIGNED, /* M-^B */ - /* 131 */ ED_UNASSIGNED, /* M-^C */ - /* 132 */ ED_UNASSIGNED, /* M-^D */ - /* 133 */ ED_UNASSIGNED, /* M-^E */ - /* 134 */ ED_UNASSIGNED, /* M-^F */ - /* 135 */ ED_UNASSIGNED, /* M-^G */ - /* 136 */ ED_UNASSIGNED, /* M-^H */ - /* 137 */ ED_UNASSIGNED, /* M-^I */ - /* 138 */ ED_UNASSIGNED, /* M-^J */ - /* 139 */ ED_UNASSIGNED, /* M-^K */ - /* 140 */ ED_UNASSIGNED, /* M-^L */ - /* 141 */ ED_UNASSIGNED, /* M-^M */ - /* 142 */ ED_UNASSIGNED, /* M-^N */ - /* 143 */ ED_UNASSIGNED, /* M-^O */ - /* 144 */ ED_UNASSIGNED, /* M-^P */ - /* 145 */ ED_UNASSIGNED, /* M-^Q */ - /* 146 */ ED_UNASSIGNED, /* M-^R */ - /* 147 */ ED_UNASSIGNED, /* M-^S */ - /* 148 */ ED_UNASSIGNED, /* M-^T */ - /* 149 */ ED_UNASSIGNED, /* M-^U */ - /* 150 */ ED_UNASSIGNED, /* M-^V */ - /* 151 */ ED_UNASSIGNED, /* M-^W */ - /* 152 */ ED_UNASSIGNED, /* M-^X */ - /* 153 */ ED_UNASSIGNED, /* M-^Y */ - /* 154 */ ED_UNASSIGNED, /* M-^Z */ - /* 155 */ ED_UNASSIGNED, /* M-^[ */ - /* 156 */ ED_UNASSIGNED, /* M-^\ */ - /* 157 */ ED_UNASSIGNED, /* M-^] */ - /* 158 */ ED_UNASSIGNED, /* M-^^ */ - /* 159 */ ED_UNASSIGNED, /* M-^_ */ - /* 160 */ ED_UNASSIGNED, /* M-SPACE */ - /* 161 */ ED_UNASSIGNED, /* M-! */ - /* 162 */ ED_UNASSIGNED, /* M-" */ - /* 163 */ ED_UNASSIGNED, /* M-# */ - /* 164 */ ED_UNASSIGNED, /* M-$ */ - /* 165 */ ED_UNASSIGNED, /* M-% */ - /* 166 */ ED_UNASSIGNED, /* M-& */ - /* 167 */ ED_UNASSIGNED, /* M-' */ - /* 168 */ ED_UNASSIGNED, /* M-( */ - /* 169 */ ED_UNASSIGNED, /* M-) */ - /* 170 */ ED_UNASSIGNED, /* M-* */ - /* 171 */ ED_UNASSIGNED, /* M-+ */ - /* 172 */ ED_UNASSIGNED, /* M-, */ - /* 173 */ ED_UNASSIGNED, /* M-- */ - /* 174 */ ED_UNASSIGNED, /* M-. */ - /* 175 */ ED_UNASSIGNED, /* M-/ */ - /* 176 */ ED_UNASSIGNED, /* M-0 */ - /* 177 */ ED_UNASSIGNED, /* M-1 */ - /* 178 */ ED_UNASSIGNED, /* M-2 */ - /* 179 */ ED_UNASSIGNED, /* M-3 */ - /* 180 */ ED_UNASSIGNED, /* M-4 */ - /* 181 */ ED_UNASSIGNED, /* M-5 */ - /* 182 */ ED_UNASSIGNED, /* M-6 */ - /* 183 */ ED_UNASSIGNED, /* M-7 */ - /* 184 */ ED_UNASSIGNED, /* M-8 */ - /* 185 */ ED_UNASSIGNED, /* M-9 */ - /* 186 */ ED_UNASSIGNED, /* M-: */ - /* 187 */ ED_UNASSIGNED, /* M-; */ - /* 188 */ ED_UNASSIGNED, /* M-< */ - /* 189 */ ED_UNASSIGNED, /* M-= */ - /* 190 */ ED_UNASSIGNED, /* M-> */ - /* 191 */ ED_UNASSIGNED, /* M-? */ - /* 192 */ ED_UNASSIGNED, /* M-@ */ - /* 193 */ ED_UNASSIGNED, /* M-A */ - /* 194 */ ED_UNASSIGNED, /* M-B */ - /* 195 */ ED_UNASSIGNED, /* M-C */ - /* 196 */ ED_UNASSIGNED, /* M-D */ - /* 197 */ ED_UNASSIGNED, /* M-E */ - /* 198 */ ED_UNASSIGNED, /* M-F */ - /* 199 */ ED_UNASSIGNED, /* M-G */ - /* 200 */ ED_UNASSIGNED, /* M-H */ - /* 201 */ ED_UNASSIGNED, /* M-I */ - /* 202 */ ED_UNASSIGNED, /* M-J */ - /* 203 */ ED_UNASSIGNED, /* M-K */ - /* 204 */ ED_UNASSIGNED, /* M-L */ - /* 205 */ ED_UNASSIGNED, /* M-M */ - /* 206 */ ED_UNASSIGNED, /* M-N */ - /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */ - /* 208 */ ED_UNASSIGNED, /* M-P */ - /* 209 */ ED_UNASSIGNED, /* M-Q */ - /* 210 */ ED_UNASSIGNED, /* M-R */ - /* 211 */ ED_UNASSIGNED, /* M-S */ - /* 212 */ ED_UNASSIGNED, /* M-T */ - /* 213 */ ED_UNASSIGNED, /* M-U */ - /* 214 */ ED_UNASSIGNED, /* M-V */ - /* 215 */ ED_UNASSIGNED, /* M-W */ - /* 216 */ ED_UNASSIGNED, /* M-X */ - /* 217 */ ED_UNASSIGNED, /* M-Y */ - /* 218 */ ED_UNASSIGNED, /* M-Z */ - /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */ - /* 220 */ ED_UNASSIGNED, /* M-\ */ - /* 221 */ ED_UNASSIGNED, /* M-] */ - /* 222 */ ED_UNASSIGNED, /* M-^ */ - /* 223 */ ED_UNASSIGNED, /* M-_ */ - /* 224 */ ED_UNASSIGNED, /* M-` */ - /* 225 */ ED_UNASSIGNED, /* M-a */ - /* 226 */ ED_UNASSIGNED, /* M-b */ - /* 227 */ ED_UNASSIGNED, /* M-c */ - /* 228 */ ED_UNASSIGNED, /* M-d */ - /* 229 */ ED_UNASSIGNED, /* M-e */ - /* 230 */ ED_UNASSIGNED, /* M-f */ - /* 231 */ ED_UNASSIGNED, /* M-g */ - /* 232 */ ED_UNASSIGNED, /* M-h */ - /* 233 */ ED_UNASSIGNED, /* M-i */ - /* 234 */ ED_UNASSIGNED, /* M-j */ - /* 235 */ ED_UNASSIGNED, /* M-k */ - /* 236 */ ED_UNASSIGNED, /* M-l */ - /* 237 */ ED_UNASSIGNED, /* M-m */ - /* 238 */ ED_UNASSIGNED, /* M-n */ - /* 239 */ ED_UNASSIGNED, /* M-o */ - /* 240 */ ED_UNASSIGNED, /* M-p */ - /* 241 */ ED_UNASSIGNED, /* M-q */ - /* 242 */ ED_UNASSIGNED, /* M-r */ - /* 243 */ ED_UNASSIGNED, /* M-s */ - /* 244 */ ED_UNASSIGNED, /* M-t */ - /* 245 */ ED_UNASSIGNED, /* M-u */ - /* 246 */ ED_UNASSIGNED, /* M-v */ - /* 247 */ ED_UNASSIGNED, /* M-w */ - /* 248 */ ED_UNASSIGNED, /* M-x */ - /* 249 */ ED_UNASSIGNED, /* M-y */ - /* 250 */ ED_UNASSIGNED, /* M-z */ - /* 251 */ ED_UNASSIGNED, /* M-{ */ - /* 252 */ ED_UNASSIGNED, /* M-| */ - /* 253 */ ED_UNASSIGNED, /* M-} */ - /* 254 */ ED_UNASSIGNED, /* M-~ */ - /* 255 */ ED_UNASSIGNED /* M-^? */ -}; - - -/* map_init(): - * Initialize and allocate the maps - */ -libedit_private int -map_init(EditLine *el) -{ - - /* - * Make sure those are correct before starting. - */ -#ifdef MAP_DEBUG - if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Emacs map incorrect\n")); - if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Vi command map incorrect\n")); - if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Vi insert map incorrect\n")); -#endif - - el->el_map.alt = el_malloc(sizeof(*el->el_map.alt) * N_KEYS); - if (el->el_map.alt == NULL) - return -1; - el->el_map.key = el_malloc(sizeof(*el->el_map.key) * N_KEYS); - if (el->el_map.key == NULL) - return -1; - el->el_map.emacs = el_map_emacs; - el->el_map.vic = el_map_vi_command; - el->el_map.vii = el_map_vi_insert; - el->el_map.help = el_malloc(sizeof(*el->el_map.help) * EL_NUM_FCNS); - if (el->el_map.help == NULL) - return -1; - (void) memcpy(el->el_map.help, el_func_help, - sizeof(*el->el_map.help) * EL_NUM_FCNS); - el->el_map.func = el_malloc(sizeof(*el->el_map.func) * EL_NUM_FCNS); - if (el->el_map.func == NULL) - return -1; - memcpy(el->el_map.func, el_func, sizeof(*el->el_map.func) - * EL_NUM_FCNS); - el->el_map.nfunc = EL_NUM_FCNS; - -#ifdef VIDEFAULT - map_init_vi(el); -#else - map_init_emacs(el); -#endif /* VIDEFAULT */ - return 0; -} - - -/* map_end(): - * Free the space taken by the editor maps - */ -libedit_private void -map_end(EditLine *el) -{ - - el_free(el->el_map.alt); - el->el_map.alt = NULL; - el_free(el->el_map.key); - el->el_map.key = NULL; - el->el_map.emacs = NULL; - el->el_map.vic = NULL; - el->el_map.vii = NULL; - el_free(el->el_map.help); - el->el_map.help = NULL; - el_free(el->el_map.func); - el->el_map.func = NULL; -} - - -/* map_init_nls(): - * Find all the printable keys and bind them to self insert - */ -static void -map_init_nls(EditLine *el) -{ - int i; - - el_action_t *map = el->el_map.key; - - for (i = 0200; i <= 0377; i++) - if (iswprint(i)) - map[i] = ED_INSERT; -} - - -/* map_init_meta(): - * Bind all the meta keys to the appropriate ESC-<key> sequence - */ -static void -map_init_meta(EditLine *el) -{ - wchar_t buf[3]; - int i; - el_action_t *map = el->el_map.key; - el_action_t *alt = el->el_map.alt; - - for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++) - continue; - - if (i > 0377) { - for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++) - continue; - if (i > 0377) { - i = 033; - if (el->el_map.type == MAP_VI) - map = alt; - } else - map = alt; - } - buf[0] = (wchar_t)i; - buf[2] = 0; - for (i = 0200; i <= 0377; i++) - switch (map[i]) { - case ED_INSERT: - case ED_UNASSIGNED: - case ED_SEQUENCE_LEAD_IN: - break; - default: - buf[1] = i & 0177; - keymacro_add(el, buf, keymacro_map_cmd(el, (int) map[i]), XK_CMD); - break; - } - map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN; -} - - -/* map_init_vi(): - * Initialize the vi bindings - */ -libedit_private void -map_init_vi(EditLine *el) -{ - int i; - el_action_t *key = el->el_map.key; - el_action_t *alt = el->el_map.alt; - const el_action_t *vii = el->el_map.vii; - const el_action_t *vic = el->el_map.vic; - - el->el_map.type = MAP_VI; - el->el_map.current = el->el_map.key; - - keymacro_reset(el); - - for (i = 0; i < N_KEYS; i++) { - key[i] = vii[i]; - alt[i] = vic[i]; - } - - map_init_meta(el); - map_init_nls(el); - - tty_bind_char(el, 1); - terminal_bind_arrow(el); -} - - -/* map_init_emacs(): - * Initialize the emacs bindings - */ -libedit_private void -map_init_emacs(EditLine *el) -{ - int i; - wchar_t buf[3]; - el_action_t *key = el->el_map.key; - el_action_t *alt = el->el_map.alt; - const el_action_t *emacs = el->el_map.emacs; - - el->el_map.type = MAP_EMACS; - el->el_map.current = el->el_map.key; - keymacro_reset(el); - - for (i = 0; i < N_KEYS; i++) { - key[i] = emacs[i]; - alt[i] = ED_UNASSIGNED; - } - - map_init_meta(el); - map_init_nls(el); - - buf[0] = CONTROL('X'); - buf[1] = CONTROL('X'); - buf[2] = 0; - keymacro_add(el, buf, keymacro_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); - - tty_bind_char(el, 1); - terminal_bind_arrow(el); -} - - -/* map_set_editor(): - * Set the editor - */ -libedit_private int -map_set_editor(EditLine *el, wchar_t *editor) -{ - - if (wcscmp(editor, L"emacs") == 0) { - map_init_emacs(el); - return 0; - } - if (wcscmp(editor, L"vi") == 0) { - map_init_vi(el); - return 0; - } - return -1; -} - - -/* map_get_editor(): - * Retrieve the editor - */ -libedit_private int -map_get_editor(EditLine *el, const wchar_t **editor) -{ - - if (editor == NULL) - return -1; - switch (el->el_map.type) { - case MAP_EMACS: - *editor = L"emacs"; - return 0; - case MAP_VI: - *editor = L"vi"; - return 0; - } - return -1; -} - - -/* map_print_key(): - * Print the function description for 1 key - */ -static void -map_print_key(EditLine *el, el_action_t *map, const wchar_t *in) -{ - char outbuf[EL_BUFSIZ]; - el_bindings_t *bp, *ep; - - if (in[0] == '\0' || in[1] == '\0') { - (void) keymacro__decode_str(in, outbuf, sizeof(outbuf), ""); - ep = &el->el_map.help[el->el_map.nfunc]; - for (bp = el->el_map.help; bp < ep; bp++) - if (bp->func == map[(unsigned char) *in]) { - (void) fprintf(el->el_outfile, - "%s\t->\t%ls\n", outbuf, bp->name); - return; - } - } else - keymacro_print(el, in); -} - - -/* map_print_some_keys(): - * Print keys from first to last - */ -static void -map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last) -{ - el_bindings_t *bp, *ep; - wchar_t firstbuf[2], lastbuf[2]; - char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; - - firstbuf[0] = first; - firstbuf[1] = 0; - lastbuf[0] = last; - lastbuf[1] = 0; - if (map[first] == ED_UNASSIGNED) { - if (first == last) { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, - "%-15s-> is undefined\n", unparsbuf); - } - return; - } - ep = &el->el_map.help[el->el_map.nfunc]; - for (bp = el->el_map.help; bp < ep; bp++) { - if (bp->func == map[first]) { - if (first == last) { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, "%-15s-> %ls\n", - unparsbuf, bp->name); - } else { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) keymacro__decode_str(lastbuf, extrabuf, - sizeof(extrabuf), STRQQ); - (void) fprintf(el->el_outfile, - "%-4s to %-7s-> %ls\n", - unparsbuf, extrabuf, bp->name); - } - return; - } - } -#ifdef MAP_DEBUG - if (map == el->el_map.key) { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", unparsbuf); - (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", - first, el->el_map.key[first]); - } else { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", unparsbuf); - (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n", - first, el->el_map.alt[first]); - } -#endif - EL_ABORT((el->el_errfile, "Error printing keys\n")); -} - - -/* map_print_all_keys(): - * Print the function description for all keys. - */ -static void -map_print_all_keys(EditLine *el) -{ - int prev, i; - - (void) fprintf(el->el_outfile, "Standard key bindings\n"); - prev = 0; - for (i = 0; i < N_KEYS; i++) { - if (el->el_map.key[prev] == el->el_map.key[i]) - continue; - map_print_some_keys(el, el->el_map.key, prev, i - 1); - prev = i; - } - map_print_some_keys(el, el->el_map.key, prev, i - 1); - - (void) fprintf(el->el_outfile, "Alternative key bindings\n"); - prev = 0; - for (i = 0; i < N_KEYS; i++) { - if (el->el_map.alt[prev] == el->el_map.alt[i]) - continue; - map_print_some_keys(el, el->el_map.alt, prev, i - 1); - prev = i; - } - map_print_some_keys(el, el->el_map.alt, prev, i - 1); - - (void) fprintf(el->el_outfile, "Multi-character bindings\n"); - keymacro_print(el, L""); - (void) fprintf(el->el_outfile, "Arrow key bindings\n"); - terminal_print_arrow(el, L""); -} - - -/* map_bind(): - * Add/remove/change bindings - */ -libedit_private int -map_bind(EditLine *el, int argc, const wchar_t **argv) -{ - el_action_t *map; - int ntype, rem; - const wchar_t *p; - wchar_t inbuf[EL_BUFSIZ]; - wchar_t outbuf[EL_BUFSIZ]; - const wchar_t *in = NULL; - wchar_t *out; - el_bindings_t *bp, *ep; - int cmd; - int key; - - if (argv == NULL) - return -1; - - map = el->el_map.key; - ntype = XK_CMD; - key = rem = 0; - for (argc = 1; (p = argv[argc]) != NULL; argc++) - if (p[0] == '-') - switch (p[1]) { - case 'a': - map = el->el_map.alt; - break; - - case 's': - ntype = XK_STR; - break; - case 'k': - key = 1; - break; - - case 'r': - rem = 1; - break; - - case 'v': - map_init_vi(el); - return 0; - - case 'e': - map_init_emacs(el); - return 0; - - case 'l': - ep = &el->el_map.help[el->el_map.nfunc]; - for (bp = el->el_map.help; bp < ep; bp++) - (void) fprintf(el->el_outfile, - "%ls\n\t%ls\n", - bp->name, bp->description); - return 0; - default: - (void) fprintf(el->el_errfile, - "%ls: Invalid switch `%lc'.\n", - argv[0], (wint_t)p[1]); - } - else - break; - - if (argv[argc] == NULL) { - map_print_all_keys(el); - return 0; - } - if (key) - in = argv[argc++]; - else if ((in = parse__string(inbuf, argv[argc++])) == NULL) { - (void) fprintf(el->el_errfile, - "%ls: Invalid \\ or ^ in instring.\n", - argv[0]); - return -1; - } - if (rem) { - if (key) { - (void) terminal_clear_arrow(el, in); - return -1; - } - if (in[1]) - (void) keymacro_delete(el, in); - else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) - (void) keymacro_delete(el, in); - else - map[(unsigned char) *in] = ED_UNASSIGNED; - return 0; - } - if (argv[argc] == NULL) { - if (key) - terminal_print_arrow(el, in); - else - map_print_key(el, map, in); - return 0; - } -#ifdef notyet - if (argv[argc + 1] != NULL) { - bindkeymacro_usage(); - return -1; - } -#endif - - switch (ntype) { - case XK_STR: - if ((out = parse__string(outbuf, argv[argc])) == NULL) { - (void) fprintf(el->el_errfile, - "%ls: Invalid \\ or ^ in outstring.\n", argv[0]); - return -1; - } - if (key) - terminal_set_arrow(el, in, keymacro_map_str(el, out), ntype); - else - keymacro_add(el, in, keymacro_map_str(el, out), ntype); - map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; - break; - - case XK_CMD: - if ((cmd = parse_cmd(el, argv[argc])) == -1) { - (void) fprintf(el->el_errfile, - "%ls: Invalid command `%ls'.\n", - argv[0], argv[argc]); - return -1; - } - if (key) - terminal_set_arrow(el, in, keymacro_map_cmd(el, cmd), ntype); - else { - if (in[1]) { - keymacro_add(el, in, keymacro_map_cmd(el, cmd), ntype); - map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; - } else { - keymacro_clear(el, map, in); - map[(unsigned char) *in] = (el_action_t)cmd; - } - } - break; - - /* coverity[dead_error_begin] */ - default: - EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); - break; - } - return 0; -} - - -/* map_addfunc(): - * add a user defined function - */ -libedit_private int -map_addfunc(EditLine *el, const wchar_t *name, const wchar_t *help, - el_func_t func) -{ - void *p; - size_t nf = el->el_map.nfunc + 1; - - if (name == NULL || help == NULL || func == NULL) - return -1; - - if ((p = el_realloc(el->el_map.func, nf * - sizeof(*el->el_map.func))) == NULL) - return -1; - el->el_map.func = p; - if ((p = el_realloc(el->el_map.help, nf * sizeof(*el->el_map.help))) - == NULL) - return -1; - el->el_map.help = p; - - nf = (size_t)el->el_map.nfunc; - el->el_map.func[nf] = func; - - el->el_map.help[nf].name = name; - el->el_map.help[nf].func = (int)nf; - el->el_map.help[nf].description = help; - el->el_map.nfunc++; - - return 0; -} diff --git a/bin/catsh/libedit/map.h b/bin/catsh/libedit/map.h deleted file mode 100644 index b4e4e289..00000000 --- a/bin/catsh/libedit/map.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $NetBSD: map.h,v 1.13 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)map.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.map.h: Editor maps - */ -#ifndef _h_el_map -#define _h_el_map - -typedef el_action_t (*el_func_t)(EditLine *, wint_t); - -typedef struct el_bindings_t { /* for the "bind" shell command */ - const wchar_t *name; /* function name for bind command */ - int func; /* function numeric value */ - const wchar_t *description; /* description of function */ -} el_bindings_t; - -typedef struct el_map_t { - el_action_t *alt; /* The current alternate key map */ - el_action_t *key; /* The current normal key map */ - el_action_t *current; /* The keymap we are using */ - const el_action_t *emacs; /* The default emacs key map */ - const el_action_t *vic; /* The vi command mode key map */ - const el_action_t *vii; /* The vi insert mode key map */ - int type; /* Emacs or vi */ - el_bindings_t *help; /* The help for the editor functions */ - el_func_t *func; /* List of available functions */ - size_t nfunc; /* The number of functions/help items */ -} el_map_t; - -#define MAP_EMACS 0 -#define MAP_VI 1 - -#define N_KEYS 256 - -libedit_private int map_bind(EditLine *, int, const wchar_t **); -libedit_private int map_init(EditLine *); -libedit_private void map_end(EditLine *); -libedit_private void map_init_vi(EditLine *); -libedit_private void map_init_emacs(EditLine *); -libedit_private int map_set_editor(EditLine *, wchar_t *); -libedit_private int map_get_editor(EditLine *, const wchar_t **); -libedit_private int map_addfunc(EditLine *, const wchar_t *, const wchar_t *, - el_func_t); - -#endif /* _h_el_map */ diff --git a/bin/catsh/libedit/parse.c b/bin/catsh/libedit/parse.c deleted file mode 100644 index fdd0d847..00000000 --- a/bin/catsh/libedit/parse.c +++ /dev/null @@ -1,289 +0,0 @@ -/* $NetBSD: parse.c,v 1.40 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: parse.c,v 1.40 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * parse.c: parse an editline extended command - * - * commands are: - * - * bind - * echotc - * edit - * gettc - * history - * settc - * setty - */ -#include <stdlib.h> -#include <string.h> - -#include "el.h" -#include "parse.h" - -static const struct { - const wchar_t *name; - int (*func)(EditLine *, int, const wchar_t **); -} cmds[] = { - { L"bind", map_bind }, - { L"echotc", terminal_echotc }, - { L"edit", el_editmode }, - { L"history", hist_command }, - { L"telltc", terminal_telltc }, - { L"settc", terminal_settc }, - { L"setty", tty_stty }, - { NULL, NULL } -}; - - -/* parse_line(): - * Parse a line and dispatch it - */ -libedit_private int -parse_line(EditLine *el, const wchar_t *line) -{ - const wchar_t **argv; - int argc; - TokenizerW *tok; - - tok = tok_winit(NULL); - tok_wstr(tok, line, &argc, &argv); - argc = el_wparse(el, argc, argv); - tok_wend(tok); - return argc; -} - - -/* el_parse(): - * Command dispatcher - */ -int -el_wparse(EditLine *el, int argc, const wchar_t *argv[]) -{ - const wchar_t *ptr; - int i; - - if (argc < 1) - return -1; - ptr = wcschr(argv[0], L':'); - if (ptr != NULL) { - wchar_t *tprog; - size_t l; - - if (ptr == argv[0]) - return 0; - l = (size_t)(ptr - argv[0] - 1); - tprog = el_malloc((l + 1) * sizeof(*tprog)); - if (tprog == NULL) - return 0; - (void) wcsncpy(tprog, argv[0], l); - tprog[l] = '\0'; - ptr++; - l = (size_t)el_match(el->el_prog, tprog); - el_free(tprog); - if (!l) - return 0; - } else - ptr = argv[0]; - - for (i = 0; cmds[i].name != NULL; i++) - if (wcscmp(cmds[i].name, ptr) == 0) { - i = (*cmds[i].func) (el, argc, argv); - return -i; - } - return -1; -} - - -/* parse__escape(): - * Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return - * the appropriate character or -1 if the escape is not valid - */ -libedit_private int -parse__escape(const wchar_t **ptr) -{ - const wchar_t *p; - wint_t c; - - p = *ptr; - - if (p[1] == 0) - return -1; - - if (*p == '\\') { - p++; - switch (*p) { - case 'a': - c = '\007'; /* Bell */ - break; - case 'b': - c = '\010'; /* Backspace */ - break; - case 't': - c = '\011'; /* Horizontal Tab */ - break; - case 'n': - c = '\012'; /* New Line */ - break; - case 'v': - c = '\013'; /* Vertical Tab */ - break; - case 'f': - c = '\014'; /* Form Feed */ - break; - case 'r': - c = '\015'; /* Carriage Return */ - break; - case 'e': - c = '\033'; /* Escape */ - break; - case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ - { - int i; - const wchar_t hex[] = L"0123456789ABCDEF"; - const wchar_t *h; - ++p; - if (*p++ != '+') - return -1; - c = 0; - for (i = 0; i < 5; ++i) { - h = wcschr(hex, *p++); - if (!h && i < 4) - return -1; - else if (h) - c = (c << 4) | ((int)(h - hex)); - else - --p; - } - if (c > 0x10FFFF) /* outside valid character range */ - return -1; - break; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int cnt, ch; - - for (cnt = 0, c = 0; cnt < 3; cnt++) { - ch = *p++; - if (ch < '0' || ch > '7') { - p--; - break; - } - c = (c << 3) | (ch - '0'); - } - if ((c & (wint_t)0xffffff00) != (wint_t)0) - return -1; - --p; - break; - } - default: - c = *p; - break; - } - } else if (*p == '^') { - p++; - c = (*p == '?') ? '\177' : (*p & 0237); - } else - c = *p; - *ptr = ++p; - return c; -} - -/* parse__string(): - * Parse the escapes from in and put the raw string out - */ -libedit_private wchar_t * -parse__string(wchar_t *out, const wchar_t *in) -{ - wchar_t *rv = out; - int n; - - for (;;) - switch (*in) { - case '\0': - *out = '\0'; - return rv; - - case '\\': - case '^': - if ((n = parse__escape(&in)) == -1) - return NULL; - *out++ = (wchar_t)n; - break; - - case 'M': - if (in[1] == '-' && in[2] != '\0') { - *out++ = '\033'; - in += 2; - break; - } - /*FALLTHROUGH*/ - - default: - *out++ = *in++; - break; - } -} - - -/* parse_cmd(): - * Return the command number for the command string given - * or -1 if one is not found - */ -libedit_private int -parse_cmd(EditLine *el, const wchar_t *cmd) -{ - el_bindings_t *b = el->el_map.help; - size_t i; - - for (i = 0; i < el->el_map.nfunc; i++) - if (wcscmp(b[i].name, cmd) == 0) - return b[i].func; - return -1; -} diff --git a/bin/catsh/libedit/parse.h b/bin/catsh/libedit/parse.h deleted file mode 100644 index fe8eb473..00000000 --- a/bin/catsh/libedit/parse.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: parse.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)parse.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.parse.h: Parser functions - */ -#ifndef _h_el_parse -#define _h_el_parse - -libedit_private int parse_line(EditLine *, const wchar_t *); -libedit_private int parse__escape(const wchar_t **); -libedit_private wchar_t *parse__string(wchar_t *, const wchar_t *); -libedit_private int parse_cmd(EditLine *, const wchar_t *); - -#endif /* _h_el_parse */ diff --git a/bin/catsh/libedit/prompt.c b/bin/catsh/libedit/prompt.c deleted file mode 100644 index 6a63f612..00000000 --- a/bin/catsh/libedit/prompt.c +++ /dev/null @@ -1,202 +0,0 @@ -/* $NetBSD: prompt.c,v 1.26.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: prompt.c,v 1.26.8.1 2017/07/23 14:41:26 snj Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * prompt.c: Prompt printing functions - */ -#include <stdio.h> -#include "el.h" - -static wchar_t *prompt_default(EditLine *); -static wchar_t *prompt_default_r(EditLine *); - -/* prompt_default(): - * Just a default prompt, in case the user did not provide one - */ -static wchar_t * -/*ARGSUSED*/ -prompt_default(EditLine *el __attribute__((__unused__))) -{ - static wchar_t a[3] = L"? "; - - return a; -} - - -/* prompt_default_r(): - * Just a default rprompt, in case the user did not provide one - */ -static wchar_t * -/*ARGSUSED*/ -prompt_default_r(EditLine *el __attribute__((__unused__))) -{ - static wchar_t a[1] = L""; - - return a; -} - - -/* prompt_print(): - * Print the prompt and update the prompt position. - */ -libedit_private void -prompt_print(EditLine *el, int op) -{ - el_prompt_t *elp; - wchar_t *p; - - if (op == EL_PROMPT) - elp = &el->el_prompt; - else - elp = &el->el_rprompt; - - if (elp->p_wide) - p = (*elp->p_func)(el); - else - p = ct_decode_string((char *)(void *)(*elp->p_func)(el), - &el->el_scratch); - - for (; *p; p++) { - if (elp->p_ignore == *p) { - wchar_t *litstart = ++p; - while (*p && *p != elp->p_ignore) - p++; - if (!*p || !p[1]) { - // XXX: We lose the last literal - break; - } - re_putliteral(el, litstart, p++); - continue; - } - re_putc(el, *p, 1); - } - - elp->p_pos.v = el->el_refresh.r_cursor.v; - elp->p_pos.h = el->el_refresh.r_cursor.h; -} - - -/* prompt_init(): - * Initialize the prompt stuff - */ -libedit_private int -prompt_init(EditLine *el) -{ - - el->el_prompt.p_func = prompt_default; - el->el_prompt.p_pos.v = 0; - el->el_prompt.p_pos.h = 0; - el->el_prompt.p_ignore = '\0'; - el->el_rprompt.p_func = prompt_default_r; - el->el_rprompt.p_pos.v = 0; - el->el_rprompt.p_pos.h = 0; - el->el_rprompt.p_ignore = '\0'; - return 0; -} - - -/* prompt_end(): - * Clean up the prompt stuff - */ -libedit_private void -/*ARGSUSED*/ -prompt_end(EditLine *el __attribute__((__unused__))) -{ -} - - -/* prompt_set(): - * Install a prompt printing function - */ -libedit_private int -prompt_set(EditLine *el, el_pfunc_t prf, wchar_t c, int op, int wide) -{ - el_prompt_t *p; - - if (op == EL_PROMPT || op == EL_PROMPT_ESC) - p = &el->el_prompt; - else - p = &el->el_rprompt; - - if (prf == NULL) { - if (op == EL_PROMPT || op == EL_PROMPT_ESC) - p->p_func = prompt_default; - else - p->p_func = prompt_default_r; - } else { - p->p_func = prf; - } - - p->p_ignore = c; - - p->p_pos.v = 0; - p->p_pos.h = 0; - p->p_wide = wide; - - return 0; -} - - -/* prompt_get(): - * Retrieve the prompt printing function - */ -libedit_private int -prompt_get(EditLine *el, el_pfunc_t *prf, wchar_t *c, int op) -{ - el_prompt_t *p; - - if (prf == NULL) - return -1; - - if (op == EL_PROMPT) - p = &el->el_prompt; - else - p = &el->el_rprompt; - - if (prf) - *prf = p->p_func; - if (c) - *c = p->p_ignore; - - return 0; -} diff --git a/bin/catsh/libedit/prompt.h b/bin/catsh/libedit/prompt.h deleted file mode 100644 index 2931428d..00000000 --- a/bin/catsh/libedit/prompt.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: prompt.h,v 1.15 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)prompt.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.prompt.h: Prompt printing stuff - */ -#ifndef _h_el_prompt -#define _h_el_prompt - -typedef wchar_t *(*el_pfunc_t)(EditLine *); - -typedef struct el_prompt_t { - el_pfunc_t p_func; /* Function to return the prompt */ - coord_t p_pos; /* position in the line after prompt */ - wchar_t p_ignore; /* character to start/end literal */ - int p_wide; -} el_prompt_t; - -libedit_private void prompt_print(EditLine *, int); -libedit_private int prompt_set(EditLine *, el_pfunc_t, wchar_t, int, int); -libedit_private int prompt_get(EditLine *, el_pfunc_t *, wchar_t *, int); -libedit_private int prompt_init(EditLine *); -libedit_private void prompt_end(EditLine *); - -#endif /* _h_el_prompt */ diff --git a/bin/catsh/libedit/read.c b/bin/catsh/libedit/read.c deleted file mode 100644 index f9b6684d..00000000 --- a/bin/catsh/libedit/read.c +++ /dev/null @@ -1,628 +0,0 @@ -/* $NetBSD: read.c,v 1.102.6.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: read.c,v 1.102.6.1 2017/07/23 14:41:26 snj Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * read.c: Terminal read functions - */ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "el.h" -#include "fcns.h" -#include "read.h" - -#define EL_MAXMACRO 10 - -struct macros { - wchar_t **macro; - int level; - int offset; -}; - -struct el_read_t { - struct macros macros; - el_rfunc_t read_char; /* Function to read a character. */ - int read_errno; -}; - -static int read__fixio(int, int); -static int read_char(EditLine *, wchar_t *); -static int read_getcmd(EditLine *, el_action_t *, wchar_t *); -static void read_clearmacros(struct macros *); -static void read_pop(struct macros *); -static const wchar_t *noedit_wgets(EditLine *, int *); - -/* read_init(): - * Initialize the read stuff - */ -libedit_private int -read_init(EditLine *el) -{ - struct macros *ma; - - if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL) - return -1; - - ma = &el->el_read->macros; - if ((ma->macro = el_malloc(EL_MAXMACRO * - sizeof(*ma->macro))) == NULL) { - free(el->el_read); - return -1; - } - ma->level = -1; - ma->offset = 0; - - /* builtin read_char */ - el->el_read->read_char = read_char; - return 0; -} - -/* el_read_end(): - * Free the data structures used by the read stuff. - */ -libedit_private void -read_end(struct el_read_t *el_read) -{ - read_clearmacros(&el_read->macros); - el_free(el_read->macros.macro); - el_read->macros.macro = NULL; - el_free(el_read); -} - -/* el_read_setfn(): - * Set the read char function to the one provided. - * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one. - */ -libedit_private int -el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc) -{ - el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc; - return 0; -} - - -/* el_read_getfn(): - * return the current read char function, or EL_BUILTIN_GETCFN - * if it is the default one - */ -libedit_private el_rfunc_t -el_read_getfn(struct el_read_t *el_read) -{ - return el_read->read_char == read_char ? - EL_BUILTIN_GETCFN : el_read->read_char; -} - - -/* read__fixio(): - * Try to recover from a read error - */ -/* ARGSUSED */ -static int -read__fixio(int fd __attribute__((__unused__)), int e) -{ - - switch (e) { - case -1: /* Make sure that the code is reachable */ - -#ifdef EWOULDBLOCK - case EWOULDBLOCK: -#ifndef TRY_AGAIN -#define TRY_AGAIN -#endif -#endif /* EWOULDBLOCK */ - -#if defined(POSIX) && defined(EAGAIN) -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - case EAGAIN: -#ifndef TRY_AGAIN -#define TRY_AGAIN -#endif -#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ -#endif /* POSIX && EAGAIN */ - - e = 0; -#ifdef TRY_AGAIN -#if defined(F_SETFL) && defined(O_NDELAY) - if ((e = fcntl(fd, F_GETFL, 0)) == -1) - return -1; - - if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) - return -1; - else - e = 1; -#endif /* F_SETFL && O_NDELAY */ - -#ifdef FIONBIO - { - int zero = 0; - - if (ioctl(fd, FIONBIO, &zero) == -1) - return -1; - else - e = 1; - } -#endif /* FIONBIO */ - -#endif /* TRY_AGAIN */ - return e ? 0 : -1; - - case EINTR: - return 0; - - default: - return -1; - } -} - - -/* el_push(): - * Push a macro - */ -void -el_wpush(EditLine *el, const wchar_t *str) -{ - struct macros *ma = &el->el_read->macros; - - if (str != NULL && ma->level + 1 < EL_MAXMACRO) { - ma->level++; - if ((ma->macro[ma->level] = wcsdup(str)) != NULL) - return; - ma->level--; - } - terminal_beep(el); - terminal__flush(el); -} - - -/* read_getcmd(): - * Get next command from the input stream, - * return 0 on success or -1 on EOF or error. - * Character values > 255 are not looked up in the map, but inserted. - */ -static int -read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch) -{ - static const wchar_t meta = (wchar_t)0x80; - el_action_t cmd; - - do { - if (el_wgetc(el, ch) != 1) - return -1; - -#ifdef KANJI - if ((*ch & meta)) { - el->el_state.metanext = 0; - cmd = CcViMap[' ']; - break; - } else -#endif /* KANJI */ - - if (el->el_state.metanext) { - el->el_state.metanext = 0; - *ch |= meta; - } - if (*ch >= N_KEYS) - cmd = ED_INSERT; - else - cmd = el->el_map.current[(unsigned char) *ch]; - if (cmd == ED_SEQUENCE_LEAD_IN) { - keymacro_value_t val; - switch (keymacro_get(el, ch, &val)) { - case XK_CMD: - cmd = val.cmd; - break; - case XK_STR: - el_wpush(el, val.str); - break; - case XK_NOD: - return -1; - default: - EL_ABORT((el->el_errfile, "Bad XK_ type \n")); - break; - } - } - } while (cmd == ED_SEQUENCE_LEAD_IN); - *cmdnum = cmd; - return 0; -} - -/* read_char(): - * Read a character from the tty. - */ -static int -read_char(EditLine *el, wchar_t *cp) -{ - ssize_t num_read; - int tried = 0; - char cbuf[MB_LEN_MAX]; - size_t cbp = 0; - int save_errno = errno; - - again: - el->el_signal->sig_no = 0; - while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) { - int e = errno; - switch (el->el_signal->sig_no) { - case SIGCONT: - el_wset(el, EL_REFRESH); - /*FALLTHROUGH*/ - case SIGWINCH: - sig_set(el); - goto again; - default: - break; - } - if (!tried && read__fixio(el->el_infd, e) == 0) { - errno = save_errno; - tried = 1; - } else { - errno = e; - *cp = L'\0'; - return -1; - } - } - - /* Test for EOF */ - if (num_read == 0) { - *cp = L'\0'; - return 0; - } - - for (;;) { - mbstate_t mbs; - - ++cbp; - /* This only works because UTF8 is stateless. */ - memset(&mbs, 0, sizeof(mbs)); - switch (mbrtowc(cp, cbuf, cbp, &mbs)) { - case (size_t)-1: - if (cbp > 1) { - /* - * Invalid sequence, discard all bytes - * except the last one. - */ - cbuf[0] = cbuf[cbp - 1]; - cbp = 0; - break; - } else { - /* Invalid byte, discard it. */ - cbp = 0; - goto again; - } - case (size_t)-2: - /* - * We don't support other multibyte charsets. - * The second condition shouldn't happen - * and is here merely for additional safety. - */ - if ((el->el_flags & CHARSET_IS_UTF8) == 0 || - cbp >= MB_LEN_MAX) { - errno = EILSEQ; - *cp = L'\0'; - return -1; - } - /* Incomplete sequence, read another byte. */ - goto again; - default: - /* Valid character, process it. */ - return 1; - } - } -} - -/* read_pop(): - * Pop a macro from the stack - */ -static void -read_pop(struct macros *ma) -{ - int i; - - el_free(ma->macro[0]); - for (i = 0; i < ma->level; i++) - ma->macro[i] = ma->macro[i + 1]; - ma->level--; - ma->offset = 0; -} - -static void -read_clearmacros(struct macros *ma) -{ - while (ma->level >= 0) - el_free(ma->macro[ma->level--]); - ma->offset = 0; -} - -/* el_wgetc(): - * Read a wide character - */ -int -el_wgetc(EditLine *el, wchar_t *cp) -{ - struct macros *ma = &el->el_read->macros; - int num_read; - - terminal__flush(el); - for (;;) { - if (ma->level < 0) - break; - - if (ma->macro[0][ma->offset] == '\0') { - read_pop(ma); - continue; - } - - *cp = ma->macro[0][ma->offset++]; - - if (ma->macro[0][ma->offset] == '\0') { - /* Needed for QuoteMode On */ - read_pop(ma); - } - - return 1; - } - - if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ - return 0; - - num_read = (*el->el_read->read_char)(el, cp); - - /* - * Remember the original reason of a read failure - * such that el_wgets() can restore it after doing - * various cleanup operation that might change errno. - */ - if (num_read < 0) - el->el_read->read_errno = errno; - - return num_read; -} - -libedit_private void -read_prepare(EditLine *el) -{ - if (el->el_flags & HANDLE_SIGNALS) - sig_set(el); - if (el->el_flags & NO_TTY) - return; - if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) - tty_rawmode(el); - - /* This is relatively cheap, and things go terribly wrong if - we have the wrong size. */ - el_resize(el); - re_clear_display(el); /* reset the display stuff */ - ch_reset(el); - re_refresh(el); /* print the prompt */ - - if (el->el_flags & UNBUFFERED) - terminal__flush(el); -} - -libedit_private void -read_finish(EditLine *el) -{ - if ((el->el_flags & UNBUFFERED) == 0) - (void) tty_cookedmode(el); - if (el->el_flags & HANDLE_SIGNALS) - sig_clr(el); -} - -static const wchar_t * -noedit_wgets(EditLine *el, int *nread) -{ - el_line_t *lp = &el->el_line; - int num; - - while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) { - if (lp->lastchar + 1 >= lp->limit && - !ch_enlargebufs(el, (size_t)2)) - break; - lp->lastchar++; - if (el->el_flags & UNBUFFERED || - lp->lastchar[-1] == '\r' || - lp->lastchar[-1] == '\n') - break; - } - if (num == -1 && errno == EINTR) - lp->lastchar = lp->buffer; - lp->cursor = lp->lastchar; - *lp->lastchar = '\0'; - *nread = (int)(lp->lastchar - lp->buffer); - return *nread ? lp->buffer : NULL; -} - -const wchar_t * -el_wgets(EditLine *el, int *nread) -{ - int retval; - el_action_t cmdnum = 0; - int num; /* how many chars we have read at NL */ - wchar_t ch; - int nrb; - - if (nread == NULL) - nread = &nrb; - *nread = 0; - el->el_read->read_errno = 0; - - if (el->el_flags & NO_TTY) { - el->el_line.lastchar = el->el_line.buffer; - return noedit_wgets(el, nread); - } - -#ifdef FIONREAD - if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) { - int chrs = 0; - - (void) ioctl(el->el_infd, FIONREAD, &chrs); - if (chrs == 0) { - if (tty_rawmode(el) < 0) { - errno = 0; - *nread = 0; - return NULL; - } - } - } -#endif /* FIONREAD */ - - if ((el->el_flags & UNBUFFERED) == 0) - read_prepare(el); - - if (el->el_flags & EDIT_DISABLED) { - if ((el->el_flags & UNBUFFERED) == 0) - el->el_line.lastchar = el->el_line.buffer; - terminal__flush(el); - return noedit_wgets(el, nread); - } - - for (num = -1; num == -1;) { /* while still editing this line */ - /* if EOF or error */ - if (read_getcmd(el, &cmdnum, &ch) == -1) - break; - if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */ - continue; /* try again */ - /* now do the real command */ - /* vi redo needs these way down the levels... */ - el->el_state.thiscmd = cmdnum; - el->el_state.thisch = ch; - if (el->el_map.type == MAP_VI && - el->el_map.current == el->el_map.key && - el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { - if (cmdnum == VI_DELETE_PREV_CHAR && - el->el_chared.c_redo.pos != el->el_chared.c_redo.buf - && iswprint(el->el_chared.c_redo.pos[-1])) - el->el_chared.c_redo.pos--; - else - *el->el_chared.c_redo.pos++ = ch; - } - retval = (*el->el_map.func[cmdnum]) (el, ch); - - /* save the last command here */ - el->el_state.lastcmd = cmdnum; - - /* use any return value */ - switch (retval) { - case CC_CURSOR: - re_refresh_cursor(el); - break; - - case CC_REDISPLAY: - re_clear_lines(el); - re_clear_display(el); - /* FALLTHROUGH */ - - case CC_REFRESH: - re_refresh(el); - break; - - case CC_REFRESH_BEEP: - re_refresh(el); - terminal_beep(el); - break; - - case CC_NORM: /* normal char */ - break; - - case CC_ARGHACK: /* Suggested by Rich Salz */ - /* <rsalz@pineapple.bbn.com> */ - continue; /* keep going... */ - - case CC_EOF: /* end of file typed */ - if ((el->el_flags & UNBUFFERED) == 0) - num = 0; - else if (num == -1) { - *el->el_line.lastchar++ = CONTROL('d'); - el->el_line.cursor = el->el_line.lastchar; - num = 1; - } - break; - - case CC_NEWLINE: /* normal end of line */ - num = (int)(el->el_line.lastchar - el->el_line.buffer); - break; - - case CC_FATAL: /* fatal error, reset to known state */ - /* put (real) cursor in a known place */ - re_clear_display(el); /* reset the display stuff */ - ch_reset(el); /* reset the input pointers */ - read_clearmacros(&el->el_read->macros); - re_refresh(el); /* print the prompt again */ - break; - - case CC_ERROR: - default: /* functions we don't know about */ - terminal_beep(el); - terminal__flush(el); - break; - } - el->el_state.argument = 1; - el->el_state.doingarg = 0; - el->el_chared.c_vcmd.action = NOP; - if (el->el_flags & UNBUFFERED) - break; - } - - terminal__flush(el); /* flush any buffered output */ - /* make sure the tty is set up correctly */ - if ((el->el_flags & UNBUFFERED) == 0) { - read_finish(el); - *nread = num != -1 ? num : 0; - } else - *nread = (int)(el->el_line.lastchar - el->el_line.buffer); - - if (*nread == 0) { - if (num == -1) { - *nread = -1; - if (el->el_read->read_errno) - errno = el->el_read->read_errno; - } - return NULL; - } else - return el->el_line.buffer; -} diff --git a/bin/catsh/libedit/read.h b/bin/catsh/libedit/read.h deleted file mode 100644 index 1acf5d67..00000000 --- a/bin/catsh/libedit/read.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $NetBSD: read.h,v 1.12 2016/05/22 19:44:26 christos Exp $ */ - -/*- - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Anthony Mallet. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * el.read.h: Character reading functions - */ -#ifndef _h_el_read -#define _h_el_read - -libedit_private int read_init(EditLine *); -libedit_private void read_end(struct el_read_t *); -libedit_private void read_prepare(EditLine *); -libedit_private void read_finish(EditLine *); -libedit_private int el_read_setfn(struct el_read_t *, el_rfunc_t); -libedit_private el_rfunc_t el_read_getfn(struct el_read_t *); - -#endif /* _h_el_read */ diff --git a/bin/catsh/libedit/readline.c b/bin/catsh/libedit/readline.c deleted file mode 100644 index bd5602de..00000000 --- a/bin/catsh/libedit/readline.c +++ /dev/null @@ -1,2371 +0,0 @@ -/* $NetBSD: readline.c,v 1.141 2017/04/21 05:38:03 abhinav Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.141 2017/04/21 05:38:03 abhinav Exp $"); -#endif /* not lint && not SCCSID */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <setjmp.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <vis.h> - -#include "readline/readline.h" -#include "el.h" -#include "fcns.h" -#include "filecomplete.h" - -void rl_prep_terminal(int); -void rl_deprep_terminal(void); - -/* for rl_complete() */ -#define TAB '\r' - -/* see comment at the #ifdef for sense of this */ -/* #define GDB_411_HACK */ - -/* readline compatibility stuff - look at readline sources/documentation */ -/* to see what these variables mean */ -const char *rl_library_version = "EditLine wrapper"; -int rl_readline_version = RL_READLINE_VERSION; -static char empty[] = { '\0' }; -static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; -static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', - '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; -char *rl_readline_name = empty; -FILE *rl_instream = NULL; -FILE *rl_outstream = NULL; -int rl_point = 0; -int rl_end = 0; -char *rl_line_buffer = NULL; -rl_vcpfunc_t *rl_linefunc = NULL; -int rl_done = 0; -VFunction *rl_event_hook = NULL; -KEYMAP_ENTRY_ARRAY emacs_standard_keymap, - emacs_meta_keymap, - emacs_ctlx_keymap; -/* - * The following is not implemented; we always catch signals in the - * libedit fashion: set handlers on entry to el_gets() and clear them - * on the way out. This simplistic approach works for most cases; if - * it does not work for your application, please let us know. - */ -int rl_catch_signals = 1; -int rl_catch_sigwinch = 1; - -int history_base = 1; /* probably never subject to change */ -int history_length = 0; -int history_offset = 0; -int max_input_history = 0; -char history_expansion_char = '!'; -char history_subst_char = '^'; -char *history_no_expand_chars = expand_chars; -Function *history_inhibit_expansion_function = NULL; -char *history_arg_extract(int start, int end, const char *str); - -int rl_inhibit_completion = 0; -int rl_attempted_completion_over = 0; -char *rl_basic_word_break_characters = break_chars; -char *rl_completer_word_break_characters = NULL; -char *rl_completer_quote_characters = NULL; -rl_compentry_func_t *rl_completion_entry_function = NULL; -char *(*rl_completion_word_break_hook)(void) = NULL; -rl_completion_func_t *rl_attempted_completion_function = NULL; -Function *rl_pre_input_hook = NULL; -Function *rl_startup1_hook = NULL; -int (*rl_getc_function)(FILE *) = NULL; -char *rl_terminal_name = NULL; -int rl_already_prompted = 0; -int rl_filename_completion_desired = 0; -int rl_ignore_completion_duplicates = 0; -int readline_echoing_p = 1; -int _rl_print_completions_horizontally = 0; -VFunction *rl_redisplay_function = NULL; -Function *rl_startup_hook = NULL; -VFunction *rl_completion_display_matches_hook = NULL; -VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; -VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; -KEYMAP_ENTRY_ARRAY emacs_meta_keymap; - -/* - * The current prompt string. - */ -char *rl_prompt = NULL; -/* - * This is set to character indicating type of completion being done by - * rl_complete_internal(); this is available for application completion - * functions. - */ -int rl_completion_type = 0; - -/* - * If more than this number of items results from query for possible - * completions, we ask user if they are sure to really display the list. - */ -int rl_completion_query_items = 100; - -/* - * List of characters which are word break characters, but should be left - * in the parsed text when it is passed to the completion function. - * Shell uses this to help determine what kind of completing to do. - */ -char *rl_special_prefixes = NULL; - -/* - * This is the character appended to the completed words if at the end of - * the line. Default is ' ' (a space). - */ -int rl_completion_append_character = ' '; - -/* stuff below is used internally by libedit for readline emulation */ - -static History *h = NULL; -static EditLine *e = NULL; -static rl_command_func_t *map[256]; -static jmp_buf topbuf; - -/* internal functions */ -static unsigned char _el_rl_complete(EditLine *, int); -static unsigned char _el_rl_tstp(EditLine *, int); -static char *_get_prompt(EditLine *); -static int _getc_function(EditLine *, wchar_t *); -static int _history_expand_command(const char *, size_t, size_t, - char **); -static char *_rl_compat_sub(const char *, const char *, - const char *, int); -static int _rl_event_read_char(EditLine *, wchar_t *); -static void _rl_update_pos(void); - -static HIST_ENTRY rl_he; - -/* ARGSUSED */ -static char * -_get_prompt(EditLine *el __attribute__((__unused__))) -{ - rl_already_prompted = 1; - return rl_prompt; -} - - -/* - * read one key from user defined input function - */ -static int -/*ARGSUSED*/ -_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) -{ - int i; - - i = (*rl_getc_function)(rl_instream); - if (i == -1) - return 0; - *c = (wchar_t)i; - return 1; -} - -static void -_resize_fun(EditLine *el, void *a) -{ - const LineInfo *li; - char **ap = a; - - li = el_line(el); - /* a cheesy way to get rid of const cast. */ - *ap = memchr(li->buffer, *li->buffer, (size_t)1); -} - -static const char * -_default_history_file(void) -{ - struct passwd *p; - static char *path; - size_t len; - - if (path) - return path; - - if ((p = getpwuid(getuid())) == NULL) - return NULL; - - len = strlen(p->pw_dir) + sizeof("/.history"); - if ((path = malloc(len)) == NULL) - return NULL; - - (void)snprintf(path, len, "%s/.history", p->pw_dir); - return path; -} - -/* - * READLINE compatibility stuff - */ - -/* - * Set the prompt - */ -int -rl_set_prompt(const char *prompt) -{ - char *p; - - if (!prompt) - prompt = ""; - if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) - return 0; - if (rl_prompt) - el_free(rl_prompt); - rl_prompt = strdup(prompt); - if (rl_prompt == NULL) - return -1; - - while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) - *p = RL_PROMPT_START_IGNORE; - - return 0; -} - -/* - * initialize rl compat stuff - */ -int -rl_initialize(void) -{ - HistEvent ev; - int editmode = 1; - struct termios t; - - if (e != NULL) - el_end(e); - if (h != NULL) - history_end(h); - - if (!rl_instream) - rl_instream = stdin; - if (!rl_outstream) - rl_outstream = stdout; - - /* - * See if we don't really want to run the editor - */ - if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) - editmode = 0; - - e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); - - if (!editmode) - el_set(e, EL_EDITMODE, 0); - - h = history_init(); - if (!e || !h) - return -1; - - history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ - history_length = 0; - max_input_history = INT_MAX; - el_set(e, EL_HIST, history, h); - - /* Setup resize function */ - el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer); - - /* setup getc function if valid */ - if (rl_getc_function) - el_set(e, EL_GETCFN, _getc_function); - - /* for proper prompt printing in readline() */ - if (rl_set_prompt("") == -1) { - history_end(h); - el_end(e); - return -1; - } - el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE); - el_set(e, EL_SIGNAL, rl_catch_signals); - - /* set default mode to "emacs"-style and read setting afterwards */ - /* so this can be overridden */ - el_set(e, EL_EDITOR, "emacs"); - if (rl_terminal_name != NULL) - el_set(e, EL_TERMINAL, rl_terminal_name); - else - el_get(e, EL_TERMINAL, &rl_terminal_name); - - /* - * Word completion - this has to go AFTER rebinding keys - * to emacs-style. - */ - el_set(e, EL_ADDFN, "rl_complete", - "ReadLine compatible completion function", - _el_rl_complete); - el_set(e, EL_BIND, "^I", "rl_complete", NULL); - - /* - * Send TSTP when ^Z is pressed. - */ - el_set(e, EL_ADDFN, "rl_tstp", - "ReadLine compatible suspend function", - _el_rl_tstp); - el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); - - /* - * Set some readline compatible key-bindings. - */ - el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL); - - /* - * Allow the use of Home/End keys. - */ - el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL); - el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL); - el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL); - el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL); - el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL); - el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL); - - /* - * Allow the use of the Delete/Insert keys. - */ - el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL); - el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL); - - /* - * Ctrl-left-arrow and Ctrl-right-arrow for word moving. - */ - el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL); - el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL); - el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL); - el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL); - el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL); - el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL); - - /* read settings from configuration file */ - el_source(e, NULL); - - /* - * Unfortunately, some applications really do use rl_point - * and rl_line_buffer directly. - */ - _resize_fun(e, &rl_line_buffer); - _rl_update_pos(); - - if (rl_startup_hook) - (*rl_startup_hook)(NULL, 0); - - return 0; -} - - -/* - * read one line from input stream and return it, chomping - * trailing newline (if there is any) - */ -char * -readline(const char *p) -{ - HistEvent ev; - const char * volatile prompt = p; - int count; - const char *ret; - char *buf; - static int used_event_hook; - - if (e == NULL || h == NULL) - rl_initialize(); - - rl_done = 0; - - (void)setjmp(topbuf); - - /* update prompt accordingly to what has been passed */ - if (rl_set_prompt(prompt) == -1) - return NULL; - - if (rl_pre_input_hook) - (*rl_pre_input_hook)(NULL, 0); - - if (rl_event_hook && !(e->el_flags&NO_TTY)) { - el_set(e, EL_GETCFN, _rl_event_read_char); - used_event_hook = 1; - } - - if (!rl_event_hook && used_event_hook) { - el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN); - used_event_hook = 0; - } - - rl_already_prompted = 0; - - /* get one line from input stream */ - ret = el_gets(e, &count); - - if (ret && count > 0) { - int lastidx; - - buf = strdup(ret); - if (buf == NULL) - return NULL; - lastidx = count - 1; - if (buf[lastidx] == '\n') - buf[lastidx] = '\0'; - } else - buf = NULL; - - history(h, &ev, H_GETSIZE); - history_length = ev.num; - - return buf; -} - -/* - * history functions - */ - -/* - * is normally called before application starts to use - * history expansion functions - */ -void -using_history(void) -{ - if (h == NULL || e == NULL) - rl_initialize(); - history_offset = history_length; -} - - -/* - * substitute ``what'' with ``with'', returning resulting string; if - * globally == 1, substitutes all occurrences of what, otherwise only the - * first one - */ -static char * -_rl_compat_sub(const char *str, const char *what, const char *with, - int globally) -{ - const char *s; - char *r, *result; - size_t len, with_len, what_len; - - len = strlen(str); - with_len = strlen(with); - what_len = strlen(what); - - /* calculate length we need for result */ - s = str; - while (*s) { - if (*s == *what && !strncmp(s, what, what_len)) { - len += with_len - what_len; - if (!globally) - break; - s += what_len; - } else - s++; - } - r = result = el_malloc((len + 1) * sizeof(*r)); - if (result == NULL) - return NULL; - s = str; - while (*s) { - if (*s == *what && !strncmp(s, what, what_len)) { - (void)strncpy(r, with, with_len); - r += with_len; - s += what_len; - if (!globally) { - (void)strcpy(r, s); - return result; - } - } else - *r++ = *s++; - } - *r = '\0'; - return result; -} - -static char *last_search_pat; /* last !?pat[?] search pattern */ -static char *last_search_match; /* last !?pat[?] that matched */ - -const char * -get_history_event(const char *cmd, int *cindex, int qchar) -{ - int idx, sign, sub, num, begin, ret; - size_t len; - char *pat; - const char *rptr; - HistEvent ev; - - idx = *cindex; - if (cmd[idx++] != history_expansion_char) - return NULL; - - /* find out which event to take */ - if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { - if (history(h, &ev, H_FIRST) != 0) - return NULL; - *cindex = cmd[idx]? (idx + 1):idx; - return ev.str; - } - sign = 0; - if (cmd[idx] == '-') { - sign = 1; - idx++; - } - - if ('0' <= cmd[idx] && cmd[idx] <= '9') { - HIST_ENTRY *he; - - num = 0; - while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { - num = num * 10 + cmd[idx] - '0'; - idx++; - } - if (sign) - num = history_length - num + history_base; - - if (!(he = history_get(num))) - return NULL; - - *cindex = idx; - return he->line; - } - sub = 0; - if (cmd[idx] == '?') { - sub = 1; - idx++; - } - begin = idx; - while (cmd[idx]) { - if (cmd[idx] == '\n') - break; - if (sub && cmd[idx] == '?') - break; - if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' - || cmd[idx] == '\t' || cmd[idx] == qchar)) - break; - idx++; - } - len = (size_t)idx - (size_t)begin; - if (sub && cmd[idx] == '?') - idx++; - if (sub && len == 0 && last_search_pat && *last_search_pat) - pat = last_search_pat; - else if (len == 0) - return NULL; - else { - if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL) - return NULL; - (void)strncpy(pat, cmd + begin, len); - pat[len] = '\0'; - } - - if (history(h, &ev, H_CURR) != 0) { - if (pat != last_search_pat) - el_free(pat); - return NULL; - } - num = ev.num; - - if (sub) { - if (pat != last_search_pat) { - if (last_search_pat) - el_free(last_search_pat); - last_search_pat = pat; - } - ret = history_search(pat, -1); - } else - ret = history_search_prefix(pat, -1); - - if (ret == -1) { - /* restore to end of list on failed search */ - history(h, &ev, H_FIRST); - (void)fprintf(rl_outstream, "%s: Event not found\n", pat); - if (pat != last_search_pat) - el_free(pat); - return NULL; - } - - if (sub && len) { - if (last_search_match && last_search_match != pat) - el_free(last_search_match); - last_search_match = pat; - } - - if (pat != last_search_pat) - el_free(pat); - - if (history(h, &ev, H_CURR) != 0) - return NULL; - *cindex = idx; - rptr = ev.str; - - /* roll back to original position */ - (void)history(h, &ev, H_SET, num); - - return rptr; -} - -/* - * the real function doing history expansion - takes as argument command - * to do and data upon which the command should be executed - * does expansion the way I've understood readline documentation - * - * returns 0 if data was not modified, 1 if it was and 2 if the string - * should be only printed and not executed; in case of error, - * returns -1 and *result points to NULL - * it's the caller's responsibility to free() the string returned in *result - */ -static int -_history_expand_command(const char *command, size_t offs, size_t cmdlen, - char **result) -{ - char *tmp, *search = NULL, *aptr; - const char *ptr, *cmd; - static char *from = NULL, *to = NULL; - int start, end, idx, has_mods = 0; - int p_on = 0, g_on = 0; - - *result = NULL; - aptr = NULL; - ptr = NULL; - - /* First get event specifier */ - idx = 0; - - if (strchr(":^*$", command[offs + 1])) { - char str[4]; - /* - * "!:" is shorthand for "!!:". - * "!^", "!*" and "!$" are shorthand for - * "!!:^", "!!:*" and "!!:$" respectively. - */ - str[0] = str[1] = '!'; - str[2] = '0'; - ptr = get_history_event(str, &idx, 0); - idx = (command[offs + 1] == ':')? 1:0; - has_mods = 1; - } else { - if (command[offs + 1] == '#') { - /* use command so far */ - if ((aptr = el_malloc((offs + 1) * sizeof(*aptr))) - == NULL) - return -1; - (void)strncpy(aptr, command, offs); - aptr[offs] = '\0'; - idx = 1; - } else { - int qchar; - - qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; - ptr = get_history_event(command + offs, &idx, qchar); - } - has_mods = command[offs + (size_t)idx] == ':'; - } - - if (ptr == NULL && aptr == NULL) - return -1; - - if (!has_mods) { - *result = strdup(aptr ? aptr : ptr); - if (aptr) - el_free(aptr); - if (*result == NULL) - return -1; - return 1; - } - - cmd = command + offs + idx + 1; - - /* Now parse any word designators */ - - if (*cmd == '%') /* last word matched by ?pat? */ - tmp = strdup(last_search_match? last_search_match:""); - else if (strchr("^*$-0123456789", *cmd)) { - start = end = -1; - if (*cmd == '^') - start = end = 1, cmd++; - else if (*cmd == '$') - start = -1, cmd++; - else if (*cmd == '*') - start = 1, cmd++; - else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { - start = 0; - while (*cmd && '0' <= *cmd && *cmd <= '9') - start = start * 10 + *cmd++ - '0'; - - if (*cmd == '-') { - if (isdigit((unsigned char) cmd[1])) { - cmd++; - end = 0; - while (*cmd && '0' <= *cmd && *cmd <= '9') - end = end * 10 + *cmd++ - '0'; - } else if (cmd[1] == '$') { - cmd += 2; - end = -1; - } else { - cmd++; - end = -2; - } - } else if (*cmd == '*') - end = -1, cmd++; - else - end = start; - } - tmp = history_arg_extract(start, end, aptr? aptr:ptr); - if (tmp == NULL) { - (void)fprintf(rl_outstream, "%s: Bad word specifier", - command + offs + idx); - if (aptr) - el_free(aptr); - return -1; - } - } else - tmp = strdup(aptr? aptr:ptr); - - if (aptr) - el_free(aptr); - - if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { - *result = tmp; - return 1; - } - - for (; *cmd; cmd++) { - if (*cmd == ':') - continue; - else if (*cmd == 'h') { /* remove trailing path */ - if ((aptr = strrchr(tmp, '/')) != NULL) - *aptr = '\0'; - } else if (*cmd == 't') { /* remove leading path */ - if ((aptr = strrchr(tmp, '/')) != NULL) { - aptr = strdup(aptr + 1); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'r') { /* remove trailing suffix */ - if ((aptr = strrchr(tmp, '.')) != NULL) - *aptr = '\0'; - } else if (*cmd == 'e') { /* remove all but suffix */ - if ((aptr = strrchr(tmp, '.')) != NULL) { - aptr = strdup(aptr); - el_free(tmp); - tmp = aptr; - } - } else if (*cmd == 'p') /* print only */ - p_on = 1; - else if (*cmd == 'g') - g_on = 2; - else if (*cmd == 's' || *cmd == '&') { - char *what, *with, delim; - size_t len, from_len; - size_t size; - - if (*cmd == '&' && (from == NULL || to == NULL)) - continue; - else if (*cmd == 's') { - delim = *(++cmd), cmd++; - size = 16; - what = el_realloc(from, size * sizeof(*what)); - if (what == NULL) { - el_free(from); - el_free(tmp); - return 0; - } - len = 0; - for (; *cmd && *cmd != delim; cmd++) { - if (*cmd == '\\' && cmd[1] == delim) - cmd++; - if (len >= size) { - char *nwhat; - nwhat = el_realloc(what, - (size <<= 1) * - sizeof(*nwhat)); - if (nwhat == NULL) { - el_free(what); - el_free(tmp); - return 0; - } - what = nwhat; - } - what[len++] = *cmd; - } - what[len] = '\0'; - from = what; - if (*what == '\0') { - el_free(what); - if (search) { - from = strdup(search); - if (from == NULL) { - el_free(tmp); - return 0; - } - } else { - from = NULL; - el_free(tmp); - return -1; - } - } - cmd++; /* shift after delim */ - if (!*cmd) - continue; - - size = 16; - with = el_realloc(to, size * sizeof(*with)); - if (with == NULL) { - el_free(to); - el_free(tmp); - return -1; - } - len = 0; - from_len = strlen(from); - for (; *cmd && *cmd != delim; cmd++) { - if (len + from_len + 1 >= size) { - char *nwith; - size += from_len + 1; - nwith = el_realloc(with, - size * sizeof(*nwith)); - if (nwith == NULL) { - el_free(with); - el_free(tmp); - return -1; - } - with = nwith; - } - if (*cmd == '&') { - /* safe */ - (void)strcpy(&with[len], from); - len += from_len; - continue; - } - if (*cmd == '\\' - && (*(cmd + 1) == delim - || *(cmd + 1) == '&')) - cmd++; - with[len++] = *cmd; - } - with[len] = '\0'; - to = with; - } - - aptr = _rl_compat_sub(tmp, from, to, g_on); - if (aptr) { - el_free(tmp); - tmp = aptr; - } - g_on = 0; - } - } - *result = tmp; - return p_on? 2:1; -} - - -/* - * csh-style history expansion - */ -int -history_expand(char *str, char **output) -{ - int ret = 0; - size_t idx, i, size; - char *tmp, *result; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (history_expansion_char == 0) { - *output = strdup(str); - return 0; - } - - *output = NULL; - if (str[0] == history_subst_char) { - /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ - *output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output)); - if (*output == NULL) - return 0; - (*output)[0] = (*output)[1] = history_expansion_char; - (*output)[2] = ':'; - (*output)[3] = 's'; - (void)strcpy((*output) + 4, str); - str = *output; - } else { - *output = strdup(str); - if (*output == NULL) - return 0; - } - -#define ADD_STRING(what, len, fr) \ - { \ - if (idx + len + 1 > size) { \ - char *nresult = el_realloc(result, \ - (size += len + 1) * sizeof(*nresult)); \ - if (nresult == NULL) { \ - el_free(*output); \ - if (/*CONSTCOND*/fr) \ - el_free(tmp); \ - return 0; \ - } \ - result = nresult; \ - } \ - (void)strncpy(&result[idx], what, len); \ - idx += len; \ - result[idx] = '\0'; \ - } - - result = NULL; - size = idx = 0; - tmp = NULL; - for (i = 0; str[i];) { - int qchar, loop_again; - size_t len, start, j; - - qchar = 0; - loop_again = 1; - start = j = i; -loop: - for (; str[j]; j++) { - if (str[j] == '\\' && - str[j + 1] == history_expansion_char) { - len = strlen(&str[j + 1]) + 1; - memmove(&str[j], &str[j + 1], len); - continue; - } - if (!loop_again) { - if (isspace((unsigned char) str[j]) - || str[j] == qchar) - break; - } - if (str[j] == history_expansion_char - && !strchr(history_no_expand_chars, str[j + 1]) - && (!history_inhibit_expansion_function || - (*history_inhibit_expansion_function)(str, - (int)j) == 0)) - break; - } - - if (str[j] && loop_again) { - i = j; - qchar = (j > 0 && str[j - 1] == '"' )? '"':0; - j++; - if (str[j] == history_expansion_char) - j++; - loop_again = 0; - goto loop; - } - len = i - start; - ADD_STRING(&str[start], len, 0); - - if (str[i] == '\0' || str[i] != history_expansion_char) { - len = j - i; - ADD_STRING(&str[i], len, 0); - if (start == 0) - ret = 0; - else - ret = 1; - break; - } - ret = _history_expand_command (str, i, (j - i), &tmp); - if (ret > 0 && tmp) { - len = strlen(tmp); - ADD_STRING(tmp, len, 1); - } - if (tmp) { - el_free(tmp); - tmp = NULL; - } - i = j; - } - - /* ret is 2 for "print only" option */ - if (ret == 2) { - add_history(result); -#ifdef GDB_411_HACK - /* gdb 4.11 has been shipped with readline, where */ - /* history_expand() returned -1 when the line */ - /* should not be executed; in readline 2.1+ */ - /* it should return 2 in such a case */ - ret = -1; -#endif - } - el_free(*output); - *output = result; - - return ret; -} - -/* -* Return a string consisting of arguments of "str" from "start" to "end". -*/ -char * -history_arg_extract(int start, int end, const char *str) -{ - size_t i, len, max; - char **arr, *result = NULL; - - arr = history_tokenize(str); - if (!arr) - return NULL; - if (arr && *arr == NULL) - goto out; - - for (max = 0; arr[max]; max++) - continue; - max--; - - if (start == '$') - start = (int)max; - if (end == '$') - end = (int)max; - if (end < 0) - end = (int)max + end + 1; - if (start < 0) - start = end; - - if (start < 0 || end < 0 || (size_t)start > max || - (size_t)end > max || start > end) - goto out; - - for (i = (size_t)start, len = 0; i <= (size_t)end; i++) - len += strlen(arr[i]) + 1; - len++; - result = el_malloc(len * sizeof(*result)); - if (result == NULL) - goto out; - - for (i = (size_t)start, len = 0; i <= (size_t)end; i++) { - (void)strcpy(result + len, arr[i]); - len += strlen(arr[i]); - if (i < (size_t)end) - result[len++] = ' '; - } - result[len] = '\0'; - -out: - for (i = 0; arr[i]; i++) - el_free(arr[i]); - el_free(arr); - - return result; -} - -/* - * Parse the string into individual tokens, - * similar to how shell would do it. - */ -char ** -history_tokenize(const char *str) -{ - int size = 1, idx = 0, i, start; - size_t len; - char **result = NULL, *temp, delim = '\0'; - - for (i = 0; str[i];) { - while (isspace((unsigned char) str[i])) - i++; - start = i; - for (; str[i];) { - if (str[i] == '\\') { - if (str[i+1] != '\0') - i++; - } else if (str[i] == delim) - delim = '\0'; - else if (!delim && - (isspace((unsigned char) str[i]) || - strchr("()<>;&|$", str[i]))) - break; - else if (!delim && strchr("'`\"", str[i])) - delim = str[i]; - if (str[i]) - i++; - } - - if (idx + 2 >= size) { - char **nresult; - size <<= 1; - nresult = el_realloc(result, (size_t)size * sizeof(*nresult)); - if (nresult == NULL) { - el_free(result); - return NULL; - } - result = nresult; - } - len = (size_t)i - (size_t)start; - temp = el_malloc((size_t)(len + 1) * sizeof(*temp)); - if (temp == NULL) { - for (i = 0; i < idx; i++) - el_free(result[i]); - el_free(result); - return NULL; - } - (void)strncpy(temp, &str[start], len); - temp[len] = '\0'; - result[idx++] = temp; - result[idx] = NULL; - if (str[i]) - i++; - } - return result; -} - - -/* - * limit size of history record to ``max'' events - */ -void -stifle_history(int max) -{ - HistEvent ev; - HIST_ENTRY *he; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (history(h, &ev, H_SETSIZE, max) == 0) { - max_input_history = max; - if (history_length > max) - history_base = history_length - max; - while (history_length > max) { - he = remove_history(0); - el_free(he->data); - el_free((void *)(unsigned long)he->line); - el_free(he); - } - } -} - - -/* - * "unlimit" size of history - set the limit to maximum allowed int value - */ -int -unstifle_history(void) -{ - HistEvent ev; - int omax; - - history(h, &ev, H_SETSIZE, INT_MAX); - omax = max_input_history; - max_input_history = INT_MAX; - return omax; /* some value _must_ be returned */ -} - - -int -history_is_stifled(void) -{ - - /* cannot return true answer */ - return max_input_history != INT_MAX; -} - -static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; - -int -history_truncate_file (const char *filename, int nlines) -{ - int ret = 0; - FILE *fp, *tp; - char template[sizeof(_history_tmp_template)]; - char buf[4096]; - int fd; - char *cp; - off_t off; - int count = 0; - ssize_t left = 0; - - if (filename == NULL && (filename = _default_history_file()) == NULL) - return errno; - if ((fp = fopen(filename, "r+")) == NULL) - return errno; - strcpy(template, _history_tmp_template); - if ((fd = mkstemp(template)) == -1) { - ret = errno; - goto out1; - } - - if ((tp = fdopen(fd, "r+")) == NULL) { - close(fd); - ret = errno; - goto out2; - } - - for(;;) { - if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) { - if (ferror(fp)) { - ret = errno; - break; - } - if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) == - (off_t)-1) { - ret = errno; - break; - } - left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp); - if (ferror(fp)) { - ret = errno; - break; - } - if (left == 0) { - count--; - left = sizeof(buf); - } else if (fwrite(buf, (size_t)left, (size_t)1, tp) - != 1) { - ret = errno; - break; - } - fflush(tp); - break; - } - if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) { - ret = errno; - break; - } - count++; - } - if (ret) - goto out3; - cp = buf + left - 1; - if(*cp != '\n') - cp++; - for(;;) { - while (--cp >= buf) { - if (*cp == '\n') { - if (--nlines == 0) { - if (++cp >= buf + sizeof(buf)) { - count++; - cp = buf; - } - break; - } - } - } - if (nlines <= 0 || count == 0) - break; - count--; - if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { - ret = errno; - break; - } - if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) { - if (ferror(tp)) { - ret = errno; - break; - } - ret = EAGAIN; - break; - } - cp = buf + sizeof(buf); - } - - if (ret || nlines > 0) - goto out3; - - if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) { - ret = errno; - goto out3; - } - - if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) == - (off_t)-1) { - ret = errno; - goto out3; - } - - for(;;) { - if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) { - if (ferror(fp)) - ret = errno; - break; - } - if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) { - ret = errno; - break; - } - } - fflush(fp); - if((off = ftello(fp)) > 0) - (void)ftruncate(fileno(fp), off); -out3: - fclose(tp); -out2: - unlink(template); -out1: - fclose(fp); - - return ret; -} - - -/* - * read history from a file given - */ -int -read_history(const char *filename) -{ - HistEvent ev; - - if (h == NULL || e == NULL) - rl_initialize(); - if (filename == NULL && (filename = _default_history_file()) == NULL) - return errno; - return history(h, &ev, H_LOAD, filename) == -1 ? - (errno ? errno : EINVAL) : 0; -} - - -/* - * write history to a file given - */ -int -write_history(const char *filename) -{ - HistEvent ev; - - if (h == NULL || e == NULL) - rl_initialize(); - if (filename == NULL && (filename = _default_history_file()) == NULL) - return errno; - return history(h, &ev, H_SAVE, filename) == -1 ? - (errno ? errno : EINVAL) : 0; -} - - -/* - * returns history ``num''th event - * - * returned pointer points to static variable - */ -HIST_ENTRY * -history_get(int num) -{ - static HIST_ENTRY she; - HistEvent ev; - int curr_num; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (num < history_base) - return NULL; - - /* save current position */ - if (history(h, &ev, H_CURR) != 0) - return NULL; - curr_num = ev.num; - - /* - * use H_DELDATA to set to nth history (without delete) by passing - * (void **)-1 -- as in history_set_pos - */ - if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) - goto out; - - /* get current entry */ - if (history(h, &ev, H_CURR) != 0) - goto out; - if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0) - goto out; - she.line = ev.str; - - /* restore pointer to where it was */ - (void)history(h, &ev, H_SET, curr_num); - - return &she; - -out: - /* restore pointer to where it was */ - (void)history(h, &ev, H_SET, curr_num); - return NULL; -} - - -/* - * add the line to history table - */ -int -add_history(const char *line) -{ - HistEvent ev; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (history(h, &ev, H_ENTER, line) == -1) - return 0; - - (void)history(h, &ev, H_GETSIZE); - if (ev.num == history_length) - history_base++; - else - history_length = ev.num; - return 0; -} - - -/* - * remove the specified entry from the history list and return it. - */ -HIST_ENTRY * -remove_history(int num) -{ - HIST_ENTRY *he; - HistEvent ev; - - if (h == NULL || e == NULL) - rl_initialize(); - - if ((he = el_malloc(sizeof(*he))) == NULL) - return NULL; - - if (history(h, &ev, H_DELDATA, num, &he->data) != 0) { - el_free(he); - return NULL; - } - - he->line = ev.str; - if (history(h, &ev, H_GETSIZE) == 0) - history_length = ev.num; - - return he; -} - - -/* - * replace the line and data of the num-th entry - */ -HIST_ENTRY * -replace_history_entry(int num, const char *line, histdata_t data) -{ - HIST_ENTRY *he; - HistEvent ev; - int curr_num; - - if (h == NULL || e == NULL) - rl_initialize(); - - /* save current position */ - if (history(h, &ev, H_CURR) != 0) - return NULL; - curr_num = ev.num; - - /* start from the oldest */ - if (history(h, &ev, H_LAST) != 0) - return NULL; /* error */ - - if ((he = el_malloc(sizeof(*he))) == NULL) - return NULL; - - /* look forwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVDATA, num, &he->data)) - goto out; - - he->line = strdup(ev.str); - if (he->line == NULL) - goto out; - - if (history(h, &ev, H_REPLACE, line, data)) - goto out; - - /* restore pointer to where it was */ - if (history(h, &ev, H_SET, curr_num)) - goto out; - - return he; -out: - el_free(he); - return NULL; -} - -/* - * clear the history list - delete all entries - */ -void -clear_history(void) -{ - HistEvent ev; - - if (h == NULL || e == NULL) - rl_initialize(); - - (void)history(h, &ev, H_CLEAR); - history_offset = history_length = 0; -} - - -/* - * returns offset of the current history event - */ -int -where_history(void) -{ - return history_offset; -} - -static HIST_ENTRY **_history_listp; -static HIST_ENTRY *_history_list; - -HIST_ENTRY ** -history_list(void) -{ - HistEvent ev; - HIST_ENTRY **nlp, *nl; - int i; - - if (history(h, &ev, H_LAST) != 0) - return NULL; - - if ((nlp = el_realloc(_history_listp, - (size_t)history_length * sizeof(*nlp))) == NULL) - return NULL; - _history_listp = nlp; - - if ((nl = el_realloc(_history_list, - (size_t)history_length * sizeof(*nl))) == NULL) - return NULL; - _history_list = nl; - - i = 0; - do { - _history_listp[i] = &_history_list[i]; - _history_list[i].line = ev.str; - _history_list[i].data = NULL; - if (i++ == history_length) - abort(); - } while (history(h, &ev, H_PREV) == 0); - return _history_listp; -} - -/* - * returns current history event or NULL if there is no such event - */ -HIST_ENTRY * -current_history(void) -{ - HistEvent ev; - - if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0) - return NULL; - - rl_he.line = ev.str; - rl_he.data = NULL; - return &rl_he; -} - - -/* - * returns total number of bytes history events' data are using - */ -int -history_total_bytes(void) -{ - HistEvent ev; - int curr_num; - size_t size; - - if (history(h, &ev, H_CURR) != 0) - return -1; - curr_num = ev.num; - - (void)history(h, &ev, H_FIRST); - size = 0; - do - size += strlen(ev.str) * sizeof(*ev.str); - while (history(h, &ev, H_NEXT) == 0); - - /* get to the same position as before */ - history(h, &ev, H_PREV_EVENT, curr_num); - - return (int)size; -} - - -/* - * sets the position in the history list to ``pos'' - */ -int -history_set_pos(int pos) -{ - if (pos >= history_length || pos < 0) - return 0; - - history_offset = pos; - return 1; -} - - -/* - * returns previous event in history and shifts pointer accordingly - * Note that readline and editline define directions in opposite ways. - */ -HIST_ENTRY * -previous_history(void) -{ - HistEvent ev; - - if (history_offset == 0) - return NULL; - - if (history(h, &ev, H_LAST) != 0) - return NULL; - - history_offset--; - return current_history(); -} - - -/* - * returns next event in history and shifts pointer accordingly - */ -HIST_ENTRY * -next_history(void) -{ - HistEvent ev; - - if (history_offset >= history_length) - return NULL; - - if (history(h, &ev, H_LAST) != 0) - return NULL; - - history_offset++; - return current_history(); -} - - -/* - * searches for first history event containing the str - */ -int -history_search(const char *str, int direction) -{ - HistEvent ev; - const char *strp; - int curr_num; - - if (history(h, &ev, H_CURR) != 0) - return -1; - curr_num = ev.num; - - for (;;) { - if ((strp = strstr(ev.str, str)) != NULL) - return (int)(strp - ev.str); - if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) - break; - } - (void)history(h, &ev, H_SET, curr_num); - return -1; -} - - -/* - * searches for first history event beginning with str - */ -int -history_search_prefix(const char *str, int direction) -{ - HistEvent ev; - - return (history(h, &ev, direction < 0 ? - H_PREV_STR : H_NEXT_STR, str)); -} - - -/* - * search for event in history containing str, starting at offset - * abs(pos); continue backward, if pos<0, forward otherwise - */ -/* ARGSUSED */ -int -history_search_pos(const char *str, - int direction __attribute__((__unused__)), int pos) -{ - HistEvent ev; - int curr_num, off; - - off = (pos > 0) ? pos : -pos; - pos = (pos > 0) ? 1 : -1; - - if (history(h, &ev, H_CURR) != 0) - return -1; - curr_num = ev.num; - - if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) - return -1; - - for (;;) { - if (strstr(ev.str, str)) - return off; - if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) - break; - } - - /* set "current" pointer back to previous state */ - (void)history(h, &ev, - pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); - - return -1; -} - - -/********************************/ -/* completion functions */ - -char * -tilde_expand(char *name) -{ - return fn_tilde_expand(name); -} - -char * -filename_completion_function(const char *name, int state) -{ - return fn_filename_completion_function(name, state); -} - -/* - * a completion generator for usernames; returns _first_ username - * which starts with supplied text - * text contains a partial username preceded by random character - * (usually '~'); state resets search from start (??? should we do that anyway) - * it's the caller's responsibility to free the returned value - */ -char * -username_completion_function(const char *text, int state) -{ -#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) - struct passwd pwres; - char pwbuf[1024]; -#endif - struct passwd *pass = NULL; - - if (text[0] == '\0') - return NULL; - - if (*text == '~') - text++; - - if (state == 0) - setpwent(); - - while ( -#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) - getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL -#else - (pass = getpwent()) != NULL -#endif - && text[0] == pass->pw_name[0] - && strcmp(text, pass->pw_name) == 0) - continue; - - if (pass == NULL) { - endpwent(); - return NULL; - } - return strdup(pass->pw_name); -} - - -/* - * el-compatible wrapper to send TSTP on ^Z - */ -/* ARGSUSED */ -static unsigned char -_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__))) -{ - (void)kill(0, SIGTSTP); - return CC_NORM; -} - -static const char * -/*ARGSUSED*/ -_rl_completion_append_character_function(const char *dummy - __attribute__((__unused__))) -{ - static char buf[2]; - buf[0] = (char)rl_completion_append_character; - buf[1] = '\0'; - return buf; -} - - -/* - * Display list of strings in columnar format on readline's output stream. - * 'matches' is list of strings, 'len' is number of strings in 'matches', - * 'max' is maximum length of string in 'matches'. - */ -void -rl_display_match_list(char **matches, int len, int max) -{ - - fn_display_match_list(e, matches, (size_t)len, (size_t)max, - _rl_completion_append_character_function); -} - -/* - * complete word at current point - */ -/* ARGSUSED */ -int -rl_complete(int ignore __attribute__((__unused__)), int invoking_key) -{ - static ct_buffer_t wbreak_conv, sprefix_conv; - char *breakchars; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (rl_inhibit_completion) { - char arr[2]; - arr[0] = (char)invoking_key; - arr[1] = '\0'; - el_insertstr(e, arr); - return CC_REFRESH; - } - - if (rl_completion_word_break_hook != NULL) - breakchars = (*rl_completion_word_break_hook)(); - else - breakchars = rl_basic_word_break_characters; - - _rl_update_pos(); - - /* Just look at how many global variables modify this operation! */ - return fn_complete(e, - (rl_compentry_func_t *)rl_completion_entry_function, - rl_attempted_completion_function, - ct_decode_string(rl_basic_word_break_characters, &wbreak_conv), - ct_decode_string(breakchars, &sprefix_conv), - _rl_completion_append_character_function, - (size_t)rl_completion_query_items, - &rl_completion_type, &rl_attempted_completion_over, - &rl_point, &rl_end); - - -} - - -/* ARGSUSED */ -static unsigned char -_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) -{ - return (unsigned char)rl_complete(0, ch); -} - -/* - * misc other functions - */ - -/* - * bind key c to readline-type function func - */ -int -rl_bind_key(int c, rl_command_func_t *func) -{ - int retval = -1; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (func == rl_insert) { - /* XXX notice there is no range checking of ``c'' */ - e->el_map.key[c] = ED_INSERT; - retval = 0; - } - return retval; -} - - -/* - * read one key from input - handles chars pushed back - * to input stream also - */ -int -rl_read_key(void) -{ - char fooarr[2 * sizeof(int)]; - - if (e == NULL || h == NULL) - rl_initialize(); - - return el_getc(e, fooarr); -} - - -/* - * reset the terminal - */ -/* ARGSUSED */ -void -rl_reset_terminal(const char *p __attribute__((__unused__))) -{ - - if (h == NULL || e == NULL) - rl_initialize(); - el_reset(e); -} - - -/* - * insert character ``c'' back into input stream, ``count'' times - */ -int -rl_insert(int count, int c) -{ - char arr[2]; - - if (h == NULL || e == NULL) - rl_initialize(); - - /* XXX - int -> char conversion can lose on multichars */ - arr[0] = (char)c; - arr[1] = '\0'; - - for (; count > 0; count--) - el_push(e, arr); - - return 0; -} - -int -rl_insert_text(const char *text) -{ - if (!text || *text == 0) - return 0; - - if (h == NULL || e == NULL) - rl_initialize(); - - if (el_insertstr(e, text) < 0) - return 0; - return (int)strlen(text); -} - -/*ARGSUSED*/ -int -rl_newline(int count __attribute__((__unused__)), - int c __attribute__((__unused__))) -{ - /* - * Readline-4.0 appears to ignore the args. - */ - return rl_insert(1, '\n'); -} - -/*ARGSUSED*/ -static unsigned char -rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c) -{ - if (map[c] == NULL) - return CC_ERROR; - - _rl_update_pos(); - - (*map[c])(1, c); - - /* If rl_done was set by the above call, deal with it here */ - if (rl_done) - return CC_EOF; - - return CC_NORM; -} - -int -rl_add_defun(const char *name, rl_command_func_t *fun, int c) -{ - char dest[8]; - if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) - return -1; - map[(unsigned char)c] = fun; - el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); - vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); - el_set(e, EL_BIND, dest, name, NULL); - return 0; -} - -void -rl_callback_read_char(void) -{ - int count = 0, done = 0; - const char *buf = el_gets(e, &count); - char *wbuf; - - if (buf == NULL || count-- <= 0) - return; - if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) - done = 1; - if (buf[count] == '\n' || buf[count] == '\r') - done = 2; - - if (done && rl_linefunc != NULL) { - el_set(e, EL_UNBUFFERED, 0); - if (done == 2) { - if ((wbuf = strdup(buf)) != NULL) - wbuf[count] = '\0'; - } else - wbuf = NULL; - (*(void (*)(const char *))rl_linefunc)(wbuf); - el_set(e, EL_UNBUFFERED, 1); - } -} - -void -rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) -{ - if (e == NULL) { - rl_initialize(); - } - (void)rl_set_prompt(prompt); - rl_linefunc = linefunc; - el_set(e, EL_UNBUFFERED, 1); -} - -void -rl_callback_handler_remove(void) -{ - el_set(e, EL_UNBUFFERED, 0); - rl_linefunc = NULL; -} - -void -rl_redisplay(void) -{ - char a[2]; - a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT]; - a[1] = '\0'; - el_push(e, a); -} - -int -rl_get_previous_history(int count, int key) -{ - char a[2]; - a[0] = (char)key; - a[1] = '\0'; - while (count--) - el_push(e, a); - return 0; -} - -void -/*ARGSUSED*/ -rl_prep_terminal(int meta_flag __attribute__((__unused__))) -{ - el_set(e, EL_PREP_TERM, 1); -} - -void -rl_deprep_terminal(void) -{ - el_set(e, EL_PREP_TERM, 0); -} - -int -rl_read_init_file(const char *s) -{ - return el_source(e, s); -} - -int -rl_parse_and_bind(const char *line) -{ - const char **argv; - int argc; - Tokenizer *tok; - - tok = tok_init(NULL); - tok_str(tok, line, &argc, &argv); - argc = el_parse(e, argc, argv); - tok_end(tok); - return argc ? 1 : 0; -} - -int -rl_variable_bind(const char *var, const char *value) -{ - /* - * The proper return value is undocument, but this is what the - * readline source seems to do. - */ - return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0; -} - -void -rl_stuff_char(int c) -{ - char buf[2]; - - buf[0] = (char)c; - buf[1] = '\0'; - el_insertstr(e, buf); -} - -static int -_rl_event_read_char(EditLine *el, wchar_t *wc) -{ - char ch; - int n; - ssize_t num_read = 0; - - ch = '\0'; - *wc = L'\0'; - while (rl_event_hook) { - - (*rl_event_hook)(); - -#if defined(FIONREAD) - if (ioctl(el->el_infd, FIONREAD, &n) < 0) - return -1; - if (n) - num_read = read(el->el_infd, &ch, (size_t)1); - else - num_read = 0; -#elif defined(F_SETFL) && defined(O_NDELAY) - if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) - return -1; - if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) - return -1; - num_read = read(el->el_infd, &ch, 1); - if (fcntl(el->el_infd, F_SETFL, n)) - return -1; -#else - /* not non-blocking, but what you gonna do? */ - num_read = read(el->el_infd, &ch, 1); - return -1; -#endif - - if (num_read < 0 && errno == EAGAIN) - continue; - if (num_read == 0) - continue; - break; - } - if (!rl_event_hook) - el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); - *wc = (wchar_t)ch; - return (int)num_read; -} - -static void -_rl_update_pos(void) -{ - const LineInfo *li = el_line(e); - - rl_point = (int)(li->cursor - li->buffer); - rl_end = (int)(li->lastchar - li->buffer); -} - -void -rl_get_screen_size(int *rows, int *cols) -{ - if (rows) - el_get(e, EL_GETTC, "li", rows, (void *)0); - if (cols) - el_get(e, EL_GETTC, "co", cols, (void *)0); -} - -void -rl_set_screen_size(int rows, int cols) -{ - char buf[64]; - (void)snprintf(buf, sizeof(buf), "%d", rows); - el_set(e, EL_SETTC, "li", buf, NULL); - (void)snprintf(buf, sizeof(buf), "%d", cols); - el_set(e, EL_SETTC, "co", buf, NULL); -} - -char ** -rl_completion_matches(const char *str, rl_compentry_func_t *fun) -{ - size_t len, max, i, j, min; - char **list, *match, *a, *b; - - len = 1; - max = 10; - if ((list = el_malloc(max * sizeof(*list))) == NULL) - return NULL; - - while ((match = (*fun)(str, (int)(len - 1))) != NULL) { - list[len++] = match; - if (len == max) { - char **nl; - max += 10; - if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL) - goto out; - list = nl; - } - } - if (len == 1) - goto out; - list[len] = NULL; - if (len == 2) { - if ((list[0] = strdup(list[1])) == NULL) - goto out; - return list; - } - qsort(&list[1], len - 1, sizeof(*list), - (int (*)(const void *, const void *)) strcmp); - min = SIZE_MAX; - for (i = 1, a = list[i]; i < len - 1; i++, a = b) { - b = list[i + 1]; - for (j = 0; a[j] && a[j] == b[j]; j++) - continue; - if (min > j) - min = j; - } - if (min == 0 && *str) { - if ((list[0] = strdup(str)) == NULL) - goto out; - } else { - if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL) - goto out; - (void)memcpy(list[0], list[1], min); - list[0][min] = '\0'; - } - return list; - -out: - el_free(list); - return NULL; -} - -char * -rl_filename_completion_function (const char *text, int state) -{ - return fn_filename_completion_function(text, state); -} - -void -rl_forced_update_display(void) -{ - el_set(e, EL_REFRESH); -} - -int -_rl_abort_internal(void) -{ - el_beep(e); - longjmp(topbuf, 1); - /*NOTREACHED*/ -} - -int -_rl_qsort_string_compare(char **s1, char **s2) -{ - return strcoll(*s1, *s2); -} - -HISTORY_STATE * -history_get_history_state(void) -{ - HISTORY_STATE *hs; - - if ((hs = el_malloc(sizeof(*hs))) == NULL) - return NULL; - hs->length = history_length; - return hs; -} - -int -/*ARGSUSED*/ -rl_kill_text(int from __attribute__((__unused__)), - int to __attribute__((__unused__))) -{ - return 0; -} - -Keymap -rl_make_bare_keymap(void) -{ - return NULL; -} - -Keymap -rl_get_keymap(void) -{ - return NULL; -} - -void -/*ARGSUSED*/ -rl_set_keymap(Keymap k __attribute__((__unused__))) -{ -} - -int -/*ARGSUSED*/ -rl_generic_bind(int type __attribute__((__unused__)), - const char * keyseq __attribute__((__unused__)), - const char * data __attribute__((__unused__)), - Keymap k __attribute__((__unused__))) -{ - return 0; -} - -int -/*ARGSUSED*/ -rl_bind_key_in_map(int key __attribute__((__unused__)), - rl_command_func_t *fun __attribute__((__unused__)), - Keymap k __attribute__((__unused__))) -{ - return 0; -} - -/* unsupported, but needed by python */ -void -rl_cleanup_after_signal(void) -{ -} - -int -rl_on_new_line(void) -{ - return 0; -} - -void -rl_free_line_state(void) -{ -} - -int -/*ARGSUSED*/ -rl_set_keyboard_input_timeout(int u __attribute__((__unused__))) -{ - return 0; -} diff --git a/bin/catsh/libedit/readline/Makefile b/bin/catsh/libedit/readline/Makefile deleted file mode 100644 index 265540b7..00000000 --- a/bin/catsh/libedit/readline/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $NetBSD: Makefile,v 1.8 2016/02/17 19:47:49 christos Exp $ - -NOOBJ= # defined - -.include <bsd.own.mk> - -.PATH: ${NETBSDSRCDIR}/lib/libedit - -INCS= readline.h -INCSDIR= /usr/include/readline -INCSYMLINKS= readline.h ${INCSDIR}/history.h - -.include <bsd.prog.mk> diff --git a/bin/catsh/libedit/readline/readline.h b/bin/catsh/libedit/readline/readline.h deleted file mode 100644 index 777a4c6f..00000000 --- a/bin/catsh/libedit/readline/readline.h +++ /dev/null @@ -1,227 +0,0 @@ -/* $NetBSD: readline.h,v 1.41 2016/10/28 18:32:35 christos Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _READLINE_H_ -#define _READLINE_H_ - -#include <sys/types.h> -#include <stdio.h> - -/* list of readline stuff supported by editline library's readline wrapper */ - -/* typedefs */ -typedef int Function(const char *, int); -typedef void VFunction(void); -typedef void rl_vcpfunc_t(char *); -typedef char **rl_completion_func_t(const char *, int, int); -typedef char *rl_compentry_func_t(const char *, int); -typedef int rl_command_func_t(int, int); - -/* only supports length */ -typedef struct { - int length; -} HISTORY_STATE; - -typedef void *histdata_t; - -typedef struct _hist_entry { - const char *line; - histdata_t data; -} HIST_ENTRY; - -typedef struct _keymap_entry { - char type; -#define ISFUNC 0 -#define ISKMAP 1 -#define ISMACR 2 - Function *function; -} KEYMAP_ENTRY; - -#define KEYMAP_SIZE 256 - -typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; -typedef KEYMAP_ENTRY *Keymap; - -#define control_character_threshold 0x20 -#define control_character_bit 0x40 - -#ifndef CTRL -#include <sys/ioctl.h> -#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) -#include <sys/ttydefaults.h> -#endif -#ifndef CTRL -#define CTRL(c) ((c) & 037) -#endif -#endif -#ifndef UNCTRL -#define UNCTRL(c) (((c) - 'a' + 'A')|control_character_bit) -#endif - -#define RUBOUT 0x7f -#define ABORT_CHAR CTRL('G') -#define RL_READLINE_VERSION 0x0402 -#define RL_PROMPT_START_IGNORE '\1' -#define RL_PROMPT_END_IGNORE '\2' - -/* global variables used by readline enabled applications */ -#ifdef __cplusplus -extern "C" { -#endif -extern const char *rl_library_version; -extern int rl_readline_version; -extern char *rl_readline_name; -extern FILE *rl_instream; -extern FILE *rl_outstream; -extern char *rl_line_buffer; -extern int rl_point, rl_end; -extern int history_base, history_length; -extern int max_input_history; -extern char *rl_basic_word_break_characters; -extern char *rl_completer_word_break_characters; -extern char *rl_completer_quote_characters; -extern rl_compentry_func_t *rl_completion_entry_function; -extern char *(*rl_completion_word_break_hook)(void); -extern rl_completion_func_t *rl_attempted_completion_function; -extern int rl_attempted_completion_over; -extern int rl_completion_type; -extern int rl_completion_query_items; -extern char *rl_special_prefixes; -extern int rl_completion_append_character; -extern int rl_inhibit_completion; -extern Function *rl_pre_input_hook; -extern Function *rl_startup_hook; -extern char *rl_terminal_name; -extern int rl_already_prompted; -extern char *rl_prompt; -extern int rl_done; -/* - * The following is not implemented - */ -extern int rl_catch_signals; -extern int rl_catch_sigwinch; -extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, - emacs_meta_keymap, - emacs_ctlx_keymap; -extern int rl_filename_completion_desired; -extern int rl_ignore_completion_duplicates; -extern int (*rl_getc_function)(FILE *); -extern VFunction *rl_redisplay_function; -extern VFunction *rl_completion_display_matches_hook; -extern VFunction *rl_prep_term_function; -extern VFunction *rl_deprep_term_function; -extern int readline_echoing_p; -extern int _rl_print_completions_horizontally; - -/* supported functions */ -char *readline(const char *); -int rl_initialize(void); - -void using_history(void); -int add_history(const char *); -void clear_history(void); -void stifle_history(int); -int unstifle_history(void); -int history_is_stifled(void); -int where_history(void); -HIST_ENTRY *current_history(void); -HIST_ENTRY *history_get(int); -HIST_ENTRY *remove_history(int); -HIST_ENTRY *replace_history_entry(int, const char *, histdata_t); -int history_total_bytes(void); -int history_set_pos(int); -HIST_ENTRY *previous_history(void); -HIST_ENTRY *next_history(void); -HIST_ENTRY **history_list(void); -int history_search(const char *, int); -int history_search_prefix(const char *, int); -int history_search_pos(const char *, int, int); -int read_history(const char *); -int write_history(const char *); -int history_truncate_file (const char *, int); -int history_expand(char *, char **); -char **history_tokenize(const char *); -const char *get_history_event(const char *, int *, int); -char *history_arg_extract(int, int, const char *); - -char *tilde_expand(char *); -char *filename_completion_function(const char *, int); -char *username_completion_function(const char *, int); -int rl_complete(int, int); -int rl_read_key(void); -char **completion_matches(const char *, rl_compentry_func_t *); -void rl_display_match_list(char **, int, int); - -int rl_insert(int, int); -int rl_insert_text(const char *); -void rl_reset_terminal(const char *); -int rl_bind_key(int, rl_command_func_t *); -int rl_newline(int, int); -void rl_callback_read_char(void); -void rl_callback_handler_install(const char *, rl_vcpfunc_t *); -void rl_callback_handler_remove(void); -void rl_redisplay(void); -int rl_get_previous_history(int, int); -void rl_prep_terminal(int); -void rl_deprep_terminal(void); -int rl_read_init_file(const char *); -int rl_parse_and_bind(const char *); -int rl_variable_bind(const char *, const char *); -void rl_stuff_char(int); -int rl_add_defun(const char *, rl_command_func_t *, int); -HISTORY_STATE *history_get_history_state(void); -void rl_get_screen_size(int *, int *); -void rl_set_screen_size(int, int); -char *rl_filename_completion_function (const char *, int); -int _rl_abort_internal(void); -int _rl_qsort_string_compare(char **, char **); -char **rl_completion_matches(const char *, rl_compentry_func_t *); -void rl_forced_update_display(void); -int rl_set_prompt(const char *); -int rl_on_new_line(void); - -/* - * The following are not implemented - */ -int rl_kill_text(int, int); -Keymap rl_get_keymap(void); -void rl_set_keymap(Keymap); -Keymap rl_make_bare_keymap(void); -int rl_generic_bind(int, const char *, const char *, Keymap); -int rl_bind_key_in_map(int, rl_command_func_t *, Keymap); -void rl_cleanup_after_signal(void); -void rl_free_line_state(void); -int rl_set_keyboard_input_timeout(int); - -#ifdef __cplusplus -} -#endif - -#endif /* _READLINE_H_ */ diff --git a/bin/catsh/libedit/refresh.c b/bin/catsh/libedit/refresh.c deleted file mode 100644 index 37c6041d..00000000 --- a/bin/catsh/libedit/refresh.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* $NetBSD: refresh.c,v 1.51.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: refresh.c,v 1.51.8.1 2017/07/23 14:41:26 snj Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * refresh.c: Lower level screen refreshing functions - */ -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "el.h" - -static void re_nextline(EditLine *); -static void re_addc(EditLine *, wint_t); -static void re_update_line(EditLine *, wchar_t *, wchar_t *, int); -static void re_insert (EditLine *, wchar_t *, int, int, wchar_t *, int); -static void re_delete(EditLine *, wchar_t *, int, int, int); -static void re_fastputc(EditLine *, wint_t); -static void re_clear_eol(EditLine *, int, int, int); -static void re__strncopy(wchar_t *, wchar_t *, size_t); -static void re__copy_and_pad(wchar_t *, const wchar_t *, size_t); - -#ifdef DEBUG_REFRESH -static void re_printstr(EditLine *, const char *, wchar_t *, wchar_t *); -#define __F el->el_errfile -#define ELRE_ASSERT(a, b, c) do \ - if (/*CONSTCOND*/ a) { \ - (void) fprintf b; \ - c; \ - } \ - while (/*CONSTCOND*/0) -#define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;) - -/* re_printstr(): - * Print a string on the debugging pty - */ -static void -re_printstr(EditLine *el, const char *str, wchar_t *f, wchar_t *t) -{ - - ELRE_DEBUG(1, (__F, "%s:\"", str)); - while (f < t) - ELRE_DEBUG(1, (__F, "%c", *f++ & 0177)); - ELRE_DEBUG(1, (__F, "\"\r\n")); -} -#else -#define ELRE_ASSERT(a, b, c) -#define ELRE_DEBUG(a, b) -#endif - -/* re_nextline(): - * Move to the next line or scroll - */ -static void -re_nextline(EditLine *el) -{ - el->el_refresh.r_cursor.h = 0; /* reset it. */ - - /* - * If we would overflow (input is longer than terminal size), - * emulate scroll by dropping first line and shuffling the rest. - * We do this via pointer shuffling - it's safe in this case - * and we avoid memcpy(). - */ - if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) { - int i, lins = el->el_terminal.t_size.v; - wchar_t *firstline = el->el_vdisplay[0]; - - for(i = 1; i < lins; i++) - el->el_vdisplay[i - 1] = el->el_vdisplay[i]; - - firstline[0] = '\0'; /* empty the string */ - el->el_vdisplay[i - 1] = firstline; - } else - el->el_refresh.r_cursor.v++; - - ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v, - (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n", - el->el_refresh.r_cursor.v, el->el_terminal.t_size.v), - abort()); -} - -/* re_addc(): - * Draw c, expanding tabs, control chars etc. - */ -static void -re_addc(EditLine *el, wint_t c) -{ - switch (ct_chr_class(c)) { - case CHTYPE_TAB: /* expand the tab */ - for (;;) { - re_putc(el, ' ', 1); - if ((el->el_refresh.r_cursor.h & 07) == 0) - break; /* go until tab stop */ - } - break; - case CHTYPE_NL: { - int oldv = el->el_refresh.r_cursor.v; - re_putc(el, '\0', 0); /* assure end of line */ - if (oldv == el->el_refresh.r_cursor.v) /* XXX */ - re_nextline(el); - break; - } - case CHTYPE_PRINT: - re_putc(el, c, 1); - break; - default: { - wchar_t visbuf[VISUAL_WIDTH_MAX]; - ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); - for (i = 0; n-- > 0; ++i) - re_putc(el, visbuf[i], 1); - break; - } - } -} - -/* re_putliteral(): - * Place the literal string given - */ -libedit_private void -re_putliteral(EditLine *el, const wchar_t *begin, const wchar_t *end) -{ - coord_t *cur = &el->el_refresh.r_cursor; - wint_t c; - int sizeh = el->el_terminal.t_size.h; - int i, w; - - c = literal_add(el, begin, end, &w); - if (c == 0 || w <= 0) - return; - el->el_vdisplay[cur->v][cur->h] = c; - - i = w; - if (i > sizeh - cur->h) /* avoid overflow */ - i = sizeh - cur->h; - while (--i > 0) - el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR; - - cur->h += w; - if (cur->h >= sizeh) { - /* assure end of line */ - el->el_vdisplay[cur->v][sizeh] = '\0'; - re_nextline(el); - } -} - -/* re_putc(): - * Draw the character given - */ -libedit_private void -re_putc(EditLine *el, wint_t c, int shift) -{ - coord_t *cur = &el->el_refresh.r_cursor; - int i, w = wcwidth(c); - int sizeh = el->el_terminal.t_size.h; - - ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c)); - if (w == -1) - w = 0; - - while (shift && (cur->h + w > sizeh)) - re_putc(el, ' ', 1); - - el->el_vdisplay[cur->v][cur->h] = c; - /* assumes !shift is only used for single-column chars */ - i = w; - while (--i > 0) - el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR; - - if (!shift) - return; - - cur->h += w; /* advance to next place */ - if (cur->h >= sizeh) { - /* assure end of line */ - el->el_vdisplay[cur->v][sizeh] = '\0'; - re_nextline(el); - } -} - - -/* re_refresh(): - * draws the new virtual screen image from the current input - * line, then goes line-by-line changing the real image to the new - * virtual image. The routine to re-draw a line can be replaced - * easily in hopes of a smarter one being placed there. - */ -libedit_private void -re_refresh(EditLine *el) -{ - int i, rhdiff; - wchar_t *cp, *st; - coord_t cur; -#ifdef notyet - size_t termsz; -#endif - - ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%ls:\r\n", - el->el_line.buffer)); - - literal_clear(el); - /* reset the Drawing cursor */ - el->el_refresh.r_cursor.h = 0; - el->el_refresh.r_cursor.v = 0; - - terminal_move_to_char(el, 0); - - /* temporarily draw rprompt to calculate its size */ - prompt_print(el, EL_RPROMPT); - - /* reset the Drawing cursor */ - el->el_refresh.r_cursor.h = 0; - el->el_refresh.r_cursor.v = 0; - - if (el->el_line.cursor >= el->el_line.lastchar) { - if (el->el_map.current == el->el_map.alt - && el->el_line.lastchar != el->el_line.buffer) - el->el_line.cursor = el->el_line.lastchar - 1; - else - el->el_line.cursor = el->el_line.lastchar; - } - - cur.h = -1; /* set flag in case I'm not set */ - cur.v = 0; - - prompt_print(el, EL_PROMPT); - - /* draw the current input buffer */ -#if notyet - termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v; - if (el->el_line.lastchar - el->el_line.buffer > termsz) { - /* - * If line is longer than terminal, process only part - * of line which would influence display. - */ - size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz; - - st = el->el_line.lastchar - rem - - (termsz - (((rem / el->el_terminal.t_size.v) - 1) - * el->el_terminal.t_size.v)); - } else -#endif - st = el->el_line.buffer; - - for (cp = st; cp < el->el_line.lastchar; cp++) { - if (cp == el->el_line.cursor) { - int w = wcwidth(*cp); - /* save for later */ - cur.h = el->el_refresh.r_cursor.h; - cur.v = el->el_refresh.r_cursor.v; - /* handle being at a linebroken doublewidth char */ - if (w > 1 && el->el_refresh.r_cursor.h + w > - el->el_terminal.t_size.h) { - cur.h = 0; - cur.v++; - } - } - re_addc(el, *cp); - } - - if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ - cur.h = el->el_refresh.r_cursor.h; - cur.v = el->el_refresh.r_cursor.v; - } - rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h - - el->el_rprompt.p_pos.h; - if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v && - !el->el_refresh.r_cursor.v && rhdiff > 1) { - /* - * have a right-hand side prompt that will fit - * on the end of the first line with at least - * one character gap to the input buffer. - */ - while (--rhdiff > 0) /* pad out with spaces */ - re_putc(el, ' ', 1); - prompt_print(el, EL_RPROMPT); - } else { - el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */ - el->el_rprompt.p_pos.v = 0; - } - - re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */ - - el->el_refresh.r_newcv = el->el_refresh.r_cursor.v; - - ELRE_DEBUG(1, (__F, - "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", - el->el_terminal.t_size.h, el->el_refresh.r_cursor.h, - el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0], - &el->el_scratch))); - - ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); - for (i = 0; i <= el->el_refresh.r_newcv; i++) { - /* NOTE THAT re_update_line MAY CHANGE el_display[i] */ - re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); - - /* - * Copy the new line to be the current one, and pad out with - * spaces to the full width of the terminal so that if we try - * moving the cursor by writing the character that is at the - * end of the screen line, it won't be a NUL or some old - * leftover stuff. - */ - re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], - (size_t) el->el_terminal.t_size.h); - } - ELRE_DEBUG(1, (__F, - "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n", - el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i)); - - if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv) - for (; i <= el->el_refresh.r_oldcv; i++) { - terminal_move_to_line(el, i); - terminal_move_to_char(el, 0); - /* This wcslen should be safe even with MB_FILL_CHARs */ - terminal_clear_EOL(el, (int) wcslen(el->el_display[i])); -#ifdef DEBUG_REFRESH - terminal_overwrite(el, L"C\b", 2); -#endif /* DEBUG_REFRESH */ - el->el_display[i][0] = '\0'; - } - - el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */ - ELRE_DEBUG(1, (__F, - "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n", - el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v, - cur.h, cur.v)); - terminal_move_to_line(el, cur.v); /* go to where the cursor is */ - terminal_move_to_char(el, cur.h); -} - - -/* re_goto_bottom(): - * used to go to last used screen line - */ -libedit_private void -re_goto_bottom(EditLine *el) -{ - - terminal_move_to_line(el, el->el_refresh.r_oldcv); - terminal__putc(el, '\n'); - re_clear_display(el); - terminal__flush(el); -} - - -/* re_insert(): - * insert num characters of s into d (in front of the character) - * at dat, maximum length of d is dlen - */ -static void -/*ARGSUSED*/ -re_insert(EditLine *el __attribute__((__unused__)), - wchar_t *d, int dat, int dlen, wchar_t *s, int num) -{ - wchar_t *a, *b; - - if (num <= 0) - return; - if (num > dlen - dat) - num = dlen - dat; - - ELRE_DEBUG(1, - (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, ct_encode_string(d, &el->el_scratch))); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s, - &el->el_scratch))); - - /* open up the space for num chars */ - if (num > 0) { - b = d + dlen - 1; - a = b - num; - while (a >= &d[dat]) - *b-- = *a--; - d[dlen] = '\0'; /* just in case */ - } - - ELRE_DEBUG(1, (__F, - "re_insert() after insert: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, ct_encode_string(d, &el->el_scratch))); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s, - &el->el_scratch))); - - /* copy the characters */ - for (a = d + dat; (a < d + dlen) && (num > 0); num--) - *a++ = *s++; - -#ifdef notyet - /* ct_encode_string() uses a static buffer, so we can't conveniently - * encode both d & s here */ - ELRE_DEBUG(1, - (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", - num, dat, dlen, d, s)); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); -#endif -} - - -/* re_delete(): - * delete num characters d at dat, maximum length of d is dlen - */ -static void -/*ARGSUSED*/ -re_delete(EditLine *el __attribute__((__unused__)), - wchar_t *d, int dat, int dlen, int num) -{ - wchar_t *a, *b; - - if (num <= 0) - return; - if (dat + num >= dlen) { - d[dat] = '\0'; - return; - } - ELRE_DEBUG(1, - (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, ct_encode_string(d, &el->el_scratch))); - - /* open up the space for num chars */ - if (num > 0) { - b = d + dat; - a = b + num; - while (a < &d[dlen]) - *b++ = *a++; - d[dlen] = '\0'; /* just in case */ - } - ELRE_DEBUG(1, - (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, ct_encode_string(d, &el->el_scratch))); -} - - -/* re__strncopy(): - * Like strncpy without padding. - */ -static void -re__strncopy(wchar_t *a, wchar_t *b, size_t n) -{ - - while (n-- && *b) - *a++ = *b++; -} - -/* re_clear_eol(): - * Find the number of characters we need to clear till the end of line - * in order to make sure that we have cleared the previous contents of - * the line. fx and sx is the number of characters inserted or deleted - * in the first or second diff, diff is the difference between the - * number of characters between the new and old line. - */ -static void -re_clear_eol(EditLine *el, int fx, int sx, int diff) -{ - - ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n", - sx, fx, diff)); - - if (fx < 0) - fx = -fx; - if (sx < 0) - sx = -sx; - if (fx > diff) - diff = fx; - if (sx > diff) - diff = sx; - - ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff)); - terminal_clear_EOL(el, diff); -} - -/***************************************************************** - re_update_line() is based on finding the middle difference of each line - on the screen; vis: - - /old first difference - /beginning of line | /old last same /old EOL - v v v v -old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as -new: eddie> Oh, my little buggy says to me, as lurgid as - ^ ^ ^ ^ - \beginning of line | \new last same \new end of line - \new first difference - - all are character pointers for the sake of speed. Special cases for - no differences, as well as for end of line additions must be handled. -**************************************************************** */ - -/* Minimum at which doing an insert it "worth it". This should be about - * half the "cost" of going into insert mode, inserting a character, and - * going back out. This should really be calculated from the termcap - * data... For the moment, a good number for ANSI terminals. - */ -#define MIN_END_KEEP 4 - -static void -re_update_line(EditLine *el, wchar_t *old, wchar_t *new, int i) -{ - wchar_t *o, *n, *p, c; - wchar_t *ofd, *ols, *oe, *nfd, *nls, *ne; - wchar_t *osb, *ose, *nsb, *nse; - int fx, sx; - size_t len; - - /* - * find first diff - */ - for (o = old, n = new; *o && (*o == *n); o++, n++) - continue; - ofd = o; - nfd = n; - - /* - * Find the end of both old and new - */ - while (*o) - o++; - /* - * Remove any trailing blanks off of the end, being careful not to - * back up past the beginning. - */ - while (ofd < o) { - if (o[-1] != ' ') - break; - o--; - } - oe = o; - *oe = '\0'; - - while (*n) - n++; - - /* remove blanks from end of new */ - while (nfd < n) { - if (n[-1] != ' ') - break; - n--; - } - ne = n; - *ne = '\0'; - - /* - * if no diff, continue to next line of redraw - */ - if (*ofd == '\0' && *nfd == '\0') { - ELRE_DEBUG(1, (__F, "no difference.\r\n")); - return; - } - /* - * find last same pointer - */ - while ((o > ofd) && (n > nfd) && (*--o == *--n)) - continue; - ols = ++o; - nls = ++n; - - /* - * find same beginning and same end - */ - osb = ols; - nsb = nls; - ose = ols; - nse = nls; - - /* - * case 1: insert: scan from nfd to nls looking for *ofd - */ - if (*ofd) { - for (c = *ofd, n = nfd; n < nls; n++) { - if (c == *n) { - for (o = ofd, p = n; - p < nls && o < ols && *o == *p; - o++, p++) - continue; - /* - * if the new match is longer and it's worth - * keeping, then we take it - */ - if (((nse - nsb) < (p - n)) && - (2 * (p - n) > n - nfd)) { - nsb = n; - nse = p; - osb = ofd; - ose = o; - } - } - } - } - /* - * case 2: delete: scan from ofd to ols looking for *nfd - */ - if (*nfd) { - for (c = *nfd, o = ofd; o < ols; o++) { - if (c == *o) { - for (n = nfd, p = o; - p < ols && n < nls && *p == *n; - p++, n++) - continue; - /* - * if the new match is longer and it's worth - * keeping, then we take it - */ - if (((ose - osb) < (p - o)) && - (2 * (p - o) > o - ofd)) { - nsb = nfd; - nse = n; - osb = o; - ose = p; - } - } - } - } - /* - * Pragmatics I: If old trailing whitespace or not enough characters to - * save to be worth it, then don't save the last same info. - */ - if ((oe - ols) < MIN_END_KEEP) { - ols = oe; - nls = ne; - } - /* - * Pragmatics II: if the terminal isn't smart enough, make the data - * dumber so the smart update doesn't try anything fancy - */ - - /* - * fx is the number of characters we need to insert/delete: in the - * beginning to bring the two same begins together - */ - fx = (int)((nsb - nfd) - (osb - ofd)); - /* - * sx is the number of characters we need to insert/delete: in the - * end to bring the two same last parts together - */ - sx = (int)((nls - nse) - (ols - ose)); - - if (!EL_CAN_INSERT) { - if (fx > 0) { - osb = ols; - ose = ols; - nsb = nls; - nse = nls; - } - if (sx > 0) { - ols = oe; - nls = ne; - } - if ((ols - ofd) < (nls - nfd)) { - ols = oe; - nls = ne; - } - } - if (!EL_CAN_DELETE) { - if (fx < 0) { - osb = ols; - ose = ols; - nsb = nls; - nse = nls; - } - if (sx < 0) { - ols = oe; - nls = ne; - } - if ((ols - ofd) > (nls - nfd)) { - ols = oe; - nls = ne; - } - } - /* - * Pragmatics III: make sure the middle shifted pointers are correct if - * they don't point to anything (we may have moved ols or nls). - */ - /* if the change isn't worth it, don't bother */ - /* was: if (osb == ose) */ - if ((ose - osb) < MIN_END_KEEP) { - osb = ols; - ose = ols; - nsb = nls; - nse = nls; - } - /* - * Now that we are done with pragmatics we recompute fx, sx - */ - fx = (int)((nsb - nfd) - (osb - ofd)); - sx = (int)((nls - nse) - (ols - ose)); - - ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx)); - ELRE_DEBUG(1, (__F, "ofd %td, osb %td, ose %td, ols %td, oe %td\n", - ofd - old, osb - old, ose - old, ols - old, oe - old)); - ELRE_DEBUG(1, (__F, "nfd %td, nsb %td, nse %td, nls %td, ne %td\n", - nfd - new, nsb - new, nse - new, nls - new, ne - new)); - ELRE_DEBUG(1, (__F, - "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n")); - ELRE_DEBUG(1, (__F, - "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n")); -#ifdef DEBUG_REFRESH - re_printstr(el, "old- oe", old, oe); - re_printstr(el, "new- ne", new, ne); - re_printstr(el, "old-ofd", old, ofd); - re_printstr(el, "new-nfd", new, nfd); - re_printstr(el, "ofd-osb", ofd, osb); - re_printstr(el, "nfd-nsb", nfd, nsb); - re_printstr(el, "osb-ose", osb, ose); - re_printstr(el, "nsb-nse", nsb, nse); - re_printstr(el, "ose-ols", ose, ols); - re_printstr(el, "nse-nls", nse, nls); - re_printstr(el, "ols- oe", ols, oe); - re_printstr(el, "nls- ne", nls, ne); -#endif /* DEBUG_REFRESH */ - - /* - * el_cursor.v to this line i MUST be in this routine so that if we - * don't have to change the line, we don't move to it. el_cursor.h to - * first diff char - */ - terminal_move_to_line(el, i); - - /* - * at this point we have something like this: - * - * /old /ofd /osb /ose /ols /oe - * v.....................v v..................v v........v - * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as - * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as - * ^.....................^ ^..................^ ^........^ - * \new \nfd \nsb \nse \nls \ne - * - * fx is the difference in length between the chars between nfd and - * nsb, and the chars between ofd and osb, and is thus the number of - * characters to delete if < 0 (new is shorter than old, as above), - * or insert (new is longer than short). - * - * sx is the same for the second differences. - */ - - /* - * if we have a net insert on the first difference, AND inserting the - * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful - * character (which is ne if nls != ne, otherwise is nse) off the edge - * of the screen (el->el_terminal.t_size.h) else we do the deletes first - * so that we keep everything we need to. - */ - - /* - * if the last same is the same like the end, there is no last same - * part, otherwise we want to keep the last same part set p to the - * last useful old character - */ - p = (ols != oe) ? oe : ose; - - /* - * if (There is a diffence in the beginning) && (we need to insert - * characters) && (the number of characters to insert is less than - * the term width) - * We need to do an insert! - * else if (we need to delete characters) - * We need to delete characters! - * else - * No insert or delete - */ - if ((nsb != nfd) && fx > 0 && - ((p - old) + fx <= el->el_terminal.t_size.h)) { - ELRE_DEBUG(1, - (__F, "first diff insert at %td...\r\n", nfd - new)); - /* - * Move to the first char to insert, where the first diff is. - */ - terminal_move_to_char(el, (int)(nfd - new)); - /* - * Check if we have stuff to keep at end - */ - if (nsb != ne) { - ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); - /* - * insert fx chars of new starting at nfd - */ - if (fx > 0) { - ELRE_DEBUG(!EL_CAN_INSERT, (__F, - "ERROR: cannot insert in early first diff\n")); - terminal_insertwrite(el, nfd, fx); - re_insert(el, old, (int)(ofd - old), - el->el_terminal.t_size.h, nfd, fx); - } - /* - * write (nsb-nfd) - fx chars of new starting at - * (nfd + fx) - */ - len = (size_t) ((nsb - nfd) - fx); - terminal_overwrite(el, (nfd + fx), len); - re__strncopy(ofd + fx, nfd + fx, len); - } else { - ELRE_DEBUG(1, (__F, "without anything to save\r\n")); - len = (size_t)(nsb - nfd); - terminal_overwrite(el, nfd, len); - re__strncopy(ofd, nfd, len); - /* - * Done - */ - return; - } - } else if (fx < 0) { - ELRE_DEBUG(1, - (__F, "first diff delete at %td...\r\n", ofd - old)); - /* - * move to the first char to delete where the first diff is - */ - terminal_move_to_char(el, (int)(ofd - old)); - /* - * Check if we have stuff to save - */ - if (osb != oe) { - ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); - /* - * fx is less than zero *always* here but we check - * for code symmetry - */ - if (fx < 0) { - ELRE_DEBUG(!EL_CAN_DELETE, (__F, - "ERROR: cannot delete in first diff\n")); - terminal_deletechars(el, -fx); - re_delete(el, old, (int)(ofd - old), - el->el_terminal.t_size.h, -fx); - } - /* - * write (nsb-nfd) chars of new starting at nfd - */ - len = (size_t) (nsb - nfd); - terminal_overwrite(el, nfd, len); - re__strncopy(ofd, nfd, len); - - } else { - ELRE_DEBUG(1, (__F, - "but with nothing left to save\r\n")); - /* - * write (nsb-nfd) chars of new starting at nfd - */ - terminal_overwrite(el, nfd, (size_t)(nsb - nfd)); - re_clear_eol(el, fx, sx, - (int)((oe - old) - (ne - new))); - /* - * Done - */ - return; - } - } else - fx = 0; - - if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) { - ELRE_DEBUG(1, (__F, - "second diff delete at %td...\r\n", (ose - old) + fx)); - /* - * Check if we have stuff to delete - */ - /* - * fx is the number of characters inserted (+) or deleted (-) - */ - - terminal_move_to_char(el, (int)((ose - old) + fx)); - /* - * Check if we have stuff to save - */ - if (ols != oe) { - ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); - /* - * Again a duplicate test. - */ - if (sx < 0) { - ELRE_DEBUG(!EL_CAN_DELETE, (__F, - "ERROR: cannot delete in second diff\n")); - terminal_deletechars(el, -sx); - } - /* - * write (nls-nse) chars of new starting at nse - */ - terminal_overwrite(el, nse, (size_t)(nls - nse)); - } else { - ELRE_DEBUG(1, (__F, - "but with nothing left to save\r\n")); - terminal_overwrite(el, nse, (size_t)(nls - nse)); - re_clear_eol(el, fx, sx, - (int)((oe - old) - (ne - new))); - } - } - /* - * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... - */ - if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { - ELRE_DEBUG(1, (__F, "late first diff insert at %td...\r\n", - nfd - new)); - - terminal_move_to_char(el, (int)(nfd - new)); - /* - * Check if we have stuff to keep at the end - */ - if (nsb != ne) { - ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); - /* - * We have to recalculate fx here because we set it - * to zero above as a flag saying that we hadn't done - * an early first insert. - */ - fx = (int)((nsb - nfd) - (osb - ofd)); - if (fx > 0) { - /* - * insert fx chars of new starting at nfd - */ - ELRE_DEBUG(!EL_CAN_INSERT, (__F, - "ERROR: cannot insert in late first diff\n")); - terminal_insertwrite(el, nfd, fx); - re_insert(el, old, (int)(ofd - old), - el->el_terminal.t_size.h, nfd, fx); - } - /* - * write (nsb-nfd) - fx chars of new starting at - * (nfd + fx) - */ - len = (size_t) ((nsb - nfd) - fx); - terminal_overwrite(el, (nfd + fx), len); - re__strncopy(ofd + fx, nfd + fx, len); - } else { - ELRE_DEBUG(1, (__F, "without anything to save\r\n")); - len = (size_t) (nsb - nfd); - terminal_overwrite(el, nfd, len); - re__strncopy(ofd, nfd, len); - } - } - /* - * line is now NEW up to nse - */ - if (sx >= 0) { - ELRE_DEBUG(1, (__F, - "second diff insert at %d...\r\n", (int)(nse - new))); - terminal_move_to_char(el, (int)(nse - new)); - if (ols != oe) { - ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); - if (sx > 0) { - /* insert sx chars of new starting at nse */ - ELRE_DEBUG(!EL_CAN_INSERT, (__F, - "ERROR: cannot insert in second diff\n")); - terminal_insertwrite(el, nse, sx); - } - /* - * write (nls-nse) - sx chars of new starting at - * (nse + sx) - */ - terminal_overwrite(el, (nse + sx), - (size_t)((nls - nse) - sx)); - } else { - ELRE_DEBUG(1, (__F, "without anything to save\r\n")); - terminal_overwrite(el, nse, (size_t)(nls - nse)); - - /* - * No need to do a clear-to-end here because we were - * doing a second insert, so we will have over - * written all of the old string. - */ - } - } - ELRE_DEBUG(1, (__F, "done.\r\n")); -} - - -/* re__copy_and_pad(): - * Copy string and pad with spaces - */ -static void -re__copy_and_pad(wchar_t *dst, const wchar_t *src, size_t width) -{ - size_t i; - - for (i = 0; i < width; i++) { - if (*src == '\0') - break; - *dst++ = *src++; - } - - for (; i < width; i++) - *dst++ = ' '; - - *dst = '\0'; -} - - -/* re_refresh_cursor(): - * Move to the new cursor position - */ -libedit_private void -re_refresh_cursor(EditLine *el) -{ - wchar_t *cp; - int h, v, th, w; - - if (el->el_line.cursor >= el->el_line.lastchar) { - if (el->el_map.current == el->el_map.alt - && el->el_line.lastchar != el->el_line.buffer) - el->el_line.cursor = el->el_line.lastchar - 1; - else - el->el_line.cursor = el->el_line.lastchar; - } - - /* first we must find where the cursor is... */ - h = el->el_prompt.p_pos.h; - v = el->el_prompt.p_pos.v; - th = el->el_terminal.t_size.h; /* optimize for speed */ - - /* do input buffer to el->el_line.cursor */ - for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { - switch (ct_chr_class(*cp)) { - case CHTYPE_NL: /* handle newline in data part too */ - h = 0; - v++; - break; - case CHTYPE_TAB: /* if a tab, to next tab stop */ - while (++h & 07) - continue; - break; - default: - w = wcwidth(*cp); - if (w > 1 && h + w > th) { /* won't fit on line */ - h = 0; - v++; - } - h += ct_visual_width(*cp); - break; - } - - if (h >= th) { /* check, extra long tabs picked up here also */ - h -= th; - v++; - } - } - /* if we have a next character, and it's a doublewidth one, we need to - * check whether we need to linebreak for it to fit */ - if (cp < el->el_line.lastchar && (w = wcwidth(*cp)) > 1) - if (h + w > th) { - h = 0; - v++; - } - - /* now go there */ - terminal_move_to_line(el, v); - terminal_move_to_char(el, h); - terminal__flush(el); -} - - -/* re_fastputc(): - * Add a character fast. - */ -static void -re_fastputc(EditLine *el, wint_t c) -{ - int w = wcwidth(c); - while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h) - re_fastputc(el, ' '); - - terminal__putc(el, c); - el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; - while (--w > 0) - el->el_display[el->el_cursor.v][el->el_cursor.h++] - = MB_FILL_CHAR; - - if (el->el_cursor.h >= el->el_terminal.t_size.h) { - /* if we must overflow */ - el->el_cursor.h = 0; - - /* - * If we would overflow (input is longer than terminal size), - * emulate scroll by dropping first line and shuffling the rest. - * We do this via pointer shuffling - it's safe in this case - * and we avoid memcpy(). - */ - if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) { - int i, lins = el->el_terminal.t_size.v; - wchar_t *firstline = el->el_display[0]; - - for(i = 1; i < lins; i++) - el->el_display[i - 1] = el->el_display[i]; - - re__copy_and_pad(firstline, L"", (size_t)0); - el->el_display[i - 1] = firstline; - } else { - el->el_cursor.v++; - el->el_refresh.r_oldcv++; - } - if (EL_HAS_AUTO_MARGINS) { - if (EL_HAS_MAGIC_MARGINS) { - terminal__putc(el, ' '); - terminal__putc(el, '\b'); - } - } else { - terminal__putc(el, '\r'); - terminal__putc(el, '\n'); - } - } -} - - -/* re_fastaddc(): - * we added just one char, handle it fast. - * Assumes that screen cursor == real cursor - */ -libedit_private void -re_fastaddc(EditLine *el) -{ - wchar_t c; - int rhdiff; - - c = el->el_line.cursor[-1]; - - if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { - re_refresh(el); /* too hard to handle */ - return; - } - rhdiff = el->el_terminal.t_size.h - el->el_cursor.h - - el->el_rprompt.p_pos.h; - if (el->el_rprompt.p_pos.h && rhdiff < 3) { - re_refresh(el); /* clear out rprompt if less than 1 char gap */ - return; - } /* else (only do at end of line, no TAB) */ - switch (ct_chr_class(c)) { - case CHTYPE_TAB: /* already handled, should never happen here */ - break; - case CHTYPE_NL: - case CHTYPE_PRINT: - re_fastputc(el, c); - break; - case CHTYPE_ASCIICTL: - case CHTYPE_NONPRINT: { - wchar_t visbuf[VISUAL_WIDTH_MAX]; - ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); - for (i = 0; n-- > 0; ++i) - re_fastputc(el, visbuf[i]); - break; - } - } - terminal__flush(el); -} - - -/* re_clear_display(): - * clear the screen buffers so that new new prompt starts fresh. - */ -libedit_private void -re_clear_display(EditLine *el) -{ - int i; - - el->el_cursor.v = 0; - el->el_cursor.h = 0; - for (i = 0; i < el->el_terminal.t_size.v; i++) - el->el_display[i][0] = '\0'; - el->el_refresh.r_oldcv = 0; -} - - -/* re_clear_lines(): - * Make sure all lines are *really* blank - */ -libedit_private void -re_clear_lines(EditLine *el) -{ - - if (EL_CAN_CEOL) { - int i; - for (i = el->el_refresh.r_oldcv; i >= 0; i--) { - /* for each line on the screen */ - terminal_move_to_line(el, i); - terminal_move_to_char(el, 0); - terminal_clear_EOL(el, el->el_terminal.t_size.h); - } - } else { - terminal_move_to_line(el, el->el_refresh.r_oldcv); - /* go to last line */ - terminal__putc(el, '\r'); /* go to BOL */ - terminal__putc(el, '\n'); /* go to new line */ - } -} diff --git a/bin/catsh/libedit/refresh.h b/bin/catsh/libedit/refresh.h deleted file mode 100644 index 09b22ef6..00000000 --- a/bin/catsh/libedit/refresh.h +++ /dev/null @@ -1,59 +0,0 @@ -/* $NetBSD: refresh.h,v 1.10.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)refresh.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.refresh.h: Screen refresh functions - */ -#ifndef _h_el_refresh -#define _h_el_refresh - -typedef struct { - coord_t r_cursor; /* Refresh cursor position */ - int r_oldcv; /* Vertical locations */ - int r_newcv; -} el_refresh_t; - -libedit_private void re_putc(EditLine *, wint_t, int); -libedit_private void re_putliteral(EditLine *, const wchar_t *, - const wchar_t *); -libedit_private void re_clear_lines(EditLine *); -libedit_private void re_clear_display(EditLine *); -libedit_private void re_refresh(EditLine *); -libedit_private void re_refresh_cursor(EditLine *); -libedit_private void re_fastaddc(EditLine *); -libedit_private void re_goto_bottom(EditLine *); - -#endif /* _h_el_refresh */ diff --git a/bin/catsh/libedit/search.c b/bin/catsh/libedit/search.c deleted file mode 100644 index 5226cf5f..00000000 --- a/bin/catsh/libedit/search.c +++ /dev/null @@ -1,641 +0,0 @@ -/* $NetBSD: search.c,v 1.47 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: search.c,v 1.47 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * search.c: History and character search functions - */ -#include <stdlib.h> -#include <string.h> -#if defined(REGEX) -#include <regex.h> -#elif defined(REGEXP) -#include <regexp.h> -#endif - -#include "el.h" -#include "common.h" -#include "fcns.h" - -/* - * Adjust cursor in vi mode to include the character under it - */ -#define EL_CURSOR(el) \ - ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \ - ((el)->el_map.current == (el)->el_map.alt))) - -/* search_init(): - * Initialize the search stuff - */ -libedit_private int -search_init(EditLine *el) -{ - - el->el_search.patbuf = el_malloc(EL_BUFSIZ * - sizeof(*el->el_search.patbuf)); - if (el->el_search.patbuf == NULL) - return -1; - el->el_search.patbuf[0] = L'\0'; - el->el_search.patlen = 0; - el->el_search.patdir = -1; - el->el_search.chacha = L'\0'; - el->el_search.chadir = CHAR_FWD; - el->el_search.chatflg = 0; - return 0; -} - - -/* search_end(): - * Initialize the search stuff - */ -libedit_private void -search_end(EditLine *el) -{ - - el_free(el->el_search.patbuf); - el->el_search.patbuf = NULL; -} - - -#ifdef REGEXP -/* regerror(): - * Handle regular expression errors - */ -void -/*ARGSUSED*/ -regerror(const char *msg) -{ -} -#endif - - -/* el_match(): - * Return if string matches pattern - */ -libedit_private int -el_match(const wchar_t *str, const wchar_t *pat) -{ - static ct_buffer_t conv; -#if defined (REGEX) - regex_t re; - int rv; -#elif defined (REGEXP) - regexp *rp; - int rv; -#else - extern char *re_comp(const char *); - extern int re_exec(const char *); -#endif - - if (wcsstr(str, pat) != 0) - return 1; - -#if defined(REGEX) - if (regcomp(&re, ct_encode_string(pat, &conv), 0) == 0) { - rv = regexec(&re, ct_encode_string(str, &conv), (size_t)0, NULL, - 0) == 0; - regfree(&re); - } else { - rv = 0; - } - return rv; -#elif defined(REGEXP) - if ((re = regcomp(ct_encode_string(pat, &conv))) != NULL) { - rv = regexec(re, ct_encode_string(str, &conv)); - el_free(re); - } else { - rv = 0; - } - return rv; -#else - if (re_comp(ct_encode_string(pat, &conv)) != NULL) - return 0; - else - return re_exec(ct_encode_string(str, &conv)) == 1; -#endif -} - - -/* c_hmatch(): - * return True if the pattern matches the prefix - */ -libedit_private int -c_hmatch(EditLine *el, const wchar_t *str) -{ -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", - el->el_search.patbuf, str); -#endif /* SDEBUG */ - - return el_match(str, el->el_search.patbuf); -} - - -/* c_setpat(): - * Set the history seatch pattern - */ -libedit_private void -c_setpat(EditLine *el) -{ - if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && - el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { - el->el_search.patlen = - (size_t)(EL_CURSOR(el) - el->el_line.buffer); - if (el->el_search.patlen >= EL_BUFSIZ) - el->el_search.patlen = EL_BUFSIZ - 1; - if (el->el_search.patlen != 0) { - (void) wcsncpy(el->el_search.patbuf, el->el_line.buffer, - el->el_search.patlen); - el->el_search.patbuf[el->el_search.patlen] = '\0'; - } else - el->el_search.patlen = wcslen(el->el_search.patbuf); - } -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "\neventno = %d\n", - el->el_history.eventno); - (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); - (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", - el->el_search.patbuf); - (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", - EL_CURSOR(el) - el->el_line.buffer, - el->el_line.lastchar - el->el_line.buffer); -#endif -} - - -/* ce_inc_search(): - * Emacs incremental search - */ -libedit_private el_action_t -ce_inc_search(EditLine *el, int dir) -{ - static const wchar_t STRfwd[] = L"fwd", STRbck[] = L"bck"; - static wchar_t pchar = L':'; /* ':' = normal, '?' = failed */ - static wchar_t endcmd[2] = {'\0', '\0'}; - wchar_t *ocursor = el->el_line.cursor, oldpchar = pchar, ch; - const wchar_t *cp; - - el_action_t ret = CC_NORM; - - int ohisteventno = el->el_history.eventno; - size_t oldpatlen = el->el_search.patlen; - int newdir = dir; - int done, redo; - - if (el->el_line.lastchar + sizeof(STRfwd) / - sizeof(*el->el_line.lastchar) + 2 + - el->el_search.patlen >= el->el_line.limit) - return CC_ERROR; - - for (;;) { - - if (el->el_search.patlen == 0) { /* first round */ - pchar = ':'; -#ifdef ANCHOR -#define LEN 2 - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; -#else -#define LEN 0 -#endif - } - done = redo = 0; - *el->el_line.lastchar++ = '\n'; - for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd; - *cp; *el->el_line.lastchar++ = *cp++) - continue; - *el->el_line.lastchar++ = pchar; - for (cp = &el->el_search.patbuf[LEN]; - cp < &el->el_search.patbuf[el->el_search.patlen]; - *el->el_line.lastchar++ = *cp++) - continue; - *el->el_line.lastchar = '\0'; - re_refresh(el); - - if (el_wgetc(el, &ch) != 1) - return ed_end_of_file(el, 0); - - switch (el->el_map.current[(unsigned char) ch]) { - case ED_INSERT: - case ED_DIGIT: - if (el->el_search.patlen >= EL_BUFSIZ - LEN) - terminal_beep(el); - else { - el->el_search.patbuf[el->el_search.patlen++] = - ch; - *el->el_line.lastchar++ = ch; - *el->el_line.lastchar = '\0'; - re_refresh(el); - } - break; - - case EM_INC_SEARCH_NEXT: - newdir = ED_SEARCH_NEXT_HISTORY; - redo++; - break; - - case EM_INC_SEARCH_PREV: - newdir = ED_SEARCH_PREV_HISTORY; - redo++; - break; - - case EM_DELETE_PREV_CHAR: - case ED_DELETE_PREV_CHAR: - if (el->el_search.patlen > LEN) - done++; - else - terminal_beep(el); - break; - - default: - switch (ch) { - case 0007: /* ^G: Abort */ - ret = CC_ERROR; - done++; - break; - - case 0027: /* ^W: Append word */ - /* No can do if globbing characters in pattern */ - for (cp = &el->el_search.patbuf[LEN];; cp++) - if (cp >= &el->el_search.patbuf[ - el->el_search.patlen]) { - el->el_line.cursor += - el->el_search.patlen - LEN - 1; - cp = c__next_word(el->el_line.cursor, - el->el_line.lastchar, 1, - ce__isword); - while (el->el_line.cursor < cp && - *el->el_line.cursor != '\n') { - if (el->el_search.patlen >= - EL_BUFSIZ - LEN) { - terminal_beep(el); - break; - } - el->el_search.patbuf[el->el_search.patlen++] = - *el->el_line.cursor; - *el->el_line.lastchar++ = - *el->el_line.cursor++; - } - el->el_line.cursor = ocursor; - *el->el_line.lastchar = '\0'; - re_refresh(el); - break; - } else if (isglob(*cp)) { - terminal_beep(el); - break; - } - break; - - default: /* Terminate and execute cmd */ - endcmd[0] = ch; - el_wpush(el, endcmd); - /* FALLTHROUGH */ - - case 0033: /* ESC: Terminate */ - ret = CC_REFRESH; - done++; - break; - } - break; - } - - while (el->el_line.lastchar > el->el_line.buffer && - *el->el_line.lastchar != '\n') - *el->el_line.lastchar-- = '\0'; - *el->el_line.lastchar = '\0'; - - if (!done) { - - /* Can't search if unmatched '[' */ - for (cp = &el->el_search.patbuf[el->el_search.patlen-1], - ch = L']'; - cp >= &el->el_search.patbuf[LEN]; - cp--) - if (*cp == '[' || *cp == ']') { - ch = *cp; - break; - } - if (el->el_search.patlen > LEN && ch != L'[') { - if (redo && newdir == dir) { - if (pchar == '?') { /* wrap around */ - el->el_history.eventno = - newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; - if (hist_get(el) == CC_ERROR) - /* el->el_history.event - * no was fixed by - * first call */ - (void) hist_get(el); - el->el_line.cursor = newdir == - ED_SEARCH_PREV_HISTORY ? - el->el_line.lastchar : - el->el_line.buffer; - } else - el->el_line.cursor += - newdir == - ED_SEARCH_PREV_HISTORY ? - -1 : 1; - } -#ifdef ANCHOR - el->el_search.patbuf[el->el_search.patlen++] = - '.'; - el->el_search.patbuf[el->el_search.patlen++] = - '*'; -#endif - el->el_search.patbuf[el->el_search.patlen] = - '\0'; - if (el->el_line.cursor < el->el_line.buffer || - el->el_line.cursor > el->el_line.lastchar || - (ret = ce_search_line(el, newdir)) - == CC_ERROR) { - /* avoid c_setpat */ - el->el_state.lastcmd = - (el_action_t) newdir; - ret = (el_action_t) - (newdir == ED_SEARCH_PREV_HISTORY ? - ed_search_prev_history(el, 0) : - ed_search_next_history(el, 0)); - if (ret != CC_ERROR) { - el->el_line.cursor = newdir == - ED_SEARCH_PREV_HISTORY ? - el->el_line.lastchar : - el->el_line.buffer; - (void) ce_search_line(el, - newdir); - } - } - el->el_search.patlen -= LEN; - el->el_search.patbuf[el->el_search.patlen] = - '\0'; - if (ret == CC_ERROR) { - terminal_beep(el); - if (el->el_history.eventno != - ohisteventno) { - el->el_history.eventno = - ohisteventno; - if (hist_get(el) == CC_ERROR) - return CC_ERROR; - } - el->el_line.cursor = ocursor; - pchar = '?'; - } else { - pchar = ':'; - } - } - ret = ce_inc_search(el, newdir); - - if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') - /* - * break abort of failed search at last - * non-failed - */ - ret = CC_NORM; - - } - if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { - /* restore on normal return or error exit */ - pchar = oldpchar; - el->el_search.patlen = oldpatlen; - if (el->el_history.eventno != ohisteventno) { - el->el_history.eventno = ohisteventno; - if (hist_get(el) == CC_ERROR) - return CC_ERROR; - } - el->el_line.cursor = ocursor; - if (ret == CC_ERROR) - re_refresh(el); - } - if (done || ret != CC_NORM) - return ret; - } -} - - -/* cv_search(): - * Vi search. - */ -libedit_private el_action_t -cv_search(EditLine *el, int dir) -{ - wchar_t ch; - wchar_t tmpbuf[EL_BUFSIZ]; - ssize_t tmplen; - -#ifdef ANCHOR - tmpbuf[0] = '.'; - tmpbuf[1] = '*'; -#endif - tmplen = LEN; - - el->el_search.patdir = dir; - - tmplen = c_gets(el, &tmpbuf[LEN], - dir == ED_SEARCH_PREV_HISTORY ? L"\n/" : L"\n?" ); - if (tmplen == -1) - return CC_REFRESH; - - tmplen += LEN; - ch = tmpbuf[tmplen]; - tmpbuf[tmplen] = '\0'; - - if (tmplen == LEN) { - /* - * Use the old pattern, but wild-card it. - */ - if (el->el_search.patlen == 0) { - re_refresh(el); - return CC_ERROR; - } -#ifdef ANCHOR - if (el->el_search.patbuf[0] != '.' && - el->el_search.patbuf[0] != '*') { - (void) wcsncpy(tmpbuf, el->el_search.patbuf, - sizeof(tmpbuf) / sizeof(*tmpbuf) - 1); - el->el_search.patbuf[0] = '.'; - el->el_search.patbuf[1] = '*'; - (void) wcsncpy(&el->el_search.patbuf[2], tmpbuf, - EL_BUFSIZ - 3); - el->el_search.patlen++; - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; - el->el_search.patbuf[el->el_search.patlen] = '\0'; - } -#endif - } else { -#ifdef ANCHOR - tmpbuf[tmplen++] = '.'; - tmpbuf[tmplen++] = '*'; -#endif - tmpbuf[tmplen] = '\0'; - (void) wcsncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); - el->el_search.patlen = (size_t)tmplen; - } - el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ - el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; - if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : - ed_search_next_history(el, 0)) == CC_ERROR) { - re_refresh(el); - return CC_ERROR; - } - if (ch == 0033) { - re_refresh(el); - return ed_newline(el, 0); - } - return CC_REFRESH; -} - - -/* ce_search_line(): - * Look for a pattern inside a line - */ -libedit_private el_action_t -ce_search_line(EditLine *el, int dir) -{ - wchar_t *cp = el->el_line.cursor; - wchar_t *pattern = el->el_search.patbuf; - wchar_t oc, *ocp; -#ifdef ANCHOR - ocp = &pattern[1]; - oc = *ocp; - *ocp = '^'; -#else - ocp = pattern; - oc = *ocp; -#endif - - if (dir == ED_SEARCH_PREV_HISTORY) { - for (; cp >= el->el_line.buffer; cp--) { - if (el_match(cp, ocp)) { - *ocp = oc; - el->el_line.cursor = cp; - return CC_NORM; - } - } - *ocp = oc; - return CC_ERROR; - } else { - for (; *cp != '\0' && cp < el->el_line.limit; cp++) { - if (el_match(cp, ocp)) { - *ocp = oc; - el->el_line.cursor = cp; - return CC_NORM; - } - } - *ocp = oc; - return CC_ERROR; - } -} - - -/* cv_repeat_srch(): - * Vi repeat search - */ -libedit_private el_action_t -cv_repeat_srch(EditLine *el, wint_t c) -{ - -#ifdef SDEBUG - (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", - c, el->el_search.patlen, ct_encode_string(el->el_search.patbuf)); -#endif - - el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ - el->el_line.lastchar = el->el_line.buffer; - - switch (c) { - case ED_SEARCH_NEXT_HISTORY: - return ed_search_next_history(el, 0); - case ED_SEARCH_PREV_HISTORY: - return ed_search_prev_history(el, 0); - default: - return CC_ERROR; - } -} - - -/* cv_csearch(): - * Vi character search - */ -libedit_private el_action_t -cv_csearch(EditLine *el, int direction, wint_t ch, int count, int tflag) -{ - wchar_t *cp; - - if (ch == 0) - return CC_ERROR; - - if (ch == (wint_t)-1) { - if (el_wgetc(el, &ch) != 1) - return ed_end_of_file(el, 0); - } - - /* Save for ';' and ',' commands */ - el->el_search.chacha = ch; - el->el_search.chadir = direction; - el->el_search.chatflg = (char)tflag; - - cp = el->el_line.cursor; - while (count--) { - if ((wint_t)*cp == ch) - cp += direction; - for (;;cp += direction) { - if (cp >= el->el_line.lastchar) - return CC_ERROR; - if (cp < el->el_line.buffer) - return CC_ERROR; - if ((wint_t)*cp == ch) - break; - } - } - - if (tflag) - cp -= direction; - - el->el_line.cursor = cp; - - if (el->el_chared.c_vcmd.action != NOP) { - if (direction > 0) - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} diff --git a/bin/catsh/libedit/search.h b/bin/catsh/libedit/search.h deleted file mode 100644 index 4ca39c4c..00000000 --- a/bin/catsh/libedit/search.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $NetBSD: search.h,v 1.14 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)search.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.search.h: Line and history searching utilities - */ -#ifndef _h_el_search -#define _h_el_search - -typedef struct el_search_t { - wchar_t *patbuf; /* The pattern buffer */ - size_t patlen; /* Length of the pattern buffer */ - int patdir; /* Direction of the last search */ - int chadir; /* Character search direction */ - wchar_t chacha; /* Character we are looking for */ - char chatflg; /* 0 if f, 1 if t */ -} el_search_t; - - -libedit_private int el_match(const wchar_t *, const wchar_t *); -libedit_private int search_init(EditLine *); -libedit_private void search_end(EditLine *); -libedit_private int c_hmatch(EditLine *, const wchar_t *); -libedit_private void c_setpat(EditLine *); -libedit_private el_action_t ce_inc_search(EditLine *, int); -libedit_private el_action_t cv_search(EditLine *, int); -libedit_private el_action_t ce_search_line(EditLine *, int); -libedit_private el_action_t cv_repeat_srch(EditLine *, wint_t); -libedit_private el_action_t cv_csearch(EditLine *, int, wint_t, int, int); - -#endif /* _h_el_search */ diff --git a/bin/catsh/libedit/shlib_version b/bin/catsh/libedit/shlib_version deleted file mode 100644 index 303609d2..00000000 --- a/bin/catsh/libedit/shlib_version +++ /dev/null @@ -1,5 +0,0 @@ -# $NetBSD: shlib_version,v 1.19 2013/01/22 20:23:21 christos Exp $ -# Remember to update distrib/sets/lists/base/shl.* when changing -# -major=3 -minor=1 diff --git a/bin/catsh/libedit/sig.c b/bin/catsh/libedit/sig.c deleted file mode 100644 index 83742a3d..00000000 --- a/bin/catsh/libedit/sig.c +++ /dev/null @@ -1,205 +0,0 @@ -/* $NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * sig.c: Signal handling stuff. - * our policy is to trap all signals, set a good state - * and pass the ball to our caller. - */ -#include <errno.h> -#include <stdlib.h> - -#include "el.h" -#include "common.h" - -static EditLine *sel = NULL; - -static const int sighdl[] = { -#define _DO(a) (a), - ALLSIGS -#undef _DO - - 1 -}; - -static void sig_handler(int); - -/* sig_handler(): - * This is the handler called for all signals - * XXX: we cannot pass any data so we just store the old editline - * state in a private variable - */ -static void -sig_handler(int signo) -{ - int i, save_errno; - sigset_t nset, oset; - - save_errno = errno; - (void) sigemptyset(&nset); - (void) sigaddset(&nset, signo); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - - sel->el_signal->sig_no = signo; - - switch (signo) { - case SIGCONT: - tty_rawmode(sel); - if (ed_redisplay(sel, 0) == CC_REFRESH) - re_refresh(sel); - terminal__flush(sel); - break; - - case SIGWINCH: - el_resize(sel); - break; - - default: - tty_cookedmode(sel); - break; - } - - for (i = 0; sighdl[i] != -1; i++) - if (signo == sighdl[i]) - break; - - (void) sigaction(signo, &sel->el_signal->sig_action[i], NULL); - sel->el_signal->sig_action[i].sa_handler = SIG_ERR; - sel->el_signal->sig_action[i].sa_flags = 0; - sigemptyset(&sel->el_signal->sig_action[i].sa_mask); - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - (void) kill(0, signo); - errno = save_errno; -} - - -/* sig_init(): - * Initialize all signal stuff - */ -libedit_private int -sig_init(EditLine *el) -{ - size_t i; - sigset_t *nset, oset; - - el->el_signal = el_malloc(sizeof(*el->el_signal)); - if (el->el_signal == NULL) - return -1; - - nset = &el->el_signal->sig_set; - (void) sigemptyset(nset); -#define _DO(a) (void) sigaddset(nset, a); - ALLSIGS -#undef _DO - (void) sigprocmask(SIG_BLOCK, nset, &oset); - - for (i = 0; sighdl[i] != -1; i++) { - el->el_signal->sig_action[i].sa_handler = SIG_ERR; - el->el_signal->sig_action[i].sa_flags = 0; - sigemptyset(&el->el_signal->sig_action[i].sa_mask); - } - - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - - return 0; -} - - -/* sig_end(): - * Clear all signal stuff - */ -libedit_private void -sig_end(EditLine *el) -{ - - el_free(el->el_signal); - el->el_signal = NULL; -} - - -/* sig_set(): - * set all the signal handlers - */ -libedit_private void -sig_set(EditLine *el) -{ - size_t i; - sigset_t oset; - struct sigaction osa, nsa; - - nsa.sa_handler = sig_handler; - nsa.sa_flags = 0; - sigemptyset(&nsa.sa_mask); - - (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset); - - for (i = 0; sighdl[i] != -1; i++) { - /* This could happen if we get interrupted */ - if (sigaction(sighdl[i], &nsa, &osa) != -1 && - osa.sa_handler != sig_handler) - el->el_signal->sig_action[i] = osa; - } - sel = el; - (void) sigprocmask(SIG_SETMASK, &oset, NULL); -} - - -/* sig_clr(): - * clear all the signal handlers - */ -libedit_private void -sig_clr(EditLine *el) -{ - size_t i; - sigset_t oset; - - (void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset); - - for (i = 0; sighdl[i] != -1; i++) - if (el->el_signal->sig_action[i].sa_handler != SIG_ERR) - (void)sigaction(sighdl[i], - &el->el_signal->sig_action[i], NULL); - - sel = NULL; /* we are going to die if the handler is - * called */ - (void)sigprocmask(SIG_SETMASK, &oset, NULL); -} diff --git a/bin/catsh/libedit/sig.h b/bin/catsh/libedit/sig.h deleted file mode 100644 index 5ee453fb..00000000 --- a/bin/catsh/libedit/sig.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $NetBSD: sig.h,v 1.11 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)sig.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.sig.h: Signal handling functions - */ -#ifndef _h_el_sig -#define _h_el_sig - -#include <signal.h> - -/* - * Define here all the signals we are going to handle - * The _DO macro is used to iterate in the source code - */ -#define ALLSIGS \ - _DO(SIGINT) \ - _DO(SIGTSTP) \ - _DO(SIGQUIT) \ - _DO(SIGHUP) \ - _DO(SIGTERM) \ - _DO(SIGCONT) \ - _DO(SIGWINCH) -#define ALLSIGSNO 7 - -typedef struct { - struct sigaction sig_action[ALLSIGSNO]; - sigset_t sig_set; - volatile sig_atomic_t sig_no; -} *el_signal_t; - -libedit_private void sig_end(EditLine*); -libedit_private int sig_init(EditLine*); -libedit_private void sig_set(EditLine*); -libedit_private void sig_clr(EditLine*); - -#endif /* _h_el_sig */ diff --git a/bin/catsh/libedit/sys.h b/bin/catsh/libedit/sys.h deleted file mode 100644 index dc0a8cb9..00000000 --- a/bin/catsh/libedit/sys.h +++ /dev/null @@ -1,113 +0,0 @@ -/* $NetBSD: sys.h,v 1.27 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)sys.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * sys.h: Put all the stupid compiler and system dependencies here... - */ -#ifndef _h_sys -#define _h_sys - -#ifdef HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif - -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) -# define __attribute__(A) -#endif - -#ifndef __BEGIN_DECLS -# ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -# else -# define __BEGIN_DECLS -# define __END_DECLS -# endif -#endif - -/* If your compiler does not support this, define it to be empty. */ -#define libedit_private __attribute__((__visibility__("hidden"))) - -#ifndef __arraycount -# define __arraycount(a) (sizeof(a) / sizeof(*(a))) -#endif - -#include <stdio.h> - -#ifndef HAVE_STRLCAT -#define strlcat libedit_strlcat -size_t strlcat(char *dst, const char *src, size_t size); -#endif - -#ifndef HAVE_STRLCPY -#define strlcpy libedit_strlcpy -size_t strlcpy(char *dst, const char *src, size_t size); -#endif - -#ifndef HAVE_GETLINE -#define getline libedit_getline -ssize_t getline(char **line, size_t *len, FILE *fp); -#endif - -#ifndef _DIAGASSERT -#define _DIAGASSERT(x) -#endif - -#ifndef __RCSID -#define __RCSID(x) -#endif - -#ifndef HAVE_U_INT32_T -typedef unsigned int u_int32_t; -#endif - -#ifndef HAVE_SIZE_MAX -#define SIZE_MAX ((size_t)-1) -#endif - -#define REGEX /* Use POSIX.2 regular expression functions */ -#undef REGEXP /* Use UNIX V8 regular expression functions */ - -#if defined(__sun) -extern int tgetent(char *, const char *); -extern int tgetflag(char *); -extern int tgetnum(char *); -extern int tputs(const char *, int, int (*)(int)); -extern char* tgoto(const char*, int, int); -extern char* tgetstr(char*, char**); -#endif - -#endif /* _h_sys */ diff --git a/bin/catsh/libedit/terminal.c b/bin/catsh/libedit/terminal.c deleted file mode 100644 index edaa5b2b..00000000 --- a/bin/catsh/libedit/terminal.c +++ /dev/null @@ -1,1681 +0,0 @@ -/* $NetBSD: terminal.c,v 1.32.8.1 2017/07/23 14:41:26 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; -#else -__RCSID("$NetBSD: terminal.c,v 1.32.8.1 2017/07/23 14:41:26 snj Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * terminal.c: Editor/termcap-curses interface - * We have to declare a static variable here, since the - * termcap putchar routine does not take an argument! - */ -#include <sys/types.h> -#include <sys/ioctl.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#ifdef HAVE_TERMCAP_H -#include <termcap.h> -#endif -#ifdef HAVE_CURSES_H -#include <curses.h> -#elif HAVE_NCURSES_H -#include <ncurses.h> -#endif - -/* Solaris's term.h does horrid things. */ -#if defined(HAVE_TERM_H) && !defined(__sun) && !defined(HAVE_TERMCAP_H) -#include <term.h> -#endif - -#ifdef _REENTRANT -#include <pthread.h> -#endif - -#include "el.h" -#include "fcns.h" - -/* - * IMPORTANT NOTE: these routines are allowed to look at the current screen - * and the current position assuming that it is correct. If this is not - * true, then the update will be WRONG! This is (should be) a valid - * assumption... - */ - -#define TC_BUFSIZE ((size_t)2048) - -#define GoodStr(a) (el->el_terminal.t_str[a] != NULL && \ - el->el_terminal.t_str[a][0] != '\0') -#define Str(a) el->el_terminal.t_str[a] -#define Val(a) el->el_terminal.t_val[a] - -static const struct termcapstr { - const char *name; - const char *long_name; -} tstr[] = { -#define T_al 0 - { "al", "add new blank line" }, -#define T_bl 1 - { "bl", "audible bell" }, -#define T_cd 2 - { "cd", "clear to bottom" }, -#define T_ce 3 - { "ce", "clear to end of line" }, -#define T_ch 4 - { "ch", "cursor to horiz pos" }, -#define T_cl 5 - { "cl", "clear screen" }, -#define T_dc 6 - { "dc", "delete a character" }, -#define T_dl 7 - { "dl", "delete a line" }, -#define T_dm 8 - { "dm", "start delete mode" }, -#define T_ed 9 - { "ed", "end delete mode" }, -#define T_ei 10 - { "ei", "end insert mode" }, -#define T_fs 11 - { "fs", "cursor from status line" }, -#define T_ho 12 - { "ho", "home cursor" }, -#define T_ic 13 - { "ic", "insert character" }, -#define T_im 14 - { "im", "start insert mode" }, -#define T_ip 15 - { "ip", "insert padding" }, -#define T_kd 16 - { "kd", "sends cursor down" }, -#define T_kl 17 - { "kl", "sends cursor left" }, -#define T_kr 18 - { "kr", "sends cursor right" }, -#define T_ku 19 - { "ku", "sends cursor up" }, -#define T_md 20 - { "md", "begin bold" }, -#define T_me 21 - { "me", "end attributes" }, -#define T_nd 22 - { "nd", "non destructive space" }, -#define T_se 23 - { "se", "end standout" }, -#define T_so 24 - { "so", "begin standout" }, -#define T_ts 25 - { "ts", "cursor to status line" }, -#define T_up 26 - { "up", "cursor up one" }, -#define T_us 27 - { "us", "begin underline" }, -#define T_ue 28 - { "ue", "end underline" }, -#define T_vb 29 - { "vb", "visible bell" }, -#define T_DC 30 - { "DC", "delete multiple chars" }, -#define T_DO 31 - { "DO", "cursor down multiple" }, -#define T_IC 32 - { "IC", "insert multiple chars" }, -#define T_LE 33 - { "LE", "cursor left multiple" }, -#define T_RI 34 - { "RI", "cursor right multiple" }, -#define T_UP 35 - { "UP", "cursor up multiple" }, -#define T_kh 36 - { "kh", "send cursor home" }, -#define T_at7 37 - { "@7", "send cursor end" }, -#define T_kD 38 - { "kD", "send cursor delete" }, -#define T_str 39 - { NULL, NULL } -}; - -static const struct termcapval { - const char *name; - const char *long_name; -} tval[] = { -#define T_am 0 - { "am", "has automatic margins" }, -#define T_pt 1 - { "pt", "has physical tabs" }, -#define T_li 2 - { "li", "Number of lines" }, -#define T_co 3 - { "co", "Number of columns" }, -#define T_km 4 - { "km", "Has meta key" }, -#define T_xt 5 - { "xt", "Tab chars destructive" }, -#define T_xn 6 - { "xn", "newline ignored at right margin" }, -#define T_MT 7 - { "MT", "Has meta key" }, /* XXX? */ -#define T_val 8 - { NULL, NULL, } -}; -/* do two or more of the attributes use me */ - -static void terminal_setflags(EditLine *); -static int terminal_rebuffer_display(EditLine *); -static void terminal_free_display(EditLine *); -static int terminal_alloc_display(EditLine *); -static void terminal_alloc(EditLine *, const struct termcapstr *, - const char *); -static void terminal_init_arrow(EditLine *); -static void terminal_reset_arrow(EditLine *); -static int terminal_putc(int); -static void terminal_tputs(EditLine *, const char *, int); - -#ifdef _REENTRANT -static pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif -static FILE *terminal_outfile = NULL; - - -/* terminal_setflags(): - * Set the terminal capability flags - */ -static void -terminal_setflags(EditLine *el) -{ - EL_FLAGS = 0; - if (el->el_tty.t_tabs) - EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0; - - EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0; - EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0; - EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0; - EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ? - TERM_CAN_INSERT : 0; - EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0; - EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0; - EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0; - - if (GoodStr(T_me) && GoodStr(T_ue)) - EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? - TERM_CAN_ME : 0; - else - EL_FLAGS &= ~TERM_CAN_ME; - if (GoodStr(T_me) && GoodStr(T_se)) - EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? - TERM_CAN_ME : 0; - - -#ifdef DEBUG_SCREEN - if (!EL_CAN_UP) { - (void) fprintf(el->el_errfile, - "WARNING: Your terminal cannot move up.\n"); - (void) fprintf(el->el_errfile, - "Editing may be odd for long lines.\n"); - } - if (!EL_CAN_CEOL) - (void) fprintf(el->el_errfile, "no clear EOL capability.\n"); - if (!EL_CAN_DELETE) - (void) fprintf(el->el_errfile, "no delete char capability.\n"); - if (!EL_CAN_INSERT) - (void) fprintf(el->el_errfile, "no insert char capability.\n"); -#endif /* DEBUG_SCREEN */ -} - -/* terminal_init(): - * Initialize the terminal stuff - */ -libedit_private int -terminal_init(EditLine *el) -{ - - el->el_terminal.t_buf = el_malloc(TC_BUFSIZE * - sizeof(*el->el_terminal.t_buf)); - if (el->el_terminal.t_buf == NULL) - goto fail1; - el->el_terminal.t_cap = el_malloc(TC_BUFSIZE * - sizeof(*el->el_terminal.t_cap)); - if (el->el_terminal.t_cap == NULL) - goto fail2; - el->el_terminal.t_fkey = el_malloc(A_K_NKEYS * - sizeof(*el->el_terminal.t_fkey)); - if (el->el_terminal.t_fkey == NULL) - goto fail3; - el->el_terminal.t_loc = 0; - el->el_terminal.t_str = el_malloc(T_str * - sizeof(*el->el_terminal.t_str)); - if (el->el_terminal.t_str == NULL) - goto fail4; - (void) memset(el->el_terminal.t_str, 0, T_str * - sizeof(*el->el_terminal.t_str)); - el->el_terminal.t_val = el_malloc(T_val * - sizeof(*el->el_terminal.t_val)); - if (el->el_terminal.t_val == NULL) - goto fail5; - (void) memset(el->el_terminal.t_val, 0, T_val * - sizeof(*el->el_terminal.t_val)); - (void) terminal_set(el, NULL); - terminal_init_arrow(el); - return 0; -fail5: - free(el->el_terminal.t_str); - el->el_terminal.t_str = NULL; -fail4: - free(el->el_terminal.t_fkey); - el->el_terminal.t_fkey = NULL; -fail3: - free(el->el_terminal.t_cap); - el->el_terminal.t_cap = NULL; -fail2: - free(el->el_terminal.t_buf); - el->el_terminal.t_buf = NULL; -fail1: - return -1; -} - -/* terminal_end(): - * Clean up the terminal stuff - */ -libedit_private void -terminal_end(EditLine *el) -{ - - el_free(el->el_terminal.t_buf); - el->el_terminal.t_buf = NULL; - el_free(el->el_terminal.t_cap); - el->el_terminal.t_cap = NULL; - el->el_terminal.t_loc = 0; - el_free(el->el_terminal.t_str); - el->el_terminal.t_str = NULL; - el_free(el->el_terminal.t_val); - el->el_terminal.t_val = NULL; - el_free(el->el_terminal.t_fkey); - el->el_terminal.t_fkey = NULL; - terminal_free_display(el); -} - - -/* terminal_alloc(): - * Maintain a string pool for termcap strings - */ -static void -terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap) -{ - char termbuf[TC_BUFSIZE]; - size_t tlen, clen; - char **tlist = el->el_terminal.t_str; - char **tmp, **str = &tlist[t - tstr]; - - (void) memset(termbuf, 0, sizeof(termbuf)); - if (cap == NULL || *cap == '\0') { - *str = NULL; - return; - } else - clen = strlen(cap); - - tlen = *str == NULL ? 0 : strlen(*str); - - /* - * New string is shorter; no need to allocate space - */ - if (clen <= tlen) { - if (*str) - (void) strcpy(*str, cap); /* XXX strcpy is safe */ - return; - } - /* - * New string is longer; see if we have enough space to append - */ - if (el->el_terminal.t_loc + 3 < TC_BUFSIZE) { - /* XXX strcpy is safe */ - (void) strcpy(*str = &el->el_terminal.t_buf[ - el->el_terminal.t_loc], cap); - el->el_terminal.t_loc += clen + 1; /* one for \0 */ - return; - } - /* - * Compact our buffer; no need to check compaction, cause we know it - * fits... - */ - tlen = 0; - for (tmp = tlist; tmp < &tlist[T_str]; tmp++) - if (*tmp != NULL && **tmp != '\0' && *tmp != *str) { - char *ptr; - - for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) - continue; - termbuf[tlen++] = '\0'; - } - memcpy(el->el_terminal.t_buf, termbuf, TC_BUFSIZE); - el->el_terminal.t_loc = tlen; - if (el->el_terminal.t_loc + 3 >= TC_BUFSIZE) { - (void) fprintf(el->el_errfile, - "Out of termcap string space.\n"); - return; - } - /* XXX strcpy is safe */ - (void) strcpy(*str = &el->el_terminal.t_buf[el->el_terminal.t_loc], - cap); - el->el_terminal.t_loc += (size_t)clen + 1; /* one for \0 */ - return; -} - - -/* terminal_rebuffer_display(): - * Rebuffer the display after the screen changed size - */ -static int -terminal_rebuffer_display(EditLine *el) -{ - coord_t *c = &el->el_terminal.t_size; - - terminal_free_display(el); - - c->h = Val(T_co); - c->v = Val(T_li); - - if (terminal_alloc_display(el) == -1) - return -1; - return 0; -} - -static wchar_t ** -terminal_alloc_buffer(EditLine *el) -{ - wint_t **b; - coord_t *c = &el->el_terminal.t_size; - int i; - - b = el_malloc(sizeof(*b) * (size_t)(c->v + 1)); - if (b == NULL) - return NULL; - for (i = 0; i < c->v; i++) { - b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1)); - if (b[i] == NULL) { - while (--i >= 0) - el_free(b[i]); - el_free(b); - return NULL; - } - } - b[c->v] = NULL; - return b; -} - -static void -terminal_free_buffer(wint_t ***bp) -{ - wint_t **b; - wint_t **bufp; - - if (*bp == NULL) - return; - - b = *bp; - *bp = NULL; - - for (bufp = b; *bufp != NULL; bufp++) - el_free(*bufp); - el_free(b); -} - -/* terminal_alloc_display(): - * Allocate a new display. - */ -static int -terminal_alloc_display(EditLine *el) -{ - el->el_display = terminal_alloc_buffer(el); - if (el->el_display == NULL) - goto done; - el->el_vdisplay = terminal_alloc_buffer(el); - if (el->el_vdisplay == NULL) - goto done; - return 0; -done: - terminal_free_display(el); - return -1; -} - - -/* terminal_free_display(): - * Free the display buffers - */ -static void -terminal_free_display(EditLine *el) -{ - terminal_free_buffer(&el->el_display); - terminal_free_buffer(&el->el_vdisplay); -} - - -/* terminal_move_to_line(): - * move to line <where> (first line == 0) - * as efficiently as possible - */ -libedit_private void -terminal_move_to_line(EditLine *el, int where) -{ - int del; - - if (where == el->el_cursor.v) - return; - - if (where > el->el_terminal.t_size.v) { -#ifdef DEBUG_SCREEN - (void) fprintf(el->el_errfile, - "%s: where is ridiculous: %d\r\n", __func__, where); -#endif /* DEBUG_SCREEN */ - return; - } - if ((del = where - el->el_cursor.v) > 0) { - while (del > 0) { - if (EL_HAS_AUTO_MARGINS && - el->el_display[el->el_cursor.v][0] != '\0') { - size_t h = (size_t) - (el->el_terminal.t_size.h - 1); - for (; h > 0 && - el->el_display[el->el_cursor.v][h] == - MB_FILL_CHAR; - h--) - continue; - /* move without newline */ - terminal_move_to_char(el, (int)h); - terminal_overwrite(el, &el->el_display - [el->el_cursor.v][el->el_cursor.h], - (size_t)(el->el_terminal.t_size.h - - el->el_cursor.h)); - /* updates Cursor */ - del--; - } else { - if ((del > 1) && GoodStr(T_DO)) { - terminal_tputs(el, tgoto(Str(T_DO), del, - del), del); - del = 0; - } else { - for (; del > 0; del--) - terminal__putc(el, '\n'); - /* because the \n will become \r\n */ - el->el_cursor.h = 0; - } - } - } - } else { /* del < 0 */ - if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) - terminal_tputs(el, tgoto(Str(T_UP), -del, -del), -del); - else { - if (GoodStr(T_up)) - for (; del < 0; del++) - terminal_tputs(el, Str(T_up), 1); - } - } - el->el_cursor.v = where;/* now where is here */ -} - - -/* terminal_move_to_char(): - * Move to the character position specified - */ -libedit_private void -terminal_move_to_char(EditLine *el, int where) -{ - int del, i; - -mc_again: - if (where == el->el_cursor.h) - return; - - if (where > el->el_terminal.t_size.h) { -#ifdef DEBUG_SCREEN - (void) fprintf(el->el_errfile, - "%s: where is ridiculous: %d\r\n", __func__, where); -#endif /* DEBUG_SCREEN */ - return; - } - if (!where) { /* if where is first column */ - terminal__putc(el, '\r'); /* do a CR */ - el->el_cursor.h = 0; - return; - } - del = where - el->el_cursor.h; - - if ((del < -4 || del > 4) && GoodStr(T_ch)) - /* go there directly */ - terminal_tputs(el, tgoto(Str(T_ch), where, where), where); - else { - if (del > 0) { /* moving forward */ - if ((del > 4) && GoodStr(T_RI)) - terminal_tputs(el, tgoto(Str(T_RI), del, del), - del); - else { - /* if I can do tabs, use them */ - if (EL_CAN_TAB) { - if ((el->el_cursor.h & 0370) != - (where & ~0x7) - && (el->el_display[ - el->el_cursor.v][where & 0370] != - MB_FILL_CHAR) - ) { - /* if not within tab stop */ - for (i = - (el->el_cursor.h & 0370); - i < (where & ~0x7); - i += 8) - terminal__putc(el, - '\t'); - /* then tab over */ - el->el_cursor.h = where & ~0x7; - } - } - /* - * it's usually cheaper to just write the - * chars, so we do. - */ - /* - * NOTE THAT terminal_overwrite() WILL CHANGE - * el->el_cursor.h!!! - */ - terminal_overwrite(el, &el->el_display[ - el->el_cursor.v][el->el_cursor.h], - (size_t)(where - el->el_cursor.h)); - - } - } else { /* del < 0 := moving backward */ - if ((-del > 4) && GoodStr(T_LE)) - terminal_tputs(el, tgoto(Str(T_LE), -del, -del), - -del); - else { /* can't go directly there */ - /* - * if the "cost" is greater than the "cost" - * from col 0 - */ - if (EL_CAN_TAB ? - ((unsigned int)-del > - (((unsigned int) where >> 3) + - (where & 07))) - : (-del > where)) { - terminal__putc(el, '\r');/* do a CR */ - el->el_cursor.h = 0; - goto mc_again; /* and try again */ - } - for (i = 0; i < -del; i++) - terminal__putc(el, '\b'); - } - } - } - el->el_cursor.h = where; /* now where is here */ -} - - -/* terminal_overwrite(): - * Overstrike num characters - * Assumes MB_FILL_CHARs are present to keep the column count correct - */ -libedit_private void -terminal_overwrite(EditLine *el, const wchar_t *cp, size_t n) -{ - if (n == 0) - return; - - if (n > (size_t)el->el_terminal.t_size.h) { -#ifdef DEBUG_SCREEN - (void) fprintf(el->el_errfile, - "%s: n is ridiculous: %zu\r\n", __func__, n); -#endif /* DEBUG_SCREEN */ - return; - } - - do { - /* terminal__putc() ignores any MB_FILL_CHARs */ - terminal__putc(el, *cp++); - el->el_cursor.h++; - } while (--n); - - if (el->el_cursor.h >= el->el_terminal.t_size.h) { /* wrap? */ - if (EL_HAS_AUTO_MARGINS) { /* yes */ - el->el_cursor.h = 0; - el->el_cursor.v++; - if (EL_HAS_MAGIC_MARGINS) { - /* force the wrap to avoid the "magic" - * situation */ - wchar_t c; - if ((c = el->el_display[el->el_cursor.v] - [el->el_cursor.h]) != '\0') { - terminal_overwrite(el, &c, (size_t)1); - while (el->el_display[el->el_cursor.v] - [el->el_cursor.h] == MB_FILL_CHAR) - el->el_cursor.h++; - } else { - terminal__putc(el, ' '); - el->el_cursor.h = 1; - } - } - } else /* no wrap, but cursor stays on screen */ - el->el_cursor.h = el->el_terminal.t_size.h - 1; - } -} - - -/* terminal_deletechars(): - * Delete num characters - */ -libedit_private void -terminal_deletechars(EditLine *el, int num) -{ - if (num <= 0) - return; - - if (!EL_CAN_DELETE) { -#ifdef DEBUG_EDIT - (void) fprintf(el->el_errfile, " ERROR: cannot delete \n"); -#endif /* DEBUG_EDIT */ - return; - } - if (num > el->el_terminal.t_size.h) { -#ifdef DEBUG_SCREEN - (void) fprintf(el->el_errfile, - "%s: num is ridiculous: %d\r\n", __func__, num); -#endif /* DEBUG_SCREEN */ - return; - } - if (GoodStr(T_DC)) /* if I have multiple delete */ - if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more - * expen. */ - terminal_tputs(el, tgoto(Str(T_DC), num, num), num); - return; - } - if (GoodStr(T_dm)) /* if I have delete mode */ - terminal_tputs(el, Str(T_dm), 1); - - if (GoodStr(T_dc)) /* else do one at a time */ - while (num--) - terminal_tputs(el, Str(T_dc), 1); - - if (GoodStr(T_ed)) /* if I have delete mode */ - terminal_tputs(el, Str(T_ed), 1); -} - - -/* terminal_insertwrite(): - * Puts terminal in insert character mode or inserts num - * characters in the line - * Assumes MB_FILL_CHARs are present to keep column count correct - */ -libedit_private void -terminal_insertwrite(EditLine *el, wchar_t *cp, int num) -{ - if (num <= 0) - return; - if (!EL_CAN_INSERT) { -#ifdef DEBUG_EDIT - (void) fprintf(el->el_errfile, " ERROR: cannot insert \n"); -#endif /* DEBUG_EDIT */ - return; - } - if (num > el->el_terminal.t_size.h) { -#ifdef DEBUG_SCREEN - (void) fprintf(el->el_errfile, - "%s: num is ridiculous: %d\r\n", __func__, num); -#endif /* DEBUG_SCREEN */ - return; - } - if (GoodStr(T_IC)) /* if I have multiple insert */ - if ((num > 1) || !GoodStr(T_ic)) { - /* if ic would be more expensive */ - terminal_tputs(el, tgoto(Str(T_IC), num, num), num); - terminal_overwrite(el, cp, (size_t)num); - /* this updates el_cursor.h */ - return; - } - if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ - terminal_tputs(el, Str(T_im), 1); - - el->el_cursor.h += num; - do - terminal__putc(el, *cp++); - while (--num); - - if (GoodStr(T_ip)) /* have to make num chars insert */ - terminal_tputs(el, Str(T_ip), 1); - - terminal_tputs(el, Str(T_ei), 1); - return; - } - do { - if (GoodStr(T_ic)) /* have to make num chars insert */ - terminal_tputs(el, Str(T_ic), 1); - - terminal__putc(el, *cp++); - - el->el_cursor.h++; - - if (GoodStr(T_ip)) /* have to make num chars insert */ - terminal_tputs(el, Str(T_ip), 1); - /* pad the inserted char */ - - } while (--num); -} - - -/* terminal_clear_EOL(): - * clear to end of line. There are num characters to clear - */ -libedit_private void -terminal_clear_EOL(EditLine *el, int num) -{ - int i; - - if (EL_CAN_CEOL && GoodStr(T_ce)) - terminal_tputs(el, Str(T_ce), 1); - else { - for (i = 0; i < num; i++) - terminal__putc(el, ' '); - el->el_cursor.h += num; /* have written num spaces */ - } -} - - -/* terminal_clear_screen(): - * Clear the screen - */ -libedit_private void -terminal_clear_screen(EditLine *el) -{ /* clear the whole screen and home */ - - if (GoodStr(T_cl)) - /* send the clear screen code */ - terminal_tputs(el, Str(T_cl), Val(T_li)); - else if (GoodStr(T_ho) && GoodStr(T_cd)) { - terminal_tputs(el, Str(T_ho), Val(T_li)); /* home */ - /* clear to bottom of screen */ - terminal_tputs(el, Str(T_cd), Val(T_li)); - } else { - terminal__putc(el, '\r'); - terminal__putc(el, '\n'); - } -} - - -/* terminal_beep(): - * Beep the way the terminal wants us - */ -libedit_private void -terminal_beep(EditLine *el) -{ - if (GoodStr(T_bl)) - /* what termcap says we should use */ - terminal_tputs(el, Str(T_bl), 1); - else - terminal__putc(el, '\007'); /* an ASCII bell; ^G */ -} - - -libedit_private void -terminal_get(EditLine *el, const char **term) -{ - *term = el->el_terminal.t_name; -} - - -/* terminal_set(): - * Read in the terminal capabilities from the requested terminal - */ -libedit_private int -terminal_set(EditLine *el, const char *term) -{ - int i; - char buf[TC_BUFSIZE]; - char *area; - const struct termcapstr *t; - sigset_t oset, nset; - int lins, cols; - - (void) sigemptyset(&nset); - (void) sigaddset(&nset, SIGWINCH); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - - area = buf; - - - if (term == NULL) - term = getenv("TERM"); - - if (!term || !term[0]) - term = "dumb"; - - if (strcmp(term, "emacs") == 0) - el->el_flags |= EDIT_DISABLED; - - (void) memset(el->el_terminal.t_cap, 0, TC_BUFSIZE); - - i = tgetent(el->el_terminal.t_cap, term); - - if (i <= 0) { - if (i == -1) - (void) fprintf(el->el_errfile, - "Cannot read termcap database;\n"); - else if (i == 0) - (void) fprintf(el->el_errfile, - "No entry for terminal type \"%s\";\n", term); - (void) fprintf(el->el_errfile, - "using dumb terminal settings.\n"); - Val(T_co) = 80; /* do a dumb terminal */ - Val(T_pt) = Val(T_km) = Val(T_li) = 0; - Val(T_xt) = Val(T_MT); - for (t = tstr; t->name != NULL; t++) - terminal_alloc(el, t, NULL); - } else { - /* auto/magic margins */ - Val(T_am) = tgetflag("am"); - Val(T_xn) = tgetflag("xn"); - /* Can we tab */ - Val(T_pt) = tgetflag("pt"); - Val(T_xt) = tgetflag("xt"); - /* do we have a meta? */ - Val(T_km) = tgetflag("km"); - Val(T_MT) = tgetflag("MT"); - /* Get the size */ - Val(T_co) = tgetnum("co"); - Val(T_li) = tgetnum("li"); - for (t = tstr; t->name != NULL; t++) { - /* XXX: some systems' tgetstr needs non const */ - terminal_alloc(el, t, tgetstr(strchr(t->name, *t->name), - &area)); - } - } - - if (Val(T_co) < 2) - Val(T_co) = 80; /* just in case */ - if (Val(T_li) < 1) - Val(T_li) = 24; - - el->el_terminal.t_size.v = Val(T_co); - el->el_terminal.t_size.h = Val(T_li); - - terminal_setflags(el); - - /* get the correct window size */ - (void) terminal_get_size(el, &lins, &cols); - if (terminal_change_size(el, lins, cols) == -1) - return -1; - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - terminal_bind_arrow(el); - el->el_terminal.t_name = term; - return i <= 0 ? -1 : 0; -} - - -/* terminal_get_size(): - * Return the new window size in lines and cols, and - * true if the size was changed. - */ -libedit_private int -terminal_get_size(EditLine *el, int *lins, int *cols) -{ - - *cols = Val(T_co); - *lins = Val(T_li); - -#ifdef TIOCGWINSZ - { - struct winsize ws; - if (ioctl(el->el_infd, TIOCGWINSZ, &ws) != -1) { - if (ws.ws_col) - *cols = ws.ws_col; - if (ws.ws_row) - *lins = ws.ws_row; - } - } -#endif -#ifdef TIOCGSIZE - { - struct ttysize ts; - if (ioctl(el->el_infd, TIOCGSIZE, &ts) != -1) { - if (ts.ts_cols) - *cols = ts.ts_cols; - if (ts.ts_lines) - *lins = ts.ts_lines; - } - } -#endif - return Val(T_co) != *cols || Val(T_li) != *lins; -} - - -/* terminal_change_size(): - * Change the size of the terminal - */ -libedit_private int -terminal_change_size(EditLine *el, int lins, int cols) -{ - /* - * Just in case - */ - Val(T_co) = (cols < 2) ? 80 : cols; - Val(T_li) = (lins < 1) ? 24 : lins; - - /* re-make display buffers */ - if (terminal_rebuffer_display(el) == -1) - return -1; - re_clear_display(el); - return 0; -} - - -/* terminal_init_arrow(): - * Initialize the arrow key bindings from termcap - */ -static void -terminal_init_arrow(EditLine *el) -{ - funckey_t *arrow = el->el_terminal.t_fkey; - - arrow[A_K_DN].name = L"down"; - arrow[A_K_DN].key = T_kd; - arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY; - arrow[A_K_DN].type = XK_CMD; - - arrow[A_K_UP].name = L"up"; - arrow[A_K_UP].key = T_ku; - arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY; - arrow[A_K_UP].type = XK_CMD; - - arrow[A_K_LT].name = L"left"; - arrow[A_K_LT].key = T_kl; - arrow[A_K_LT].fun.cmd = ED_PREV_CHAR; - arrow[A_K_LT].type = XK_CMD; - - arrow[A_K_RT].name = L"right"; - arrow[A_K_RT].key = T_kr; - arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR; - arrow[A_K_RT].type = XK_CMD; - - arrow[A_K_HO].name = L"home"; - arrow[A_K_HO].key = T_kh; - arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG; - arrow[A_K_HO].type = XK_CMD; - - arrow[A_K_EN].name = L"end"; - arrow[A_K_EN].key = T_at7; - arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END; - arrow[A_K_EN].type = XK_CMD; - - arrow[A_K_DE].name = L"delete"; - arrow[A_K_DE].key = T_kD; - arrow[A_K_DE].fun.cmd = ED_DELETE_NEXT_CHAR; - arrow[A_K_DE].type = XK_CMD; -} - - -/* terminal_reset_arrow(): - * Reset arrow key bindings - */ -static void -terminal_reset_arrow(EditLine *el) -{ - funckey_t *arrow = el->el_terminal.t_fkey; - static const wchar_t strA[] = L"\033[A"; - static const wchar_t strB[] = L"\033[B"; - static const wchar_t strC[] = L"\033[C"; - static const wchar_t strD[] = L"\033[D"; - static const wchar_t strH[] = L"\033[H"; - static const wchar_t strF[] = L"\033[F"; - static const wchar_t stOA[] = L"\033OA"; - static const wchar_t stOB[] = L"\033OB"; - static const wchar_t stOC[] = L"\033OC"; - static const wchar_t stOD[] = L"\033OD"; - static const wchar_t stOH[] = L"\033OH"; - static const wchar_t stOF[] = L"\033OF"; - - keymacro_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - keymacro_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - keymacro_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - keymacro_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - keymacro_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); - keymacro_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); - keymacro_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - keymacro_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - keymacro_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - keymacro_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - keymacro_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); - keymacro_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); - - if (el->el_map.type != MAP_VI) - return; - keymacro_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - keymacro_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - keymacro_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - keymacro_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - keymacro_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); - keymacro_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); - keymacro_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - keymacro_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - keymacro_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - keymacro_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - keymacro_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); - keymacro_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); -} - - -/* terminal_set_arrow(): - * Set an arrow key binding - */ -libedit_private int -terminal_set_arrow(EditLine *el, const wchar_t *name, keymacro_value_t *fun, - int type) -{ - funckey_t *arrow = el->el_terminal.t_fkey; - int i; - - for (i = 0; i < A_K_NKEYS; i++) - if (wcscmp(name, arrow[i].name) == 0) { - arrow[i].fun = *fun; - arrow[i].type = type; - return 0; - } - return -1; -} - - -/* terminal_clear_arrow(): - * Clear an arrow key binding - */ -libedit_private int -terminal_clear_arrow(EditLine *el, const wchar_t *name) -{ - funckey_t *arrow = el->el_terminal.t_fkey; - int i; - - for (i = 0; i < A_K_NKEYS; i++) - if (wcscmp(name, arrow[i].name) == 0) { - arrow[i].type = XK_NOD; - return 0; - } - return -1; -} - - -/* terminal_print_arrow(): - * Print the arrow key bindings - */ -libedit_private void -terminal_print_arrow(EditLine *el, const wchar_t *name) -{ - int i; - funckey_t *arrow = el->el_terminal.t_fkey; - - for (i = 0; i < A_K_NKEYS; i++) - if (*name == '\0' || wcscmp(name, arrow[i].name) == 0) - if (arrow[i].type != XK_NOD) - keymacro_kprint(el, arrow[i].name, - &arrow[i].fun, arrow[i].type); -} - - -/* terminal_bind_arrow(): - * Bind the arrow keys - */ -libedit_private void -terminal_bind_arrow(EditLine *el) -{ - el_action_t *map; - const el_action_t *dmap; - int i, j; - char *p; - funckey_t *arrow = el->el_terminal.t_fkey; - - /* Check if the components needed are initialized */ - if (el->el_terminal.t_buf == NULL || el->el_map.key == NULL) - return; - - map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key; - dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs; - - terminal_reset_arrow(el); - - for (i = 0; i < A_K_NKEYS; i++) { - wchar_t wt_str[VISUAL_WIDTH_MAX]; - wchar_t *px; - size_t n; - - p = el->el_terminal.t_str[arrow[i].key]; - if (!p || !*p) - continue; - for (n = 0; n < VISUAL_WIDTH_MAX && p[n]; ++n) - wt_str[n] = p[n]; - while (n < VISUAL_WIDTH_MAX) - wt_str[n++] = '\0'; - px = wt_str; - j = (unsigned char) *p; - /* - * Assign the arrow keys only if: - * - * 1. They are multi-character arrow keys and the user - * has not re-assigned the leading character, or - * has re-assigned the leading character to be - * ED_SEQUENCE_LEAD_IN - * 2. They are single arrow keys pointing to an - * unassigned key. - */ - if (arrow[i].type == XK_NOD) - keymacro_clear(el, map, px); - else { - if (p[1] && (dmap[j] == map[j] || - map[j] == ED_SEQUENCE_LEAD_IN)) { - keymacro_add(el, px, &arrow[i].fun, - arrow[i].type); - map[j] = ED_SEQUENCE_LEAD_IN; - } else if (map[j] == ED_UNASSIGNED) { - keymacro_clear(el, map, px); - if (arrow[i].type == XK_CMD) - map[j] = arrow[i].fun.cmd; - else - keymacro_add(el, px, &arrow[i].fun, - arrow[i].type); - } - } - } -} - -/* terminal_putc(): - * Add a character - */ -static int -terminal_putc(int c) -{ - if (terminal_outfile == NULL) - return -1; - return fputc(c, terminal_outfile); -} - -static void -terminal_tputs(EditLine *el, const char *cap, int affcnt) -{ -#ifdef _REENTRANT - pthread_mutex_lock(&terminal_mutex); -#endif - terminal_outfile = el->el_outfile; - (void)tputs(cap, affcnt, terminal_putc); -#ifdef _REENTRANT - pthread_mutex_unlock(&terminal_mutex); -#endif -} - -/* terminal__putc(): - * Add a character - */ -libedit_private int -terminal__putc(EditLine *el, wint_t c) -{ - char buf[MB_LEN_MAX +1]; - ssize_t i; - if (c == (wint_t)MB_FILL_CHAR) - return 0; - if (c & EL_LITERAL) - return fputs(literal_get(el, c), el->el_outfile); - i = ct_encode_char(buf, (size_t)MB_LEN_MAX, c); - if (i <= 0) - return (int)i; - buf[i] = '\0'; - return fputs(buf, el->el_outfile); -} - -/* terminal__flush(): - * Flush output - */ -libedit_private void -terminal__flush(EditLine *el) -{ - - (void) fflush(el->el_outfile); -} - -/* terminal_writec(): - * Write the given character out, in a human readable form - */ -libedit_private void -terminal_writec(EditLine *el, wint_t c) -{ - wchar_t visbuf[VISUAL_WIDTH_MAX +1]; - ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); - if (vcnt < 0) - vcnt = 0; - visbuf[vcnt] = '\0'; - terminal_overwrite(el, visbuf, (size_t)vcnt); - terminal__flush(el); -} - - -/* terminal_telltc(): - * Print the current termcap characteristics - */ -libedit_private int -/*ARGSUSED*/ -terminal_telltc(EditLine *el, int argc __attribute__((__unused__)), - const wchar_t **argv __attribute__((__unused__))) -{ - const struct termcapstr *t; - char **ts; - - (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n"); - (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n"); - (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n", - Val(T_co), Val(T_li)); - (void) fprintf(el->el_outfile, - "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no"); - (void) fprintf(el->el_outfile, - "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not "); - (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n", - EL_HAS_AUTO_MARGINS ? "has" : "does not have"); - if (EL_HAS_AUTO_MARGINS) - (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", - EL_HAS_MAGIC_MARGINS ? "has" : "does not have"); - - for (t = tstr, ts = el->el_terminal.t_str; t->name != NULL; t++, ts++) { - const char *ub; - if (*ts && **ts) { - ub = ct_encode_string(ct_visual_string( - ct_decode_string(*ts, &el->el_scratch), - &el->el_visual), &el->el_scratch); - } else { - ub = "(empty)"; - } - (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", - t->long_name, t->name, ub); - } - (void) fputc('\n', el->el_outfile); - return 0; -} - - -/* terminal_settc(): - * Change the current terminal characteristics - */ -libedit_private int -/*ARGSUSED*/ -terminal_settc(EditLine *el, int argc __attribute__((__unused__)), - const wchar_t **argv) -{ - const struct termcapstr *ts; - const struct termcapval *tv; - char what[8], how[8]; - - if (argv == NULL || argv[1] == NULL || argv[2] == NULL) - return -1; - - strncpy(what, ct_encode_string(argv[1], &el->el_scratch), sizeof(what)); - what[sizeof(what) - 1] = '\0'; - strncpy(how, ct_encode_string(argv[2], &el->el_scratch), sizeof(how)); - how[sizeof(how) - 1] = '\0'; - - /* - * Do the strings first - */ - for (ts = tstr; ts->name != NULL; ts++) - if (strcmp(ts->name, what) == 0) - break; - - if (ts->name != NULL) { - terminal_alloc(el, ts, how); - terminal_setflags(el); - return 0; - } - /* - * Do the numeric ones second - */ - for (tv = tval; tv->name != NULL; tv++) - if (strcmp(tv->name, what) == 0) - break; - - if (tv->name != NULL) - return -1; - - if (tv == &tval[T_pt] || tv == &tval[T_km] || - tv == &tval[T_am] || tv == &tval[T_xn]) { - if (strcmp(how, "yes") == 0) - el->el_terminal.t_val[tv - tval] = 1; - else if (strcmp(how, "no") == 0) - el->el_terminal.t_val[tv - tval] = 0; - else { - (void) fprintf(el->el_errfile, - "%ls: Bad value `%s'.\n", argv[0], how); - return -1; - } - terminal_setflags(el); - if (terminal_change_size(el, Val(T_li), Val(T_co)) == -1) - return -1; - return 0; - } else { - long i; - char *ep; - - i = strtol(how, &ep, 10); - if (*ep != '\0') { - (void) fprintf(el->el_errfile, - "%ls: Bad value `%s'.\n", argv[0], how); - return -1; - } - el->el_terminal.t_val[tv - tval] = (int) i; - el->el_terminal.t_size.v = Val(T_co); - el->el_terminal.t_size.h = Val(T_li); - if (tv == &tval[T_co] || tv == &tval[T_li]) - if (terminal_change_size(el, Val(T_li), Val(T_co)) - == -1) - return -1; - return 0; - } -} - - -/* terminal_gettc(): - * Get the current terminal characteristics - */ -libedit_private int -/*ARGSUSED*/ -terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) -{ - const struct termcapstr *ts; - const struct termcapval *tv; - char *what; - void *how; - - if (argv == NULL || argv[1] == NULL || argv[2] == NULL) - return -1; - - what = argv[1]; - how = argv[2]; - - /* - * Do the strings first - */ - for (ts = tstr; ts->name != NULL; ts++) - if (strcmp(ts->name, what) == 0) - break; - - if (ts->name != NULL) { - *(char **)how = el->el_terminal.t_str[ts - tstr]; - return 0; - } - /* - * Do the numeric ones second - */ - for (tv = tval; tv->name != NULL; tv++) - if (strcmp(tv->name, what) == 0) - break; - - if (tv->name == NULL) - return -1; - - if (tv == &tval[T_pt] || tv == &tval[T_km] || - tv == &tval[T_am] || tv == &tval[T_xn]) { - static char yes[] = "yes"; - static char no[] = "no"; - if (el->el_terminal.t_val[tv - tval]) - *(char **)how = yes; - else - *(char **)how = no; - return 0; - } else { - *(int *)how = el->el_terminal.t_val[tv - tval]; - return 0; - } -} - -/* terminal_echotc(): - * Print the termcap string out with variable substitution - */ -libedit_private int -/*ARGSUSED*/ -terminal_echotc(EditLine *el, int argc __attribute__((__unused__)), - const wchar_t **argv) -{ - char *cap, *scap; - wchar_t *ep; - int arg_need, arg_cols, arg_rows; - int verbose = 0, silent = 0; - char *area; - static const char fmts[] = "%s\n", fmtd[] = "%d\n"; - const struct termcapstr *t; - char buf[TC_BUFSIZE]; - long i; - - area = buf; - - if (argv == NULL || argv[1] == NULL) - return -1; - argv++; - - if (argv[0][0] == '-') { - switch (argv[0][1]) { - case 'v': - verbose = 1; - break; - case 's': - silent = 1; - break; - default: - /* stderror(ERR_NAME | ERR_TCUSAGE); */ - break; - } - argv++; - } - if (!*argv || *argv[0] == '\0') - return 0; - if (wcscmp(*argv, L"tabs") == 0) { - (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); - return 0; - } else if (wcscmp(*argv, L"meta") == 0) { - (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no"); - return 0; - } else if (wcscmp(*argv, L"xn") == 0) { - (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ? - "yes" : "no"); - return 0; - } else if (wcscmp(*argv, L"am") == 0) { - (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ? - "yes" : "no"); - return 0; - } else if (wcscmp(*argv, L"baud") == 0) { - (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed); - return 0; - } else if (wcscmp(*argv, L"rows") == 0 || - wcscmp(*argv, L"lines") == 0) { - (void) fprintf(el->el_outfile, fmtd, Val(T_li)); - return 0; - } else if (wcscmp(*argv, L"cols") == 0) { - (void) fprintf(el->el_outfile, fmtd, Val(T_co)); - return 0; - } - /* - * Try to use our local definition first - */ - scap = NULL; - for (t = tstr; t->name != NULL; t++) - if (strcmp(t->name, - ct_encode_string(*argv, &el->el_scratch)) == 0) { - scap = el->el_terminal.t_str[t - tstr]; - break; - } - if (t->name == NULL) { - /* XXX: some systems' tgetstr needs non const */ - scap = tgetstr(ct_encode_string(*argv, &el->el_scratch), &area); - } - if (!scap || scap[0] == '\0') { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Termcap parameter `%ls' not found.\n", - *argv); - return -1; - } - /* - * Count home many values we need for this capability. - */ - for (cap = scap, arg_need = 0; *cap; cap++) - if (*cap == '%') - switch (*++cap) { - case 'd': - case '2': - case '3': - case '.': - case '+': - arg_need++; - break; - case '%': - case '>': - case 'i': - case 'r': - case 'n': - case 'B': - case 'D': - break; - default: - /* - * hpux has lot's of them... - */ - if (verbose) - (void) fprintf(el->el_errfile, - "echotc: Warning: unknown termcap %% `%c'.\n", - *cap); - /* This is bad, but I won't complain */ - break; - } - - switch (arg_need) { - case 0: - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%ls'.\n", - *argv); - return -1; - } - terminal_tputs(el, scap, 1); - break; - case 1: - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - arg_cols = 0; - i = wcstol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Bad value `%ls' for rows.\n", - *argv); - return -1; - } - arg_rows = (int) i; - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%ls" - "'.\n", *argv); - return -1; - } - terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), 1); - break; - default: - /* This is wrong, but I will ignore it... */ - if (verbose) - (void) fprintf(el->el_errfile, - "echotc: Warning: Too many required arguments (%d).\n", - arg_need); - /* FALLTHROUGH */ - case 2: - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - i = wcstol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Bad value `%ls' for cols.\n", - *argv); - return -1; - } - arg_cols = (int) i; - argv++; - if (!*argv || *argv[0] == '\0') { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Missing argument.\n"); - return -1; - } - i = wcstol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Bad value `%ls' for rows.\n", - *argv); - return -1; - } - arg_rows = (int) i; - if (*ep != '\0') { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Bad value `%ls'.\n", *argv); - return -1; - } - argv++; - if (*argv && *argv[0]) { - if (!silent) - (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%ls" - "'.\n", *argv); - return -1; - } - terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows); - break; - } - return 0; -} diff --git a/bin/catsh/libedit/terminal.h b/bin/catsh/libedit/terminal.h deleted file mode 100644 index ae61beb1..00000000 --- a/bin/catsh/libedit/terminal.h +++ /dev/null @@ -1,125 +0,0 @@ -/* $NetBSD: terminal.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)term.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.term.h: Termcap header - */ -#ifndef _h_el_terminal -#define _h_el_terminal - -typedef struct { /* Symbolic function key bindings */ - const wchar_t *name; /* name of the key */ - int key; /* Index in termcap table */ - keymacro_value_t fun; /* Function bound to it */ - int type; /* Type of function */ -} funckey_t; - -typedef struct { - const char *t_name; /* the terminal name */ - coord_t t_size; /* # lines and cols */ - int t_flags; -#define TERM_CAN_INSERT 0x001 /* Has insert cap */ -#define TERM_CAN_DELETE 0x002 /* Has delete cap */ -#define TERM_CAN_CEOL 0x004 /* Has CEOL cap */ -#define TERM_CAN_TAB 0x008 /* Can use tabs */ -#define TERM_CAN_ME 0x010 /* Can turn all attrs. */ -#define TERM_CAN_UP 0x020 /* Can move up */ -#define TERM_HAS_META 0x040 /* Has a meta key */ -#define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */ -#define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */ - char *t_buf; /* Termcap buffer */ - size_t t_loc; /* location used */ - char **t_str; /* termcap strings */ - int *t_val; /* termcap values */ - char *t_cap; /* Termcap buffer */ - funckey_t *t_fkey; /* Array of keys */ -} el_terminal_t; - -/* - * fKey indexes - */ -#define A_K_DN 0 -#define A_K_UP 1 -#define A_K_LT 2 -#define A_K_RT 3 -#define A_K_HO 4 -#define A_K_EN 5 -#define A_K_DE 6 -#define A_K_NKEYS 7 - -libedit_private void terminal_move_to_line(EditLine *, int); -libedit_private void terminal_move_to_char(EditLine *, int); -libedit_private void terminal_clear_EOL(EditLine *, int); -libedit_private void terminal_overwrite(EditLine *, const wchar_t *, size_t); -libedit_private void terminal_insertwrite(EditLine *, wchar_t *, int); -libedit_private void terminal_deletechars(EditLine *, int); -libedit_private void terminal_clear_screen(EditLine *); -libedit_private void terminal_beep(EditLine *); -libedit_private int terminal_change_size(EditLine *, int, int); -libedit_private int terminal_get_size(EditLine *, int *, int *); -libedit_private int terminal_init(EditLine *); -libedit_private void terminal_bind_arrow(EditLine *); -libedit_private void terminal_print_arrow(EditLine *, const wchar_t *); -libedit_private int terminal_clear_arrow(EditLine *, const wchar_t *); -libedit_private int terminal_set_arrow(EditLine *, const wchar_t *, - keymacro_value_t *, int); -libedit_private void terminal_end(EditLine *); -libedit_private void terminal_get(EditLine *, const char **); -libedit_private int terminal_set(EditLine *, const char *); -libedit_private int terminal_settc(EditLine *, int, const wchar_t **); -libedit_private int terminal_gettc(EditLine *, int, char **); -libedit_private int terminal_telltc(EditLine *, int, const wchar_t **); -libedit_private int terminal_echotc(EditLine *, int, const wchar_t **); -libedit_private void terminal_writec(EditLine *, wint_t); -libedit_private int terminal__putc(EditLine *, wint_t); -libedit_private void terminal__flush(EditLine *); - -/* - * Easy access macros - */ -#define EL_FLAGS (el)->el_terminal.t_flags - -#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT) -#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE) -#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL) -#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB) -#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME) -#define EL_CAN_UP (EL_FLAGS & TERM_CAN_UP) -#define EL_HAS_META (EL_FLAGS & TERM_HAS_META) -#define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS) -#define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS) - -#endif /* _h_el_terminal */ diff --git a/bin/catsh/libedit/tokenizer.c b/bin/catsh/libedit/tokenizer.c deleted file mode 100644 index 18532240..00000000 --- a/bin/catsh/libedit/tokenizer.c +++ /dev/null @@ -1,466 +0,0 @@ -/* $NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* We build this file twice, once as NARROW, once as WIDE. */ -/* - * tokenize.c: Bourne shell like tokenizer - */ -#include <stdlib.h> -#include <string.h> - -#include "histedit.h" - -typedef enum { - Q_none, Q_single, Q_double, Q_one, Q_doubleone -} quote_t; - -#define TOK_KEEP 1 -#define TOK_EAT 2 - -#define WINCR 20 -#define AINCR 10 - -#define IFS STR("\t \n") - -#define tok_malloc(a) malloc(a) -#define tok_free(a) free(a) -#define tok_realloc(a, b) realloc(a, b) - -#ifdef NARROWCHAR -#define Char char -#define FUN(prefix, rest) prefix ## _ ## rest -#define TYPE(type) type -#define STR(x) x -#define Strchr(s, c) strchr(s, c) -#define tok_strdup(s) strdup(s) -#else -#define Char wchar_t -#define FUN(prefix, rest) prefix ## _w ## rest -#define TYPE(type) type ## W -#define STR(x) L ## x -#define Strchr(s, c) wcschr(s, c) -#define tok_strdup(s) wcsdup(s) -#endif - -struct TYPE(tokenizer) { - Char *ifs; /* In field separator */ - size_t argc, amax; /* Current and maximum number of args */ - Char **argv; /* Argument list */ - Char *wptr, *wmax; /* Space and limit on the word buffer */ - Char *wstart; /* Beginning of next word */ - Char *wspace; /* Space of word buffer */ - quote_t quote; /* Quoting state */ - int flags; /* flags; */ -}; - - -static void FUN(tok,finish)(TYPE(Tokenizer) *); - - -/* FUN(tok,finish)(): - * Finish a word in the tokenizer. - */ -static void -FUN(tok,finish)(TYPE(Tokenizer) *tok) -{ - - *tok->wptr = '\0'; - if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) { - tok->argv[tok->argc++] = tok->wstart; - tok->argv[tok->argc] = NULL; - tok->wstart = ++tok->wptr; - } - tok->flags &= ~TOK_KEEP; -} - - -/* FUN(tok,init)(): - * Initialize the tokenizer - */ -TYPE(Tokenizer) * -FUN(tok,init)(const Char *ifs) -{ - TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok)); - - if (tok == NULL) - return NULL; - tok->ifs = tok_strdup(ifs ? ifs : IFS); - if (tok->ifs == NULL) { - tok_free(tok); - return NULL; - } - tok->argc = 0; - tok->amax = AINCR; - tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax); - if (tok->argv == NULL) { - tok_free(tok->ifs); - tok_free(tok); - return NULL; - } - tok->argv[0] = NULL; - tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace)); - if (tok->wspace == NULL) { - tok_free(tok->argv); - tok_free(tok->ifs); - tok_free(tok); - return NULL; - } - tok->wmax = tok->wspace + WINCR; - tok->wstart = tok->wspace; - tok->wptr = tok->wspace; - tok->flags = 0; - tok->quote = Q_none; - - return tok; -} - - -/* FUN(tok,reset)(): - * Reset the tokenizer - */ -void -FUN(tok,reset)(TYPE(Tokenizer) *tok) -{ - - tok->argc = 0; - tok->wstart = tok->wspace; - tok->wptr = tok->wspace; - tok->flags = 0; - tok->quote = Q_none; -} - - -/* FUN(tok,end)(): - * Clean up - */ -void -FUN(tok,end)(TYPE(Tokenizer) *tok) -{ - - tok_free(tok->ifs); - tok_free(tok->wspace); - tok_free(tok->argv); - tok_free(tok); -} - - - -/* FUN(tok,line)(): - * Bourne shell (sh(1)) like tokenizing - * Arguments: - * tok current tokenizer state (setup with FUN(tok,init)()) - * line line to parse - * Returns: - * -1 Internal error - * 3 Quoted return - * 2 Unmatched double quote - * 1 Unmatched single quote - * 0 Ok - * Modifies (if return value is 0): - * argc number of arguments - * argv argument array - * cursorc if !NULL, argv element containing cursor - * cursorv if !NULL, offset in argv[cursorc] of cursor - */ -int -FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line, - int *argc, const Char ***argv, int *cursorc, int *cursoro) -{ - const Char *ptr; - int cc, co; - - cc = co = -1; - ptr = line->buffer; - for (ptr = line->buffer; ;ptr++) { - if (ptr >= line->lastchar) - ptr = STR(""); - if (ptr == line->cursor) { - cc = (int)tok->argc; - co = (int)(tok->wptr - tok->wstart); - } - switch (*ptr) { - case '\'': - tok->flags |= TOK_KEEP; - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - tok->quote = Q_single; /* Enter single quote - * mode */ - break; - - case Q_single: /* Exit single quote mode */ - tok->quote = Q_none; - break; - - case Q_one: /* Quote this ' */ - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - case Q_double: /* Stay in double quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this ' */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return -1; - } - break; - - case '"': - tok->flags &= ~TOK_EAT; - tok->flags |= TOK_KEEP; - switch (tok->quote) { - case Q_none: /* Enter double quote mode */ - tok->quote = Q_double; - break; - - case Q_double: /* Exit double quote mode */ - tok->quote = Q_none; - break; - - case Q_one: /* Quote this " */ - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - case Q_single: /* Stay in single quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this " */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return -1; - } - break; - - case '\\': - tok->flags |= TOK_KEEP; - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: /* Quote next character */ - tok->quote = Q_one; - break; - - case Q_double: /* Quote next character */ - tok->quote = Q_doubleone; - break; - - case Q_one: /* Quote this, restore state */ - *tok->wptr++ = *ptr; - tok->quote = Q_none; - break; - - case Q_single: /* Stay in single quote mode */ - *tok->wptr++ = *ptr; - break; - - case Q_doubleone: /* Quote this \ */ - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - default: - return -1; - } - break; - - case '\n': - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - goto tok_line_outok; - - case Q_single: - case Q_double: - *tok->wptr++ = *ptr; /* Add the return */ - break; - - case Q_doubleone: /* Back to double, eat the '\n' */ - tok->flags |= TOK_EAT; - tok->quote = Q_double; - break; - - case Q_one: /* No quote, more eat the '\n' */ - tok->flags |= TOK_EAT; - tok->quote = Q_none; - break; - - default: - return 0; - } - break; - - case '\0': - switch (tok->quote) { - case Q_none: - /* Finish word and return */ - if (tok->flags & TOK_EAT) { - tok->flags &= ~TOK_EAT; - return 3; - } - goto tok_line_outok; - - case Q_single: - return 1; - - case Q_double: - return 2; - - case Q_doubleone: - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - case Q_one: - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - default: - return -1; - } - break; - - default: - tok->flags &= ~TOK_EAT; - switch (tok->quote) { - case Q_none: - if (Strchr(tok->ifs, *ptr) != NULL) - FUN(tok,finish)(tok); - else - *tok->wptr++ = *ptr; - break; - - case Q_single: - case Q_double: - *tok->wptr++ = *ptr; - break; - - - case Q_doubleone: - *tok->wptr++ = '\\'; - tok->quote = Q_double; - *tok->wptr++ = *ptr; - break; - - case Q_one: - tok->quote = Q_none; - *tok->wptr++ = *ptr; - break; - - default: - return -1; - - } - break; - } - - if (tok->wptr >= tok->wmax - 4) { - size_t size = (size_t)(tok->wmax - tok->wspace + WINCR); - Char *s = tok_realloc(tok->wspace, - size * sizeof(*s)); - if (s == NULL) - return -1; - - if (s != tok->wspace) { - size_t i; - for (i = 0; i < tok->argc; i++) { - tok->argv[i] = - (tok->argv[i] - tok->wspace) + s; - } - tok->wptr = (tok->wptr - tok->wspace) + s; - tok->wstart = (tok->wstart - tok->wspace) + s; - tok->wspace = s; - } - tok->wmax = s + size; - } - if (tok->argc >= tok->amax - 4) { - Char **p; - tok->amax += AINCR; - p = tok_realloc(tok->argv, tok->amax * sizeof(*p)); - if (p == NULL) { - tok->amax -= AINCR; - return -1; - } - tok->argv = p; - } - } - tok_line_outok: - if (cc == -1 && co == -1) { - cc = (int)tok->argc; - co = (int)(tok->wptr - tok->wstart); - } - if (cursorc != NULL) - *cursorc = cc; - if (cursoro != NULL) - *cursoro = co; - FUN(tok,finish)(tok); - *argv = (const Char **)tok->argv; - *argc = (int)tok->argc; - return 0; -} - -/* FUN(tok,str)(): - * Simpler version of tok_line, taking a NUL terminated line - * and splitting into words, ignoring cursor state. - */ -int -FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, - const Char ***argv) -{ - TYPE(LineInfo) li; - - memset(&li, 0, sizeof(li)); - li.buffer = line; - li.cursor = li.lastchar = Strchr(line, '\0'); - return FUN(tok,line)(tok, &li, argc, argv, NULL, NULL); -} diff --git a/bin/catsh/libedit/tokenizern.c b/bin/catsh/libedit/tokenizern.c deleted file mode 100644 index 5846b606..00000000 --- a/bin/catsh/libedit/tokenizern.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" -#define NARROWCHAR -#include "tokenizer.c" diff --git a/bin/catsh/libedit/tty.c b/bin/catsh/libedit/tty.c deleted file mode 100644 index f524da47..00000000 --- a/bin/catsh/libedit/tty.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* $NetBSD: tty.c,v 1.65 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: tty.c,v 1.65 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * tty.c: tty interface stuff - */ -#include <assert.h> -#include <errno.h> -#include <stdlib.h> /* for abort */ -#include <string.h> -#include <strings.h> /* for ffs */ -#include <unistd.h> /* for isatty */ - -#include "el.h" -#include "fcns.h" -#include "parse.h" - -typedef struct ttymodes_t { - const char *m_name; - unsigned int m_value; - int m_type; -} ttymodes_t; - -typedef struct ttymap_t { - wint_t nch, och; /* Internal and termio rep of chars */ - el_action_t bind[3]; /* emacs, vi, and vi-cmd */ -} ttymap_t; - - -static const ttyperm_t ttyperm = { - { - {"iflag:", ICRNL, (INLCR | IGNCR)}, - {"oflag:", (OPOST | ONLCR), ONLRET}, - {"cflag:", 0, 0}, - {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), - (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, - {"chars:", 0, 0}, - }, - { - {"iflag:", (INLCR | ICRNL), IGNCR}, - {"oflag:", (OPOST | ONLCR), ONLRET}, - {"cflag:", 0, 0}, - {"lflag:", ISIG, - (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)}, - {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) | - C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) | - C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0} - }, - { - {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, - {"oflag:", 0, 0}, - {"cflag:", 0, 0}, - {"lflag:", 0, ISIG | IEXTEN}, - {"chars:", 0, 0}, - } -}; - -static const ttychar_t ttychar = { - { - CINTR, CQUIT, CERASE, CKILL, - CEOF, CEOL, CEOL2, CSWTCH, - CDSWTCH, CERASE2, CSTART, CSTOP, - CWERASE, CSUSP, CDSUSP, CREPRINT, - CDISCARD, CLNEXT, CSTATUS, CPAGE, - CPGOFF, CKILL2, CBRK, CMIN, - CTIME - }, - { - CINTR, CQUIT, CERASE, CKILL, - _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, - _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, - _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, - CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, - _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, - 0 - }, - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0 - } -}; - -static const ttymap_t tty_map[] = { -#ifdef VERASE - {C_ERASE, VERASE, - {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, -#endif /* VERASE */ -#ifdef VERASE2 - {C_ERASE2, VERASE2, - {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, -#endif /* VERASE2 */ -#ifdef VKILL - {C_KILL, VKILL, - {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, -#endif /* VKILL */ -#ifdef VKILL2 - {C_KILL2, VKILL2, - {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, -#endif /* VKILL2 */ -#ifdef VEOF - {C_EOF, VEOF, - {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}}, -#endif /* VEOF */ -#ifdef VWERASE - {C_WERASE, VWERASE, - {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}}, -#endif /* VWERASE */ -#ifdef VREPRINT - {C_REPRINT, VREPRINT, - {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}}, -#endif /* VREPRINT */ -#ifdef VLNEXT - {C_LNEXT, VLNEXT, - {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, -#endif /* VLNEXT */ - {(wint_t)-1, (wint_t)-1, - {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} -}; - -static const ttymodes_t ttymodes[] = { -#ifdef IGNBRK - {"ignbrk", IGNBRK, MD_INP}, -#endif /* IGNBRK */ -#ifdef BRKINT - {"brkint", BRKINT, MD_INP}, -#endif /* BRKINT */ -#ifdef IGNPAR - {"ignpar", IGNPAR, MD_INP}, -#endif /* IGNPAR */ -#ifdef PARMRK - {"parmrk", PARMRK, MD_INP}, -#endif /* PARMRK */ -#ifdef INPCK - {"inpck", INPCK, MD_INP}, -#endif /* INPCK */ -#ifdef ISTRIP - {"istrip", ISTRIP, MD_INP}, -#endif /* ISTRIP */ -#ifdef INLCR - {"inlcr", INLCR, MD_INP}, -#endif /* INLCR */ -#ifdef IGNCR - {"igncr", IGNCR, MD_INP}, -#endif /* IGNCR */ -#ifdef ICRNL - {"icrnl", ICRNL, MD_INP}, -#endif /* ICRNL */ -#ifdef IUCLC - {"iuclc", IUCLC, MD_INP}, -#endif /* IUCLC */ -#ifdef IXON - {"ixon", IXON, MD_INP}, -#endif /* IXON */ -#ifdef IXANY - {"ixany", IXANY, MD_INP}, -#endif /* IXANY */ -#ifdef IXOFF - {"ixoff", IXOFF, MD_INP}, -#endif /* IXOFF */ -#ifdef IMAXBEL - {"imaxbel", IMAXBEL, MD_INP}, -#endif /* IMAXBEL */ - -#ifdef OPOST - {"opost", OPOST, MD_OUT}, -#endif /* OPOST */ -#ifdef OLCUC - {"olcuc", OLCUC, MD_OUT}, -#endif /* OLCUC */ -#ifdef ONLCR - {"onlcr", ONLCR, MD_OUT}, -#endif /* ONLCR */ -#ifdef OCRNL - {"ocrnl", OCRNL, MD_OUT}, -#endif /* OCRNL */ -#ifdef ONOCR - {"onocr", ONOCR, MD_OUT}, -#endif /* ONOCR */ -#ifdef ONOEOT - {"onoeot", ONOEOT, MD_OUT}, -#endif /* ONOEOT */ -#ifdef ONLRET - {"onlret", ONLRET, MD_OUT}, -#endif /* ONLRET */ -#ifdef OFILL - {"ofill", OFILL, MD_OUT}, -#endif /* OFILL */ -#ifdef OFDEL - {"ofdel", OFDEL, MD_OUT}, -#endif /* OFDEL */ -#ifdef NLDLY - {"nldly", NLDLY, MD_OUT}, -#endif /* NLDLY */ -#ifdef CRDLY - {"crdly", CRDLY, MD_OUT}, -#endif /* CRDLY */ -#ifdef TABDLY - {"tabdly", TABDLY, MD_OUT}, -#endif /* TABDLY */ -#ifdef XTABS - {"xtabs", XTABS, MD_OUT}, -#endif /* XTABS */ -#ifdef BSDLY - {"bsdly", BSDLY, MD_OUT}, -#endif /* BSDLY */ -#ifdef VTDLY - {"vtdly", VTDLY, MD_OUT}, -#endif /* VTDLY */ -#ifdef FFDLY - {"ffdly", FFDLY, MD_OUT}, -#endif /* FFDLY */ -#ifdef PAGEOUT - {"pageout", PAGEOUT, MD_OUT}, -#endif /* PAGEOUT */ -#ifdef WRAP - {"wrap", WRAP, MD_OUT}, -#endif /* WRAP */ - -#ifdef CIGNORE - {"cignore", CIGNORE, MD_CTL}, -#endif /* CBAUD */ -#ifdef CBAUD - {"cbaud", CBAUD, MD_CTL}, -#endif /* CBAUD */ -#ifdef CSTOPB - {"cstopb", CSTOPB, MD_CTL}, -#endif /* CSTOPB */ -#ifdef CREAD - {"cread", CREAD, MD_CTL}, -#endif /* CREAD */ -#ifdef PARENB - {"parenb", PARENB, MD_CTL}, -#endif /* PARENB */ -#ifdef PARODD - {"parodd", PARODD, MD_CTL}, -#endif /* PARODD */ -#ifdef HUPCL - {"hupcl", HUPCL, MD_CTL}, -#endif /* HUPCL */ -#ifdef CLOCAL - {"clocal", CLOCAL, MD_CTL}, -#endif /* CLOCAL */ -#ifdef LOBLK - {"loblk", LOBLK, MD_CTL}, -#endif /* LOBLK */ -#ifdef CIBAUD - {"cibaud", CIBAUD, MD_CTL}, -#endif /* CIBAUD */ -#ifdef CRTSCTS -#ifdef CCTS_OFLOW - {"ccts_oflow", CCTS_OFLOW, MD_CTL}, -#else - {"crtscts", CRTSCTS, MD_CTL}, -#endif /* CCTS_OFLOW */ -#endif /* CRTSCTS */ -#ifdef CRTS_IFLOW - {"crts_iflow", CRTS_IFLOW, MD_CTL}, -#endif /* CRTS_IFLOW */ -#ifdef CDTRCTS - {"cdtrcts", CDTRCTS, MD_CTL}, -#endif /* CDTRCTS */ -#ifdef MDMBUF - {"mdmbuf", MDMBUF, MD_CTL}, -#endif /* MDMBUF */ -#ifdef RCV1EN - {"rcv1en", RCV1EN, MD_CTL}, -#endif /* RCV1EN */ -#ifdef XMT1EN - {"xmt1en", XMT1EN, MD_CTL}, -#endif /* XMT1EN */ - -#ifdef ISIG - {"isig", ISIG, MD_LIN}, -#endif /* ISIG */ -#ifdef ICANON - {"icanon", ICANON, MD_LIN}, -#endif /* ICANON */ -#ifdef XCASE - {"xcase", XCASE, MD_LIN}, -#endif /* XCASE */ -#ifdef ECHO - {"echo", ECHO, MD_LIN}, -#endif /* ECHO */ -#ifdef ECHOE - {"echoe", ECHOE, MD_LIN}, -#endif /* ECHOE */ -#ifdef ECHOK - {"echok", ECHOK, MD_LIN}, -#endif /* ECHOK */ -#ifdef ECHONL - {"echonl", ECHONL, MD_LIN}, -#endif /* ECHONL */ -#ifdef NOFLSH - {"noflsh", NOFLSH, MD_LIN}, -#endif /* NOFLSH */ -#ifdef TOSTOP - {"tostop", TOSTOP, MD_LIN}, -#endif /* TOSTOP */ -#ifdef ECHOCTL - {"echoctl", ECHOCTL, MD_LIN}, -#endif /* ECHOCTL */ -#ifdef ECHOPRT - {"echoprt", ECHOPRT, MD_LIN}, -#endif /* ECHOPRT */ -#ifdef ECHOKE - {"echoke", ECHOKE, MD_LIN}, -#endif /* ECHOKE */ -#ifdef DEFECHO - {"defecho", DEFECHO, MD_LIN}, -#endif /* DEFECHO */ -#ifdef FLUSHO - {"flusho", FLUSHO, MD_LIN}, -#endif /* FLUSHO */ -#ifdef PENDIN - {"pendin", PENDIN, MD_LIN}, -#endif /* PENDIN */ -#ifdef IEXTEN - {"iexten", IEXTEN, MD_LIN}, -#endif /* IEXTEN */ -#ifdef NOKERNINFO - {"nokerninfo", NOKERNINFO, MD_LIN}, -#endif /* NOKERNINFO */ -#ifdef ALTWERASE - {"altwerase", ALTWERASE, MD_LIN}, -#endif /* ALTWERASE */ -#ifdef EXTPROC - {"extproc", EXTPROC, MD_LIN}, -#endif /* EXTPROC */ - -#if defined(VINTR) - {"intr", C_SH(C_INTR), MD_CHAR}, -#endif /* VINTR */ -#if defined(VQUIT) - {"quit", C_SH(C_QUIT), MD_CHAR}, -#endif /* VQUIT */ -#if defined(VERASE) - {"erase", C_SH(C_ERASE), MD_CHAR}, -#endif /* VERASE */ -#if defined(VKILL) - {"kill", C_SH(C_KILL), MD_CHAR}, -#endif /* VKILL */ -#if defined(VEOF) - {"eof", C_SH(C_EOF), MD_CHAR}, -#endif /* VEOF */ -#if defined(VEOL) - {"eol", C_SH(C_EOL), MD_CHAR}, -#endif /* VEOL */ -#if defined(VEOL2) - {"eol2", C_SH(C_EOL2), MD_CHAR}, -#endif /* VEOL2 */ -#if defined(VSWTCH) - {"swtch", C_SH(C_SWTCH), MD_CHAR}, -#endif /* VSWTCH */ -#if defined(VDSWTCH) - {"dswtch", C_SH(C_DSWTCH), MD_CHAR}, -#endif /* VDSWTCH */ -#if defined(VERASE2) - {"erase2", C_SH(C_ERASE2), MD_CHAR}, -#endif /* VERASE2 */ -#if defined(VSTART) - {"start", C_SH(C_START), MD_CHAR}, -#endif /* VSTART */ -#if defined(VSTOP) - {"stop", C_SH(C_STOP), MD_CHAR}, -#endif /* VSTOP */ -#if defined(VWERASE) - {"werase", C_SH(C_WERASE), MD_CHAR}, -#endif /* VWERASE */ -#if defined(VSUSP) - {"susp", C_SH(C_SUSP), MD_CHAR}, -#endif /* VSUSP */ -#if defined(VDSUSP) - {"dsusp", C_SH(C_DSUSP), MD_CHAR}, -#endif /* VDSUSP */ -#if defined(VREPRINT) - {"reprint", C_SH(C_REPRINT), MD_CHAR}, -#endif /* VREPRINT */ -#if defined(VDISCARD) - {"discard", C_SH(C_DISCARD), MD_CHAR}, -#endif /* VDISCARD */ -#if defined(VLNEXT) - {"lnext", C_SH(C_LNEXT), MD_CHAR}, -#endif /* VLNEXT */ -#if defined(VSTATUS) - {"status", C_SH(C_STATUS), MD_CHAR}, -#endif /* VSTATUS */ -#if defined(VPAGE) - {"page", C_SH(C_PAGE), MD_CHAR}, -#endif /* VPAGE */ -#if defined(VPGOFF) - {"pgoff", C_SH(C_PGOFF), MD_CHAR}, -#endif /* VPGOFF */ -#if defined(VKILL2) - {"kill2", C_SH(C_KILL2), MD_CHAR}, -#endif /* VKILL2 */ -#if defined(VBRK) - {"brk", C_SH(C_BRK), MD_CHAR}, -#endif /* VBRK */ -#if defined(VMIN) - {"min", C_SH(C_MIN), MD_CHAR}, -#endif /* VMIN */ -#if defined(VTIME) - {"time", C_SH(C_TIME), MD_CHAR}, -#endif /* VTIME */ - {NULL, 0, -1}, -}; - - - -#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) -#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) -#define tty__cooked_mode(td) ((td)->c_lflag & ICANON) - -static int tty_getty(EditLine *, struct termios *); -static int tty_setty(EditLine *, int, const struct termios *); -static int tty__getcharindex(int); -static void tty__getchar(struct termios *, unsigned char *); -static void tty__setchar(struct termios *, unsigned char *); -static speed_t tty__getspeed(struct termios *); -static int tty_setup(EditLine *); -static void tty_setup_flags(EditLine *, struct termios *, int); - -#define t_qu t_ts - -/* tty_getty(): - * Wrapper for tcgetattr to handle EINTR - */ -static int -tty_getty(EditLine *el, struct termios *t) -{ - int rv; - while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) - continue; - return rv; -} - -/* tty_setty(): - * Wrapper for tcsetattr to handle EINTR - */ -static int -tty_setty(EditLine *el, int action, const struct termios *t) -{ - int rv; - while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) - continue; - return rv; -} - -/* tty_setup(): - * Get the tty parameters and initialize the editing state - */ -static int -tty_setup(EditLine *el) -{ - int rst = 1; - - if (el->el_flags & EDIT_DISABLED) - return 0; - - if (el->el_tty.t_initialized) - return -1; - - if (!isatty(el->el_outfd)) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - if (tty_getty(el, &el->el_tty.t_or) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or; - - el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); - el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); - el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); - - tty_setup_flags(el, &el->el_tty.t_ex, EX_IO); - - /* - * Reset the tty chars to reasonable defaults - * If they are disabled, then enable them. - */ - if (rst) { - if (tty__cooked_mode(&el->el_tty.t_ts)) { - tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); - /* - * Don't affect CMIN and CTIME for the editor mode - */ - for (rst = 0; rst < C_NCC - 2; rst++) - if (el->el_tty.t_c[TS_IO][rst] != - el->el_tty.t_vdisable - && el->el_tty.t_c[ED_IO][rst] != - el->el_tty.t_vdisable) - el->el_tty.t_c[ED_IO][rst] = - el->el_tty.t_c[TS_IO][rst]; - for (rst = 0; rst < C_NCC; rst++) - if (el->el_tty.t_c[TS_IO][rst] != - el->el_tty.t_vdisable) - el->el_tty.t_c[EX_IO][rst] = - el->el_tty.t_c[TS_IO][rst]; - } - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", - __func__, strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - } - - tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); - - tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); - tty_bind_char(el, 1); - el->el_tty.t_initialized = 1; - return 0; -} - -libedit_private int -tty_init(EditLine *el) -{ - - el->el_tty.t_mode = EX_IO; - el->el_tty.t_vdisable = _POSIX_VDISABLE; - el->el_tty.t_initialized = 0; - (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); - (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); - return tty_setup(el); -} - - -/* tty_end(): - * Restore the tty to its original settings - */ -libedit_private void -/*ARGSUSED*/ -tty_end(EditLine *el) -{ - if (el->el_flags & EDIT_DISABLED) - return; - - if (!el->el_tty.t_initialized) - return; - - if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, - "%s: tty_setty: %s\n", __func__, strerror(errno)); -#endif /* DEBUG_TTY */ - } -} - - -/* tty__getspeed(): - * Get the tty speed - */ -static speed_t -tty__getspeed(struct termios *td) -{ - speed_t spd; - - if ((spd = cfgetispeed(td)) == 0) - spd = cfgetospeed(td); - return spd; -} - -/* tty__getspeed(): - * Return the index of the asked char in the c_cc array - */ -static int -tty__getcharindex(int i) -{ - switch (i) { -#ifdef VINTR - case C_INTR: - return VINTR; -#endif /* VINTR */ -#ifdef VQUIT - case C_QUIT: - return VQUIT; -#endif /* VQUIT */ -#ifdef VERASE - case C_ERASE: - return VERASE; -#endif /* VERASE */ -#ifdef VKILL - case C_KILL: - return VKILL; -#endif /* VKILL */ -#ifdef VEOF - case C_EOF: - return VEOF; -#endif /* VEOF */ -#ifdef VEOL - case C_EOL: - return VEOL; -#endif /* VEOL */ -#ifdef VEOL2 - case C_EOL2: - return VEOL2; -#endif /* VEOL2 */ -#ifdef VSWTCH - case C_SWTCH: - return VSWTCH; -#endif /* VSWTCH */ -#ifdef VDSWTCH - case C_DSWTCH: - return VDSWTCH; -#endif /* VDSWTCH */ -#ifdef VERASE2 - case C_ERASE2: - return VERASE2; -#endif /* VERASE2 */ -#ifdef VSTART - case C_START: - return VSTART; -#endif /* VSTART */ -#ifdef VSTOP - case C_STOP: - return VSTOP; -#endif /* VSTOP */ -#ifdef VWERASE - case C_WERASE: - return VWERASE; -#endif /* VWERASE */ -#ifdef VSUSP - case C_SUSP: - return VSUSP; -#endif /* VSUSP */ -#ifdef VDSUSP - case C_DSUSP: - return VDSUSP; -#endif /* VDSUSP */ -#ifdef VREPRINT - case C_REPRINT: - return VREPRINT; -#endif /* VREPRINT */ -#ifdef VDISCARD - case C_DISCARD: - return VDISCARD; -#endif /* VDISCARD */ -#ifdef VLNEXT - case C_LNEXT: - return VLNEXT; -#endif /* VLNEXT */ -#ifdef VSTATUS - case C_STATUS: - return VSTATUS; -#endif /* VSTATUS */ -#ifdef VPAGE - case C_PAGE: - return VPAGE; -#endif /* VPAGE */ -#ifdef VPGOFF - case C_PGOFF: - return VPGOFF; -#endif /* VPGOFF */ -#ifdef VKILL2 - case C_KILL2: - return VKILL2; -#endif /* KILL2 */ -#ifdef VMIN - case C_MIN: - return VMIN; -#endif /* VMIN */ -#ifdef VTIME - case C_TIME: - return VTIME; -#endif /* VTIME */ - default: - return -1; - } -} - -/* tty__getchar(): - * Get the tty characters - */ -static void -tty__getchar(struct termios *td, unsigned char *s) -{ - -#ifdef VINTR - s[C_INTR] = td->c_cc[VINTR]; -#endif /* VINTR */ -#ifdef VQUIT - s[C_QUIT] = td->c_cc[VQUIT]; -#endif /* VQUIT */ -#ifdef VERASE - s[C_ERASE] = td->c_cc[VERASE]; -#endif /* VERASE */ -#ifdef VKILL - s[C_KILL] = td->c_cc[VKILL]; -#endif /* VKILL */ -#ifdef VEOF - s[C_EOF] = td->c_cc[VEOF]; -#endif /* VEOF */ -#ifdef VEOL - s[C_EOL] = td->c_cc[VEOL]; -#endif /* VEOL */ -#ifdef VEOL2 - s[C_EOL2] = td->c_cc[VEOL2]; -#endif /* VEOL2 */ -#ifdef VSWTCH - s[C_SWTCH] = td->c_cc[VSWTCH]; -#endif /* VSWTCH */ -#ifdef VDSWTCH - s[C_DSWTCH] = td->c_cc[VDSWTCH]; -#endif /* VDSWTCH */ -#ifdef VERASE2 - s[C_ERASE2] = td->c_cc[VERASE2]; -#endif /* VERASE2 */ -#ifdef VSTART - s[C_START] = td->c_cc[VSTART]; -#endif /* VSTART */ -#ifdef VSTOP - s[C_STOP] = td->c_cc[VSTOP]; -#endif /* VSTOP */ -#ifdef VWERASE - s[C_WERASE] = td->c_cc[VWERASE]; -#endif /* VWERASE */ -#ifdef VSUSP - s[C_SUSP] = td->c_cc[VSUSP]; -#endif /* VSUSP */ -#ifdef VDSUSP - s[C_DSUSP] = td->c_cc[VDSUSP]; -#endif /* VDSUSP */ -#ifdef VREPRINT - s[C_REPRINT] = td->c_cc[VREPRINT]; -#endif /* VREPRINT */ -#ifdef VDISCARD - s[C_DISCARD] = td->c_cc[VDISCARD]; -#endif /* VDISCARD */ -#ifdef VLNEXT - s[C_LNEXT] = td->c_cc[VLNEXT]; -#endif /* VLNEXT */ -#ifdef VSTATUS - s[C_STATUS] = td->c_cc[VSTATUS]; -#endif /* VSTATUS */ -#ifdef VPAGE - s[C_PAGE] = td->c_cc[VPAGE]; -#endif /* VPAGE */ -#ifdef VPGOFF - s[C_PGOFF] = td->c_cc[VPGOFF]; -#endif /* VPGOFF */ -#ifdef VKILL2 - s[C_KILL2] = td->c_cc[VKILL2]; -#endif /* KILL2 */ -#ifdef VMIN - s[C_MIN] = td->c_cc[VMIN]; -#endif /* VMIN */ -#ifdef VTIME - s[C_TIME] = td->c_cc[VTIME]; -#endif /* VTIME */ -} /* tty__getchar */ - - -/* tty__setchar(): - * Set the tty characters - */ -static void -tty__setchar(struct termios *td, unsigned char *s) -{ - -#ifdef VINTR - td->c_cc[VINTR] = s[C_INTR]; -#endif /* VINTR */ -#ifdef VQUIT - td->c_cc[VQUIT] = s[C_QUIT]; -#endif /* VQUIT */ -#ifdef VERASE - td->c_cc[VERASE] = s[C_ERASE]; -#endif /* VERASE */ -#ifdef VKILL - td->c_cc[VKILL] = s[C_KILL]; -#endif /* VKILL */ -#ifdef VEOF - td->c_cc[VEOF] = s[C_EOF]; -#endif /* VEOF */ -#ifdef VEOL - td->c_cc[VEOL] = s[C_EOL]; -#endif /* VEOL */ -#ifdef VEOL2 - td->c_cc[VEOL2] = s[C_EOL2]; -#endif /* VEOL2 */ -#ifdef VSWTCH - td->c_cc[VSWTCH] = s[C_SWTCH]; -#endif /* VSWTCH */ -#ifdef VDSWTCH - td->c_cc[VDSWTCH] = s[C_DSWTCH]; -#endif /* VDSWTCH */ -#ifdef VERASE2 - td->c_cc[VERASE2] = s[C_ERASE2]; -#endif /* VERASE2 */ -#ifdef VSTART - td->c_cc[VSTART] = s[C_START]; -#endif /* VSTART */ -#ifdef VSTOP - td->c_cc[VSTOP] = s[C_STOP]; -#endif /* VSTOP */ -#ifdef VWERASE - td->c_cc[VWERASE] = s[C_WERASE]; -#endif /* VWERASE */ -#ifdef VSUSP - td->c_cc[VSUSP] = s[C_SUSP]; -#endif /* VSUSP */ -#ifdef VDSUSP - td->c_cc[VDSUSP] = s[C_DSUSP]; -#endif /* VDSUSP */ -#ifdef VREPRINT - td->c_cc[VREPRINT] = s[C_REPRINT]; -#endif /* VREPRINT */ -#ifdef VDISCARD - td->c_cc[VDISCARD] = s[C_DISCARD]; -#endif /* VDISCARD */ -#ifdef VLNEXT - td->c_cc[VLNEXT] = s[C_LNEXT]; -#endif /* VLNEXT */ -#ifdef VSTATUS - td->c_cc[VSTATUS] = s[C_STATUS]; -#endif /* VSTATUS */ -#ifdef VPAGE - td->c_cc[VPAGE] = s[C_PAGE]; -#endif /* VPAGE */ -#ifdef VPGOFF - td->c_cc[VPGOFF] = s[C_PGOFF]; -#endif /* VPGOFF */ -#ifdef VKILL2 - td->c_cc[VKILL2] = s[C_KILL2]; -#endif /* VKILL2 */ -#ifdef VMIN - td->c_cc[VMIN] = s[C_MIN]; -#endif /* VMIN */ -#ifdef VTIME - td->c_cc[VTIME] = s[C_TIME]; -#endif /* VTIME */ -} /* tty__setchar */ - - -/* tty_bind_char(): - * Rebind the editline functions - */ -libedit_private void -tty_bind_char(EditLine *el, int force) -{ - - unsigned char *t_n = el->el_tty.t_c[ED_IO]; - unsigned char *t_o = el->el_tty.t_ed.c_cc; - wchar_t new[2], old[2]; - const ttymap_t *tp; - el_action_t *map, *alt; - const el_action_t *dmap, *dalt; - new[1] = old[1] = '\0'; - - map = el->el_map.key; - alt = el->el_map.alt; - if (el->el_map.type == MAP_VI) { - dmap = el->el_map.vii; - dalt = el->el_map.vic; - } else { - dmap = el->el_map.emacs; - dalt = NULL; - } - - for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { - new[0] = (wchar_t)t_n[tp->nch]; - old[0] = (wchar_t)t_o[tp->och]; - if (new[0] == old[0] && !force) - continue; - /* Put the old default binding back, and set the new binding */ - keymacro_clear(el, map, old); - map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]]; - keymacro_clear(el, map, new); - /* MAP_VI == 1, MAP_EMACS == 0... */ - map[(unsigned char)new[0]] = tp->bind[el->el_map.type]; - if (dalt) { - keymacro_clear(el, alt, old); - alt[(unsigned char)old[0]] = - dalt[(unsigned char)old[0]]; - keymacro_clear(el, alt, new); - alt[(unsigned char)new[0]] = - tp->bind[el->el_map.type + 1]; - } - } -} - - -static tcflag_t * -tty__get_flag(struct termios *t, int kind) { - switch (kind) { - case MD_INP: - return &t->c_iflag; - case MD_OUT: - return &t->c_oflag; - case MD_CTL: - return &t->c_cflag; - case MD_LIN: - return &t->c_lflag; - default: - abort(); - /*NOTREACHED*/ - } -} - - -static tcflag_t -tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) -{ - f &= ~el->el_tty.t_t[mode][kind].t_clrmask; - f |= el->el_tty.t_t[mode][kind].t_setmask; - return f; -} - - -static void -tty_update_flags(EditLine *el, int kind) -{ - tcflag_t *tt, *ed, *ex; - tt = tty__get_flag(&el->el_tty.t_ts, kind); - ed = tty__get_flag(&el->el_tty.t_ed, kind); - ex = tty__get_flag(&el->el_tty.t_ex, kind); - - if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { - *ed = tty_update_flag(el, *tt, ED_IO, kind); - *ex = tty_update_flag(el, *tt, EX_IO, kind); - } -} - - -static void -tty_update_char(EditLine *el, int mode, int c) { - if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) - && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) - el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; - if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) - el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; -} - - -/* tty_rawmode(): - * Set terminal into 1 character at a time mode. - */ -libedit_private int -tty_rawmode(EditLine *el) -{ - - if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) - return 0; - - if (el->el_flags & EDIT_DISABLED) - return 0; - - if (tty_getty(el, &el->el_tty.t_ts) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - /* - * We always keep up with the eight bit setting and the speed of the - * tty. But we only believe changes that are made to cooked mode! - */ - el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); - el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); - - if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || - tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { - (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); - (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); - (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); - (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); - } - if (tty__cooked_mode(&el->el_tty.t_ts)) { - int i; - - for (i = MD_INP; i <= MD_LIN; i++) - tty_update_flags(el, i); - - if (tty__gettabs(&el->el_tty.t_ex) == 0) - el->el_tty.t_tabs = 0; - else - el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; - - tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); - /* - * Check if the user made any changes. - * If he did, then propagate the changes to the - * edit and execute data structures. - */ - for (i = 0; i < C_NCC; i++) - if (el->el_tty.t_c[TS_IO][i] != - el->el_tty.t_c[EX_IO][i]) - break; - - if (i != C_NCC) { - /* - * Propagate changes only to the unlibedit_private - * chars that have been modified just now. - */ - for (i = 0; i < C_NCC; i++) - tty_update_char(el, ED_IO, i); - - tty_bind_char(el, 0); - tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); - - for (i = 0; i < C_NCC; i++) - tty_update_char(el, EX_IO, i); - - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - } - } - if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = ED_IO; - return 0; -} - - -/* tty_cookedmode(): - * Set the tty back to normal mode - */ -libedit_private int -tty_cookedmode(EditLine *el) -{ /* set tty in normal setup */ - - if (el->el_tty.t_mode == EX_IO) - return 0; - - if (el->el_flags & EDIT_DISABLED) - return 0; - - if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = EX_IO; - return 0; -} - - -/* tty_quotemode(): - * Turn on quote mode - */ -libedit_private int -tty_quotemode(EditLine *el) -{ - if (el->el_tty.t_mode == QU_IO) - return 0; - - el->el_tty.t_qu = el->el_tty.t_ed; - - tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); - - if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = QU_IO; - return 0; -} - - -/* tty_noquotemode(): - * Turn off quote mode - */ -libedit_private int -tty_noquotemode(EditLine *el) -{ - - if (el->el_tty.t_mode != QU_IO) - return 0; - if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, - strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - el->el_tty.t_mode = ED_IO; - return 0; -} - - -/* tty_stty(): - * Stty builtin - */ -libedit_private int -/*ARGSUSED*/ -tty_stty(EditLine *el, int argc __attribute__((__unused__)), - const wchar_t **argv) -{ - const ttymodes_t *m; - char x; - int aflag = 0; - const wchar_t *s, *d; - char name[EL_BUFSIZ]; - struct termios *tios = &el->el_tty.t_ex; - int z = EX_IO; - - if (argv == NULL) - return -1; - strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); - name[sizeof(name) - 1] = '\0'; - - while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') - switch (argv[0][1]) { - case 'a': - aflag++; - argv++; - break; - case 'd': - argv++; - tios = &el->el_tty.t_ed; - z = ED_IO; - break; - case 'x': - argv++; - tios = &el->el_tty.t_ex; - z = EX_IO; - break; - case 'q': - argv++; - tios = &el->el_tty.t_ts; - z = QU_IO; - break; - default: - (void) fprintf(el->el_errfile, - "%s: Unknown switch `%lc'.\n", - name, (wint_t)argv[0][1]); - return -1; - } - - if (!argv || !*argv) { - int i = -1; - size_t len = 0, st = 0, cu; - for (m = ttymodes; m->m_name; m++) { - if (m->m_type != i) { - (void) fprintf(el->el_outfile, "%s%s", - i != -1 ? "\n" : "", - el->el_tty.t_t[z][m->m_type].t_name); - i = m->m_type; - st = len = - strlen(el->el_tty.t_t[z][m->m_type].t_name); - } - if (i != -1) { - x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) - ? '+' : '\0'; - - if (el->el_tty.t_t[z][i].t_clrmask & m->m_value) - x = '-'; - } else { - x = '\0'; - } - - if (x != '\0' || aflag) { - - cu = strlen(m->m_name) + (x != '\0') + 1; - - if (len + cu >= - (size_t)el->el_terminal.t_size.h) { - (void) fprintf(el->el_outfile, "\n%*s", - (int)st, ""); - len = st + cu; - } else - len += cu; - - if (x != '\0') - (void) fprintf(el->el_outfile, "%c%s ", - x, m->m_name); - else - (void) fprintf(el->el_outfile, "%s ", - m->m_name); - } - } - (void) fprintf(el->el_outfile, "\n"); - return 0; - } - while (argv && (s = *argv++)) { - const wchar_t *p; - switch (*s) { - case '+': - case '-': - x = (char)*s++; - break; - default: - x = '\0'; - break; - } - d = s; - p = wcschr(s, L'='); - for (m = ttymodes; m->m_name; m++) - if ((p ? strncmp(m->m_name, ct_encode_string(d, - &el->el_scratch), (size_t)(p - d)) : - strcmp(m->m_name, ct_encode_string(d, - &el->el_scratch))) == 0 && - (p == NULL || m->m_type == MD_CHAR)) - break; - - if (!m->m_name) { - (void) fprintf(el->el_errfile, - "%s: Invalid argument `%ls'.\n", name, d); - return -1; - } - if (p) { - int c = ffs((int)m->m_value); - int v = *++p ? parse__escape(&p) : - el->el_tty.t_vdisable; - assert(c != 0); - c--; - c = tty__getcharindex(c); - assert(c != -1); - tios->c_cc[c] = (cc_t)v; - continue; - } - switch (x) { - case '+': - el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; - break; - case '-': - el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; - break; - default: - el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; - el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; - break; - } - } - - tty_setup_flags(el, tios, z); - if (el->el_tty.t_mode == z) { - if (tty_setty(el, TCSADRAIN, tios) == -1) { -#ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", - __func__, strerror(errno)); -#endif /* DEBUG_TTY */ - return -1; - } - } - - return 0; -} - - -#ifdef notyet -/* tty_printchar(): - * DEbugging routine to print the tty characters - */ -static void -tty_printchar(EditLine *el, unsigned char *s) -{ - ttyperm_t *m; - int i; - - for (i = 0; i < C_NCC; i++) { - for (m = el->el_tty.t_t; m->m_name; m++) - if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) - break; - if (m->m_name) - (void) fprintf(el->el_errfile, "%s ^%c ", - m->m_name, s[i] + 'A' - 1); - if (i % 5 == 0) - (void) fprintf(el->el_errfile, "\n"); - } - (void) fprintf(el->el_errfile, "\n"); -} -#endif /* notyet */ - - -static void -tty_setup_flags(EditLine *el, struct termios *tios, int mode) -{ - int kind; - for (kind = MD_INP; kind <= MD_LIN; kind++) { - tcflag_t *f = tty__get_flag(tios, kind); - *f = tty_update_flag(el, *f, mode, kind); - } -} diff --git a/bin/catsh/libedit/tty.h b/bin/catsh/libedit/tty.h deleted file mode 100644 index 2603e1ad..00000000 --- a/bin/catsh/libedit/tty.h +++ /dev/null @@ -1,481 +0,0 @@ -/* $NetBSD: tty.h,v 1.21 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tty.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.tty.h: Local terminal header - */ -#ifndef _h_el_tty -#define _h_el_tty - -#include <termios.h> -#include <unistd.h> - -/* Define our own since everyone gets it wrong! */ -#define CONTROL(A) ((A) & 037) - -/* - * Aix compatible names - */ -# if defined(VWERSE) && !defined(VWERASE) -# define VWERASE VWERSE -# endif /* VWERSE && !VWERASE */ - -# if defined(VDISCRD) && !defined(VDISCARD) -# define VDISCARD VDISCRD -# endif /* VDISCRD && !VDISCARD */ - -# if defined(VFLUSHO) && !defined(VDISCARD) -# define VDISCARD VFLUSHO -# endif /* VFLUSHO && VDISCARD */ - -# if defined(VSTRT) && !defined(VSTART) -# define VSTART VSTRT -# endif /* VSTRT && ! VSTART */ - -# if defined(VSTAT) && !defined(VSTATUS) -# define VSTATUS VSTAT -# endif /* VSTAT && ! VSTATUS */ - -# ifndef ONLRET -# define ONLRET 0 -# endif /* ONLRET */ - -# ifndef TAB3 -# ifdef OXTABS -# define TAB3 OXTABS -# else -# define TAB3 0 -# endif /* OXTABS */ -# endif /* !TAB3 */ - -# if defined(OXTABS) && !defined(XTABS) -# define XTABS OXTABS -# endif /* OXTABS && !XTABS */ - -# ifndef ONLCR -# define ONLCR 0 -# endif /* ONLCR */ - -# ifndef IEXTEN -# define IEXTEN 0 -# endif /* IEXTEN */ - -# ifndef ECHOCTL -# define ECHOCTL 0 -# endif /* ECHOCTL */ - -# ifndef PARENB -# define PARENB 0 -# endif /* PARENB */ - -# ifndef EXTPROC -# define EXTPROC 0 -# endif /* EXTPROC */ - -# ifndef FLUSHO -# define FLUSHO 0 -# endif /* FLUSHO */ - - -# if defined(VDISABLE) && !defined(_POSIX_VDISABLE) -# define _POSIX_VDISABLE VDISABLE -# endif /* VDISABLE && ! _POSIX_VDISABLE */ - -/* - * Work around ISC's definition of IEXTEN which is - * XCASE! - */ -# ifdef ISC -# if defined(IEXTEN) && defined(XCASE) -# if IEXTEN == XCASE -# undef IEXTEN -# define IEXTEN 0 -# endif /* IEXTEN == XCASE */ -# endif /* IEXTEN && XCASE */ -# if defined(IEXTEN) && !defined(XCASE) -# define XCASE IEXTEN -# undef IEXTEN -# define IEXTEN 0 -# endif /* IEXTEN && !XCASE */ -# endif /* ISC */ - -/* - * Work around convex weirdness where turning off IEXTEN makes us - * lose all postprocessing! - */ -#if defined(convex) || defined(__convex__) -# if defined(IEXTEN) && IEXTEN != 0 -# undef IEXTEN -# define IEXTEN 0 -# endif /* IEXTEN != 0 */ -#endif /* convex || __convex__ */ - -/* - * So that we don't lose job control. - */ -#ifdef __SVR4 -# undef CSWTCH -#endif - -#ifndef _POSIX_VDISABLE -# define _POSIX_VDISABLE ((unsigned char) -1) -#endif /* _POSIX_VDISABLE */ - -#if !defined(CREPRINT) && defined(CRPRNT) -# define CREPRINT CRPRNT -#endif /* !CREPRINT && CRPRNT */ -#if !defined(CDISCARD) && defined(CFLUSH) -# define CDISCARD CFLUSH -#endif /* !CDISCARD && CFLUSH */ - -#ifndef CINTR -# define CINTR CONTROL('c') -#endif /* CINTR */ -#ifndef CQUIT -# define CQUIT 034 /* ^\ */ -#endif /* CQUIT */ -#ifndef CERASE -# define CERASE 0177 /* ^? */ -#endif /* CERASE */ -#ifndef CKILL -# define CKILL CONTROL('u') -#endif /* CKILL */ -#ifndef CEOF -# define CEOF CONTROL('d') -#endif /* CEOF */ -#ifndef CEOL -# define CEOL _POSIX_VDISABLE -#endif /* CEOL */ -#ifndef CEOL2 -# define CEOL2 _POSIX_VDISABLE -#endif /* CEOL2 */ -#ifndef CSWTCH -# define CSWTCH _POSIX_VDISABLE -#endif /* CSWTCH */ -#ifndef CDSWTCH -# define CDSWTCH _POSIX_VDISABLE -#endif /* CDSWTCH */ -#ifndef CERASE2 -# define CERASE2 _POSIX_VDISABLE -#endif /* CERASE2 */ -#ifndef CSTART -# define CSTART CONTROL('q') -#endif /* CSTART */ -#ifndef CSTOP -# define CSTOP CONTROL('s') -#endif /* CSTOP */ -#ifndef CSUSP -# define CSUSP CONTROL('z') -#endif /* CSUSP */ -#ifndef CDSUSP -# define CDSUSP CONTROL('y') -#endif /* CDSUSP */ - -#ifdef hpux - -# ifndef CREPRINT -# define CREPRINT _POSIX_VDISABLE -# endif /* CREPRINT */ -# ifndef CDISCARD -# define CDISCARD _POSIX_VDISABLE -# endif /* CDISCARD */ -# ifndef CLNEXT -# define CLNEXT _POSIX_VDISABLE -# endif /* CLNEXT */ -# ifndef CWERASE -# define CWERASE _POSIX_VDISABLE -# endif /* CWERASE */ - -#else /* !hpux */ - -# ifndef CREPRINT -# define CREPRINT CONTROL('r') -# endif /* CREPRINT */ -# ifndef CDISCARD -# define CDISCARD CONTROL('o') -# endif /* CDISCARD */ -# ifndef CLNEXT -# define CLNEXT CONTROL('v') -# endif /* CLNEXT */ -# ifndef CWERASE -# define CWERASE CONTROL('w') -# endif /* CWERASE */ - -#endif /* hpux */ - -#ifndef CSTATUS -# define CSTATUS CONTROL('t') -#endif /* CSTATUS */ -#ifndef CPAGE -# define CPAGE ' ' -#endif /* CPAGE */ -#ifndef CPGOFF -# define CPGOFF CONTROL('m') -#endif /* CPGOFF */ -#ifndef CKILL2 -# define CKILL2 _POSIX_VDISABLE -#endif /* CKILL2 */ -#ifndef CBRK -# ifndef masscomp -# define CBRK 0377 -# else -# define CBRK '\0' -# endif /* masscomp */ -#endif /* CBRK */ -#ifndef CMIN -# define CMIN CEOF -#endif /* CMIN */ -#ifndef CTIME -# define CTIME CEOL -#endif /* CTIME */ - -/* - * Fix for sun inconsistency. On termio VSUSP and the rest of the - * ttychars > NCC are defined. So we undefine them. - */ -#if defined(TERMIO) || defined(POSIX) -# if defined(POSIX) && defined(NCCS) -# define NUMCC NCCS -# else -# ifdef NCC -# define NUMCC NCC -# endif /* NCC */ -# endif /* POSIX && NCCS */ -# ifdef NUMCC -# ifdef VINTR -# if NUMCC <= VINTR -# undef VINTR -# endif /* NUMCC <= VINTR */ -# endif /* VINTR */ -# ifdef VQUIT -# if NUMCC <= VQUIT -# undef VQUIT -# endif /* NUMCC <= VQUIT */ -# endif /* VQUIT */ -# ifdef VERASE -# if NUMCC <= VERASE -# undef VERASE -# endif /* NUMCC <= VERASE */ -# endif /* VERASE */ -# ifdef VKILL -# if NUMCC <= VKILL -# undef VKILL -# endif /* NUMCC <= VKILL */ -# endif /* VKILL */ -# ifdef VEOF -# if NUMCC <= VEOF -# undef VEOF -# endif /* NUMCC <= VEOF */ -# endif /* VEOF */ -# ifdef VEOL -# if NUMCC <= VEOL -# undef VEOL -# endif /* NUMCC <= VEOL */ -# endif /* VEOL */ -# ifdef VEOL2 -# if NUMCC <= VEOL2 -# undef VEOL2 -# endif /* NUMCC <= VEOL2 */ -# endif /* VEOL2 */ -# ifdef VSWTCH -# if NUMCC <= VSWTCH -# undef VSWTCH -# endif /* NUMCC <= VSWTCH */ -# endif /* VSWTCH */ -# ifdef VDSWTCH -# if NUMCC <= VDSWTCH -# undef VDSWTCH -# endif /* NUMCC <= VDSWTCH */ -# endif /* VDSWTCH */ -# ifdef VERASE2 -# if NUMCC <= VERASE2 -# undef VERASE2 -# endif /* NUMCC <= VERASE2 */ -# endif /* VERASE2 */ -# ifdef VSTART -# if NUMCC <= VSTART -# undef VSTART -# endif /* NUMCC <= VSTART */ -# endif /* VSTART */ -# ifdef VSTOP -# if NUMCC <= VSTOP -# undef VSTOP -# endif /* NUMCC <= VSTOP */ -# endif /* VSTOP */ -# ifdef VWERASE -# if NUMCC <= VWERASE -# undef VWERASE -# endif /* NUMCC <= VWERASE */ -# endif /* VWERASE */ -# ifdef VSUSP -# if NUMCC <= VSUSP -# undef VSUSP -# endif /* NUMCC <= VSUSP */ -# endif /* VSUSP */ -# ifdef VDSUSP -# if NUMCC <= VDSUSP -# undef VDSUSP -# endif /* NUMCC <= VDSUSP */ -# endif /* VDSUSP */ -# ifdef VREPRINT -# if NUMCC <= VREPRINT -# undef VREPRINT -# endif /* NUMCC <= VREPRINT */ -# endif /* VREPRINT */ -# ifdef VDISCARD -# if NUMCC <= VDISCARD -# undef VDISCARD -# endif /* NUMCC <= VDISCARD */ -# endif /* VDISCARD */ -# ifdef VLNEXT -# if NUMCC <= VLNEXT -# undef VLNEXT -# endif /* NUMCC <= VLNEXT */ -# endif /* VLNEXT */ -# ifdef VSTATUS -# if NUMCC <= VSTATUS -# undef VSTATUS -# endif /* NUMCC <= VSTATUS */ -# endif /* VSTATUS */ -# ifdef VPAGE -# if NUMCC <= VPAGE -# undef VPAGE -# endif /* NUMCC <= VPAGE */ -# endif /* VPAGE */ -# ifdef VPGOFF -# if NUMCC <= VPGOFF -# undef VPGOFF -# endif /* NUMCC <= VPGOFF */ -# endif /* VPGOFF */ -# ifdef VKILL2 -# if NUMCC <= VKILL2 -# undef VKILL2 -# endif /* NUMCC <= VKILL2 */ -# endif /* VKILL2 */ -# ifdef VBRK -# if NUMCC <= VBRK -# undef VBRK -# endif /* NUMCC <= VBRK */ -# endif /* VBRK */ -# ifdef VMIN -# if NUMCC <= VMIN -# undef VMIN -# endif /* NUMCC <= VMIN */ -# endif /* VMIN */ -# ifdef VTIME -# if NUMCC <= VTIME -# undef VTIME -# endif /* NUMCC <= VTIME */ -# endif /* VTIME */ -# endif /* NUMCC */ -#endif /* !POSIX */ - -#define C_INTR 0 -#define C_QUIT 1 -#define C_ERASE 2 -#define C_KILL 3 -#define C_EOF 4 -#define C_EOL 5 -#define C_EOL2 6 -#define C_SWTCH 7 -#define C_DSWTCH 8 -#define C_ERASE2 9 -#define C_START 10 -#define C_STOP 11 -#define C_WERASE 12 -#define C_SUSP 13 -#define C_DSUSP 14 -#define C_REPRINT 15 -#define C_DISCARD 16 -#define C_LNEXT 17 -#define C_STATUS 18 -#define C_PAGE 19 -#define C_PGOFF 20 -#define C_KILL2 21 -#define C_BRK 22 -#define C_MIN 23 -#define C_TIME 24 -#define C_NCC 25 -#define C_SH(A) ((unsigned int)(1 << (A))) - -/* - * Terminal dependend data structures - */ -#define EX_IO 0 /* while we are executing */ -#define ED_IO 1 /* while we are editing */ -#define TS_IO 2 /* new mode from terminal */ -#define QU_IO 2 /* used only for quoted chars */ -#define NN_IO 3 /* The number of entries */ - -/* Don't re-order */ -#define MD_INP 0 -#define MD_OUT 1 -#define MD_CTL 2 -#define MD_LIN 3 -#define MD_CHAR 4 -#define MD_NN 5 - -typedef struct { - const char *t_name; - unsigned int t_setmask; - unsigned int t_clrmask; -} ttyperm_t[NN_IO][MD_NN]; - -typedef unsigned char ttychar_t[NN_IO][C_NCC]; - -libedit_private int tty_init(EditLine *); -libedit_private void tty_end(EditLine *); -libedit_private int tty_stty(EditLine *, int, const wchar_t **); -libedit_private int tty_rawmode(EditLine *); -libedit_private int tty_cookedmode(EditLine *); -libedit_private int tty_quotemode(EditLine *); -libedit_private int tty_noquotemode(EditLine *); -libedit_private void tty_bind_char(EditLine *, int); - -typedef struct { - ttyperm_t t_t; - ttychar_t t_c; - struct termios t_or, t_ex, t_ed, t_ts; - int t_tabs; - int t_eight; - speed_t t_speed; - unsigned char t_mode; - unsigned char t_vdisable; - unsigned char t_initialized; -} el_tty_t; - - -#endif /* _h_el_tty */ diff --git a/bin/catsh/libedit/vi.c b/bin/catsh/libedit/vi.c deleted file mode 100644 index 0c37bfb9..00000000 --- a/bin/catsh/libedit/vi.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* $NetBSD: vi.c,v 1.62 2016/05/09 21:46:56 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: vi.c,v 1.62 2016/05/09 21:46:56 christos Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * vi.c: Vi mode commands. - */ -#include <sys/wait.h> -#include <ctype.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "el.h" -#include "common.h" -#include "emacs.h" -#include "fcns.h" -#include "vi.h" - -static el_action_t cv_action(EditLine *, wint_t); -static el_action_t cv_paste(EditLine *, wint_t); - -/* cv_action(): - * Handle vi actions. - */ -static el_action_t -cv_action(EditLine *el, wint_t c) -{ - - if (el->el_chared.c_vcmd.action != NOP) { - /* 'cc', 'dd' and (possibly) friends */ - if (c != (wint_t)el->el_chared.c_vcmd.action) - return CC_ERROR; - - if (!(c & YANK)) - cv_undo(el); - cv_yank(el, el->el_line.buffer, - (int)(el->el_line.lastchar - el->el_line.buffer)); - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - if (!(c & YANK)) { - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; - } - if (c & INSERT) - el->el_map.current = el->el_map.key; - - return CC_REFRESH; - } - el->el_chared.c_vcmd.pos = el->el_line.cursor; - el->el_chared.c_vcmd.action = c; - return CC_ARGHACK; -} - -/* cv_paste(): - * Paste previous deletion before or after the cursor - */ -static el_action_t -cv_paste(EditLine *el, wint_t c) -{ - c_kill_t *k = &el->el_chared.c_kill; - size_t len = (size_t)(k->last - k->buf); - - if (k->buf == NULL || len == 0) - return CC_ERROR; -#ifdef DEBUG_PASTE - (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len, - k->buf); -#endif - - cv_undo(el); - - if (!c && el->el_line.cursor < el->el_line.lastchar) - el->el_line.cursor++; - - c_insert(el, (int)len); - if (el->el_line.cursor + len > el->el_line.lastchar) - return CC_ERROR; - (void) memcpy(el->el_line.cursor, k->buf, len * - sizeof(*el->el_line.cursor)); - - return CC_REFRESH; -} - - -/* vi_paste_next(): - * Vi paste previous deletion to the right of the cursor - * [p] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_paste(el, 0); -} - - -/* vi_paste_prev(): - * Vi paste previous deletion to the left of the cursor - * [P] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_paste(el, 1); -} - - -/* vi_prev_big_word(): - * Vi move to the previous space delimited word - * [B] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - - el->el_line.cursor = cv_prev_word(el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - cv__isWord); - - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_prev_word(): - * Vi move to the previous word - * [b] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor == el->el_line.buffer) - return CC_ERROR; - - el->el_line.cursor = cv_prev_word(el->el_line.cursor, - el->el_line.buffer, - el->el_state.argument, - cv__isword); - - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_next_big_word(): - * Vi move to the next space delimited word - * [W] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor >= el->el_line.lastchar - 1) - return CC_ERROR; - - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument, cv__isWord); - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_next_word(): - * Vi move to the next word - * [w] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor >= el->el_line.lastchar - 1) - return CC_ERROR; - - el->el_line.cursor = cv_next_word(el, el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument, cv__isword); - - if (el->el_map.type == MAP_VI) - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_change_case(): - * Vi change case of character under the cursor and advance one character - * [~] - */ -libedit_private el_action_t -vi_change_case(EditLine *el, wint_t c) -{ - int i; - - if (el->el_line.cursor >= el->el_line.lastchar) - return CC_ERROR; - cv_undo(el); - for (i = 0; i < el->el_state.argument; i++) { - - c = *el->el_line.cursor; - if (iswupper(c)) - *el->el_line.cursor = towlower(c); - else if (iswlower(c)) - *el->el_line.cursor = towupper(c); - - if (++el->el_line.cursor >= el->el_line.lastchar) { - el->el_line.cursor--; - re_fastaddc(el); - break; - } - re_fastaddc(el); - } - return CC_NORM; -} - - -/* vi_change_meta(): - * Vi change prefix command - * [c] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - /* - * Delete with insert == change: first we delete and then we leave in - * insert mode. - */ - return cv_action(el, DELETE | INSERT); -} - - -/* vi_insert_at_bol(): - * Vi enter insert mode at the beginning of line - * [I] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_line.cursor = el->el_line.buffer; - cv_undo(el); - el->el_map.current = el->el_map.key; - return CC_CURSOR; -} - - -/* vi_replace_char(): - * Vi replace character under the cursor with the next character typed - * [r] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor >= el->el_line.lastchar) - return CC_ERROR; - - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE_1; - cv_undo(el); - return CC_ARGHACK; -} - - -/* vi_replace_mode(): - * Vi enter replace mode - * [R] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_map.current = el->el_map.key; - el->el_state.inputmode = MODE_REPLACE; - cv_undo(el); - return CC_NORM; -} - - -/* vi_substitute_char(): - * Vi replace character under the cursor and enter insert mode - * [s] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - c_delafter(el, el->el_state.argument); - el->el_map.current = el->el_map.key; - return CC_REFRESH; -} - - -/* vi_substitute_line(): - * Vi substitute entire line - * [S] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - cv_undo(el); - cv_yank(el, el->el_line.buffer, - (int)(el->el_line.lastchar - el->el_line.buffer)); - (void) em_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; -} - - -/* vi_change_to_eol(): - * Vi change to end of line - * [C] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - cv_undo(el); - cv_yank(el, el->el_line.cursor, - (int)(el->el_line.lastchar - el->el_line.cursor)); - (void) ed_kill_line(el, 0); - el->el_map.current = el->el_map.key; - return CC_REFRESH; -} - - -/* vi_insert(): - * Vi enter insert mode - * [i] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_map.current = el->el_map.key; - cv_undo(el); - return CC_NORM; -} - - -/* vi_add(): - * Vi enter insert mode after the cursor - * [a] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_add(EditLine *el, wint_t c __attribute__((__unused__))) -{ - int ret; - - el->el_map.current = el->el_map.key; - if (el->el_line.cursor < el->el_line.lastchar) { - el->el_line.cursor++; - if (el->el_line.cursor > el->el_line.lastchar) - el->el_line.cursor = el->el_line.lastchar; - ret = CC_CURSOR; - } else - ret = CC_NORM; - - cv_undo(el); - - return (el_action_t)ret; -} - - -/* vi_add_at_eol(): - * Vi enter insert mode at end of line - * [A] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_map.current = el->el_map.key; - el->el_line.cursor = el->el_line.lastchar; - cv_undo(el); - return CC_CURSOR; -} - - -/* vi_delete_meta(): - * Vi delete prefix command - * [d] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_action(el, DELETE); -} - - -/* vi_end_big_word(): - * Vi move to the end of the current space delimited word - * [E] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - - el->el_line.cursor = cv__endword(el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument, cv__isWord); - - if (el->el_chared.c_vcmd.action != NOP) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_end_word(): - * Vi move to the end of the current word - * [e] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor == el->el_line.lastchar) - return CC_ERROR; - - el->el_line.cursor = cv__endword(el->el_line.cursor, - el->el_line.lastchar, el->el_state.argument, cv__isword); - - if (el->el_chared.c_vcmd.action != NOP) { - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_undo(): - * Vi undo last change - * [u] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) -{ - c_undo_t un = el->el_chared.c_undo; - - if (un.len == -1) - return CC_ERROR; - - /* switch line buffer and undo buffer */ - el->el_chared.c_undo.buf = el->el_line.buffer; - el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; - el->el_chared.c_undo.cursor = - (int)(el->el_line.cursor - el->el_line.buffer); - el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); - el->el_line.buffer = un.buf; - el->el_line.cursor = un.buf + un.cursor; - el->el_line.lastchar = un.buf + un.len; - - return CC_REFRESH; -} - - -/* vi_command_mode(): - * Vi enter command mode (use alternative key bindings) - * [<ESC>] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - /* [Esc] cancels pending action */ - el->el_chared.c_vcmd.action = NOP; - el->el_chared.c_vcmd.pos = 0; - - el->el_state.doingarg = 0; - - el->el_state.inputmode = MODE_INSERT; - el->el_map.current = el->el_map.alt; -#ifdef VI_MOVE - if (el->el_line.cursor > el->el_line.buffer) - el->el_line.cursor--; -#endif - return CC_CURSOR; -} - - -/* vi_zero(): - * Vi move to the beginning of line - * [0] - */ -libedit_private el_action_t -vi_zero(EditLine *el, wint_t c) -{ - - if (el->el_state.doingarg) - return ed_argument_digit(el, c); - - el->el_line.cursor = el->el_line.buffer; - if (el->el_chared.c_vcmd.action != NOP) { - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - - -/* vi_delete_prev_char(): - * Vi move to previous character (backspace) - * [^H] in insert mode only - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_line.cursor <= el->el_line.buffer) - return CC_ERROR; - - c_delbefore1(el); - el->el_line.cursor--; - return CC_REFRESH; -} - - -/* vi_list_or_eof(): - * Vi list choices for completion or indicate end of file if empty line - * [^D] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_list_or_eof(EditLine *el, wint_t c) -{ - - if (el->el_line.cursor == el->el_line.lastchar) { - if (el->el_line.cursor == el->el_line.buffer) { - terminal_writec(el, c); /* then do a EOF */ - return CC_EOF; - } else { - /* - * Here we could list completions, but it is an - * error right now - */ - terminal_beep(el); - return CC_ERROR; - } - } else { -#ifdef notyet - re_goto_bottom(el); - *el->el_line.lastchar = '\0'; /* just in case */ - return CC_LIST_CHOICES; -#else - /* - * Just complain for now. - */ - terminal_beep(el); - return CC_ERROR; -#endif - } -} - - -/* vi_kill_line_prev(): - * Vi cut from beginning of line to cursor - * [^U] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__))) -{ - wchar_t *kp, *cp; - - cp = el->el_line.buffer; - kp = el->el_chared.c_kill.buf; - while (cp < el->el_line.cursor) - *kp++ = *cp++; /* copy it */ - el->el_chared.c_kill.last = kp; - c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); - el->el_line.cursor = el->el_line.buffer; /* zap! */ - return CC_REFRESH; -} - - -/* vi_search_prev(): - * Vi search history previous - * [?] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_search(el, ED_SEARCH_PREV_HISTORY); -} - - -/* vi_search_next(): - * Vi search history next - * [/] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_search(el, ED_SEARCH_NEXT_HISTORY); -} - - -/* vi_repeat_search_next(): - * Vi repeat current search in the same search direction - * [n] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return cv_repeat_srch(el, el->el_search.patdir); -} - - -/* vi_repeat_search_prev(): - * Vi repeat current search in the opposite search direction - * [N] - */ -/*ARGSUSED*/ -libedit_private el_action_t -vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - if (el->el_search.patlen == 0) - return CC_ERROR; - else - return (cv_repeat_srch(el, - el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? - ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); -} - - -/* vi_next_char(): - * Vi move to the character specified next - * [f] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); -} - - -/* vi_prev_char(): - * Vi move to the character specified previous - * [F] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); -} - - -/* vi_to_next_char(): - * Vi move up to the character specified next - * [t] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); -} - - -/* vi_to_prev_char(): - * Vi move up to the character specified previous - * [T] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); -} - - -/* vi_repeat_next_char(): - * Vi repeat current character search in the same search direction - * [;] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, - el->el_state.argument, el->el_search.chatflg); -} - - -/* vi_repeat_prev_char(): - * Vi repeat current character search in the opposite search direction - * [,] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) -{ - el_action_t r; - int dir = el->el_search.chadir; - - r = cv_csearch(el, -dir, el->el_search.chacha, - el->el_state.argument, el->el_search.chatflg); - el->el_search.chadir = dir; - return r; -} - - -/* vi_match(): - * Vi go to matching () {} or [] - * [%] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_match(EditLine *el, wint_t c __attribute__((__unused__))) -{ - const wchar_t match_chars[] = L"()[]{}"; - wchar_t *cp; - size_t delta, i, count; - wchar_t o_ch, c_ch; - - *el->el_line.lastchar = '\0'; /* just in case */ - - i = wcscspn(el->el_line.cursor, match_chars); - o_ch = el->el_line.cursor[i]; - if (o_ch == 0) - return CC_ERROR; - delta = (size_t)(wcschr(match_chars, o_ch) - match_chars); - c_ch = match_chars[delta ^ 1]; - count = 1; - delta = 1 - (delta & 1) * 2; - - for (cp = &el->el_line.cursor[i]; count; ) { - cp += delta; - if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) - return CC_ERROR; - if (*cp == o_ch) - count++; - else if (*cp == c_ch) - count--; - } - - el->el_line.cursor = cp; - - if (el->el_chared.c_vcmd.action != NOP) { - /* NB posix says char under cursor should NOT be deleted - for -ve delta - this is different to netbsd vi. */ - if (delta > 0) - el->el_line.cursor++; - cv_delfini(el); - return CC_REFRESH; - } - return CC_CURSOR; -} - -/* vi_undo_line(): - * Vi undo all changes to line - * [U] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - cv_undo(el); - return hist_get(el); -} - -/* vi_to_column(): - * Vi go to specified column - * [|] - * NB netbsd vi goes to screen column 'n', posix says nth character - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_line.cursor = el->el_line.buffer; - el->el_state.argument--; - return ed_next_char(el, 0); -} - -/* vi_yank_end(): - * Vi yank to end of line - * [Y] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - cv_yank(el, el->el_line.cursor, - (int)(el->el_line.lastchar - el->el_line.cursor)); - return CC_REFRESH; -} - -/* vi_yank(): - * Vi yank - * [y] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_yank(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - return cv_action(el, YANK); -} - -/* vi_comment_out(): - * Vi comment out current command - * [#] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) -{ - - el->el_line.cursor = el->el_line.buffer; - c_insert(el, 1); - *el->el_line.cursor = '#'; - re_refresh(el); - return ed_newline(el, 0); -} - -/* vi_alias(): - * Vi include shell alias - * [@] - * NB: posix implies that we should enter insert mode, however - * this is against historical precedent... - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_alias(EditLine *el, wint_t c __attribute__((__unused__))) -{ - char alias_name[3]; - const char *alias_text; - - if (el->el_chared.c_aliasfun == NULL) - return CC_ERROR; - - alias_name[0] = '_'; - alias_name[2] = 0; - if (el_getc(el, &alias_name[1]) != 1) - return CC_ERROR; - - alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, - alias_name); - if (alias_text != NULL) - el_wpush(el, ct_decode_string(alias_text, &el->el_scratch)); - return CC_NORM; -} - -/* vi_to_history_line(): - * Vi go to specified history file line. - * [G] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) -{ - int sv_event_no = el->el_history.eventno; - el_action_t rval; - - - if (el->el_history.eventno == 0) { - (void) wcsncpy(el->el_history.buf, el->el_line.buffer, - EL_BUFSIZ); - el->el_history.last = el->el_history.buf + - (el->el_line.lastchar - el->el_line.buffer); - } - - /* Lack of a 'count' means oldest, not 1 */ - if (!el->el_state.doingarg) { - el->el_history.eventno = 0x7fffffff; - hist_get(el); - } else { - /* This is brain dead, all the rest of this code counts - * upwards going into the past. Here we need count in the - * other direction (to match the output of fc -l). - * I could change the world, but this seems to suffice. - */ - el->el_history.eventno = 1; - if (hist_get(el) == CC_ERROR) - return CC_ERROR; - el->el_history.eventno = 1 + el->el_history.ev.num - - el->el_state.argument; - if (el->el_history.eventno < 0) { - el->el_history.eventno = sv_event_no; - return CC_ERROR; - } - } - rval = hist_get(el); - if (rval == CC_ERROR) - el->el_history.eventno = sv_event_no; - return rval; -} - -/* vi_histedit(): - * Vi edit history line with vi - * [v] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) -{ - int fd; - pid_t pid; - ssize_t st; - int status; - char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; - char *cp = NULL; - size_t len; - wchar_t *line = NULL; - - if (el->el_state.doingarg) { - if (vi_to_history_line(el, 0) == CC_ERROR) - return CC_ERROR; - } - - fd = mkstemp(tempfile); - if (fd < 0) - return CC_ERROR; - len = (size_t)(el->el_line.lastchar - el->el_line.buffer); -#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) - cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); - if (cp == NULL) - goto error; - line = el_malloc(len * sizeof(*line) + 1); - if (line == NULL) - goto error; - wcsncpy(line, el->el_line.buffer, len); - line[len] = '\0'; - wcstombs(cp, line, TMP_BUFSIZ - 1); - cp[TMP_BUFSIZ - 1] = '\0'; - len = strlen(cp); - write(fd, cp, len); - write(fd, "\n", (size_t)1); - pid = fork(); - switch (pid) { - case -1: - goto error; - case 0: - close(fd); - execlp("vi", "vi", tempfile, (char *)NULL); - exit(0); - /*NOTREACHED*/ - default: - while (waitpid(pid, &status, 0) != pid) - continue; - lseek(fd, (off_t)0, SEEK_SET); - st = read(fd, cp, TMP_BUFSIZ - 1); - if (st > 0) { - cp[st] = '\0'; - len = (size_t)(el->el_line.limit - el->el_line.buffer); - len = mbstowcs(el->el_line.buffer, cp, len); - if (len > 0 && el->el_line.buffer[len - 1] == '\n') - --len; - } - else - len = 0; - el->el_line.cursor = el->el_line.buffer; - el->el_line.lastchar = el->el_line.buffer + len; - el_free(cp); - el_free(line); - break; - } - - close(fd); - unlink(tempfile); - /* return CC_REFRESH; */ - return ed_newline(el, 0); -error: - el_free(line); - el_free(cp); - close(fd); - unlink(tempfile); - return CC_ERROR; -} - -/* vi_history_word(): - * Vi append word from previous input line - * [_] - * Who knows where this one came from! - * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) -{ - const wchar_t *wp = HIST_FIRST(el); - const wchar_t *wep, *wsp; - int len; - wchar_t *cp; - const wchar_t *lim; - - if (wp == NULL) - return CC_ERROR; - - wep = wsp = NULL; - do { - while (iswspace(*wp)) - wp++; - if (*wp == 0) - break; - wsp = wp; - while (*wp && !iswspace(*wp)) - wp++; - wep = wp; - } while ((!el->el_state.doingarg || --el->el_state.argument > 0) - && *wp != 0); - - if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) - return CC_ERROR; - - cv_undo(el); - len = (int)(wep - wsp); - if (el->el_line.cursor < el->el_line.lastchar) - el->el_line.cursor++; - c_insert(el, len + 1); - cp = el->el_line.cursor; - lim = el->el_line.limit; - if (cp < lim) - *cp++ = ' '; - while (wsp < wep && cp < lim) - *cp++ = *wsp++; - el->el_line.cursor = cp; - - el->el_map.current = el->el_map.key; - return CC_REFRESH; -} - -/* vi_redo(): - * Vi redo last non-motion command - * [.] - */ -libedit_private el_action_t -/*ARGSUSED*/ -vi_redo(EditLine *el, wint_t c __attribute__((__unused__))) -{ - c_redo_t *r = &el->el_chared.c_redo; - - if (!el->el_state.doingarg && r->count) { - el->el_state.doingarg = 1; - el->el_state.argument = r->count; - } - - el->el_chared.c_vcmd.pos = el->el_line.cursor; - el->el_chared.c_vcmd.action = r->action; - if (r->pos != r->buf) { - if (r->pos + 1 > r->lim) - /* sanity */ - r->pos = r->lim - 1; - r->pos[0] = 0; - el_wpush(el, r->buf); - } - - el->el_state.thiscmd = r->cmd; - el->el_state.thisch = r->ch; - return (*el->el_map.func[r->cmd])(el, r->ch); -} diff --git a/bin/catsh/mail.c b/bin/catsh/mail.c deleted file mode 100644 index 6f8a3d39..00000000 --- a/bin/catsh/mail.c +++ /dev/null @@ -1,120 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/mail.c 336303 2018-07-15 09:14:30Z jilles $"); - -/* - * Routines to check for mail. (Perhaps make part of main.c?) - */ - -#include "shell.h" -#include "mail.h" -#include "var.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <stdlib.h> - - -#define MAXMBOXES 10 - - -static int nmboxes; /* number of mailboxes */ -static time_t mailtime[MAXMBOXES]; /* times of mailboxes */ - - - -/* - * Print appropriate message(s) if mail has arrived. If the argument is - * nozero, then the value of MAIL has changed, so we just update the - * values. - */ - -void -chkmail(int silent) -{ - int i; - char *mpath; - char *p; - char *msg; - struct stackmark smark; - struct stat statb; - - if (silent) - nmboxes = 10; - if (nmboxes == 0) - return; - setstackmark(&smark); - mpath = stsavestr(mpathset()? mpathval() : mailval()); - for (i = 0 ; i < nmboxes ; i++) { - p = mpath; - if (*p == '\0') - break; - mpath = strchr(p, ':'); - if (!mpath) mpath = strchr(p, '\0'); - if (*mpath != '\0') { - *mpath++ = '\0'; - if (p == mpath - 1) - continue; - } - msg = strchr(p, '%'); - if (msg != NULL) - *msg++ = '\0'; -#ifdef notdef /* this is what the System V shell claims to do (it lies) */ - if (stat(p, &statb) < 0) - statb.st_mtime = 0; - if (statb.st_mtime > mailtime[i] && ! silent) { - out2str(msg? msg : "you have mail"); - out2c('\n'); - } - mailtime[i] = statb.st_mtime; -#else /* this is what it should do */ - if (stat(p, &statb) < 0) - statb.st_size = 0; - if (statb.st_size > mailtime[i] && ! silent) { - out2str(msg? msg : "you have mail"); - out2c('\n'); - } - mailtime[i] = statb.st_size; -#endif - } - nmboxes = i; - popstackmark(&smark); -} diff --git a/bin/catsh/mail.h b/bin/catsh/mail.h deleted file mode 100644 index adeced2d..00000000 --- a/bin/catsh/mail.h +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mail.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/mail.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -void chkmail(int); diff --git a/bin/catsh/main.c b/bin/catsh/main.c deleted file mode 100644 index 7a0bf25b..00000000 --- a/bin/catsh/main.c +++ /dev/null @@ -1,350 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/main.c 336320 2018-07-15 21:55:17Z jilles $"); - -#include <stdio.h> -#include <signal.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <locale.h> -#include <errno.h> - -#include "shell.h" -#include "main.h" -#include "mail.h" -#include "options.h" -#include "output.h" -#include "parser.h" -#include "nodes.h" -#include "expand.h" -#include "eval.h" -#include "jobs.h" -#include "input.h" -#include "trap.h" -#include "var.h" -#include "show.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "exec.h" -#include "cd.h" -#include "redir.h" -#include "builtins.h" - -int rootpid; -int rootshell; -struct jmploc main_handler; -int localeisutf8, initial_localeisutf8; - -static void reset(void); -static void cmdloop(int); -static void read_profile(const char *); -static char *find_dot_file(char *); - -/* - * Main routine. We initialize things, parse the arguments, execute - * profiles if we're a login shell, and then call cmdloop to execute - * commands. The setjmp call sets up the location to jump to when an - * exception occurs. When an exception occurs the variable "state" - * is used to figure out how far we had gotten. - */ - -int -main(int argc, char *argv[]) -{ - struct stackmark smark, smark2; - volatile int state; - char *shinit; - - (void) setlocale(LC_ALL, ""); - initcharset(); - state = 0; - if (setjmp(main_handler.loc)) { - switch (exception) { - case EXEXEC: - exitstatus = exerrno; - break; - - case EXERROR: - exitstatus = 2; - break; - - default: - break; - } - - if (state == 0 || iflag == 0 || ! rootshell || - exception == EXEXIT) - exitshell(exitstatus); - reset(); - if (exception == EXINT) - out2fmt_flush("\n"); - popstackmark(&smark); - FORCEINTON; /* enable interrupts */ - if (state == 1) - goto state1; - else if (state == 2) - goto state2; - else if (state == 3) - goto state3; - else - goto state4; - } - handler = &main_handler; -#ifdef DEBUG - opentrace(); - trputs("Shell args: "); trargs(argv); -#endif - rootpid = getpid(); - rootshell = 1; - INTOFF; - initvar(); - setstackmark(&smark); - setstackmark(&smark2); - procargs(argc, argv); - pwd_init(iflag); - INTON; - if (iflag) - chkmail(1); - if (argv[0] && argv[0][0] == '-') { - state = 1; - read_profile("/etc/profile"); -state1: - state = 2; - if (privileged == 0) - read_profile("${HOME-}/.profile"); - else - read_profile("/etc/suid_profile"); - } -state2: - state = 3; - if (!privileged && iflag) { - if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { - state = 3; - read_profile(shinit); - } - } -state3: - state = 4; - popstackmark(&smark2); - if (minusc) { - evalstring(minusc, sflag ? 0 : EV_EXIT); - } -state4: - if (sflag || minusc == NULL) { - cmdloop(1); - } - iflag = 0; - optschanged(); - exitshell(exitstatus); - /*NOTREACHED*/ - return 0; -} - -static void -reset(void) -{ - reseteval(); - resetinput(); -} - -/* - * Read and execute commands. "Top" is nonzero for the top level command - * loop; it turns on prompting if the shell is interactive. - */ - -static void -cmdloop(int top) -{ - union node *n; - struct stackmark smark; - int inter; - int numeof = 0; - - TRACE(("cmdloop(%d) called\n", top)); - setstackmark(&smark); - for (;;) { - if (pendingsig) - dotrap(); - inter = 0; - if (iflag && top) { - inter++; - showjobs(1, SHOWJOBS_DEFAULT); - chkmail(0); - flushout(&output); - } - n = parsecmd(inter); - /* showtree(n); DEBUG */ - if (n == NEOF) { - if (!top || numeof >= 50) - break; - if (!stoppedjobs()) { - if (!Iflag) - break; - out2fmt_flush("\nUse \"exit\" to leave shell.\n"); - } - numeof++; - } else if (n != NULL && nflag == 0) { - job_warning = (job_warning == 2) ? 1 : 0; - numeof = 0; - evaltree(n, 0); - } - popstackmark(&smark); - setstackmark(&smark); - if (evalskip != 0) { - if (evalskip == SKIPRETURN) - evalskip = 0; - break; - } - } - popstackmark(&smark); -} - - - -/* - * Read /etc/profile or .profile. Return on error. - */ - -static void -read_profile(const char *name) -{ - int fd; - const char *expandedname; - - expandedname = expandstr(name); - if (expandedname == NULL) - return; - INTOFF; - if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0) - setinputfd(fd, 1); - INTON; - if (fd < 0) - return; - cmdloop(0); - popfile(); -} - - - -/* - * Read a file containing shell functions. - */ - -void -readcmdfile(const char *name) -{ - setinputfile(name, 1); - cmdloop(0); - popfile(); -} - - - -/* - * Take commands from a file. To be compatible we should do a path - * search for the file, which is necessary to find sub-commands. - */ - - -static char * -find_dot_file(char *basename) -{ - char *fullname; - const char *opt; - const char *path = pathval(); - struct stat statb; - - /* don't try this for absolute or relative paths */ - if( strchr(basename, '/')) - return basename; - - while ((fullname = padvance(&path, &opt, basename)) != NULL) { - if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { - /* - * Don't bother freeing here, since it will - * be freed by the caller. - */ - return fullname; - } - stunalloc(fullname); - } - return basename; -} - -int -dotcmd(int argc, char **argv) -{ - char *filename, *fullname; - - if (argc < 2) - error("missing filename"); - - exitstatus = 0; - - /* - * Because we have historically not supported any options, - * only treat "--" specially. - */ - filename = argc > 2 && strcmp(argv[1], "--") == 0 ? argv[2] : argv[1]; - - fullname = find_dot_file(filename); - setinputfile(fullname, 1); - commandname = fullname; - cmdloop(0); - popfile(); - return exitstatus; -} - - -int -exitcmd(int argc, char **argv) -{ - if (stoppedjobs()) - return 0; - iflag = 0; - optschanged(); - if (argc > 1) - exitshell(number(argv[1])); - else - exitshell_savedstatus(); -} diff --git a/bin/catsh/main.h b/bin/catsh/main.h deleted file mode 100644 index f37fd99e..00000000 --- a/bin/catsh/main.h +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)main.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/main.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -extern int rootpid; /* pid of main shell */ -extern int rootshell; /* true if we aren't a child of the main shell */ -extern struct jmploc main_handler; /* top level exception handler */ - -void readcmdfile(const char *); diff --git a/bin/catsh/memalloc.c b/bin/catsh/memalloc.c deleted file mode 100644 index e43ce4cd..00000000 --- a/bin/catsh/memalloc.c +++ /dev/null @@ -1,344 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/memalloc.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <sys/param.h> -#include "shell.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "expand.h" -#include <stdlib.h> -#include <unistd.h> - -/* - * Like malloc, but returns an error when out of space. - */ - -pointer -ckmalloc(size_t nbytes) -{ - pointer p; - - INTOFF; - p = malloc(nbytes); - INTON; - if (p == NULL) - error("Out of space"); - return p; -} - - -/* - * Same for realloc. - */ - -pointer -ckrealloc(pointer p, int nbytes) -{ - INTOFF; - p = realloc(p, nbytes); - INTON; - if (p == NULL) - error("Out of space"); - return p; -} - -void -ckfree(pointer p) -{ - INTOFF; - free(p); - INTON; -} - - -/* - * Make a copy of a string in safe storage. - */ - -char * -savestr(const char *s) -{ - char *p; - size_t len; - - len = strlen(s); - p = ckmalloc(len + 1); - memcpy(p, s, len + 1); - return p; -} - - -/* - * Parse trees for commands are allocated in lifo order, so we use a stack - * to make this more efficient, and also to avoid all sorts of exception - * handling code to handle interrupts in the middle of a parse. - * - * The size 496 was chosen because with 16-byte alignment the total size - * for the allocated block is 512. - */ - -#define MINSIZE 496 /* minimum size of a block. */ - - -struct stack_block { - struct stack_block *prev; - /* Data follows */ -}; -#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block))) - -static struct stack_block *stackp; -char *stacknxt; -int stacknleft; -char *sstrend; - - -static void -stnewblock(int nbytes) -{ - struct stack_block *sp; - int allocsize; - - if (nbytes < MINSIZE) - nbytes = MINSIZE; - - allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes); - - INTOFF; - sp = ckmalloc(allocsize); - sp->prev = stackp; - stacknxt = SPACE(sp); - stacknleft = allocsize - (stacknxt - (char*)sp); - sstrend = stacknxt + stacknleft; - stackp = sp; - INTON; -} - - -pointer -stalloc(int nbytes) -{ - char *p; - - nbytes = ALIGN(nbytes); - if (nbytes > stacknleft) - stnewblock(nbytes); - p = stacknxt; - stacknxt += nbytes; - stacknleft -= nbytes; - return p; -} - - -void -stunalloc(pointer p) -{ - if (p == NULL) { /*DEBUG */ - write(STDERR_FILENO, "stunalloc\n", 10); - abort(); - } - stacknleft += stacknxt - (char *)p; - stacknxt = p; -} - - -char * -stsavestr(const char *s) -{ - char *p; - size_t len; - - len = strlen(s); - p = stalloc(len + 1); - memcpy(p, s, len + 1); - return p; -} - - -void -setstackmark(struct stackmark *mark) -{ - mark->stackp = stackp; - mark->stacknxt = stacknxt; - mark->stacknleft = stacknleft; - /* Ensure this block stays in place. */ - if (stackp != NULL && stacknxt == SPACE(stackp)) - stalloc(1); -} - - -void -popstackmark(struct stackmark *mark) -{ - struct stack_block *sp; - - INTOFF; - while (stackp != mark->stackp) { - sp = stackp; - stackp = sp->prev; - ckfree(sp); - } - stacknxt = mark->stacknxt; - stacknleft = mark->stacknleft; - sstrend = stacknxt + stacknleft; - INTON; -} - - -/* - * When the parser reads in a string, it wants to stick the string on the - * stack and only adjust the stack pointer when it knows how big the - * string is. Stackblock (defined in stack.h) returns a pointer to a block - * of space on top of the stack and stackblocklen returns the length of - * this block. Growstackblock will grow this space by at least one byte, - * possibly moving it (like realloc). Grabstackblock actually allocates the - * part of the block that has been used. - */ - -static void -growstackblock(int min) -{ - char *p; - int newlen; - char *oldspace; - int oldlen; - struct stack_block *sp; - struct stack_block *oldstackp; - - if (min < stacknleft) - min = stacknleft; - if ((unsigned int)min >= - INT_MAX / 2 - ALIGN(sizeof(struct stack_block))) - error("Out of space"); - min += stacknleft; - min += ALIGN(sizeof(struct stack_block)); - newlen = 512; - while (newlen < min) - newlen <<= 1; - oldspace = stacknxt; - oldlen = stacknleft; - - if (stackp != NULL && stacknxt == SPACE(stackp)) { - INTOFF; - oldstackp = stackp; - stackp = oldstackp->prev; - sp = ckrealloc((pointer)oldstackp, newlen); - sp->prev = stackp; - stackp = sp; - stacknxt = SPACE(sp); - stacknleft = newlen - (stacknxt - (char*)sp); - sstrend = stacknxt + stacknleft; - INTON; - } else { - newlen -= ALIGN(sizeof(struct stack_block)); - p = stalloc(newlen); - if (oldlen != 0) - memcpy(p, oldspace, oldlen); - stunalloc(p); - } -} - - - -/* - * The following routines are somewhat easier to use that the above. - * The user declares a variable of type STACKSTR, which may be declared - * to be a register. The macro STARTSTACKSTR initializes things. Then - * the user uses the macro STPUTC to add characters to the string. In - * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is - * grown as necessary. When the user is done, she can just leave the - * string there and refer to it using stackblock(). Or she can allocate - * the space for it using grabstackstr(). If it is necessary to allow - * someone else to use the stack temporarily and then continue to grow - * the string, the user should use grabstack to allocate the space, and - * then call ungrabstr(p) to return to the previous mode of operation. - * - * USTPUTC is like STPUTC except that it doesn't check for overflow. - * CHECKSTACKSPACE can be called before USTPUTC to ensure that there - * is space for at least one character. - */ - -static char * -growstrstackblock(int n, int min) -{ - growstackblock(min); - return stackblock() + n; -} - -char * -growstackstr(void) -{ - int len; - - len = stackblocksize(); - return (growstrstackblock(len, 0)); -} - - -/* - * Called from CHECKSTRSPACE. - */ - -char * -makestrspace(int min, char *p) -{ - int len; - - len = p - stackblock(); - return (growstrstackblock(len, min)); -} - - -char * -stputbin(const char *data, size_t len, char *p) -{ - CHECKSTRSPACE(len, p); - memcpy(p, data, len); - return (p + len); -} - -char * -stputs(const char *data, char *p) -{ - return (stputbin(data, strlen(data), p)); -} diff --git a/bin/catsh/memalloc.h b/bin/catsh/memalloc.h deleted file mode 100644 index 216275d8..00000000 --- a/bin/catsh/memalloc.h +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)memalloc.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/memalloc.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -#include <string.h> - -struct stackmark { - struct stack_block *stackp; - char *stacknxt; - int stacknleft; -}; - - -extern char *stacknxt; -extern int stacknleft; -extern char *sstrend; - -pointer ckmalloc(size_t); -pointer ckrealloc(pointer, int); -void ckfree(pointer); -char *savestr(const char *); -pointer stalloc(int); -void stunalloc(pointer); -char *stsavestr(const char *); -void setstackmark(struct stackmark *); -void popstackmark(struct stackmark *); -char *growstackstr(void); -char *makestrspace(int, char *); -char *stputbin(const char *data, size_t len, char *p); -char *stputs(const char *data, char *p); - - - -#define stackblock() stacknxt -#define stackblocksize() stacknleft -#define grabstackblock(n) stalloc(n) -#define STARTSTACKSTR(p) p = stackblock() -#define STPUTC(c, p) do { if (p == sstrend) p = growstackstr(); *p++ = (c); } while(0) -#define CHECKSTRSPACE(n, p) { if ((size_t)(sstrend - p) < n) p = makestrspace(n, p); } -#define USTPUTC(c, p) (*p++ = (c)) -/* - * STACKSTRNUL's use is where we want to be able to turn a stack - * (non-sentinel, character counting string) into a C string, - * and later pretend the NUL is not there. - * Note: Because of STACKSTRNUL's semantics, STACKSTRNUL cannot be used - * on a stack that will grabstackstr()ed. - */ -#define STACKSTRNUL(p) (p == sstrend ? (p = growstackstr(), *p = '\0') : (*p = '\0')) -#define STUNPUTC(p) (--p) -#define STTOPC(p) p[-1] -#define STADJUST(amount, p) (p += (amount)) -#define grabstackstr(p) stalloc((char *)p - stackblock()) -#define ungrabstackstr(s, p) stunalloc((s)) -#define STPUTBIN(s, len, p) p = stputbin((s), (len), p) -#define STPUTS(s, p) p = stputs((s), p) diff --git a/bin/catsh/miscbltin.c b/bin/catsh/miscbltin.c deleted file mode 100644 index 7f0c42e7..00000000 --- a/bin/catsh/miscbltin.c +++ /dev/null @@ -1,534 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/miscbltin.c 326025 2017-11-20 19:49:47Z pfg $"); - -/* - * Miscellaneous builtins. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include "shell.h" -#include "options.h" -#include "var.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "syntax.h" -#include "trap.h" - -#undef eflag - -int readcmd(int, char **); -int umaskcmd(int, char **); -int ulimitcmd(int, char **); - -/* - * The read builtin. The -r option causes backslashes to be treated like - * ordinary characters. - * - * This uses unbuffered input, which may be avoidable in some cases. - * - * Note that if IFS=' :' then read x y should work so that: - * 'a b' x='a', y='b' - * ' a b ' x='a', y='b' - * ':b' x='', y='b' - * ':' x='', y='' - * '::' x='', y='' - * ': :' x='', y='' - * ':::' x='', y='::' - * ':b c:' x='', y='b c:' - */ - -int -readcmd(int argc __unused, char **argv __unused) -{ - char **ap; - int backslash; - char c; - int rflag; - char *prompt; - const char *ifs; - char *p; - int startword; - int status; - int i; - int is_ifs; - int saveall = 0; - ptrdiff_t lastnonifs, lastnonifsws; - struct timeval tv; - char *tvptr; - fd_set ifds; - ssize_t nread; - int sig; - - rflag = 0; - prompt = NULL; - tv.tv_sec = -1; - tv.tv_usec = 0; - while ((i = nextopt("erp:t:")) != '\0') { - switch(i) { - case 'p': - prompt = shoptarg; - break; - case 'e': - break; - case 'r': - rflag = 1; - break; - case 't': - tv.tv_sec = strtol(shoptarg, &tvptr, 0); - if (tvptr == shoptarg) - error("timeout value"); - switch(*tvptr) { - case 0: - case 's': - break; - case 'h': - tv.tv_sec *= 60; - /* FALLTHROUGH */ - case 'm': - tv.tv_sec *= 60; - break; - default: - error("timeout unit"); - } - break; - } - } - if (prompt && isatty(0)) { - out2str(prompt); - flushall(); - } - if (*(ap = argptr) == NULL) - error("arg count"); - if ((ifs = bltinlookup("IFS", 1)) == NULL) - ifs = " \t\n"; - - if (tv.tv_sec >= 0) { - /* - * Wait for something to become available. - */ - FD_ZERO(&ifds); - FD_SET(0, &ifds); - status = select(1, &ifds, NULL, NULL, &tv); - /* - * If there's nothing ready, return an error. - */ - if (status <= 0) { - sig = pendingsig; - return (128 + (sig != 0 ? sig : SIGALRM)); - } - } - - status = 0; - startword = 2; - backslash = 0; - STARTSTACKSTR(p); - lastnonifs = lastnonifsws = -1; - for (;;) { - nread = read(STDIN_FILENO, &c, 1); - if (nread == -1) { - if (errno == EINTR) { - sig = pendingsig; - if (sig == 0) - continue; - status = 128 + sig; - break; - } - warning("read error: %s", strerror(errno)); - status = 2; - break; - } else if (nread != 1) { - status = 1; - break; - } - if (c == '\0') - continue; - CHECKSTRSPACE(1, p); - if (backslash) { - backslash = 0; - if (c != '\n') { - startword = 0; - lastnonifs = lastnonifsws = p - stackblock(); - USTPUTC(c, p); - } - continue; - } - if (!rflag && c == '\\') { - backslash++; - continue; - } - if (c == '\n') - break; - if (strchr(ifs, c)) - is_ifs = strchr(" \t\n", c) ? 1 : 2; - else - is_ifs = 0; - - if (startword != 0) { - if (is_ifs == 1) { - /* Ignore leading IFS whitespace */ - if (saveall) - USTPUTC(c, p); - continue; - } - if (is_ifs == 2 && startword == 1) { - /* Only one non-whitespace IFS per word */ - startword = 2; - if (saveall) { - lastnonifsws = p - stackblock(); - USTPUTC(c, p); - } - continue; - } - } - - if (is_ifs == 0) { - /* append this character to the current variable */ - startword = 0; - if (saveall) - /* Not just a spare terminator */ - saveall++; - lastnonifs = lastnonifsws = p - stackblock(); - USTPUTC(c, p); - continue; - } - - /* end of variable... */ - startword = is_ifs; - - if (ap[1] == NULL) { - /* Last variable needs all IFS chars */ - saveall++; - if (is_ifs == 2) - lastnonifsws = p - stackblock(); - USTPUTC(c, p); - continue; - } - - STACKSTRNUL(p); - setvar(*ap, stackblock(), 0); - ap++; - STARTSTACKSTR(p); - lastnonifs = lastnonifsws = -1; - } - STACKSTRNUL(p); - - /* - * Remove trailing IFS chars: always remove whitespace, don't remove - * non-whitespace unless it was naked - */ - if (saveall <= 1) - lastnonifsws = lastnonifs; - stackblock()[lastnonifsws + 1] = '\0'; - setvar(*ap, stackblock(), 0); - - /* Set any remaining args to "" */ - while (*++ap != NULL) - setvar(*ap, "", 0); - return status; -} - - - -int -umaskcmd(int argc __unused, char **argv __unused) -{ - char *ap; - int mask; - int i; - int symbolic_mode = 0; - - while ((i = nextopt("S")) != '\0') { - symbolic_mode = 1; - } - - INTOFF; - mask = umask(0); - umask(mask); - INTON; - - if ((ap = *argptr) == NULL) { - if (symbolic_mode) { - char u[4], g[4], o[4]; - - i = 0; - if ((mask & S_IRUSR) == 0) - u[i++] = 'r'; - if ((mask & S_IWUSR) == 0) - u[i++] = 'w'; - if ((mask & S_IXUSR) == 0) - u[i++] = 'x'; - u[i] = '\0'; - - i = 0; - if ((mask & S_IRGRP) == 0) - g[i++] = 'r'; - if ((mask & S_IWGRP) == 0) - g[i++] = 'w'; - if ((mask & S_IXGRP) == 0) - g[i++] = 'x'; - g[i] = '\0'; - - i = 0; - if ((mask & S_IROTH) == 0) - o[i++] = 'r'; - if ((mask & S_IWOTH) == 0) - o[i++] = 'w'; - if ((mask & S_IXOTH) == 0) - o[i++] = 'x'; - o[i] = '\0'; - - out1fmt("u=%s,g=%s,o=%s\n", u, g, o); - } else { - out1fmt("%.4o\n", mask); - } - } else { - if (is_digit(*ap)) { - mask = 0; - do { - if (*ap >= '8' || *ap < '0') - error("Illegal number: %s", *argptr); - mask = (mask << 3) + (*ap - '0'); - } while (*++ap != '\0'); - umask(mask); - } else { - void *set; - INTOFF; - if ((set = setmode (ap)) == NULL) - error("Illegal number: %s", ap); - - mask = getmode (set, ~mask & 0777); - umask(~mask & 0777); - free(set); - INTON; - } - } - return 0; -} - -/* - * ulimit builtin - * - * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and - * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with - * ash by J.T. Conklin. - * - * Public domain. - */ - -struct limits { - const char *name; - const char *units; - int cmd; - short factor; /* multiply by to get rlim_{cur,max} values */ - char option; -}; - -static const struct limits limits[] = { -#ifdef RLIMIT_CPU - { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, -#endif -#ifdef RLIMIT_FSIZE - { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, -#endif -#ifdef RLIMIT_DATA - { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, -#endif -#ifdef RLIMIT_STACK - { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, -#endif -#ifdef RLIMIT_CORE - { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, -#endif -#ifdef RLIMIT_RSS - { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, -#endif -#ifdef RLIMIT_MEMLOCK - { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, -#endif -#ifdef RLIMIT_NPROC - { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, -#endif -#ifdef RLIMIT_NOFILE - { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, -#endif -#ifdef RLIMIT_VMEM - { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, -#endif -#ifdef RLIMIT_SWAP - { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, -#endif -#ifdef RLIMIT_SBSIZE - { "socket buffer size", "bytes", RLIMIT_SBSIZE, 1, 'b' }, -#endif -#ifdef RLIMIT_NPTS - { "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' }, -#endif -#ifdef RLIMIT_KQUEUES - { "kqueues", (char *)0, RLIMIT_KQUEUES, 1, 'k' }, -#endif -#ifdef RLIMIT_UMTXP - { "umtx shared locks", (char *)0, RLIMIT_UMTXP, 1, 'o' }, -#endif - { (char *) 0, (char *)0, 0, 0, '\0' } -}; - -enum limithow { SOFT = 0x1, HARD = 0x2 }; - -static void -printlimit(enum limithow how, const struct rlimit *limit, - const struct limits *l) -{ - rlim_t val = 0; - - if (how & SOFT) - val = limit->rlim_cur; - else if (how & HARD) - val = limit->rlim_max; - if (val == RLIM_INFINITY) - out1str("unlimited\n"); - else - { - val /= l->factor; - out1fmt("%jd\n", (intmax_t)val); - } -} - -int -ulimitcmd(int argc __unused, char **argv __unused) -{ - rlim_t val = 0; - enum limithow how = SOFT | HARD; - const struct limits *l; - int set, all = 0; - int optc, what; - struct rlimit limit; - - what = 'f'; - while ((optc = nextopt("HSatfdsmcnuvlbpwko")) != '\0') - switch (optc) { - case 'H': - how = HARD; - break; - case 'S': - how = SOFT; - break; - case 'a': - all = 1; - break; - default: - what = optc; - } - - for (l = limits; l->name && l->option != what; l++) - ; - if (!l->name) - error("internal error (%c)", what); - - set = *argptr ? 1 : 0; - if (set) { - char *p = *argptr; - - if (all || argptr[1]) - error("too many arguments"); - if (strcmp(p, "unlimited") == 0) - val = RLIM_INFINITY; - else { - char *end; - uintmax_t uval; - - if (*p < '0' || *p > '9') - error("bad number"); - errno = 0; - uval = strtoumax(p, &end, 10); - if (errno != 0 || *end != '\0') - error("bad number"); - if (uval > UINTMAX_MAX / l->factor) - error("bad number"); - uval *= l->factor; - val = (rlim_t)uval; - if (val < 0 || (uintmax_t)val != uval || - val == RLIM_INFINITY) - error("bad number"); - } - } - if (all) { - for (l = limits; l->name; l++) { - char optbuf[40]; - if (getrlimit(l->cmd, &limit) < 0) - error("can't get limit: %s", strerror(errno)); - - if (l->units) - snprintf(optbuf, sizeof(optbuf), - "(%s, -%c) ", l->units, l->option); - else - snprintf(optbuf, sizeof(optbuf), - "(-%c) ", l->option); - out1fmt("%-18s %18s ", l->name, optbuf); - printlimit(how, &limit, l); - } - return 0; - } - - if (getrlimit(l->cmd, &limit) < 0) - error("can't get limit: %s", strerror(errno)); - if (set) { - if (how & SOFT) - limit.rlim_cur = val; - if (how & HARD) - limit.rlim_max = val; - if (setrlimit(l->cmd, &limit) < 0) - error("bad limit: %s", strerror(errno)); - } else - printlimit(how, &limit, l); - return 0; -} diff --git a/bin/catsh/mkbuiltins b/bin/catsh/mkbuiltins deleted file mode 100755 index 32c09ec0..00000000 --- a/bin/catsh/mkbuiltins +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh - - -#- -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95 -# $FreeBSD: releng/12.0/bin/sh/mkbuiltins 328934 2018-02-06 15:41:35Z arichardson $ - -temp=`mktemp -t ka` -havehist=1 -if [ "X$1" = "X-h" ]; then - havehist=0 - shift -fi -srcdir=$1 -havejobs=0 -if grep '^#define[ ]*JOBS[ ]*1' $srcdir/shell.h > /dev/null -then havejobs=1 -fi -exec > builtins.c -cat <<\! -/* - * This file was generated by the mkbuiltins program. - */ - -#include <stdlib.h> -#include "shell.h" -#include "builtins.h" - -! -awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \ - print $0}' $srcdir/builtins.def | sed 's/-[hj]//' > $temp -echo 'int (*const builtinfunc[])(int, char **) = {' -awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp -echo '}; - -const unsigned char builtincmd[] = {' -awk '{ for (i = 2 ; i <= NF ; i++) { - if ($i == "-s") { - spc = 1; - } else if ($i == "-n") { - # Handled later for builtins.h - continue - } else { - printf "\t\"\\%03o\\%03o%s\"\n", length($i), (spc ? 128 : 0) + NR-1, $i - spc = 0; - } - }}' $temp -echo '};' - -exec > builtins.h -cat <<\! -/* - * This file was generated by the mkbuiltins program. - */ - -#include <sys/cdefs.h> -! -tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp | - awk '{ printf "#define %s %d\n", $1, NR-1}' -echo ' -#define BUILTIN_SPECIAL 0x80 - -extern int (*const builtinfunc[])(int, char **); -extern const unsigned char builtincmd[]; -' -awk '{ printf "int %s(int, char **);\n", $1}' $temp - -# Build safe_builtin_always() -cat <<EOF - -static inline int -safe_builtin_always(int idx) -{ -EOF -awk ' -BEGIN { printed = 0 } -{ - for (i = 2 ; i <= NF ; i++) { - if ($i == "-s") { - continue - } else if ($i == "-n") { - nofork = 1; - } else { - if (nofork == 0) { - continue - } - if (printed == 1) { - printf " || \n\t " - } else { - printf "\tif (" - } - printf "idx == " toupper($1) - printed = 1 - nofork = 0; - # Only need to check each once - break - } - } -}' $temp - -cat << EOF -) - return (1); - return(0); -} -EOF - -rm -f $temp diff --git a/bin/catsh/mknodes.c b/bin/catsh/mknodes.c deleted file mode 100644 index cdc615fc..00000000 --- a/bin/catsh/mknodes.c +++ /dev/null @@ -1,461 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if 0 -#ifndef lint -static char const copyright[] = -"@(#) Copyright (c) 1991, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95"; -#endif /* not lint */ -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/mknodes.c 326025 2017-11-20 19:49:47Z pfg $"); - -/* - * This program reads the nodetypes file and nodes.c.pat file. It generates - * the files nodes.h and nodes.c. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <stdarg.h> - -#define MAXTYPES 50 /* max number of node types */ -#define MAXFIELDS 20 /* max fields in a structure */ -#define BUFLEN 100 /* size of character buffers */ - -/* field types */ -#define T_NODE 1 /* union node *field */ -#define T_NODELIST 2 /* struct nodelist *field */ -#define T_STRING 3 -#define T_INT 4 /* int field */ -#define T_OTHER 5 /* other */ -#define T_TEMP 6 /* don't copy this field */ - - -struct field { /* a structure field */ - char *name; /* name of field */ - int type; /* type of field */ - char *decl; /* declaration of field */ -}; - - -struct str { /* struct representing a node structure */ - char *tag; /* structure tag */ - int nfields; /* number of fields in the structure */ - struct field field[MAXFIELDS]; /* the fields of the structure */ - int done; /* set if fully parsed */ -}; - - -static int ntypes; /* number of node types */ -static char *nodename[MAXTYPES]; /* names of the nodes */ -static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */ -static int nstr; /* number of structures */ -static struct str str[MAXTYPES]; /* the structures */ -static struct str *curstr; /* current structure */ -static char line[1024]; -static int linno; -static char *linep; - -static void parsenode(void); -static void parsefield(void); -static void output(char *); -static void outsizes(FILE *); -static void outfunc(FILE *, int); -static void indent(int, FILE *); -static int nextfield(char *); -static void skipbl(void); -static int readline(FILE *); -static void error(const char *, ...) __printf0like(1, 2) __dead2; -static char *savestr(const char *); - - -int -main(int argc, char *argv[]) -{ - FILE *infp; - - if (argc != 3) - error("usage: mknodes file"); - if ((infp = fopen(argv[1], "r")) == NULL) - error("Can't open %s: %s", argv[1], strerror(errno)); - while (readline(infp)) { - if (line[0] == ' ' || line[0] == '\t') - parsefield(); - else if (line[0] != '\0') - parsenode(); - } - fclose(infp); - output(argv[2]); - exit(0); -} - - - -static void -parsenode(void) -{ - char name[BUFLEN]; - char tag[BUFLEN]; - struct str *sp; - - if (curstr && curstr->nfields > 0) - curstr->done = 1; - nextfield(name); - if (! nextfield(tag)) - error("Tag expected"); - if (*linep != '\0') - error("Garbage at end of line"); - nodename[ntypes] = savestr(name); - for (sp = str ; sp < str + nstr ; sp++) { - if (strcmp(sp->tag, tag) == 0) - break; - } - if (sp >= str + nstr) { - sp->tag = savestr(tag); - sp->nfields = 0; - curstr = sp; - nstr++; - } - nodestr[ntypes] = sp; - ntypes++; -} - - -static void -parsefield(void) -{ - char name[BUFLEN]; - char type[BUFLEN]; - char decl[2 * BUFLEN]; - struct field *fp; - - if (curstr == NULL || curstr->done) - error("No current structure to add field to"); - if (! nextfield(name)) - error("No field name"); - if (! nextfield(type)) - error("No field type"); - fp = &curstr->field[curstr->nfields]; - fp->name = savestr(name); - if (strcmp(type, "nodeptr") == 0) { - fp->type = T_NODE; - sprintf(decl, "union node *%s", name); - } else if (strcmp(type, "nodelist") == 0) { - fp->type = T_NODELIST; - sprintf(decl, "struct nodelist *%s", name); - } else if (strcmp(type, "string") == 0) { - fp->type = T_STRING; - sprintf(decl, "char *%s", name); - } else if (strcmp(type, "int") == 0) { - fp->type = T_INT; - sprintf(decl, "int %s", name); - } else if (strcmp(type, "other") == 0) { - fp->type = T_OTHER; - } else if (strcmp(type, "temp") == 0) { - fp->type = T_TEMP; - } else { - error("Unknown type %s", type); - } - if (fp->type == T_OTHER || fp->type == T_TEMP) { - skipbl(); - fp->decl = savestr(linep); - } else { - if (*linep) - error("Garbage at end of line"); - fp->decl = savestr(decl); - } - curstr->nfields++; -} - - -static const char writer[] = "\ -/*\n\ - * This file was generated by the mknodes program.\n\ - */\n\ -\n"; - -static void -output(char *file) -{ - FILE *hfile; - FILE *cfile; - FILE *patfile; - int i; - struct str *sp; - struct field *fp; - char *p; - - if ((patfile = fopen(file, "r")) == NULL) - error("Can't open %s: %s", file, strerror(errno)); - if ((hfile = fopen("nodes.h", "w")) == NULL) - error("Can't create nodes.h: %s", strerror(errno)); - if ((cfile = fopen("nodes.c", "w")) == NULL) - error("Can't create nodes.c"); - fputs(writer, hfile); - for (i = 0 ; i < ntypes ; i++) - fprintf(hfile, "#define %s %d\n", nodename[i], i); - fputs("\n\n\n", hfile); - for (sp = str ; sp < &str[nstr] ; sp++) { - fprintf(hfile, "struct %s {\n", sp->tag); - for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) { - fprintf(hfile, " %s;\n", fp->decl); - } - fputs("};\n\n\n", hfile); - } - fputs("union node {\n", hfile); - fprintf(hfile, " int type;\n"); - for (sp = str ; sp < &str[nstr] ; sp++) { - fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag); - } - fputs("};\n\n\n", hfile); - fputs("struct nodelist {\n", hfile); - fputs("\tstruct nodelist *next;\n", hfile); - fputs("\tunion node *n;\n", hfile); - fputs("};\n\n\n", hfile); - fputs("struct funcdef;\n", hfile); - fputs("struct funcdef *copyfunc(union node *);\n", hfile); - fputs("union node *getfuncnode(struct funcdef *);\n", hfile); - fputs("void reffunc(struct funcdef *);\n", hfile); - fputs("void unreffunc(struct funcdef *);\n", hfile); - if (ferror(hfile)) - error("Can't write to nodes.h"); - if (fclose(hfile)) - error("Can't close nodes.h"); - - fputs(writer, cfile); - while (fgets(line, sizeof line, patfile) != NULL) { - for (p = line ; *p == ' ' || *p == '\t' ; p++); - if (strcmp(p, "%SIZES\n") == 0) - outsizes(cfile); - else if (strcmp(p, "%CALCSIZE\n") == 0) - outfunc(cfile, 1); - else if (strcmp(p, "%COPY\n") == 0) - outfunc(cfile, 0); - else - fputs(line, cfile); - } - fclose(patfile); - if (ferror(cfile)) - error("Can't write to nodes.c"); - if (fclose(cfile)) - error("Can't close nodes.c"); -} - - - -static void -outsizes(FILE *cfile) -{ - int i; - - fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes); - for (i = 0 ; i < ntypes ; i++) { - fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag); - } - fprintf(cfile, "};\n"); -} - - -static void -outfunc(FILE *cfile, int calcsize) -{ - struct str *sp; - struct field *fp; - int i; - - fputs(" if (n == NULL)\n", cfile); - if (calcsize) - fputs(" return;\n", cfile); - else - fputs(" return NULL;\n", cfile); - if (calcsize) - fputs(" result->blocksize += nodesize[n->type];\n", cfile); - else { - fputs(" new = state->block;\n", cfile); - fputs(" state->block = (char *)state->block + nodesize[n->type];\n", cfile); - } - fputs(" switch (n->type) {\n", cfile); - for (sp = str ; sp < &str[nstr] ; sp++) { - for (i = 0 ; i < ntypes ; i++) { - if (nodestr[i] == sp) - fprintf(cfile, " case %s:\n", nodename[i]); - } - for (i = sp->nfields ; --i >= 1 ; ) { - fp = &sp->field[i]; - switch (fp->type) { - case T_NODE: - if (calcsize) { - indent(12, cfile); - fprintf(cfile, "calcsize(n->%s.%s, result);\n", - sp->tag, fp->name); - } else { - indent(12, cfile); - fprintf(cfile, "new->%s.%s = copynode(n->%s.%s, state);\n", - sp->tag, fp->name, sp->tag, fp->name); - } - break; - case T_NODELIST: - if (calcsize) { - indent(12, cfile); - fprintf(cfile, "sizenodelist(n->%s.%s, result);\n", - sp->tag, fp->name); - } else { - indent(12, cfile); - fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s, state);\n", - sp->tag, fp->name, sp->tag, fp->name); - } - break; - case T_STRING: - if (calcsize) { - indent(12, cfile); - fprintf(cfile, "result->stringsize += strlen(n->%s.%s) + 1;\n", - sp->tag, fp->name); - } else { - indent(12, cfile); - fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s, state);\n", - sp->tag, fp->name, sp->tag, fp->name); - } - break; - case T_INT: - case T_OTHER: - if (! calcsize) { - indent(12, cfile); - fprintf(cfile, "new->%s.%s = n->%s.%s;\n", - sp->tag, fp->name, sp->tag, fp->name); - } - break; - } - } - indent(12, cfile); - fputs("break;\n", cfile); - } - fputs(" };\n", cfile); - if (! calcsize) - fputs(" new->type = n->type;\n", cfile); -} - - -static void -indent(int amount, FILE *fp) -{ - while (amount >= 8) { - putc('\t', fp); - amount -= 8; - } - while (--amount >= 0) { - putc(' ', fp); - } -} - - -static int -nextfield(char *buf) -{ - char *p, *q; - - p = linep; - while (*p == ' ' || *p == '\t') - p++; - q = buf; - while (*p != ' ' && *p != '\t' && *p != '\0') - *q++ = *p++; - *q = '\0'; - linep = p; - return (q > buf); -} - - -static void -skipbl(void) -{ - while (*linep == ' ' || *linep == '\t') - linep++; -} - - -static int -readline(FILE *infp) -{ - char *p; - - if (fgets(line, 1024, infp) == NULL) - return 0; - for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++); - while (p > line && (p[-1] == ' ' || p[-1] == '\t')) - p--; - *p = '\0'; - linep = line; - linno++; - if (p - line > BUFLEN) - error("Line too long"); - return 1; -} - - - -static void -error(const char *msg, ...) -{ - va_list va; - va_start(va, msg); - - (void) fprintf(stderr, "line %d: ", linno); - (void) vfprintf(stderr, msg, va); - (void) fputc('\n', stderr); - - va_end(va); - - exit(2); -} - - - -static char * -savestr(const char *s) -{ - char *p; - - if ((p = malloc(strlen(s) + 1)) == NULL) - error("Out of space"); - (void) strcpy(p, s); - return p; -} diff --git a/bin/catsh/mksyntax.c b/bin/catsh/mksyntax.c deleted file mode 100644 index a023da60..00000000 --- a/bin/catsh/mksyntax.c +++ /dev/null @@ -1,332 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if 0 -#ifndef lint -static char const copyright[] = -"@(#) Copyright (c) 1991, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95"; -#endif /* not lint */ -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/mksyntax.c 334008 2018-05-21 21:52:48Z jilles $"); - -/* - * This program creates syntax.h and syntax.c. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "parser.h" - - -struct synclass { - const char *name; - const char *comment; -}; - -/* Syntax classes */ -static const struct synclass synclass[] = { - { "CWORD", "character is nothing special" }, - { "CNL", "newline character" }, - { "CQNL", "newline character in quotes" }, - { "CBACK", "a backslash character" }, - { "CSBACK", "a backslash character in single quotes" }, - { "CSQUOTE", "single quote" }, - { "CDQUOTE", "double quote" }, - { "CENDQUOTE", "a terminating quote" }, - { "CBQUOTE", "backwards single quote" }, - { "CVAR", "a dollar sign" }, - { "CENDVAR", "a '}' character" }, - { "CLP", "a left paren in arithmetic" }, - { "CRP", "a right paren in arithmetic" }, - { "CEOF", "end of file" }, - { "CCTL", "like CWORD, except it must be escaped" }, - { "CSPCL", "these terminate a word" }, - { "CIGN", "character should be ignored" }, - { NULL, NULL } -}; - - -/* - * Syntax classes for is_ functions. Warning: if you add new classes - * you may have to change the definition of the is_in_name macro. - */ -static const struct synclass is_entry[] = { - { "ISDIGIT", "a digit" }, - { "ISUPPER", "an upper case letter" }, - { "ISLOWER", "a lower case letter" }, - { "ISUNDER", "an underscore" }, - { "ISSPECL", "the name of a special parameter" }, - { NULL, NULL } -}; - -static const char writer[] = "\ -/*\n\ - * This file was generated by the mksyntax program.\n\ - */\n\ -\n"; - - -static FILE *cfile; -static FILE *hfile; - -static void add_default(void); -static void finish(void); -static void init(const char *); -static void add(const char *, const char *); -static void output_type_macros(void); - -int -main(int argc __unused, char **argv __unused) -{ - int i; - char buf[80]; - int pos; - - /* Create output files */ - if ((cfile = fopen("syntax.c", "w")) == NULL) { - perror("syntax.c"); - exit(2); - } - if ((hfile = fopen("syntax.h", "w")) == NULL) { - perror("syntax.h"); - exit(2); - } - fputs(writer, hfile); - fputs(writer, cfile); - - fputs("#include <sys/cdefs.h>\n", hfile); - fputs("#include <limits.h>\n\n", hfile); - - /* Generate the #define statements in the header file */ - fputs("/* Syntax classes */\n", hfile); - for (i = 0 ; synclass[i].name ; i++) { - sprintf(buf, "#define %s %d", synclass[i].name, i); - fputs(buf, hfile); - for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) - putc('\t', hfile); - fprintf(hfile, "/* %s */\n", synclass[i].comment); - } - putc('\n', hfile); - fputs("/* Syntax classes for is_ functions */\n", hfile); - for (i = 0 ; is_entry[i].name ; i++) { - sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); - fputs(buf, hfile); - for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) - putc('\t', hfile); - fprintf(hfile, "/* %s */\n", is_entry[i].comment); - } - putc('\n', hfile); - fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile); - fputs("#define PEOF -SYNBASE\n\n", hfile); - putc('\n', hfile); - fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); - fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); - fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); - fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); - putc('\n', hfile); - output_type_macros(); /* is_digit, etc. */ - putc('\n', hfile); - - /* Generate the syntax tables. */ - fputs("#include \"parser.h\"\n", cfile); - fputs("#include \"shell.h\"\n", cfile); - fputs("#include \"syntax.h\"\n\n", cfile); - - fputs("/* syntax table used when not in quotes */\n", cfile); - init("basesyntax"); - add_default(); - add("\n", "CNL"); - add("\\", "CBACK"); - add("'", "CSQUOTE"); - add("\"", "CDQUOTE"); - add("`", "CBQUOTE"); - add("$", "CVAR"); - add("}", "CENDVAR"); - add("<>();&| \t", "CSPCL"); - finish(); - - fputs("\n/* syntax table used when in double quotes */\n", cfile); - init("dqsyntax"); - add_default(); - add("\n", "CQNL"); - add("\\", "CBACK"); - add("\"", "CENDQUOTE"); - add("`", "CBQUOTE"); - add("$", "CVAR"); - add("}", "CENDVAR"); - /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */ - add("!*?[]=~:/-^", "CCTL"); - finish(); - - fputs("\n/* syntax table used when in single quotes */\n", cfile); - init("sqsyntax"); - add_default(); - add("\n", "CQNL"); - add("\\", "CSBACK"); - add("'", "CENDQUOTE"); - /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */ - add("!*?[]=~:/-^", "CCTL"); - finish(); - - fputs("\n/* syntax table used when in arithmetic */\n", cfile); - init("arisyntax"); - add_default(); - add("\n", "CQNL"); - add("\\", "CBACK"); - add("`", "CBQUOTE"); - add("\"", "CIGN"); - add("$", "CVAR"); - add("}", "CENDVAR"); - add("(", "CLP"); - add(")", "CRP"); - finish(); - - fputs("\n/* character classification table */\n", cfile); - init("is_type"); - add("0123456789", "ISDIGIT"); - add("abcdefghijklmnopqrstuvwxyz", "ISLOWER"); - add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER"); - add("_", "ISUNDER"); - add("#?$!-*@", "ISSPECL"); - finish(); - - exit(0); -} - - -/* - * Output the header and declaration of a syntax table. - */ - -static void -init(const char *name) -{ - fprintf(hfile, "extern const char %s[];\n", name); - fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name); -} - - -static void -add_one(const char *key, const char *type) -{ - fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type); -} - - -/* - * Add default values to the syntax table. - */ - -static void -add_default(void) -{ - add_one("PEOF", "CEOF"); - add_one("CTLESC", "CCTL"); - add_one("CTLVAR", "CCTL"); - add_one("CTLENDVAR", "CCTL"); - add_one("CTLBACKQ", "CCTL"); - add_one("CTLBACKQ + CTLQUOTE", "CCTL"); - add_one("CTLARI", "CCTL"); - add_one("CTLENDARI", "CCTL"); - add_one("CTLQUOTEMARK", "CCTL"); - add_one("CTLQUOTEEND", "CCTL"); -} - - -/* - * Output the footer of a syntax table. - */ - -static void -finish(void) -{ - fputs("};\n", cfile); -} - - -/* - * Add entries to the syntax table. - */ - -static void -add(const char *p, const char *type) -{ - for (; *p; ++p) { - char c = *p; - switch (c) { - case '\t': c = 't'; break; - case '\n': c = 'n'; break; - case '\'': c = '\''; break; - case '\\': c = '\\'; break; - - default: - fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type); - continue; - } - fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type); - } -} - - -/* - * Output character classification macros (e.g. is_digit). If digits are - * contiguous, we can test for them quickly. - */ - -static const char *macro[] = { - "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)", - "#define is_eof(c)\t((c) == PEOF)", - "#define is_alpha(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER))", - "#define is_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER))", - "#define is_in_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))", - "#define is_special(c)\t((is_type+SYNBASE)[(int)c] & (ISSPECL|ISDIGIT))", - "#define digit_val(c)\t((c) - '0')", - NULL -}; - -static void -output_type_macros(void) -{ - const char **pp; - - for (pp = macro ; *pp ; pp++) - fprintf(hfile, "%s\n", *pp); -} diff --git a/bin/catsh/mktokens b/bin/catsh/mktokens deleted file mode 100644 index da6ae962..00000000 --- a/bin/catsh/mktokens +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh - - -#- -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)mktokens 8.1 (Berkeley) 5/31/93 -# $FreeBSD: releng/12.0/bin/sh/mktokens 328934 2018-02-06 15:41:35Z arichardson $ - -# The following is a list of tokens. The second column is nonzero if the -# token marks the end of a list. The third column is the name to print in -# error messages. - -temp=`mktemp -t ka` -cat > $temp <<\! -TEOF 1 end of file -TNL 0 newline -TSEMI 0 ";" -TBACKGND 0 "&" -TAND 0 "&&" -TOR 0 "||" -TPIPE 0 "|" -TLP 0 "(" -TRP 1 ")" -TENDCASE 1 ";;" -TFALLTHRU 1 ";&" -TREDIR 0 redirection -TWORD 0 word -TIF 0 "if" -TTHEN 1 "then" -TELSE 1 "else" -TELIF 1 "elif" -TFI 1 "fi" -TWHILE 0 "while" -TUNTIL 0 "until" -TFOR 0 "for" -TDO 1 "do" -TDONE 1 "done" -TBEGIN 0 "{" -TEND 1 "}" -TCASE 0 "case" -TESAC 1 "esac" -TNOT 0 "!" -! -nl=`wc -l $temp` -exec > token.h -awk '{print "#define " $1 " " NR-1}' $temp -echo ' -/* Array indicating which tokens mark the end of a list */ -static const char tokendlist[] = {' -awk '{print "\t" $2 ","}' $temp -echo '}; - -static const char *const tokname[] = {' -sed -e 's/"/\\"/g' \ - -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \ - $temp -echo '}; -' -sed 's/"//g' $temp | awk ' -/TIF/{print "#define KWDOFFSET " NR-1; print ""; print "const char *const parsekwd[] = {"} -/TIF/,/neverfound/{print " \"" $3 "\","}' -echo ' 0 -};' - -rm $temp diff --git a/bin/catsh/myhistedit.h b/bin/catsh/myhistedit.h deleted file mode 100644 index 6eebe521..00000000 --- a/bin/catsh/myhistedit.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)myhistedit.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/myhistedit.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -#include <histedit.h> - -extern History *hist; -extern EditLine *el; -extern int displayhist; - -void histedit(void); -void sethistfile(const char *); -void sethistsize(const char *); -void setpslit(const char *); -void setterm(const char *); - diff --git a/bin/catsh/mystring.c b/bin/catsh/mystring.c deleted file mode 100644 index a96d4fa5..00000000 --- a/bin/catsh/mystring.c +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/mystring.c 326025 2017-11-20 19:49:47Z pfg $"); - -/* - * String functions. - * - * equal(s1, s2) Return true if strings are equal. - * number(s) Convert a string of digits to an integer. - * is_number(s) Return true if s is a string of digits. - */ - -#include <stdlib.h> -#include "shell.h" -#include "syntax.h" -#include "error.h" -#include "mystring.h" - - -char nullstr[1]; /* zero length string */ - -/* - * equal - #defined in mystring.h - */ - - -/* - * Convert a string of digits to an integer, printing an error message on - * failure. - */ - -int -number(const char *s) -{ - if (! is_number(s)) - error("Illegal number: %s", s); - return atoi(s); -} - - - -/* - * Check for a valid number. This should be elsewhere. - */ - -int -is_number(const char *p) -{ - const char *q; - - if (*p == '\0') - return 0; - while (*p == '0') - p++; - for (q = p; *q != '\0'; q++) - if (! is_digit(*q)) - return 0; - if (q - p > 10 || - (q - p == 10 && memcmp(p, "2147483647", 10) > 0)) - return 0; - return 1; -} diff --git a/bin/catsh/mystring.h b/bin/catsh/mystring.h deleted file mode 100644 index f4fc9af4..00000000 --- a/bin/catsh/mystring.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mystring.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/mystring.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -#include <string.h> - -int number(const char *); -int is_number(const char *); - -#define equal(s1, s2) (strcmp(s1, s2) == 0) diff --git a/bin/catsh/nodes.c.pat b/bin/catsh/nodes.c.pat deleted file mode 100644 index eeb82737..00000000 --- a/bin/catsh/nodes.c.pat +++ /dev/null @@ -1,193 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/nodes.c.pat 314436 2017-02-28 23:42:47Z imp $ - */ - -#include <sys/param.h> -#include <stdlib.h> -#include <stddef.h> -/* - * Routine for dealing with parsed shell commands. - */ - -#include "shell.h" -#include "nodes.h" -#include "memalloc.h" -#include "mystring.h" - - -struct nodesize { - int blocksize; /* size of structures in function */ - int stringsize; /* size of strings in node */ -}; - -struct nodecopystate { - pointer block; /* block to allocate function from */ - char *string; /* block to allocate strings from */ -}; - -%SIZES - - -static void calcsize(union node *, struct nodesize *); -static void sizenodelist(struct nodelist *, struct nodesize *); -static union node *copynode(union node *, struct nodecopystate *); -static struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *); -static char *nodesavestr(const char *, struct nodecopystate *); - - -struct funcdef { - unsigned int refcount; - union node n; -}; - -/* - * Make a copy of a parse tree. - */ - -struct funcdef * -copyfunc(union node *n) -{ - struct nodesize sz; - struct nodecopystate st; - struct funcdef *fn; - - if (n == NULL) - return NULL; - sz.blocksize = offsetof(struct funcdef, n); - sz.stringsize = 0; - calcsize(n, &sz); - fn = ckmalloc(sz.blocksize + sz.stringsize); - fn->refcount = 1; - st.block = (char *)fn + offsetof(struct funcdef, n); - st.string = (char *)fn + sz.blocksize; - copynode(n, &st); - return fn; -} - - -union node * -getfuncnode(struct funcdef *fn) -{ - return fn == NULL ? NULL : &fn->n; -} - - -static void -calcsize(union node *n, struct nodesize *result) -{ - %CALCSIZE -} - - - -static void -sizenodelist(struct nodelist *lp, struct nodesize *result) -{ - while (lp) { - result->blocksize += ALIGN(sizeof(struct nodelist)); - calcsize(lp->n, result); - lp = lp->next; - } -} - - - -static union node * -copynode(union node *n, struct nodecopystate *state) -{ - union node *new; - - %COPY - return new; -} - - -static struct nodelist * -copynodelist(struct nodelist *lp, struct nodecopystate *state) -{ - struct nodelist *start; - struct nodelist **lpp; - - lpp = &start; - while (lp) { - *lpp = state->block; - state->block = (char *)state->block + - ALIGN(sizeof(struct nodelist)); - (*lpp)->n = copynode(lp->n, state); - lp = lp->next; - lpp = &(*lpp)->next; - } - *lpp = NULL; - return start; -} - - - -static char * -nodesavestr(const char *s, struct nodecopystate *state) -{ - const char *p = s; - char *q = state->string; - char *rtn = state->string; - - while ((*q++ = *p++) != '\0') - continue; - state->string = q; - return rtn; -} - - -void -reffunc(struct funcdef *fn) -{ - if (fn) - fn->refcount++; -} - - -/* - * Decrement the reference count of a function definition, freeing it - * if it falls to 0. - */ - -void -unreffunc(struct funcdef *fn) -{ - if (fn) { - fn->refcount--; - if (fn->refcount > 0) - return; - ckfree(fn); - } -} diff --git a/bin/catsh/nodetypes b/bin/catsh/nodetypes deleted file mode 100644 index 0bb29c8e..00000000 --- a/bin/catsh/nodetypes +++ /dev/null @@ -1,145 +0,0 @@ -#- -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)nodetypes 8.2 (Berkeley) 5/4/95 -# $FreeBSD: releng/12.0/bin/sh/nodetypes 314436 2017-02-28 23:42:47Z imp $ - -# This file describes the nodes used in parse trees. Unindented lines -# contain a node type followed by a structure tag. Subsequent indented -# lines specify the fields of the structure. Several node types can share -# the same structure, in which case the fields of the structure should be -# specified only once. -# -# A field of a structure is described by the name of the field followed -# by a type. The currently implemented types are: -# nodeptr - a pointer to a node -# nodelist - a pointer to a list of nodes -# string - a pointer to a nul terminated string -# int - an integer -# other - any type that can be copied by assignment -# temp - a field that doesn't have to be copied when the node is copied -# The last two types should be followed by the text of a C declaration for -# the field. - -NSEMI nbinary # two commands separated by a semicolon - type int - ch1 nodeptr # the first child - ch2 nodeptr # the second child - -NCMD ncmd # a simple command - type int - args nodeptr # the arguments - redirect nodeptr # list of file redirections - -NPIPE npipe # a pipeline - type int - backgnd int # set to run pipeline in background - cmdlist nodelist # the commands in the pipeline - -NREDIR nredir # redirection (of a compex command) - type int - n nodeptr # the command - redirect nodeptr # list of file redirections - -NBACKGND nredir # run command in background -NSUBSHELL nredir # run command in a subshell - -NAND nbinary # the && operator -NOR nbinary # the || operator - -NIF nif # the if statement. Elif clauses are handled - type int # using multiple if nodes. - test nodeptr # if test - ifpart nodeptr # then ifpart - elsepart nodeptr # else elsepart - -NWHILE nbinary # the while statement. First child is the test -NUNTIL nbinary # the until statement - -NFOR nfor # the for statement - type int - args nodeptr # for var in args - body nodeptr # do body; done - var string # the for variable - -NCASE ncase # a case statement - type int - expr nodeptr # the word to switch on - cases nodeptr # the list of cases (NCLIST nodes) - -NCLIST nclist # a case ending with ;; - type int - next nodeptr # the next case in list - pattern nodeptr # list of patterns for this case - body nodeptr # code to execute for this case - -NCLISTFALLTHRU nclist # a case ending with ;& - -NDEFUN narg # define a function. The "next" field contains - # the body of the function. - -NARG narg # represents a word - type int - next nodeptr # next word in list - text string # the text of the word - backquote nodelist # list of commands in back quotes - -NTO nfile # fd> fname -NFROM nfile # fd< fname -NFROMTO nfile # fd<> fname -NAPPEND nfile # fd>> fname -NCLOBBER nfile # fd>| fname - type int - fd int # file descriptor being redirected - next nodeptr # next redirection in list - fname nodeptr # file name, in a NARG node - expfname temp char *expfname # actual file name - -NTOFD ndup # fd<&dupfd -NFROMFD ndup # fd>&dupfd - type int - fd int # file descriptor being redirected - next nodeptr # next redirection in list - dupfd int # file descriptor to duplicate - vname nodeptr # file name if fd>&$var - - -NHERE nhere # fd<<\! -NXHERE nhere # fd<<! - type int - fd int # file descriptor being redirected - next nodeptr # next redirection in list - doc nodeptr # input to command (NARG node) - expdoc temp const char *expdoc # actual document (for NXHERE) - -NNOT nnot # ! command (actually pipeline) - type int - com nodeptr diff --git a/bin/catsh/options.c b/bin/catsh/options.c deleted file mode 100644 index 422c0f19..00000000 --- a/bin/catsh/options.c +++ /dev/null @@ -1,594 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/options.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> - -#include "shell.h" -#define DEFINE_OPTIONS -#include "options.h" -#undef DEFINE_OPTIONS -#include "nodes.h" /* for other header files */ -#include "eval.h" -#include "jobs.h" -#include "input.h" -#include "output.h" -#include "trap.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "builtins.h" -#ifndef NO_HISTORY -#include "myhistedit.h" -#endif - -char *arg0; /* value of $0 */ -struct shparam shellparam; /* current positional parameters */ -char **argptr; /* argument list for builtin commands */ -char *shoptarg; /* set by nextopt (like getopt) */ -char *nextopt_optptr; /* used by nextopt */ - -char *minusc; /* argument to -c option */ - - -static void options(int); -static void minus_o(char *, int); -static void setoption(int, int); -static void setoptionbyindex(int, int); -static void setparam(int, char **); -static int getopts(char *, char *, char **, char ***, char **); - - -/* - * Process the shell command line arguments. - */ - -void -procargs(int argc, char **argv) -{ - int i; - char *scriptname; - - argptr = argv; - if (argc > 0) - argptr++; - for (i = 0; i < NOPTS; i++) - optval[i] = 2; - privileged = (getuid() != geteuid() || getgid() != getegid()); - options(1); - if (*argptr == NULL && minusc == NULL) - sflag = 1; - if (iflag != 0 && sflag == 1 && isatty(0) && isatty(1)) { - iflag = 1; - if (Eflag == 2) - Eflag = 1; - } - if (mflag == 2) - mflag = iflag; - for (i = 0; i < NOPTS; i++) - if (optval[i] == 2) - optval[i] = 0; - arg0 = argv[0]; - if (sflag == 0 && minusc == NULL) { - scriptname = *argptr++; - setinputfile(scriptname, 0); - commandname = arg0 = scriptname; - } - /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ - if (argptr && minusc && *argptr) - arg0 = *argptr++; - - shellparam.p = argptr; - shellparam.reset = 1; - /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ - while (*argptr) { - shellparam.nparam++; - argptr++; - } - optschanged(); -} - - -void -optschanged(void) -{ - setinteractive(); -#ifndef NO_HISTORY - histedit(); -#endif - setjobctl(mflag); -} - -/* - * Process shell options. The global variable argptr contains a pointer - * to the argument list; we advance it past the options. - * If cmdline is true, process the shell's argv; otherwise, process arguments - * to the set special builtin. - */ - -static void -options(int cmdline) -{ - char *kp, *p; - int val; - int c; - - if (cmdline) - minusc = NULL; - while ((p = *argptr) != NULL) { - argptr++; - if ((c = *p++) == '-') { - val = 1; - /* A "-" or "--" terminates options */ - if (p[0] == '\0') - goto end_options1; - if (p[0] == '-' && p[1] == '\0') - goto end_options2; - /** - * For the benefit of `#!' lines in shell scripts, - * treat a string of '-- *#.*' the same as '--'. - * This is needed so that a script starting with: - * #!/bin/sh -- # -*- perl -*- - * will continue to work after a change is made to - * kern/imgact_shell.c to NOT token-ize the options - * specified on a '#!' line. A bit of a kludge, - * but that trick is recommended in documentation - * for some scripting languages, and we might as - * well continue to support it. - */ - if (p[0] == '-') { - kp = p + 1; - while (*kp == ' ' || *kp == '\t') - kp++; - if (*kp == '#' || *kp == '\0') - goto end_options2; - } - } else if (c == '+') { - val = 0; - } else { - argptr--; - break; - } - while ((c = *p++) != '\0') { - if (c == 'c' && cmdline) { - char *q; - - q = *argptr++; - if (q == NULL || minusc != NULL) - error("Bad -c option"); - minusc = q; - } else if (c == 'o') { - minus_o(*argptr, val); - if (*argptr) - argptr++; - } else - setoption(c, val); - } - } - return; - - /* When processing `set', a single "-" means turn off -x and -v */ -end_options1: - if (!cmdline) { - xflag = vflag = 0; - return; - } - - /* - * When processing `set', a "--" means the remaining arguments - * replace the positional parameters in the active shell. If - * there are no remaining options, then all the positional - * parameters are cleared (equivalent to doing ``shift $#''). - */ -end_options2: - if (!cmdline) { - if (*argptr == NULL) - setparam(0, argptr); - return; - } - - /* - * At this point we are processing options given to 'sh' on a command - * line. If an end-of-options marker ("-" or "--") is followed by an - * arg of "#", then skip over all remaining arguments. Some scripting - * languages (e.g.: perl) document that /bin/sh will implement this - * behavior, and they recommend that users take advantage of it to - * solve certain issues that can come up when writing a perl script. - * Yes, this feature is in /bin/sh to help users write perl scripts. - */ - p = *argptr; - if (p != NULL && p[0] == '#' && p[1] == '\0') { - while (*argptr != NULL) - argptr++; - /* We need to keep the final argument */ - argptr--; - } -} - -static void -minus_o(char *name, int val) -{ - int i; - const unsigned char *on; - size_t len; - - if (name == NULL) { - if (val) { - /* "Pretty" output. */ - out1str("Current option settings\n"); - for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) - out1fmt("%-16.*s%s\n", *on, on + 1, - optval[i] ? "on" : "off"); - } else { - /* Output suitable for re-input to shell. */ - for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) - out1fmt("%s %co %.*s%s", - i % 6 == 0 ? "set" : "", - optval[i] ? '-' : '+', - *on, on + 1, - i % 6 == 5 || i == NOPTS - 1 ? "\n" : ""); - } - } else { - len = strlen(name); - for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) - if (*on == len && memcmp(on + 1, name, len) == 0) { - setoptionbyindex(i, val); - return; - } - error("Illegal option -o %s", name); - } -} - - -static void -setoptionbyindex(int idx, int val) -{ - if (&optval[idx] == &privileged && !val && privileged) { - if (setgid(getgid()) == -1) - error("setgid"); - if (setuid(getuid()) == -1) - error("setuid"); - } - optval[idx] = val; - if (val) { - /* #%$ hack for ksh semantics */ - if (&optval[idx] == &Vflag) - Eflag = 0; - else if (&optval[idx] == &Eflag) - Vflag = 0; - } -} - -static void -setoption(int flag, int val) -{ - int i; - - for (i = 0; i < NSHORTOPTS; i++) - if (optletter[i] == flag) { - setoptionbyindex(i, val); - return; - } - error("Illegal option -%c", flag); -} - - -/* - * Set the shell parameters. - */ - -static void -setparam(int argc, char **argv) -{ - char **newparam; - char **ap; - - ap = newparam = ckmalloc((argc + 1) * sizeof *ap); - while (*argv) { - *ap++ = savestr(*argv++); - } - *ap = NULL; - freeparam(&shellparam); - shellparam.malloc = 1; - shellparam.nparam = argc; - shellparam.p = newparam; - shellparam.optp = NULL; - shellparam.reset = 1; - shellparam.optnext = NULL; -} - - -/* - * Free the list of positional parameters. - */ - -void -freeparam(struct shparam *param) -{ - char **ap; - - if (param->malloc) { - for (ap = param->p ; *ap ; ap++) - ckfree(*ap); - ckfree(param->p); - } - if (param->optp) { - for (ap = param->optp ; *ap ; ap++) - ckfree(*ap); - ckfree(param->optp); - } -} - - - -/* - * The shift builtin command. - */ - -int -shiftcmd(int argc, char **argv) -{ - int i, n; - - n = 1; - if (argc > 1) - n = number(argv[1]); - if (n > shellparam.nparam) - return 1; - INTOFF; - shellparam.nparam -= n; - if (shellparam.malloc) - for (i = 0; i < n; i++) - ckfree(shellparam.p[i]); - memmove(shellparam.p, shellparam.p + n, - (shellparam.nparam + 1) * sizeof(shellparam.p[0])); - shellparam.reset = 1; - INTON; - return 0; -} - - - -/* - * The set builtin command. - */ - -int -setcmd(int argc, char **argv) -{ - if (argc == 1) - return showvarscmd(argc, argv); - INTOFF; - options(0); - optschanged(); - if (*argptr != NULL) { - setparam(argc - (argptr - argv), argptr); - } - INTON; - return 0; -} - - -void -getoptsreset(const char *value) -{ - while (*value == '0') - value++; - if (strcmp(value, "1") == 0) - shellparam.reset = 1; -} - -/* - * The getopts builtin. Shellparam.optnext points to the next argument - * to be processed. Shellparam.optptr points to the next character to - * be processed in the current argument. If shellparam.optnext is NULL, - * then it's the first time getopts has been called. - */ - -int -getoptscmd(int argc, char **argv) -{ - char **optbase = NULL, **ap; - int i; - - if (argc < 3) - error("usage: getopts optstring var [arg]"); - - if (shellparam.reset == 1) { - INTOFF; - if (shellparam.optp) { - for (ap = shellparam.optp ; *ap ; ap++) - ckfree(*ap); - ckfree(shellparam.optp); - shellparam.optp = NULL; - } - if (argc > 3) { - shellparam.optp = ckmalloc((argc - 2) * sizeof *ap); - memset(shellparam.optp, '\0', (argc - 2) * sizeof *ap); - for (i = 0; i < argc - 3; i++) - shellparam.optp[i] = savestr(argv[i + 3]); - } - INTON; - optbase = argc == 3 ? shellparam.p : shellparam.optp; - shellparam.optnext = optbase; - shellparam.optptr = NULL; - shellparam.reset = 0; - } else - optbase = shellparam.optp ? shellparam.optp : shellparam.p; - - return getopts(argv[1], argv[2], optbase, &shellparam.optnext, - &shellparam.optptr); -} - -static int -getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, - char **optptr) -{ - char *p, *q; - char c = '?'; - int done = 0; - int ind = 0; - int err = 0; - char s[10]; - const char *newoptarg = NULL; - - if ((p = *optptr) == NULL || *p == '\0') { - /* Current word is done, advance */ - if (*optnext == NULL) - return 1; - p = **optnext; - if (p == NULL || *p != '-' || *++p == '\0') { -atend: - ind = *optnext - optfirst + 1; - *optnext = NULL; - p = NULL; - done = 1; - goto out; - } - (*optnext)++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - goto atend; - } - - c = *p++; - for (q = optstr; *q != c; ) { - if (*q == '\0') { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - newoptarg = s; - } - else - out2fmt_flush("Illegal option -%c\n", c); - c = '?'; - goto out; - } - if (*++q == ':') - q++; - } - - if (*++q == ':') { - if (*p == '\0' && (p = **optnext) == NULL) { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - newoptarg = s; - c = ':'; - } - else { - out2fmt_flush("No arg for -%c option\n", c); - c = '?'; - } - goto out; - } - - if (p == **optnext) - (*optnext)++; - newoptarg = p; - p = NULL; - } - -out: - if (*optnext != NULL) - ind = *optnext - optfirst + 1; - *optptr = p; - if (newoptarg != NULL) - err |= setvarsafe("OPTARG", newoptarg, 0); - else { - INTOFF; - err |= unsetvar("OPTARG"); - INTON; - } - fmtstr(s, sizeof(s), "%d", ind); - err |= setvarsafe("OPTIND", s, VNOFUNC); - s[0] = c; - s[1] = '\0'; - err |= setvarsafe(optvar, s, 0); - if (err) { - *optnext = NULL; - *optptr = NULL; - flushall(); - exraise(EXERROR); - } - return done; -} - -/* - * Standard option processing (a la getopt) for builtin routines. The - * only argument that is passed to nextopt is the option string; the - * other arguments are unnecessary. It returns the option, or '\0' on - * end of input. - */ - -int -nextopt(const char *optstring) -{ - char *p; - const char *q; - char c; - - if ((p = nextopt_optptr) == NULL || *p == '\0') { - p = *argptr; - if (p == NULL || *p != '-' || *++p == '\0') - return '\0'; - argptr++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - return '\0'; - } - c = *p++; - for (q = optstring ; *q != c ; ) { - if (*q == '\0') - error("Illegal option -%c", c); - if (*++q == ':') - q++; - } - if (*++q == ':') { - if (*p == '\0' && (p = *argptr++) == NULL) - error("No arg for -%c option", c); - shoptarg = p; - p = NULL; - } - nextopt_optptr = p; - return c; -} diff --git a/bin/catsh/options.h b/bin/catsh/options.h deleted file mode 100644 index 1242b095..00000000 --- a/bin/catsh/options.h +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)options.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/options.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -struct shparam { - int nparam; /* # of positional parameters (without $0) */ - unsigned char malloc; /* if parameter list dynamically allocated */ - unsigned char reset; /* if getopts has been reset */ - char **p; /* parameter list */ - char **optp; /* parameter list for getopts */ - char **optnext; /* next parameter to be processed by getopts */ - char *optptr; /* used by getopts */ -}; - - - -#define eflag optval[0] -#define fflag optval[1] -#define Iflag optval[2] -#define iflag optval[3] -#define mflag optval[4] -#define nflag optval[5] -#define sflag optval[6] -#define xflag optval[7] -#define vflag optval[8] -#define Vflag optval[9] -#define Eflag optval[10] -#define Cflag optval[11] -#define aflag optval[12] -#define bflag optval[13] -#define uflag optval[14] -#define privileged optval[15] -#define Tflag optval[16] -#define Pflag optval[17] -#define hflag optval[18] -#define nologflag optval[19] - -#define NSHORTOPTS 19 -#define NOPTS 20 - -extern char optval[NOPTS]; -extern const char optletter[NSHORTOPTS]; -#ifdef DEFINE_OPTIONS -char optval[NOPTS]; -const char optletter[NSHORTOPTS] = "efIimnsxvVECabupTPh"; -static const unsigned char optname[] = - "\007errexit" - "\006noglob" - "\011ignoreeof" - "\013interactive" - "\007monitor" - "\006noexec" - "\005stdin" - "\006xtrace" - "\007verbose" - "\002vi" - "\005emacs" - "\011noclobber" - "\011allexport" - "\006notify" - "\007nounset" - "\012privileged" - "\012trapsasync" - "\010physical" - "\010trackall" - "\005nolog" -; -#endif - - -extern char *minusc; /* argument to -c option */ -extern char *arg0; /* $0 */ -extern struct shparam shellparam; /* $@ */ -extern char **argptr; /* argument list for builtin commands */ -extern char *shoptarg; /* set by nextopt */ -extern char *nextopt_optptr; /* used by nextopt */ - -void procargs(int, char **); -void optschanged(void); -void freeparam(struct shparam *); -int nextopt(const char *); -void getoptsreset(const char *); diff --git a/bin/catsh/output.c b/bin/catsh/output.c deleted file mode 100644 index 1eb8b692..00000000 --- a/bin/catsh/output.c +++ /dev/null @@ -1,370 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/output.c 326025 2017-11-20 19:49:47Z pfg $"); - -/* - * Shell output routines. We use our own output routines because: - * When a builtin command is interrupted we have to discard - * any pending output. - * When a builtin command appears in back quotes, we want to - * save the output of the command in a region obtained - * via malloc, rather than doing a fork and reading the - * output of the command via a pipe. - */ - -#include <stdio.h> /* defines BUFSIZ */ -#include <string.h> -#include <stdarg.h> -#include <errno.h> -#include <unistd.h> -#include <stdlib.h> -#include <wchar.h> -#include <wctype.h> - -#include "shell.h" -#include "syntax.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "var.h" - - -#define OUTBUFSIZ BUFSIZ -#define MEM_OUT -2 /* output to dynamically allocated memory */ -#define OUTPUT_ERR 01 /* error occurred on output */ - -static int doformat_wr(void *, const char *, int); - -struct output output = {NULL, NULL, NULL, OUTBUFSIZ, 1, 0}; -struct output errout = {NULL, NULL, NULL, 256, 2, 0}; -struct output memout = {NULL, NULL, NULL, 64, MEM_OUT, 0}; -struct output *out1 = &output; -struct output *out2 = &errout; - -void -outcslow(int c, struct output *file) -{ - outc(c, file); -} - -void -out1str(const char *p) -{ - outstr(p, out1); -} - -void -out1qstr(const char *p) -{ - outqstr(p, out1); -} - -void -out2str(const char *p) -{ - outstr(p, out2); -} - -void -out2qstr(const char *p) -{ - outqstr(p, out2); -} - -void -outstr(const char *p, struct output *file) -{ - outbin(p, strlen(p), file); -} - -static void -byteseq(int ch, struct output *file) -{ - char seq[4]; - - seq[0] = '\\'; - seq[1] = (ch >> 6 & 0x3) + '0'; - seq[2] = (ch >> 3 & 0x7) + '0'; - seq[3] = (ch & 0x7) + '0'; - outbin(seq, 4, file); -} - -static void -outdqstr(const char *p, struct output *file) -{ - const char *end; - mbstate_t mbs; - size_t clen; - wchar_t wc; - - memset(&mbs, '\0', sizeof(mbs)); - end = p + strlen(p); - outstr("$'", file); - while ((clen = mbrtowc(&wc, p, end - p + 1, &mbs)) != 0) { - if (clen == (size_t)-2) { - while (p < end) - byteseq(*p++, file); - break; - } - if (clen == (size_t)-1) { - memset(&mbs, '\0', sizeof(mbs)); - byteseq(*p++, file); - continue; - } - if (wc == L'\n') - outcslow('\n', file), p++; - else if (wc == L'\r') - outstr("\\r", file), p++; - else if (wc == L'\t') - outstr("\\t", file), p++; - else if (!iswprint(wc)) { - for (; clen > 0; clen--) - byteseq(*p++, file); - } else { - if (wc == L'\'' || wc == L'\\') - outcslow('\\', file); - outbin(p, clen, file); - p += clen; - } - } - outcslow('\'', file); -} - -/* Like outstr(), but quote for re-input into the shell. */ -void -outqstr(const char *p, struct output *file) -{ - int i; - - if (p[0] == '\0') { - outstr("''", file); - return; - } - for (i = 0; p[i] != '\0'; i++) { - if ((p[i] > '\0' && p[i] < ' ' && p[i] != '\n') || - (p[i] & 0x80) != 0 || p[i] == '\'') { - outdqstr(p, file); - return; - } - } - - if (p[strcspn(p, "|&;<>()$`\\\" \n*?[~#=")] == '\0' || - strcmp(p, "[") == 0) { - outstr(p, file); - return; - } - - outcslow('\'', file); - outstr(p, file); - outcslow('\'', file); -} - -void -outbin(const void *data, size_t len, struct output *file) -{ - const char *p; - - p = data; - while (len-- > 0) - outc(*p++, file); -} - -void -emptyoutbuf(struct output *dest) -{ - int offset, newsize; - - if (dest->buf == NULL) { - INTOFF; - dest->buf = ckmalloc(dest->bufsize); - dest->nextc = dest->buf; - dest->bufend = dest->buf + dest->bufsize; - INTON; - } else if (dest->fd == MEM_OUT) { - offset = dest->nextc - dest->buf; - newsize = dest->bufsize << 1; - INTOFF; - dest->buf = ckrealloc(dest->buf, newsize); - dest->bufsize = newsize; - dest->bufend = dest->buf + newsize; - dest->nextc = dest->buf + offset; - INTON; - } else { - flushout(dest); - } -} - - -void -flushall(void) -{ - flushout(&output); - flushout(&errout); -} - - -void -flushout(struct output *dest) -{ - - if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0) - return; - if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0) - dest->flags |= OUTPUT_ERR; - dest->nextc = dest->buf; -} - - -void -freestdout(void) -{ - output.nextc = output.buf; -} - - -int -outiserror(struct output *file) -{ - return (file->flags & OUTPUT_ERR); -} - - -void -outclearerror(struct output *file) -{ - file->flags &= ~OUTPUT_ERR; -} - - -void -outfmt(struct output *file, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(file, fmt, ap); - va_end(ap); -} - - -void -out1fmt(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(out1, fmt, ap); - va_end(ap); -} - -void -out2fmt_flush(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(out2, fmt, ap); - va_end(ap); - flushout(out2); -} - -void -fmtstr(char *outbuf, int length, const char *fmt, ...) -{ - va_list ap; - - INTOFF; - va_start(ap, fmt); - vsnprintf(outbuf, length, fmt, ap); - va_end(ap); - INTON; -} - -static int -doformat_wr(void *cookie, const char *buf, int len) -{ - struct output *o; - - o = (struct output *)cookie; - outbin(buf, len, o); - - return (len); -} - -void -doformat(struct output *dest, const char *f, va_list ap) -{ - FILE *fp; - - if ((fp = fwopen(dest, doformat_wr)) != NULL) { - vfprintf(fp, f, ap); - fclose(fp); - } -} - -/* - * Version of write which resumes after a signal is caught. - */ - -int -xwrite(int fd, const char *buf, int nbytes) -{ - int ntry; - int i; - int n; - - n = nbytes; - ntry = 0; - for (;;) { - i = write(fd, buf, n); - if (i > 0) { - if ((n -= i) <= 0) - return nbytes; - buf += i; - ntry = 0; - } else if (i == 0) { - if (++ntry > 10) - return nbytes - n; - } else if (errno != EINTR) { - return -1; - } - } -} diff --git a/bin/catsh/output.h b/bin/catsh/output.h deleted file mode 100644 index 511c7078..00000000 --- a/bin/catsh/output.h +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)output.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/output.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -#ifndef OUTPUT_INCL - -#include <stdarg.h> -#include <stddef.h> - -struct output { - char *nextc; - char *bufend; - char *buf; - int bufsize; - short fd; - short flags; -}; - -extern struct output output; /* to fd 1 */ -extern struct output errout; /* to fd 2 */ -extern struct output memout; -extern struct output *out1; /* &memout if backquote, otherwise &output */ -extern struct output *out2; /* &memout if backquote with 2>&1, otherwise - &errout */ - -void outcslow(int, struct output *); -void out1str(const char *); -void out1qstr(const char *); -void out2str(const char *); -void out2qstr(const char *); -void outstr(const char *, struct output *); -void outqstr(const char *, struct output *); -void outbin(const void *, size_t, struct output *); -void emptyoutbuf(struct output *); -void flushall(void); -void flushout(struct output *); -void freestdout(void); -int outiserror(struct output *); -void outclearerror(struct output *); -void outfmt(struct output *, const char *, ...) __printflike(2, 3); -void out1fmt(const char *, ...) __printflike(1, 2); -void out2fmt_flush(const char *, ...) __printflike(1, 2); -void fmtstr(char *, int, const char *, ...) __printflike(3, 4); -void doformat(struct output *, const char *, va_list) __printflike(2, 0); -int xwrite(int, const char *, int); - -#define outc(c, file) ((file)->nextc == (file)->bufend ? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c))) -#define out1c(c) outc(c, out1); -#define out2c(c) outcslow(c, out2); - -#define OUTPUT_INCL -#endif diff --git a/bin/catsh/parser.c b/bin/catsh/parser.c deleted file mode 100644 index 377ab78f..00000000 --- a/bin/catsh/parser.c +++ /dev/null @@ -1,2170 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/parser.c 334008 2018-05-21 21:52:48Z jilles $"); - -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> - -#include "shell.h" -#include "parser.h" -#include "nodes.h" -#include "expand.h" /* defines rmescapes() */ -#include "syntax.h" -#include "options.h" -#include "input.h" -#include "output.h" -#include "var.h" -#include "error.h" -#include "memalloc.h" -#include "mystring.h" -#include "alias.h" -#include "show.h" -#include "eval.h" -#include "exec.h" /* to check for special builtins */ -#ifndef NO_HISTORY -#include "myhistedit.h" -#endif - -/* - * Shell command parser. - */ - -#define PROMPTLEN 128 - -/* values of checkkwd variable */ -#define CHKALIAS 0x1 -#define CHKKWD 0x2 -#define CHKNL 0x4 - -/* values returned by readtoken */ -#include "token.h" - - - -struct heredoc { - struct heredoc *next; /* next here document in list */ - union node *here; /* redirection node */ - char *eofmark; /* string indicating end of input */ - int striptabs; /* if set, strip leading tabs */ -}; - -struct parser_temp { - struct parser_temp *next; - void *data; -}; - - -static struct heredoc *heredoclist; /* list of here documents to read */ -static int doprompt; /* if set, prompt the user */ -static int needprompt; /* true if interactive and at start of line */ -static int lasttoken; /* last token read */ -static int tokpushback; /* last token pushed back */ -static char *wordtext; /* text of last word returned by readtoken */ -static int checkkwd; -static struct nodelist *backquotelist; -static union node *redirnode; -static struct heredoc *heredoc; -static int quoteflag; /* set if (part of) last token was quoted */ -static int startlinno; /* line # where last token started */ -static int funclinno; /* line # where the current function started */ -static struct parser_temp *parser_temp; - -#define NOEOFMARK ((const char *)&heredoclist) - - -static union node *list(int); -static union node *andor(void); -static union node *pipeline(void); -static union node *command(void); -static union node *simplecmd(union node **, union node *); -static union node *makename(void); -static union node *makebinary(int type, union node *n1, union node *n2); -static void parsefname(void); -static void parseheredoc(void); -static int peektoken(void); -static int readtoken(void); -static int xxreadtoken(void); -static int readtoken1(int, const char *, const char *, int); -static int noexpand(char *); -static void consumetoken(int); -static void synexpect(int) __dead2; -static void synerror(const char *) __dead2; -static void setprompt(int); -static char *expandprompt(const char *); -static int pgetc_linecont(void); - - -static void * -parser_temp_alloc(size_t len) -{ - struct parser_temp *t; - - INTOFF; - t = ckmalloc(sizeof(*t)); - t->data = NULL; - t->next = parser_temp; - parser_temp = t; - t->data = ckmalloc(len); - INTON; - return t->data; -} - - -static void * -parser_temp_realloc(void *ptr, size_t len) -{ - struct parser_temp *t; - - INTOFF; - t = parser_temp; - if (ptr != t->data) - error("bug: parser_temp_realloc misused"); - t->data = ckrealloc(t->data, len); - INTON; - return t->data; -} - - -static void -parser_temp_free_upto(void *ptr) -{ - struct parser_temp *t; - int done = 0; - - INTOFF; - while (parser_temp != NULL && !done) { - t = parser_temp; - parser_temp = t->next; - done = t->data == ptr; - ckfree(t->data); - ckfree(t); - } - INTON; - if (!done) - error("bug: parser_temp_free_upto misused"); -} - - -static void -parser_temp_free_all(void) -{ - struct parser_temp *t; - - INTOFF; - while (parser_temp != NULL) { - t = parser_temp; - parser_temp = t->next; - ckfree(t->data); - ckfree(t); - } - INTON; -} - - -/* - * Read and parse a command. Returns NEOF on end of file. (NULL is a - * valid parse tree indicating a blank line.) - */ - -union node * -parsecmd(int interact) -{ - int t; - - /* This assumes the parser is not re-entered, - * which could happen if we add command substitution on PS1/PS2. - */ - parser_temp_free_all(); - heredoclist = NULL; - - tokpushback = 0; - checkkwd = 0; - doprompt = interact; - if (doprompt) - setprompt(1); - else - setprompt(0); - needprompt = 0; - t = readtoken(); - if (t == TEOF) - return NEOF; - if (t == TNL) - return NULL; - tokpushback++; - return list(1); -} - - -/* - * Read and parse words for wordexp. - * Returns a list of NARG nodes; NULL if there are no words. - */ -union node * -parsewordexp(void) -{ - union node *n, *first = NULL, **pnext; - int t; - - /* This assumes the parser is not re-entered, - * which could happen if we add command substitution on PS1/PS2. - */ - parser_temp_free_all(); - heredoclist = NULL; - - tokpushback = 0; - checkkwd = 0; - doprompt = 0; - setprompt(0); - needprompt = 0; - pnext = &first; - while ((t = readtoken()) != TEOF) { - if (t != TWORD) - synexpect(TWORD); - n = makename(); - *pnext = n; - pnext = &n->narg.next; - } - return first; -} - - -static union node * -list(int nlflag) -{ - union node *ntop, *n1, *n2, *n3; - int tok; - - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (!nlflag && tokendlist[peektoken()]) - return NULL; - ntop = n1 = NULL; - for (;;) { - n2 = andor(); - tok = readtoken(); - if (tok == TBACKGND) { - if (n2 != NULL && n2->type == NPIPE) { - n2->npipe.backgnd = 1; - } else if (n2 != NULL && n2->type == NREDIR) { - n2->type = NBACKGND; - } else { - n3 = (union node *)stalloc(sizeof (struct nredir)); - n3->type = NBACKGND; - n3->nredir.n = n2; - n3->nredir.redirect = NULL; - n2 = n3; - } - } - if (ntop == NULL) - ntop = n2; - else if (n1 == NULL) { - n1 = makebinary(NSEMI, ntop, n2); - ntop = n1; - } - else { - n3 = makebinary(NSEMI, n1->nbinary.ch2, n2); - n1->nbinary.ch2 = n3; - n1 = n3; - } - switch (tok) { - case TBACKGND: - case TSEMI: - tok = readtoken(); - /* FALLTHROUGH */ - case TNL: - if (tok == TNL) { - parseheredoc(); - if (nlflag) - return ntop; - } else if (tok == TEOF && nlflag) { - parseheredoc(); - return ntop; - } else { - tokpushback++; - } - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (!nlflag && tokendlist[peektoken()]) - return ntop; - break; - case TEOF: - if (heredoclist) - parseheredoc(); - else - pungetc(); /* push back EOF on input */ - return ntop; - default: - if (nlflag) - synexpect(-1); - tokpushback++; - return ntop; - } - } -} - - - -static union node * -andor(void) -{ - union node *n; - int t; - - n = pipeline(); - for (;;) { - if ((t = readtoken()) == TAND) { - t = NAND; - } else if (t == TOR) { - t = NOR; - } else { - tokpushback++; - return n; - } - n = makebinary(t, n, pipeline()); - } -} - - - -static union node * -pipeline(void) -{ - union node *n1, *n2, *pipenode; - struct nodelist *lp, *prev; - int negate, t; - - negate = 0; - checkkwd = CHKNL | CHKKWD | CHKALIAS; - TRACE(("pipeline: entered\n")); - while (readtoken() == TNOT) - negate = !negate; - tokpushback++; - n1 = command(); - if (readtoken() == TPIPE) { - pipenode = (union node *)stalloc(sizeof (struct npipe)); - pipenode->type = NPIPE; - pipenode->npipe.backgnd = 0; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - pipenode->npipe.cmdlist = lp; - lp->n = n1; - do { - prev = lp; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - checkkwd = CHKNL | CHKKWD | CHKALIAS; - t = readtoken(); - tokpushback++; - if (t == TNOT) - lp->n = pipeline(); - else - lp->n = command(); - prev->next = lp; - } while (readtoken() == TPIPE); - lp->next = NULL; - n1 = pipenode; - } - tokpushback++; - if (negate) { - n2 = (union node *)stalloc(sizeof (struct nnot)); - n2->type = NNOT; - n2->nnot.com = n1; - return n2; - } else - return n1; -} - - - -static union node * -command(void) -{ - union node *n1, *n2; - union node *ap, **app; - union node *cp, **cpp; - union node *redir, **rpp; - int t; - int is_subshell; - - checkkwd = CHKNL | CHKKWD | CHKALIAS; - is_subshell = 0; - redir = NULL; - n1 = NULL; - rpp = &redir; - - /* Check for redirection which may precede command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - - switch (readtoken()) { - case TIF: - n1 = (union node *)stalloc(sizeof (struct nif)); - n1->type = NIF; - if ((n1->nif.test = list(0)) == NULL) - synexpect(-1); - consumetoken(TTHEN); - n1->nif.ifpart = list(0); - n2 = n1; - while (readtoken() == TELIF) { - n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); - n2 = n2->nif.elsepart; - n2->type = NIF; - if ((n2->nif.test = list(0)) == NULL) - synexpect(-1); - consumetoken(TTHEN); - n2->nif.ifpart = list(0); - } - if (lasttoken == TELSE) - n2->nif.elsepart = list(0); - else { - n2->nif.elsepart = NULL; - tokpushback++; - } - consumetoken(TFI); - checkkwd = CHKKWD | CHKALIAS; - break; - case TWHILE: - case TUNTIL: - t = lasttoken; - if ((n1 = list(0)) == NULL) - synexpect(-1); - consumetoken(TDO); - n1 = makebinary((t == TWHILE)? NWHILE : NUNTIL, n1, list(0)); - consumetoken(TDONE); - checkkwd = CHKKWD | CHKALIAS; - break; - case TFOR: - if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) - synerror("Bad for loop variable"); - n1 = (union node *)stalloc(sizeof (struct nfor)); - n1->type = NFOR; - n1->nfor.var = wordtext; - while (readtoken() == TNL) - ; - if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) { - app = ≈ - while (readtoken() == TWORD) { - n2 = makename(); - *app = n2; - app = &n2->narg.next; - } - *app = NULL; - n1->nfor.args = ap; - if (lasttoken != TNL && lasttoken != TSEMI) - synexpect(-1); - } else { - static char argvars[5] = { - CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' - }; - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = argvars; - n2->narg.backquote = NULL; - n2->narg.next = NULL; - n1->nfor.args = n2; - /* - * Newline or semicolon here is optional (but note - * that the original Bourne shell only allowed NL). - */ - if (lasttoken != TNL && lasttoken != TSEMI) - tokpushback++; - } - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if ((t = readtoken()) == TDO) - t = TDONE; - else if (t == TBEGIN) - t = TEND; - else - synexpect(-1); - n1->nfor.body = list(0); - consumetoken(t); - checkkwd = CHKKWD | CHKALIAS; - break; - case TCASE: - n1 = (union node *)stalloc(sizeof (struct ncase)); - n1->type = NCASE; - consumetoken(TWORD); - n1->ncase.expr = makename(); - while (readtoken() == TNL); - if (lasttoken != TWORD || ! equal(wordtext, "in")) - synerror("expecting \"in\""); - cpp = &n1->ncase.cases; - checkkwd = CHKNL | CHKKWD, readtoken(); - while (lasttoken != TESAC) { - *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); - cp->type = NCLIST; - app = &cp->nclist.pattern; - if (lasttoken == TLP) - readtoken(); - for (;;) { - *app = ap = makename(); - checkkwd = CHKNL | CHKKWD; - if (readtoken() != TPIPE) - break; - app = &ap->narg.next; - readtoken(); - } - ap->narg.next = NULL; - if (lasttoken != TRP) - synexpect(TRP); - cp->nclist.body = list(0); - - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if ((t = readtoken()) != TESAC) { - if (t == TENDCASE) - ; - else if (t == TFALLTHRU) - cp->type = NCLISTFALLTHRU; - else - synexpect(TENDCASE); - checkkwd = CHKNL | CHKKWD, readtoken(); - } - cpp = &cp->nclist.next; - } - *cpp = NULL; - checkkwd = CHKKWD | CHKALIAS; - break; - case TLP: - n1 = (union node *)stalloc(sizeof (struct nredir)); - n1->type = NSUBSHELL; - n1->nredir.n = list(0); - n1->nredir.redirect = NULL; - consumetoken(TRP); - checkkwd = CHKKWD | CHKALIAS; - is_subshell = 1; - break; - case TBEGIN: - n1 = list(0); - consumetoken(TEND); - checkkwd = CHKKWD | CHKALIAS; - break; - /* A simple command must have at least one redirection or word. */ - case TBACKGND: - case TSEMI: - case TAND: - case TOR: - case TPIPE: - case TENDCASE: - case TFALLTHRU: - case TEOF: - case TNL: - case TRP: - if (!redir) - synexpect(-1); - case TWORD: - tokpushback++; - n1 = simplecmd(rpp, redir); - return n1; - default: - synexpect(-1); - } - - /* Now check for redirection which may follow command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - *rpp = NULL; - if (redir) { - if (!is_subshell) { - n2 = (union node *)stalloc(sizeof (struct nredir)); - n2->type = NREDIR; - n2->nredir.n = n1; - n1 = n2; - } - n1->nredir.redirect = redir; - } - - return n1; -} - - -static union node * -simplecmd(union node **rpp, union node *redir) -{ - union node *args, **app; - union node **orig_rpp = rpp; - union node *n = NULL; - int special; - int savecheckkwd; - - /* If we don't have any redirections already, then we must reset */ - /* rpp to be the address of the local redir variable. */ - if (redir == NULL) - rpp = &redir; - - args = NULL; - app = &args; - /* - * We save the incoming value, because we need this for shell - * functions. There can not be a redirect or an argument between - * the function name and the open parenthesis. - */ - orig_rpp = rpp; - - savecheckkwd = CHKALIAS; - - for (;;) { - checkkwd = savecheckkwd; - if (readtoken() == TWORD) { - n = makename(); - *app = n; - app = &n->narg.next; - if (savecheckkwd != 0 && !isassignment(wordtext)) - savecheckkwd = 0; - } else if (lasttoken == TREDIR) { - *rpp = n = redirnode; - rpp = &n->nfile.next; - parsefname(); /* read name of redirection file */ - } else if (lasttoken == TLP && app == &args->narg.next - && rpp == orig_rpp) { - /* We have a function */ - consumetoken(TRP); - funclinno = plinno; - /* - * - Require plain text. - * - Functions with '/' cannot be called. - * - Reject name=(). - * - Reject ksh extended glob patterns. - */ - if (!noexpand(n->narg.text) || quoteflag || - strchr(n->narg.text, '/') || - strchr("!%*+-=?@}~", - n->narg.text[strlen(n->narg.text) - 1])) - synerror("Bad function name"); - rmescapes(n->narg.text); - if (find_builtin(n->narg.text, &special) >= 0 && - special) - synerror("Cannot override a special builtin with a function"); - n->type = NDEFUN; - n->narg.next = command(); - funclinno = 0; - return n; - } else { - tokpushback++; - break; - } - } - *app = NULL; - *rpp = NULL; - n = (union node *)stalloc(sizeof (struct ncmd)); - n->type = NCMD; - n->ncmd.args = args; - n->ncmd.redirect = redir; - return n; -} - -static union node * -makename(void) -{ - union node *n; - - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.next = NULL; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - return n; -} - -static union node * -makebinary(int type, union node *n1, union node *n2) -{ - union node *n; - - n = (union node *)stalloc(sizeof (struct nbinary)); - n->type = type; - n->nbinary.ch1 = n1; - n->nbinary.ch2 = n2; - return (n); -} - -void -forcealias(void) -{ - checkkwd |= CHKALIAS; -} - -void -fixredir(union node *n, const char *text, int err) -{ - TRACE(("Fix redir %s %d\n", text, err)); - if (!err) - n->ndup.vname = NULL; - - if (is_digit(text[0]) && text[1] == '\0') - n->ndup.dupfd = digit_val(text[0]); - else if (text[0] == '-' && text[1] == '\0') - n->ndup.dupfd = -1; - else { - - if (err) - synerror("Bad fd number"); - else - n->ndup.vname = makename(); - } -} - - -static void -parsefname(void) -{ - union node *n = redirnode; - - consumetoken(TWORD); - if (n->type == NHERE) { - struct heredoc *here = heredoc; - struct heredoc *p; - - if (quoteflag == 0) - n->type = NXHERE; - TRACE(("Here document %d\n", n->type)); - if (here->striptabs) { - while (*wordtext == '\t') - wordtext++; - } - if (! noexpand(wordtext)) - synerror("Illegal eof marker for << redirection"); - rmescapes(wordtext); - here->eofmark = wordtext; - here->next = NULL; - if (heredoclist == NULL) - heredoclist = here; - else { - for (p = heredoclist ; p->next ; p = p->next); - p->next = here; - } - } else if (n->type == NTOFD || n->type == NFROMFD) { - fixredir(n, wordtext, 0); - } else { - n->nfile.fname = makename(); - } -} - - -/* - * Input any here documents. - */ - -static void -parseheredoc(void) -{ - struct heredoc *here; - union node *n; - - while (heredoclist) { - here = heredoclist; - heredoclist = here->next; - if (needprompt) { - setprompt(2); - needprompt = 0; - } - readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, - here->eofmark, here->striptabs); - n = makename(); - here->here->nhere.doc = n; - } -} - -static int -peektoken(void) -{ - int t; - - t = readtoken(); - tokpushback++; - return (t); -} - -static int -readtoken(void) -{ - int t; - struct alias *ap; -#ifdef DEBUG - int alreadyseen = tokpushback; -#endif - - top: - t = xxreadtoken(); - - /* - * eat newlines - */ - if (checkkwd & CHKNL) { - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } - } - - /* - * check for keywords and aliases - */ - if (t == TWORD && !quoteflag) - { - const char * const *pp; - - if (checkkwd & CHKKWD) - for (pp = parsekwd; *pp; pp++) { - if (**pp == *wordtext && equal(*pp, wordtext)) - { - lasttoken = t = pp - parsekwd + KWDOFFSET; - TRACE(("keyword %s recognized\n", tokname[t])); - goto out; - } - } - if (checkkwd & CHKALIAS && - (ap = lookupalias(wordtext, 1)) != NULL) { - pushstring(ap->val, strlen(ap->val), ap); - goto top; - } - } -out: - if (t != TNOT) - checkkwd = 0; - -#ifdef DEBUG - if (!alreadyseen) - TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); - else - TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); -#endif - return (t); -} - - -/* - * Read the next input token. - * If the token is a word, we set backquotelist to the list of cmds in - * backquotes. We set quoteflag to true if any part of the word was - * quoted. - * If the token is TREDIR, then we set redirnode to a structure containing - * the redirection. - * In all cases, the variable startlinno is set to the number of the line - * on which the token starts. - * - * [Change comment: here documents and internal procedures] - * [Readtoken shouldn't have any arguments. Perhaps we should make the - * word parsing code into a separate routine. In this case, readtoken - * doesn't need to have any internal procedures, but parseword does. - * We could also make parseoperator in essence the main routine, and - * have parseword (readtoken1?) handle both words and redirection.] - */ - -#define RETURN(token) return lasttoken = token - -static int -xxreadtoken(void) -{ - int c; - - if (tokpushback) { - tokpushback = 0; - return lasttoken; - } - if (needprompt) { - setprompt(2); - needprompt = 0; - } - startlinno = plinno; - for (;;) { /* until token or start of word found */ - c = pgetc_macro(); - switch (c) { - case ' ': case '\t': - continue; - case '#': - while ((c = pgetc()) != '\n' && c != PEOF); - pungetc(); - continue; - case '\\': - if (pgetc() == '\n') { - startlinno = ++plinno; - if (doprompt) - setprompt(2); - else - setprompt(0); - continue; - } - pungetc(); - /* FALLTHROUGH */ - default: - return readtoken1(c, BASESYNTAX, (char *)NULL, 0); - case '\n': - plinno++; - needprompt = doprompt; - RETURN(TNL); - case PEOF: - RETURN(TEOF); - case '&': - if (pgetc_linecont() == '&') - RETURN(TAND); - pungetc(); - RETURN(TBACKGND); - case '|': - if (pgetc_linecont() == '|') - RETURN(TOR); - pungetc(); - RETURN(TPIPE); - case ';': - c = pgetc_linecont(); - if (c == ';') - RETURN(TENDCASE); - else if (c == '&') - RETURN(TFALLTHRU); - pungetc(); - RETURN(TSEMI); - case '(': - RETURN(TLP); - case ')': - RETURN(TRP); - } - } -#undef RETURN -} - - -#define MAXNEST_static 8 -struct tokenstate -{ - const char *syntax; /* *SYNTAX */ - int parenlevel; /* levels of parentheses in arithmetic */ - enum tokenstate_category - { - TSTATE_TOP, - TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */ - TSTATE_VAR_NEW, /* other ${var...}, own dquote state */ - TSTATE_ARITH - } category; -}; - - -/* - * Check to see whether we are at the end of the here document. When this - * is called, c is set to the first character of the next input line. If - * we are at the end of the here document, this routine sets the c to PEOF. - * The new value of c is returned. - */ - -static int -checkend(int c, const char *eofmark, int striptabs) -{ - if (striptabs) { - while (c == '\t') - c = pgetc(); - } - if (c == *eofmark) { - int c2; - const char *q; - - for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++) - ; - if ((c2 == PEOF || c2 == '\n') && *q == '\0') { - c = PEOF; - if (c2 == '\n') { - plinno++; - needprompt = doprompt; - } - } else { - pungetc(); - pushstring(eofmark + 1, q - (eofmark + 1), NULL); - } - } else if (c == '\n' && *eofmark == '\0') { - c = PEOF; - plinno++; - needprompt = doprompt; - } - return (c); -} - - -/* - * Parse a redirection operator. The variable "out" points to a string - * specifying the fd to be redirected. The variable "c" contains the - * first character of the redirection operator. - */ - -static void -parseredir(char *out, int c) -{ - char fd = *out; - union node *np; - - np = (union node *)stalloc(sizeof (struct nfile)); - if (c == '>') { - np->nfile.fd = 1; - c = pgetc_linecont(); - if (c == '>') - np->type = NAPPEND; - else if (c == '&') - np->type = NTOFD; - else if (c == '|') - np->type = NCLOBBER; - else { - np->type = NTO; - pungetc(); - } - } else { /* c == '<' */ - np->nfile.fd = 0; - c = pgetc_linecont(); - if (c == '<') { - if (sizeof (struct nfile) != sizeof (struct nhere)) { - np = (union node *)stalloc(sizeof (struct nhere)); - np->nfile.fd = 0; - } - np->type = NHERE; - heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); - heredoc->here = np; - if ((c = pgetc_linecont()) == '-') { - heredoc->striptabs = 1; - } else { - heredoc->striptabs = 0; - pungetc(); - } - } else if (c == '&') - np->type = NFROMFD; - else if (c == '>') - np->type = NFROMTO; - else { - np->type = NFROM; - pungetc(); - } - } - if (fd != '\0') - np->nfile.fd = digit_val(fd); - redirnode = np; -} - -/* - * Called to parse command substitutions. - */ - -static char * -parsebackq(char *out, struct nodelist **pbqlist, - int oldstyle, int dblquote, int quoted) -{ - struct nodelist **nlpp; - union node *n; - char *volatile str; - struct jmploc jmploc; - struct jmploc *const savehandler = handler; - size_t savelen; - int saveprompt; - const int bq_startlinno = plinno; - char *volatile ostr = NULL; - struct parsefile *const savetopfile = getcurrentfile(); - struct heredoc *const saveheredoclist = heredoclist; - struct heredoc *here; - - str = NULL; - if (setjmp(jmploc.loc)) { - popfilesupto(savetopfile); - if (str) - ckfree(str); - if (ostr) - ckfree(ostr); - heredoclist = saveheredoclist; - handler = savehandler; - if (exception == EXERROR) { - startlinno = bq_startlinno; - synerror("Error in command substitution"); - } - longjmp(handler->loc, 1); - } - INTOFF; - savelen = out - stackblock(); - if (savelen > 0) { - str = ckmalloc(savelen); - memcpy(str, stackblock(), savelen); - } - handler = &jmploc; - heredoclist = NULL; - INTON; - if (oldstyle) { - /* We must read until the closing backquote, giving special - treatment to some slashes, and then push the string and - reread it as input, interpreting it normally. */ - char *oout; - int c; - int olen; - - - STARTSTACKSTR(oout); - for (;;) { - if (needprompt) { - setprompt(2); - needprompt = 0; - } - CHECKSTRSPACE(2, oout); - c = pgetc_linecont(); - if (c == '`') - break; - switch (c) { - case '\\': - c = pgetc(); - if (c != '\\' && c != '`' && c != '$' - && (!dblquote || c != '"')) - USTPUTC('\\', oout); - break; - - case '\n': - plinno++; - needprompt = doprompt; - break; - - case PEOF: - startlinno = plinno; - synerror("EOF in backquote substitution"); - break; - - default: - break; - } - USTPUTC(c, oout); - } - USTPUTC('\0', oout); - olen = oout - stackblock(); - INTOFF; - ostr = ckmalloc(olen); - memcpy(ostr, stackblock(), olen); - setinputstring(ostr, 1); - INTON; - } - nlpp = pbqlist; - while (*nlpp) - nlpp = &(*nlpp)->next; - *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - (*nlpp)->next = NULL; - - if (oldstyle) { - saveprompt = doprompt; - doprompt = 0; - } - - n = list(0); - - if (oldstyle) { - if (peektoken() != TEOF) - synexpect(-1); - doprompt = saveprompt; - } else - consumetoken(TRP); - - (*nlpp)->n = n; - if (oldstyle) { - /* - * Start reading from old file again, ignoring any pushed back - * tokens left from the backquote parsing - */ - popfile(); - tokpushback = 0; - } - STARTSTACKSTR(out); - CHECKSTRSPACE(savelen + 1, out); - INTOFF; - if (str) { - memcpy(out, str, savelen); - STADJUST(savelen, out); - ckfree(str); - str = NULL; - } - if (ostr) { - ckfree(ostr); - ostr = NULL; - } - here = saveheredoclist; - if (here != NULL) { - while (here->next != NULL) - here = here->next; - here->next = heredoclist; - heredoclist = saveheredoclist; - } - handler = savehandler; - INTON; - if (quoted) - USTPUTC(CTLBACKQ | CTLQUOTE, out); - else - USTPUTC(CTLBACKQ, out); - return out; -} - - -/* - * Called to parse a backslash escape sequence inside $'...'. - * The backslash has already been read. - */ -static char * -readcstyleesc(char *out) -{ - int c, vc, i, n; - unsigned int v; - - c = pgetc(); - switch (c) { - case '\0': - synerror("Unterminated quoted string"); - case '\n': - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - return out; - case '\\': - case '\'': - case '"': - v = c; - break; - case 'a': v = '\a'; break; - case 'b': v = '\b'; break; - case 'e': v = '\033'; break; - case 'f': v = '\f'; break; - case 'n': v = '\n'; break; - case 'r': v = '\r'; break; - case 't': v = '\t'; break; - case 'v': v = '\v'; break; - case 'x': - v = 0; - for (;;) { - c = pgetc(); - if (c >= '0' && c <= '9') - v = (v << 4) + c - '0'; - else if (c >= 'A' && c <= 'F') - v = (v << 4) + c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - v = (v << 4) + c - 'a' + 10; - else - break; - } - pungetc(); - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - v = c - '0'; - c = pgetc(); - if (c >= '0' && c <= '7') { - v <<= 3; - v += c - '0'; - c = pgetc(); - if (c >= '0' && c <= '7') { - v <<= 3; - v += c - '0'; - } else - pungetc(); - } else - pungetc(); - break; - case 'c': - c = pgetc(); - if (c < 0x3f || c > 0x7a || c == 0x60) - synerror("Bad escape sequence"); - if (c == '\\' && pgetc() != '\\') - synerror("Bad escape sequence"); - if (c == '?') - v = 127; - else - v = c & 0x1f; - break; - case 'u': - case 'U': - n = c == 'U' ? 8 : 4; - v = 0; - for (i = 0; i < n; i++) { - c = pgetc(); - if (c >= '0' && c <= '9') - v = (v << 4) + c - '0'; - else if (c >= 'A' && c <= 'F') - v = (v << 4) + c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - v = (v << 4) + c - 'a' + 10; - else - synerror("Bad escape sequence"); - } - if (v == 0 || (v >= 0xd800 && v <= 0xdfff)) - synerror("Bad escape sequence"); - /* We really need iconv here. */ - if (initial_localeisutf8 && v > 127) { - CHECKSTRSPACE(4, out); - /* - * We cannot use wctomb() as the locale may have - * changed. - */ - if (v <= 0x7ff) { - USTPUTC(0xc0 | v >> 6, out); - USTPUTC(0x80 | (v & 0x3f), out); - return out; - } else if (v <= 0xffff) { - USTPUTC(0xe0 | v >> 12, out); - USTPUTC(0x80 | ((v >> 6) & 0x3f), out); - USTPUTC(0x80 | (v & 0x3f), out); - return out; - } else if (v <= 0x10ffff) { - USTPUTC(0xf0 | v >> 18, out); - USTPUTC(0x80 | ((v >> 12) & 0x3f), out); - USTPUTC(0x80 | ((v >> 6) & 0x3f), out); - USTPUTC(0x80 | (v & 0x3f), out); - return out; - } - } - if (v > 127) - v = '?'; - break; - default: - synerror("Bad escape sequence"); - } - vc = (char)v; - /* - * We can't handle NUL bytes. - * POSIX says we should skip till the closing quote. - */ - if (vc == '\0') { - while ((c = pgetc()) != '\'') { - if (c == '\\') - c = pgetc(); - if (c == PEOF) - synerror("Unterminated quoted string"); - if (c == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - } - } - pungetc(); - return out; - } - if (SQSYNTAX[vc] == CCTL) - USTPUTC(CTLESC, out); - USTPUTC(vc, out); - return out; -} - - -/* - * If eofmark is NULL, read a word or a redirection symbol. If eofmark - * is not NULL, read a here document. In the latter case, eofmark is the - * word which marks the end of the document and striptabs is true if - * leading tabs should be stripped from the document. The argument firstc - * is the first character of the input token or document. - * - * Because C does not have internal subroutines, I have simulated them - * using goto's to implement the subroutine linkage. The following macros - * will run code that appears at the end of readtoken1. - */ - -#define PARSESUB() {goto parsesub; parsesub_return:;} -#define PARSEARITH() {goto parsearith; parsearith_return:;} - -static int -readtoken1(int firstc, char const *initialsyntax, const char *eofmark, - int striptabs) -{ - int c = firstc; - char *out; - int len; - struct nodelist *bqlist; - int quotef; - int newvarnest; - int level; - int synentry; - struct tokenstate state_static[MAXNEST_static]; - int maxnest = MAXNEST_static; - struct tokenstate *state = state_static; - int sqiscstyle = 0; - - startlinno = plinno; - quotef = 0; - bqlist = NULL; - newvarnest = 0; - level = 0; - state[level].syntax = initialsyntax; - state[level].parenlevel = 0; - state[level].category = TSTATE_TOP; - - STARTSTACKSTR(out); - loop: { /* for each line, until end of word */ - if (eofmark && eofmark != NOEOFMARK) - /* set c to PEOF if at end of here document */ - c = checkend(c, eofmark, striptabs); - for (;;) { /* until end of line or end of word */ - CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ - - synentry = state[level].syntax[c]; - - switch(synentry) { - case CNL: /* '\n' */ - if (level == 0) - goto endword; /* exit outer loop */ - /* FALLTHROUGH */ - case CQNL: - USTPUTC(c, out); - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - c = pgetc(); - goto loop; /* continue outer loop */ - case CSBACK: - if (sqiscstyle) { - out = readcstyleesc(out); - break; - } - /* FALLTHROUGH */ - case CWORD: - USTPUTC(c, out); - break; - case CCTL: - if (eofmark == NULL || initialsyntax != SQSYNTAX) - USTPUTC(CTLESC, out); - USTPUTC(c, out); - break; - case CBACK: /* backslash */ - c = pgetc(); - if (c == PEOF) { - USTPUTC('\\', out); - pungetc(); - } else if (c == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - } else { - if (state[level].syntax == DQSYNTAX && - c != '\\' && c != '`' && c != '$' && - (c != '"' || (eofmark != NULL && - newvarnest == 0)) && - (c != '}' || state[level].category != TSTATE_VAR_OLD)) - USTPUTC('\\', out); - if ((eofmark == NULL || - newvarnest > 0) && - state[level].syntax == BASESYNTAX) - USTPUTC(CTLQUOTEMARK, out); - if (SQSYNTAX[c] == CCTL) - USTPUTC(CTLESC, out); - USTPUTC(c, out); - if ((eofmark == NULL || - newvarnest > 0) && - state[level].syntax == BASESYNTAX && - state[level].category == TSTATE_VAR_OLD) - USTPUTC(CTLQUOTEEND, out); - quotef++; - } - break; - case CSQUOTE: - USTPUTC(CTLQUOTEMARK, out); - state[level].syntax = SQSYNTAX; - sqiscstyle = 0; - break; - case CDQUOTE: - USTPUTC(CTLQUOTEMARK, out); - state[level].syntax = DQSYNTAX; - break; - case CENDQUOTE: - if (eofmark != NULL && newvarnest == 0) - USTPUTC(c, out); - else { - if (state[level].category == TSTATE_VAR_OLD) - USTPUTC(CTLQUOTEEND, out); - state[level].syntax = BASESYNTAX; - quotef++; - } - break; - case CVAR: /* '$' */ - PARSESUB(); /* parse substitution */ - break; - case CENDVAR: /* '}' */ - if (level > 0 && - ((state[level].category == TSTATE_VAR_OLD && - state[level].syntax == - state[level - 1].syntax) || - (state[level].category == TSTATE_VAR_NEW && - state[level].syntax == BASESYNTAX))) { - if (state[level].category == TSTATE_VAR_NEW) - newvarnest--; - level--; - USTPUTC(CTLENDVAR, out); - } else { - USTPUTC(c, out); - } - break; - case CLP: /* '(' in arithmetic */ - state[level].parenlevel++; - USTPUTC(c, out); - break; - case CRP: /* ')' in arithmetic */ - if (state[level].parenlevel > 0) { - USTPUTC(c, out); - --state[level].parenlevel; - } else { - if (pgetc_linecont() == ')') { - if (level > 0 && - state[level].category == TSTATE_ARITH) { - level--; - USTPUTC(CTLENDARI, out); - } else - USTPUTC(')', out); - } else { - /* - * unbalanced parens - * (don't 2nd guess - no error) - */ - pungetc(); - USTPUTC(')', out); - } - } - break; - case CBQUOTE: /* '`' */ - out = parsebackq(out, &bqlist, 1, - state[level].syntax == DQSYNTAX && - (eofmark == NULL || newvarnest > 0), - state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX); - break; - case CEOF: - goto endword; /* exit outer loop */ - case CIGN: - break; - default: - if (level == 0) - goto endword; /* exit outer loop */ - USTPUTC(c, out); - } - c = pgetc_macro(); - } - } -endword: - if (state[level].syntax == ARISYNTAX) - synerror("Missing '))'"); - if (state[level].syntax != BASESYNTAX && eofmark == NULL) - synerror("Unterminated quoted string"); - if (state[level].category == TSTATE_VAR_OLD || - state[level].category == TSTATE_VAR_NEW) { - startlinno = plinno; - synerror("Missing '}'"); - } - if (state != state_static) - parser_temp_free_upto(state); - USTPUTC('\0', out); - len = out - stackblock(); - out = stackblock(); - if (eofmark == NULL) { - if ((c == '>' || c == '<') - && quotef == 0 - && len <= 2 - && (*out == '\0' || is_digit(*out))) { - parseredir(out, c); - return lasttoken = TREDIR; - } else { - pungetc(); - } - } - quoteflag = quotef; - backquotelist = bqlist; - grabstackblock(len); - wordtext = out; - return lasttoken = TWORD; -/* end of readtoken routine */ - - -/* - * Parse a substitution. At this point, we have read the dollar sign - * and nothing else. - */ - -parsesub: { - int subtype; - int typeloc; - int flags; - char *p; - static const char types[] = "}-+?="; - int linno; - int length; - int c1; - - c = pgetc_linecont(); - if (c == '(') { /* $(command) or $((arith)) */ - if (pgetc_linecont() == '(') { - PARSEARITH(); - } else { - pungetc(); - out = parsebackq(out, &bqlist, 0, - state[level].syntax == DQSYNTAX && - (eofmark == NULL || newvarnest > 0), - state[level].syntax == DQSYNTAX || - state[level].syntax == ARISYNTAX); - } - } else if (c == '{' || is_name(c) || is_special(c)) { - USTPUTC(CTLVAR, out); - typeloc = out - stackblock(); - USTPUTC(VSNORMAL, out); - subtype = VSNORMAL; - flags = 0; - if (c == '{') { - c = pgetc_linecont(); - subtype = 0; - } -varname: - if (!is_eof(c) && is_name(c)) { - length = 0; - do { - STPUTC(c, out); - c = pgetc_linecont(); - length++; - } while (!is_eof(c) && is_in_name(c)); - if (length == 6 && - strncmp(out - length, "LINENO", length) == 0) { - /* Replace the variable name with the - * current line number. */ - STADJUST(-6, out); - CHECKSTRSPACE(11, out); - linno = plinno; - if (funclinno != 0) - linno -= funclinno - 1; - length = snprintf(out, 11, "%d", linno); - if (length > 10) - length = 10; - out += length; - flags |= VSLINENO; - } - } else if (is_digit(c)) { - if (subtype != VSNORMAL) { - do { - STPUTC(c, out); - c = pgetc_linecont(); - } while (is_digit(c)); - } else { - USTPUTC(c, out); - c = pgetc_linecont(); - } - } else if (is_special(c)) { - c1 = c; - c = pgetc_linecont(); - if (subtype == 0 && c1 == '#') { - subtype = VSLENGTH; - if (strchr(types, c) == NULL && c != ':' && - c != '#' && c != '%') - goto varname; - c1 = c; - c = pgetc_linecont(); - if (c1 != '}' && c == '}') { - pungetc(); - c = c1; - goto varname; - } - pungetc(); - c = c1; - c1 = '#'; - subtype = 0; - } - USTPUTC(c1, out); - } else { - subtype = VSERROR; - if (c == '}') - pungetc(); - else if (c == '\n' || c == PEOF) - synerror("Unexpected end of line in substitution"); - else if (BASESYNTAX[c] != CCTL) - USTPUTC(c, out); - } - if (subtype == 0) { - switch (c) { - case ':': - flags |= VSNUL; - c = pgetc_linecont(); - /*FALLTHROUGH*/ - default: - p = strchr(types, c); - if (p == NULL) { - if (c == '\n' || c == PEOF) - synerror("Unexpected end of line in substitution"); - if (flags == VSNUL) - STPUTC(':', out); - if (BASESYNTAX[c] != CCTL) - STPUTC(c, out); - subtype = VSERROR; - } else - subtype = p - types + VSNORMAL; - break; - case '%': - case '#': - { - int cc = c; - subtype = c == '#' ? VSTRIMLEFT : - VSTRIMRIGHT; - c = pgetc_linecont(); - if (c == cc) - subtype++; - else - pungetc(); - break; - } - } - } else if (subtype != VSERROR) { - if (subtype == VSLENGTH && c != '}') - subtype = VSERROR; - pungetc(); - } - STPUTC('=', out); - if (state[level].syntax == DQSYNTAX || - state[level].syntax == ARISYNTAX) - flags |= VSQUOTE; - *(stackblock() + typeloc) = subtype | flags; - if (subtype != VSNORMAL) { - if (level + 1 >= maxnest) { - maxnest *= 2; - if (state == state_static) { - state = parser_temp_alloc( - maxnest * sizeof(*state)); - memcpy(state, state_static, - MAXNEST_static * sizeof(*state)); - } else - state = parser_temp_realloc(state, - maxnest * sizeof(*state)); - } - level++; - state[level].parenlevel = 0; - if (subtype == VSMINUS || subtype == VSPLUS || - subtype == VSQUESTION || subtype == VSASSIGN) { - /* - * For operators that were in the Bourne shell, - * inherit the double-quote state. - */ - state[level].syntax = state[level - 1].syntax; - state[level].category = TSTATE_VAR_OLD; - } else { - /* - * The other operators take a pattern, - * so go to BASESYNTAX. - * Also, ' and " are now special, even - * in here documents. - */ - state[level].syntax = BASESYNTAX; - state[level].category = TSTATE_VAR_NEW; - newvarnest++; - } - } - } else if (c == '\'' && state[level].syntax == BASESYNTAX) { - /* $'cstylequotes' */ - USTPUTC(CTLQUOTEMARK, out); - state[level].syntax = SQSYNTAX; - sqiscstyle = 1; - } else { - USTPUTC('$', out); - pungetc(); - } - goto parsesub_return; -} - - -/* - * Parse an arithmetic expansion (indicate start of one and set state) - */ -parsearith: { - - if (level + 1 >= maxnest) { - maxnest *= 2; - if (state == state_static) { - state = parser_temp_alloc( - maxnest * sizeof(*state)); - memcpy(state, state_static, - MAXNEST_static * sizeof(*state)); - } else - state = parser_temp_realloc(state, - maxnest * sizeof(*state)); - } - level++; - state[level].syntax = ARISYNTAX; - state[level].parenlevel = 0; - state[level].category = TSTATE_ARITH; - USTPUTC(CTLARI, out); - if (state[level - 1].syntax == DQSYNTAX) - USTPUTC('"',out); - else - USTPUTC(' ',out); - goto parsearith_return; -} - -} /* end of readtoken */ - - -/* - * Returns true if the text contains nothing to expand (no dollar signs - * or backquotes). - */ - -static int -noexpand(char *text) -{ - char *p; - char c; - - p = text; - while ((c = *p++) != '\0') { - if ( c == CTLQUOTEMARK) - continue; - if (c == CTLESC) - p++; - else if (BASESYNTAX[(int)c] == CCTL) - return 0; - } - return 1; -} - - -/* - * Return true if the argument is a legal variable name (a letter or - * underscore followed by zero or more letters, underscores, and digits). - */ - -int -goodname(const char *name) -{ - const char *p; - - p = name; - if (! is_name(*p)) - return 0; - while (*++p) { - if (! is_in_name(*p)) - return 0; - } - return 1; -} - - -int -isassignment(const char *p) -{ - if (!is_name(*p)) - return 0; - p++; - for (;;) { - if (*p == '=') - return 1; - else if (!is_in_name(*p)) - return 0; - p++; - } -} - - -static void -consumetoken(int token) -{ - if (readtoken() != token) - synexpect(token); -} - - -/* - * Called when an unexpected token is read during the parse. The argument - * is the token that is expected, or -1 if more than one type of token can - * occur at this point. - */ - -static void -synexpect(int token) -{ - char msg[64]; - - if (token >= 0) { - fmtstr(msg, 64, "%s unexpected (expecting %s)", - tokname[lasttoken], tokname[token]); - } else { - fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); - } - synerror(msg); -} - - -static void -synerror(const char *msg) -{ - if (commandname) - outfmt(out2, "%s: %d: ", commandname, startlinno); - else if (arg0) - outfmt(out2, "%s: ", arg0); - outfmt(out2, "Syntax error: %s\n", msg); - error((char *)NULL); -} - -static void -setprompt(int which) -{ - whichprompt = which; - if (which == 0) - return; - - if (which == 1 && *ps0val()) { - out2str(expandprompt(ps0val())); - flushout(out2); - } - -#ifndef NO_HISTORY - if (!el) -#endif - { - out2str(getprompt(NULL)); - flushout(out2); - } -} - -static int -pgetc_linecont(void) -{ - int c; - - while ((c = pgetc_macro()) == '\\') { - c = pgetc(); - if (c == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - } else { - pungetc(); - /* Allow the backslash to be pushed back. */ - pushstring("\\", 1, NULL); - return (pgetc()); - } - } - return (c); -} - -static char * -expandprompt(const char *fmt) { - static char ps[PROMPTLEN]; - const char *pwd, *home; - int i, trim; - - /* - * Format prompt string. - */ - for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++) - if (*fmt == '\\') - switch (*++fmt) { - - /* - * Hostname. - * - * \h specifies just the local hostname, - * \H specifies fully-qualified hostname. - */ - case 'h': - case 'H': - ps[i] = '\0'; - gethostname(&ps[i], PROMPTLEN - i - 1); - ps[PROMPTLEN - 1] = '\0'; - /* Skip to end of hostname. */ - trim = (*fmt == 'h') ? '.' : '\0'; - while ((ps[i] != '\0') && (ps[i] != trim)) - i++; - --i; - break; - - /* - * Working directory. - * - * \W specifies just the final component, - * \w specifies the entire path. - */ - case 'W': - case 'w': - pwd = lookupvar("PWD"); - home = lookupvar("HOME"); - if (pwd == NULL || *pwd == '\0') - pwd = "?"; - if (home == NULL || *home == '\0') - home = "?"; - if (*fmt == 'W' && - *pwd == '/' && pwd[1] != '\0' && - strcmp(pwd, home) != 0) { - strlcpy(&ps[i], strrchr(pwd, '/') + 1, - PROMPTLEN - i); - } else { - if (strncmp(pwd, home, strlen(home)) == 0) { - ps[i++] = '~'; - pwd += strlen(home); - } - strlcpy(&ps[i], pwd, PROMPTLEN - i); - } - /* Skip to end of path. */ - while (ps[i] != '\0') - i++; - --i; - break; - - /* - * Superuser status. - * - * '$' for normal users, '#' for root. - */ - case '$': - ps[i] = (geteuid() != 0) ? '$' : '#'; - break; - - /* - * A literal \. - */ - case '\\': - ps[i] = '\\'; - break; - - /* - * Emit unrecognized formats verbatim. - */ - default: - ps[i] = '\\'; - if (i < PROMPTLEN - 2) - ps[++i] = *fmt; - break; - } - else - ps[i] = *fmt; - ps[i] = '\0'; - return (ps); -} - -/* - * called by editline -- any expansions to the prompt - * should be added here. - */ -char * -getprompt(void *unused __unused) -{ - const char *fmt; - static char internal_error[] = "??"; - - /* - * Select prompt format. - */ - switch (whichprompt) { - case 0: - fmt = ""; - break; - case 1: - fmt = ps1val(); - break; - case 2: - fmt = ps2val(); - break; - default: - return internal_error; - } - - return expandprompt(fmt); -} - -char * -getrprompt(void *unused __unused) -{ - const char *fmt; - static char internal_error[] = "??"; - - /* - * Select prompt format. - */ - switch (whichprompt) { - case 0: - fmt = ""; - break; - case 1: - fmt = rps1val(); - break; - case 2: - fmt = rps2val(); - break; - default: - return internal_error; - } - - return expandprompt(fmt); -} - - -const char * -expandstr(const char *ps) -{ - union node n; - struct jmploc jmploc; - struct jmploc *const savehandler = handler; - const int saveprompt = doprompt; - struct parsefile *const savetopfile = getcurrentfile(); - struct parser_temp *const saveparser_temp = parser_temp; - const char *result = NULL; - - if (!setjmp(jmploc.loc)) { - handler = &jmploc; - parser_temp = NULL; - setinputstring(ps, 1); - doprompt = 0; - readtoken1(pgetc(), DQSYNTAX, NOEOFMARK, 0); - if (backquotelist != NULL) - error("Command substitution not allowed here"); - - n.narg.type = NARG; - n.narg.next = NULL; - n.narg.text = wordtext; - n.narg.backquote = backquotelist; - - expandarg(&n, NULL, 0); - result = stackblock(); - INTOFF; - } - handler = savehandler; - doprompt = saveprompt; - popfilesupto(savetopfile); - if (parser_temp != saveparser_temp) { - parser_temp_free_all(); - parser_temp = saveparser_temp; - } - if (result != NULL) { - INTON; - } else if (exception == EXINT) - raise(SIGINT); - return result; -} diff --git a/bin/catsh/parser.h b/bin/catsh/parser.h deleted file mode 100644 index bc86f7e4..00000000 --- a/bin/catsh/parser.h +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)parser.h 8.3 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/parser.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -/* control characters in argument strings */ -#define CTLESC '\300' -#define CTLVAR '\301' -#define CTLENDVAR '\371' -#define CTLBACKQ '\372' -#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ -/* CTLBACKQ | CTLQUOTE == '\373' */ -#define CTLARI '\374' -#define CTLENDARI '\375' -#define CTLQUOTEMARK '\376' -#define CTLQUOTEEND '\377' /* only for ${v+-...} */ - -/* variable substitution byte (follows CTLVAR) */ -#define VSTYPE 0x0f /* type of variable substitution */ -#define VSNUL 0x10 /* colon--treat the empty string as unset */ -#define VSLINENO 0x20 /* expansion of $LINENO, the line number \ - follows immediately */ -#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ - -/* values of VSTYPE field */ -#define VSNORMAL 0x1 /* normal variable: $var or ${var} */ -#define VSMINUS 0x2 /* ${var-text} */ -#define VSPLUS 0x3 /* ${var+text} */ -#define VSQUESTION 0x4 /* ${var?message} */ -#define VSASSIGN 0x5 /* ${var=text} */ -#define VSTRIMLEFT 0x6 /* ${var#pattern} */ -#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ -#define VSTRIMRIGHT 0x8 /* ${var%pattern} */ -#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ -#define VSLENGTH 0xa /* ${#var} */ -#define VSERROR 0xb /* Syntax error, issue when expanded */ - - -/* - * NEOF is returned by parsecmd when it encounters an end of file. It - * must be distinct from NULL. - */ -#define NEOF ((union node *)-1) -extern int whichprompt; /* 1 == PS1, 2 == PS2 */ -extern const char *const parsekwd[]; - - -union node *parsecmd(int); -union node *parsewordexp(void); -void forcealias(void); -void fixredir(union node *, const char *, int); -int goodname(const char *); -int isassignment(const char *); -char *getprompt(void *); -char *getrprompt(void *); -const char *expandstr(const char *); diff --git a/bin/catsh/printf.c b/bin/catsh/printf.c deleted file mode 100644 index e698c417..00000000 --- a/bin/catsh/printf.c +++ /dev/null @@ -1,688 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> - * Copyright 2014 Garrett D'Amore <garrett@damore.org> - * Copyright 2010 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * Important: This file is used both as a standalone program /usr/bin/printf - * and as a builtin for /bin/sh (#define SHELL). - */ - -#ifndef SHELL -#ifndef lint -static char const copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ -#endif - -#ifndef lint -#if 0 -static char const sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93"; -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/usr.bin/printf/printf.c 337618 2018-08-11 11:13:34Z jilles $"); -#endif /* not lint */ - -#include <sys/types.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <inttypes.h> -#include <limits.h> -#include <locale.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <wchar.h> - -#ifdef SHELL -#define main printfcmd -#include "bltin.h" -#include "options.h" -#endif - -#define PF(f, func) do { \ - if (havewidth) \ - if (haveprec) \ - (void)printf(f, fieldwidth, precision, func); \ - else \ - (void)printf(f, fieldwidth, func); \ - else if (haveprec) \ - (void)printf(f, precision, func); \ - else \ - (void)printf(f, func); \ -} while (0) - -static int asciicode(void); -static char *printf_doformat(char *, int *); -static int escape(char *, int, size_t *); -static int getchr(void); -static int getfloating(long double *, int); -static int getint(int *); -static int getnum(intmax_t *, uintmax_t *, int); -static const char - *getstr(void); -static char *mknum(char *, char); -static void usage(void); - -static const char digits[] = "0123456789"; - -static char end_fmt[1]; - -static int myargc; -static char **myargv; -static char **gargv; -static char **maxargv; - -int -main(int argc, char *argv[]) -{ - size_t len; - int end, rval; - char *format, *fmt, *start; -#ifndef SHELL - int ch; - - (void) setlocale(LC_ALL, ""); -#endif - -#ifdef SHELL - nextopt(""); - argc -= argptr - argv; - argv = argptr; -#else - while ((ch = getopt(argc, argv, "")) != -1) - switch (ch) { - case '?': - default: - usage(); - return (1); - } - argc -= optind; - argv += optind; -#endif - - if (argc < 1) { - usage(); - return (1); - } - -#ifdef SHELL - INTOFF; -#endif - /* - * Basic algorithm is to scan the format string for conversion - * specifications -- once one is found, find out if the field - * width or precision is a '*'; if it is, gather up value. Note, - * format strings are reused as necessary to use up the provided - * arguments, arguments of zero/null string are provided to use - * up the format string. - */ - fmt = format = *argv; - escape(fmt, 1, &len); /* backslash interpretation */ - rval = end = 0; - gargv = ++argv; - - for (;;) { - maxargv = gargv; - - myargv = gargv; - for (myargc = 0; gargv[myargc]; myargc++) - /* nop */; - start = fmt; - while (fmt < format + len) { - if (fmt[0] == '%') { - fwrite(start, 1, fmt - start, stdout); - if (fmt[1] == '%') { - /* %% prints a % */ - putchar('%'); - fmt += 2; - } else { - fmt = printf_doformat(fmt, &rval); - if (fmt == NULL || fmt == end_fmt) { -#ifdef SHELL - INTON; -#endif - return (fmt == NULL ? 1 : rval); - } - end = 0; - } - start = fmt; - } else - fmt++; - if (gargv > maxargv) - maxargv = gargv; - } - gargv = maxargv; - - if (end == 1) { - warnx("missing format character"); -#ifdef SHELL - INTON; -#endif - return (1); - } - fwrite(start, 1, fmt - start, stdout); - if (!*gargv) { -#ifdef SHELL - INTON; -#endif - return (rval); - } - /* Restart at the beginning of the format string. */ - fmt = format; - end = 1; - } - /* NOTREACHED */ -} - - -static char * -printf_doformat(char *fmt, int *rval) -{ - static const char skip1[] = "#'-+ 0"; - int fieldwidth, haveprec, havewidth, mod_ldbl, precision; - char convch, nextch; - char start[strlen(fmt) + 1]; - char **fargv; - char *dptr; - int l; - - dptr = start; - *dptr++ = '%'; - *dptr = 0; - - fmt++; - - /* look for "n$" field index specifier */ - l = strspn(fmt, digits); - if ((l > 0) && (fmt[l] == '$')) { - int idx = atoi(fmt); - if (idx <= myargc) { - gargv = &myargv[idx - 1]; - } else { - gargv = &myargv[myargc]; - } - if (gargv > maxargv) - maxargv = gargv; - fmt += l + 1; - - /* save format argument */ - fargv = gargv; - } else { - fargv = NULL; - } - - /* skip to field width */ - while (*fmt && strchr(skip1, *fmt) != NULL) { - *dptr++ = *fmt++; - *dptr = 0; - } - - if (*fmt == '*') { - - fmt++; - l = strspn(fmt, digits); - if ((l > 0) && (fmt[l] == '$')) { - int idx = atoi(fmt); - if (fargv == NULL) { - warnx("incomplete use of n$"); - return (NULL); - } - if (idx <= myargc) { - gargv = &myargv[idx - 1]; - } else { - gargv = &myargv[myargc]; - } - fmt += l + 1; - } else if (fargv != NULL) { - warnx("incomplete use of n$"); - return (NULL); - } - - if (getint(&fieldwidth)) - return (NULL); - if (gargv > maxargv) - maxargv = gargv; - havewidth = 1; - - *dptr++ = '*'; - *dptr = 0; - } else { - havewidth = 0; - - /* skip to possible '.', get following precision */ - while (isdigit(*fmt)) { - *dptr++ = *fmt++; - *dptr = 0; - } - } - - if (*fmt == '.') { - /* precision present? */ - fmt++; - *dptr++ = '.'; - - if (*fmt == '*') { - - fmt++; - l = strspn(fmt, digits); - if ((l > 0) && (fmt[l] == '$')) { - int idx = atoi(fmt); - if (fargv == NULL) { - warnx("incomplete use of n$"); - return (NULL); - } - if (idx <= myargc) { - gargv = &myargv[idx - 1]; - } else { - gargv = &myargv[myargc]; - } - fmt += l + 1; - } else if (fargv != NULL) { - warnx("incomplete use of n$"); - return (NULL); - } - - if (getint(&precision)) - return (NULL); - if (gargv > maxargv) - maxargv = gargv; - haveprec = 1; - *dptr++ = '*'; - *dptr = 0; - } else { - haveprec = 0; - - /* skip to conversion char */ - while (isdigit(*fmt)) { - *dptr++ = *fmt++; - *dptr = 0; - } - } - } else - haveprec = 0; - if (!*fmt) { - warnx("missing format character"); - return (NULL); - } - *dptr++ = *fmt; - *dptr = 0; - - /* - * Look for a length modifier. POSIX doesn't have these, so - * we only support them for floating-point conversions, which - * are extensions. This is useful because the L modifier can - * be used to gain extra range and precision, while omitting - * it is more likely to produce consistent results on different - * architectures. This is not so important for integers - * because overflow is the only bad thing that can happen to - * them, but consider the command printf %a 1.1 - */ - if (*fmt == 'L') { - mod_ldbl = 1; - fmt++; - if (!strchr("aAeEfFgG", *fmt)) { - warnx("bad modifier L for %%%c", *fmt); - return (NULL); - } - } else { - mod_ldbl = 0; - } - - /* save the current arg offset, and set to the format arg */ - if (fargv != NULL) { - gargv = fargv; - } - - convch = *fmt; - nextch = *++fmt; - - *fmt = '\0'; - switch (convch) { - case 'b': { - size_t len; - char *p; - int getout; - - /* Convert "b" to "s" for output. */ - start[strlen(start) - 1] = 's'; - if ((p = strdup(getstr())) == NULL) { - warnx("%s", strerror(ENOMEM)); - return (NULL); - } - getout = escape(p, 0, &len); - PF(start, p); - /* Restore format for next loop. */ - - free(p); - if (getout) - return (end_fmt); - break; - } - case 'c': { - char p; - - p = getchr(); - if (p != '\0') - PF(start, p); - break; - } - case 's': { - const char *p; - - p = getstr(); - PF(start, p); - break; - } - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { - char *f; - intmax_t val; - uintmax_t uval; - int signedconv; - - signedconv = (convch == 'd' || convch == 'i'); - if ((f = mknum(start, convch)) == NULL) - return (NULL); - if (getnum(&val, &uval, signedconv)) - *rval = 1; - if (signedconv) - PF(f, val); - else - PF(f, uval); - break; - } - case 'e': case 'E': - case 'f': case 'F': - case 'g': case 'G': - case 'a': case 'A': { - long double p; - - if (getfloating(&p, mod_ldbl)) - *rval = 1; - if (mod_ldbl) - PF(start, p); - else - PF(start, (double)p); - break; - } - default: - warnx("illegal format character %c", convch); - return (NULL); - } - *fmt = nextch; - /* return the gargv to the next element */ - return (fmt); -} - -static char * -mknum(char *str, char ch) -{ - static char *copy; - static size_t copy_size; - char *newcopy; - size_t len, newlen; - - len = strlen(str) + 2; - if (len > copy_size) { - newlen = ((len + 1023) >> 10) << 10; - if ((newcopy = realloc(copy, newlen)) == NULL) { - warnx("%s", strerror(ENOMEM)); - return (NULL); - } - copy = newcopy; - copy_size = newlen; - } - - memmove(copy, str, len - 3); - copy[len - 3] = 'j'; - copy[len - 2] = ch; - copy[len - 1] = '\0'; - return (copy); -} - -static int -escape(char *fmt, int percent, size_t *len) -{ - char *save, *store, c; - int value; - - for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) { - if (c != '\\') { - *store = c; - continue; - } - switch (*++fmt) { - case '\0': /* EOS, user error */ - *store = '\\'; - *++store = '\0'; - *len = store - save; - return (0); - case '\\': /* backslash */ - case '\'': /* single quote */ - *store = *fmt; - break; - case 'a': /* bell/alert */ - *store = '\a'; - break; - case 'b': /* backspace */ - *store = '\b'; - break; - case 'c': - if (!percent) { - *store = '\0'; - *len = store - save; - return (1); - } - *store = 'c'; - break; - case 'f': /* form-feed */ - *store = '\f'; - break; - case 'n': /* newline */ - *store = '\n'; - break; - case 'r': /* carriage-return */ - *store = '\r'; - break; - case 't': /* horizontal tab */ - *store = '\t'; - break; - case 'v': /* vertical tab */ - *store = '\v'; - break; - /* octal constant */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - c = (!percent && *fmt == '0') ? 4 : 3; - for (value = 0; - c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { - value <<= 3; - value += *fmt - '0'; - } - --fmt; - if (percent && value == '%') { - *store++ = '%'; - *store = '%'; - } else - *store = (char)value; - break; - default: - *store = *fmt; - break; - } - } - *store = '\0'; - *len = store - save; - return (0); -} - -static int -getchr(void) -{ - if (!*gargv) - return ('\0'); - return ((int)**gargv++); -} - -static const char * -getstr(void) -{ - if (!*gargv) - return (""); - return (*gargv++); -} - -static int -getint(int *ip) -{ - intmax_t val; - uintmax_t uval; - int rval; - - if (getnum(&val, &uval, 1)) - return (1); - rval = 0; - if (val < INT_MIN || val > INT_MAX) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - rval = 1; - } - *ip = (int)val; - return (rval); -} - -static int -getnum(intmax_t *ip, uintmax_t *uip, int signedconv) -{ - char *ep; - int rval; - - if (!*gargv) { - *ip = *uip = 0; - return (0); - } - if (**gargv == '"' || **gargv == '\'') { - if (signedconv) - *ip = asciicode(); - else - *uip = asciicode(); - return (0); - } - rval = 0; - errno = 0; - if (signedconv) - *ip = strtoimax(*gargv, &ep, 0); - else - *uip = strtoumax(*gargv, &ep, 0); - if (ep == *gargv) { - warnx("%s: expected numeric value", *gargv); - rval = 1; - } - else if (*ep != '\0') { - warnx("%s: not completely converted", *gargv); - rval = 1; - } - if (errno == ERANGE) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - rval = 1; - } - ++gargv; - return (rval); -} - -static int -getfloating(long double *dp, int mod_ldbl) -{ - char *ep; - int rval; - - if (!*gargv) { - *dp = 0.0; - return (0); - } - if (**gargv == '"' || **gargv == '\'') { - *dp = asciicode(); - return (0); - } - rval = 0; - errno = 0; - if (mod_ldbl) - *dp = strtold(*gargv, &ep); - else - *dp = strtod(*gargv, &ep); - if (ep == *gargv) { - warnx("%s: expected numeric value", *gargv); - rval = 1; - } else if (*ep != '\0') { - warnx("%s: not completely converted", *gargv); - rval = 1; - } - if (errno == ERANGE) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - rval = 1; - } - ++gargv; - return (rval); -} - -static int -asciicode(void) -{ - int ch; - wchar_t wch; - mbstate_t mbs; - - ch = (unsigned char)**gargv; - if (ch == '\'' || ch == '"') { - memset(&mbs, 0, sizeof(mbs)); - switch (mbrtowc(&wch, *gargv + 1, MB_LEN_MAX, &mbs)) { - case (size_t)-2: - case (size_t)-1: - wch = (unsigned char)gargv[0][1]; - break; - case 0: - wch = 0; - break; - } - ch = wch; - } - ++gargv; - return (ch); -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: printf format [arguments ...]\n"); -} diff --git a/bin/catsh/redir.c b/bin/catsh/redir.c deleted file mode 100644 index 616053cf..00000000 --- a/bin/catsh/redir.c +++ /dev/null @@ -1,365 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/redir.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <stdlib.h> - -/* - * Code for dealing with input/output redirection. - */ - -#include "shell.h" -#include "nodes.h" -#include "jobs.h" -#include "expand.h" -#include "redir.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "options.h" - - -#define EMPTY -2 /* marks an unused slot in redirtab */ -#define CLOSED -1 /* fd was not open before redir */ - - -struct redirtab { - struct redirtab *next; - int renamed[10]; - int fd0_redirected; - unsigned int empty_redirs; -}; - - -static struct redirtab *redirlist; - -/* - * We keep track of whether or not fd0 has been redirected. This is for - * background commands, where we want to redirect fd0 to /dev/null only - * if it hasn't already been redirected. -*/ -static int fd0_redirected = 0; - -/* Number of redirtabs that have not been allocated. */ -static unsigned int empty_redirs = 0; - -static void openredirect(union node *, char[10 ]); -static int openhere(union node *); - - -/* - * Process a list of redirection commands. If the REDIR_PUSH flag is set, - * old file descriptors are stashed away so that the redirection can be - * undone by calling popredir. If the REDIR_BACKQ flag is set, then the - * standard output, and the standard error if it becomes a duplicate of - * stdout, is saved in memory. -* - * We suppress interrupts so that we won't leave open file - * descriptors around. Because the signal handler remains - * installed and we do not use system call restart, interrupts - * will still abort blocking opens such as fifos (they will fail - * with EINTR). There is, however, a race condition if an interrupt - * arrives after INTOFF and before open blocks. - */ - -void -redirect(union node *redir, int flags) -{ - union node *n; - struct redirtab *sv = NULL; - int i; - int fd; - char memory[10]; /* file descriptors to write to memory */ - - INTOFF; - for (i = 10 ; --i >= 0 ; ) - memory[i] = 0; - memory[1] = flags & REDIR_BACKQ; - if (flags & REDIR_PUSH) { - empty_redirs++; - if (redir != NULL) { - sv = ckmalloc(sizeof (struct redirtab)); - for (i = 0 ; i < 10 ; i++) - sv->renamed[i] = EMPTY; - sv->fd0_redirected = fd0_redirected; - sv->empty_redirs = empty_redirs - 1; - sv->next = redirlist; - redirlist = sv; - empty_redirs = 0; - } - } - for (n = redir ; n ; n = n->nfile.next) { - fd = n->nfile.fd; - if (fd == 0) - fd0_redirected = 1; - if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && - n->ndup.dupfd == fd) - continue; /* redirect from/to same file descriptor */ - - if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { - INTOFF; - if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) { - switch (errno) { - case EBADF: - i = CLOSED; - break; - default: - INTON; - error("%d: %s", fd, strerror(errno)); - break; - } - } - sv->renamed[fd] = i; - INTON; - } - openredirect(n, memory); - INTON; - INTOFF; - } - if (memory[1]) - out1 = &memout; - if (memory[2]) - out2 = &memout; - INTON; -} - - -static void -openredirect(union node *redir, char memory[10]) -{ - struct stat sb; - int fd = redir->nfile.fd; - const char *fname; - int f; - int e; - - memory[fd] = 0; - switch (redir->nfile.type) { - case NFROM: - fname = redir->nfile.expfname; - if ((f = open(fname, O_RDONLY)) < 0) - error("cannot open %s: %s", fname, strerror(errno)); - break; - case NFROMTO: - fname = redir->nfile.expfname; - if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - break; - case NTO: - if (Cflag) { - fname = redir->nfile.expfname; - if (stat(fname, &sb) == -1) { - if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - } else if (!S_ISREG(sb.st_mode)) { - if ((f = open(fname, O_WRONLY, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) { - close(f); - error("cannot create %s: %s", fname, - strerror(EEXIST)); - } - } else - error("cannot create %s: %s", fname, - strerror(EEXIST)); - break; - } - /* FALLTHROUGH */ - case NCLOBBER: - fname = redir->nfile.expfname; - if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - break; - case NAPPEND: - fname = redir->nfile.expfname; - if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) - error("cannot create %s: %s", fname, strerror(errno)); - break; - case NTOFD: - case NFROMFD: - if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ - if (memory[redir->ndup.dupfd]) - memory[fd] = 1; - else { - if (dup2(redir->ndup.dupfd, fd) < 0) - error("%d: %s", redir->ndup.dupfd, - strerror(errno)); - } - } else { - close(fd); - } - return; - case NHERE: - case NXHERE: - f = openhere(redir); - break; - default: - abort(); - } - if (f != fd) { - if (dup2(f, fd) == -1) { - e = errno; - close(f); - error("%d: %s", fd, strerror(e)); - } - close(f); - } -} - - -/* - * Handle here documents. Normally we fork off a process to write the - * data to a pipe. If the document is short, we can stuff the data in - * the pipe without forking. - */ - -static int -openhere(union node *redir) -{ - const char *p; - int pip[2]; - size_t len = 0; - int flags; - ssize_t written = 0; - - if (pipe(pip) < 0) - error("Pipe call failed: %s", strerror(errno)); - - if (redir->type == NXHERE) - p = redir->nhere.expdoc; - else - p = redir->nhere.doc->narg.text; - len = strlen(p); - if (len == 0) - goto out; - flags = fcntl(pip[1], F_GETFL, 0); - if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) { - written = write(pip[1], p, len); - if (written < 0) - written = 0; - if ((size_t)written == len) - goto out; - fcntl(pip[1], F_SETFL, flags); - } - - if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { - close(pip[0]); - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - signal(SIGPIPE, SIG_DFL); - xwrite(pip[1], p + written, len - written); - _exit(0); - } -out: - close(pip[1]); - return pip[0]; -} - - - -/* - * Undo the effects of the last redirection. - */ - -void -popredir(void) -{ - struct redirtab *rp = redirlist; - int i; - - INTOFF; - if (empty_redirs > 0) { - empty_redirs--; - INTON; - return; - } - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] != EMPTY) { - if (rp->renamed[i] >= 0) { - dup2(rp->renamed[i], i); - close(rp->renamed[i]); - } else { - close(i); - } - } - } - fd0_redirected = rp->fd0_redirected; - empty_redirs = rp->empty_redirs; - redirlist = rp->next; - ckfree(rp); - INTON; -} - -/* Return true if fd 0 has already been redirected at least once. */ -int -fd0_redirected_p(void) -{ - return fd0_redirected != 0; -} - -/* - * Discard all saved file descriptors. - */ - -void -clearredir(void) -{ - struct redirtab *rp; - int i; - - for (rp = redirlist ; rp ; rp = rp->next) { - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] >= 0) { - close(rp->renamed[i]); - } - rp->renamed[i] = EMPTY; - } - } -} diff --git a/bin/catsh/redir.h b/bin/catsh/redir.h deleted file mode 100644 index 8c171423..00000000 --- a/bin/catsh/redir.h +++ /dev/null @@ -1,47 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)redir.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/redir.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -/* flags passed to redirect */ -#define REDIR_PUSH 01 /* save previous values of file descriptors */ -#define REDIR_BACKQ 02 /* save the command output in memory */ - -union node; -void redirect(union node *, int); -void popredir(void); -int fd0_redirected_p(void); -void clearredir(void); - diff --git a/bin/catsh/shell.h b/bin/catsh/shell.h deleted file mode 100644 index 5e3d60dc..00000000 --- a/bin/catsh/shell.h +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)shell.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/shell.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -#ifndef SHELL_H_ -#define SHELL_H_ - -#include <inttypes.h> - -/* - * The follow should be set to reflect the type of system you have: - * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * define DEBUG=1 to compile in debugging (set global "debug" to turn on) - * define DEBUG=2 to compile in and turn on debugging. - * - * When debugging is on, debugging info will be written to ./trace and - * a quit signal will generate a core dump. - */ - - -#define JOBS 1 -/* #define DEBUG 1 */ - -/* - * Type of used arithmetics. SUSv3 requires us to have at least signed long. - */ -typedef intmax_t arith_t; -#define ARITH_FORMAT_STR "%" PRIdMAX -#define atoarith_t(arg) strtoimax(arg, NULL, 0) -#define strtoarith_t(nptr, endptr, base) strtoimax(nptr, endptr, base) -#define ARITH_MIN INTMAX_MIN -#define ARITH_MAX INTMAX_MAX - -typedef void *pointer; - -#include <sys/cdefs.h> - -extern char nullstr[1]; /* null string */ - -#ifdef DEBUG -#define TRACE(param) sh_trace param -#else -#define TRACE(param) -#endif - -#endif /* !SHELL_H_ */ diff --git a/bin/catsh/show.c b/bin/catsh/show.c deleted file mode 100644 index e8a55886..00000000 --- a/bin/catsh/show.c +++ /dev/null @@ -1,410 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/show.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <errno.h> - -#include "shell.h" -#include "parser.h" -#include "nodes.h" -#include "mystring.h" -#include "show.h" - - -#ifdef DEBUG -static void shtree(union node *, int, char *, FILE*); -static void shcmd(union node *, FILE *); -static void sharg(union node *, FILE *); -static void indent(int, char *, FILE *); -static void trstring(char *); - - -void -showtree(union node *n) -{ - trputs("showtree called\n"); - shtree(n, 1, NULL, stdout); -} - - -static void -shtree(union node *n, int ind, char *pfx, FILE *fp) -{ - struct nodelist *lp; - char *s; - - if (n == NULL) - return; - - indent(ind, pfx, fp); - switch(n->type) { - case NSEMI: - s = "; "; - goto binop; - case NAND: - s = " && "; - goto binop; - case NOR: - s = " || "; -binop: - shtree(n->nbinary.ch1, ind, NULL, fp); - /* if (ind < 0) */ - fputs(s, fp); - shtree(n->nbinary.ch2, ind, NULL, fp); - break; - case NCMD: - shcmd(n, fp); - if (ind >= 0) - putc('\n', fp); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - shcmd(lp->n, fp); - if (lp->next) - fputs(" | ", fp); - } - if (n->npipe.backgnd) - fputs(" &", fp); - if (ind >= 0) - putc('\n', fp); - break; - default: - fprintf(fp, "<node type %d>", n->type); - if (ind >= 0) - putc('\n', fp); - break; - } -} - - - -static void -shcmd(union node *cmd, FILE *fp) -{ - union node *np; - int first; - char *s; - int dftfd; - - first = 1; - for (np = cmd->ncmd.args ; np ; np = np->narg.next) { - if (! first) - putchar(' '); - sharg(np, fp); - first = 0; - } - for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { - if (! first) - putchar(' '); - switch (np->nfile.type) { - case NTO: s = ">"; dftfd = 1; break; - case NAPPEND: s = ">>"; dftfd = 1; break; - case NTOFD: s = ">&"; dftfd = 1; break; - case NCLOBBER: s = ">|"; dftfd = 1; break; - case NFROM: s = "<"; dftfd = 0; break; - case NFROMTO: s = "<>"; dftfd = 0; break; - case NFROMFD: s = "<&"; dftfd = 0; break; - case NHERE: s = "<<"; dftfd = 0; break; - case NXHERE: s = "<<"; dftfd = 0; break; - default: s = "*error*"; dftfd = 0; break; - } - if (np->nfile.fd != dftfd) - fprintf(fp, "%d", np->nfile.fd); - fputs(s, fp); - if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { - if (np->ndup.dupfd >= 0) - fprintf(fp, "%d", np->ndup.dupfd); - else - fprintf(fp, "-"); - } else if (np->nfile.type == NHERE) { - fprintf(fp, "HERE"); - } else if (np->nfile.type == NXHERE) { - fprintf(fp, "XHERE"); - } else { - sharg(np->nfile.fname, fp); - } - first = 0; - } -} - - - -static void -sharg(union node *arg, FILE *fp) -{ - char *p; - struct nodelist *bqlist; - int subtype; - - if (arg->type != NARG) { - printf("<node type %d>\n", arg->type); - fflush(stdout); - abort(); - } - bqlist = arg->narg.backquote; - for (p = arg->narg.text ; *p ; p++) { - switch (*p) { - case CTLESC: - putc(*++p, fp); - break; - case CTLVAR: - putc('$', fp); - putc('{', fp); - subtype = *++p; - if (subtype == VSLENGTH) - putc('#', fp); - - while (*p != '=') - putc(*p++, fp); - - if (subtype & VSNUL) - putc(':', fp); - - switch (subtype & VSTYPE) { - case VSNORMAL: - putc('}', fp); - break; - case VSMINUS: - putc('-', fp); - break; - case VSPLUS: - putc('+', fp); - break; - case VSQUESTION: - putc('?', fp); - break; - case VSASSIGN: - putc('=', fp); - break; - case VSTRIMLEFT: - putc('#', fp); - break; - case VSTRIMLEFTMAX: - putc('#', fp); - putc('#', fp); - break; - case VSTRIMRIGHT: - putc('%', fp); - break; - case VSTRIMRIGHTMAX: - putc('%', fp); - putc('%', fp); - break; - case VSLENGTH: - break; - default: - printf("<subtype %d>", subtype); - } - break; - case CTLENDVAR: - putc('}', fp); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - putc('$', fp); - putc('(', fp); - shtree(bqlist->n, -1, NULL, fp); - putc(')', fp); - break; - default: - putc(*p, fp); - break; - } - } -} - - -static void -indent(int amount, char *pfx, FILE *fp) -{ - int i; - - for (i = 0 ; i < amount ; i++) { - if (pfx && i == amount - 1) - fputs(pfx, fp); - putc('\t', fp); - } -} - - -/* - * Debugging stuff. - */ - - -FILE *tracefile; - -#if DEBUG >= 2 -int debug = 1; -#else -int debug = 0; -#endif - - -void -trputc(int c) -{ - if (tracefile == NULL) - return; - putc(c, tracefile); - if (c == '\n') - fflush(tracefile); -} - - -void -sh_trace(const char *fmt, ...) -{ - va_list va; - va_start(va, fmt); - if (tracefile != NULL) { - (void) vfprintf(tracefile, fmt, va); - if (strchr(fmt, '\n')) - (void) fflush(tracefile); - } - va_end(va); -} - - -void -trputs(const char *s) -{ - if (tracefile == NULL) - return; - fputs(s, tracefile); - if (strchr(s, '\n')) - fflush(tracefile); -} - - -static void -trstring(char *s) -{ - char *p; - char c; - - if (tracefile == NULL) - return; - putc('"', tracefile); - for (p = s ; *p ; p++) { - switch (*p) { - case '\n': c = 'n'; goto backslash; - case '\t': c = 't'; goto backslash; - case '\r': c = 'r'; goto backslash; - case '"': c = '"'; goto backslash; - case '\\': c = '\\'; goto backslash; - case CTLESC: c = 'e'; goto backslash; - case CTLVAR: c = 'v'; goto backslash; - case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; - case CTLBACKQ: c = 'q'; goto backslash; - case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; -backslash: putc('\\', tracefile); - putc(c, tracefile); - break; - default: - if (*p >= ' ' && *p <= '~') - putc(*p, tracefile); - else { - putc('\\', tracefile); - putc(*p >> 6 & 03, tracefile); - putc(*p >> 3 & 07, tracefile); - putc(*p & 07, tracefile); - } - break; - } - } - putc('"', tracefile); -} - - -void -trargs(char **ap) -{ - if (tracefile == NULL) - return; - while (*ap) { - trstring(*ap++); - if (*ap) - putc(' ', tracefile); - else - putc('\n', tracefile); - } - fflush(tracefile); -} - - -void -opentrace(void) -{ - char s[100]; - int flags; - - if (!debug) - return; -#ifdef not_this_way - { - char *p; - if ((p = getenv("HOME")) == NULL) { - if (geteuid() == 0) - p = "/"; - else - p = "/tmp"; - } - strcpy(s, p); - strcat(s, "/trace"); - } -#else - strcpy(s, "./trace"); -#endif /* not_this_way */ - if ((tracefile = fopen(s, "a")) == NULL) { - fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); - return; - } - if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) - fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); - fputs("\nTracing started.\n", tracefile); - fflush(tracefile); -} -#endif /* DEBUG */ diff --git a/bin/catsh/show.h b/bin/catsh/show.h deleted file mode 100644 index 587c5ada..00000000 --- a/bin/catsh/show.h +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)show.h 1.1 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/show.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -void showtree(union node *); -#ifdef DEBUG -void sh_trace(const char *, ...) __printflike(1, 2); -void trargs(char **); -void trputc(int); -void trputs(const char *); -void opentrace(void); -#endif diff --git a/bin/catsh/test.c b/bin/catsh/test.c deleted file mode 100644 index a153cdb3..00000000 --- a/bin/catsh/test.c +++ /dev/null @@ -1,630 +0,0 @@ -/* $NetBSD: test.c,v 1.21 1999/04/05 09:48:38 kleink Exp $ */ - -/*- - * test(1); version 7-like -- author Erik Baalbergen - * modified by Eric Gisin to be used as built-in. - * modified by Arnold Robbins to add SVR3 compatibility - * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). - * modified by J.T. Conklin for NetBSD. - * - * This program is in the Public Domain. - */ -/* - * Important: This file is used both as a standalone program /bin/test and - * as a builtin for /bin/sh (#define SHELL). - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/test/test.c 298232 2016-04-19 00:38:07Z araujo $"); - -#include <sys/types.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#ifdef SHELL -#define main testcmd -#include "bltin.h" -#else -#include <locale.h> - -static void error(const char *, ...) __dead2 __printf0like(1, 2); - -static void -error(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - verrx(2, msg, ap); - /*NOTREACHED*/ - va_end(ap); -} -#endif - -/* test(1) accepts the following grammar: - oexpr ::= aexpr | aexpr "-o" oexpr ; - aexpr ::= nexpr | nexpr "-a" aexpr ; - nexpr ::= primary | "!" primary - primary ::= unary-operator operand - | operand binary-operator operand - | operand - | "(" oexpr ")" - ; - unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| - "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; - - binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"; - operand ::= <any legal UNIX file name> -*/ - -enum token_types { - UNOP = 0x100, - BINOP = 0x200, - BUNOP = 0x300, - BBINOP = 0x400, - PAREN = 0x500 -}; - -enum token { - EOI, - OPERAND, - FILRD = UNOP + 1, - FILWR, - FILEX, - FILEXIST, - FILREG, - FILDIR, - FILCDEV, - FILBDEV, - FILFIFO, - FILSOCK, - FILSYM, - FILGZ, - FILTT, - FILSUID, - FILSGID, - FILSTCK, - STREZ, - STRNZ, - FILUID, - FILGID, - FILNT = BINOP + 1, - FILOT, - FILEQ, - STREQ, - STRNE, - STRLT, - STRGT, - INTEQ, - INTNE, - INTGE, - INTGT, - INTLE, - INTLT, - UNOT = BUNOP + 1, - BAND = BBINOP + 1, - BOR, - LPAREN = PAREN + 1, - RPAREN -}; - -#define TOKEN_TYPE(token) ((token) & 0xff00) - -static const struct t_op { - char op_text[2]; - short op_num; -} ops1[] = { - {"=", STREQ}, - {"<", STRLT}, - {">", STRGT}, - {"!", UNOT}, - {"(", LPAREN}, - {")", RPAREN}, -}, opsm1[] = { - {"r", FILRD}, - {"w", FILWR}, - {"x", FILEX}, - {"e", FILEXIST}, - {"f", FILREG}, - {"d", FILDIR}, - {"c", FILCDEV}, - {"b", FILBDEV}, - {"p", FILFIFO}, - {"u", FILSUID}, - {"g", FILSGID}, - {"k", FILSTCK}, - {"s", FILGZ}, - {"t", FILTT}, - {"z", STREZ}, - {"n", STRNZ}, - {"h", FILSYM}, /* for backwards compat */ - {"O", FILUID}, - {"G", FILGID}, - {"L", FILSYM}, - {"S", FILSOCK}, - {"a", BAND}, - {"o", BOR}, -}, ops2[] = { - {"==", STREQ}, - {"!=", STRNE}, -}, opsm2[] = { - {"eq", INTEQ}, - {"ne", INTNE}, - {"ge", INTGE}, - {"gt", INTGT}, - {"le", INTLE}, - {"lt", INTLT}, - {"nt", FILNT}, - {"ot", FILOT}, - {"ef", FILEQ}, -}; - -static int nargc; -static char **t_wp; -static int parenlevel; - -static int aexpr(enum token); -static int binop(enum token); -static int equalf(const char *, const char *); -static int filstat(char *, enum token); -static int getn(const char *); -static intmax_t getq(const char *); -static int intcmp(const char *, const char *); -static int isunopoperand(void); -static int islparenoperand(void); -static int isrparenoperand(void); -static int newerf(const char *, const char *); -static int nexpr(enum token); -static int oexpr(enum token); -static int olderf(const char *, const char *); -static int primary(enum token); -static void syntax(const char *, const char *); -static enum token t_lex(char *); - -int -main(int argc, char **argv) -{ - int res; - char *p; - - if ((p = strrchr(argv[0], '/')) == NULL) - p = argv[0]; - else - p++; - if (strcmp(p, "[") == 0) { - if (strcmp(argv[--argc], "]") != 0) - error("missing ]"); - argv[argc] = NULL; - } - - /* no expression => false */ - if (--argc <= 0) - return 1; - -#ifndef SHELL - (void)setlocale(LC_CTYPE, ""); -#endif - nargc = argc; - t_wp = &argv[1]; - parenlevel = 0; - if (nargc == 4 && strcmp(*t_wp, "!") == 0) { - /* Things like ! "" -o x do not fit in the normal grammar. */ - --nargc; - ++t_wp; - res = oexpr(t_lex(*t_wp)); - } else - res = !oexpr(t_lex(*t_wp)); - - if (--nargc > 0) - syntax(*t_wp, "unexpected operator"); - - return res; -} - -static void -syntax(const char *op, const char *msg) -{ - - if (op && *op) - error("%s: %s", op, msg); - else - error("%s", msg); -} - -static int -oexpr(enum token n) -{ - int res; - - res = aexpr(n); - if (t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL) == BOR) - return oexpr(t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL)) || - res; - t_wp--; - nargc++; - return res; -} - -static int -aexpr(enum token n) -{ - int res; - - res = nexpr(n); - if (t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL) == BAND) - return aexpr(t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL)) && - res; - t_wp--; - nargc++; - return res; -} - -static int -nexpr(enum token n) -{ - if (n == UNOT) - return !nexpr(t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL)); - return primary(n); -} - -static int -primary(enum token n) -{ - enum token nn; - int res; - - if (n == EOI) - return 0; /* missing expression */ - if (n == LPAREN) { - parenlevel++; - if ((nn = t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL)) == - RPAREN) { - parenlevel--; - return 0; /* missing expression */ - } - res = oexpr(nn); - if (t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL) != RPAREN) - syntax(NULL, "closing paren expected"); - parenlevel--; - return res; - } - if (TOKEN_TYPE(n) == UNOP) { - /* unary expression */ - if (--nargc == 0) - syntax(NULL, "argument expected"); /* impossible */ - switch (n) { - case STREZ: - return strlen(*++t_wp) == 0; - case STRNZ: - return strlen(*++t_wp) != 0; - case FILTT: - return isatty(getn(*++t_wp)); - default: - return filstat(*++t_wp, n); - } - } - - nn = t_lex(nargc > 0 ? t_wp[1] : NULL); - if (TOKEN_TYPE(nn) == BINOP) - return binop(nn); - - return strlen(*t_wp) > 0; -} - -static int -binop(enum token n) -{ - const char *opnd1, *op, *opnd2; - - opnd1 = *t_wp; - op = nargc > 0 ? (--nargc, *++t_wp) : NULL; - - if ((opnd2 = nargc > 0 ? (--nargc, *++t_wp) : NULL) == NULL) - syntax(op, "argument expected"); - - switch (n) { - case STREQ: - return strcmp(opnd1, opnd2) == 0; - case STRNE: - return strcmp(opnd1, opnd2) != 0; - case STRLT: - return strcmp(opnd1, opnd2) < 0; - case STRGT: - return strcmp(opnd1, opnd2) > 0; - case INTEQ: - return intcmp(opnd1, opnd2) == 0; - case INTNE: - return intcmp(opnd1, opnd2) != 0; - case INTGE: - return intcmp(opnd1, opnd2) >= 0; - case INTGT: - return intcmp(opnd1, opnd2) > 0; - case INTLE: - return intcmp(opnd1, opnd2) <= 0; - case INTLT: - return intcmp(opnd1, opnd2) < 0; - case FILNT: - return newerf (opnd1, opnd2); - case FILOT: - return olderf (opnd1, opnd2); - case FILEQ: - return equalf (opnd1, opnd2); - default: - abort(); - /* NOTREACHED */ - } -} - -static int -filstat(char *nm, enum token mode) -{ - struct stat s; - - if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) - return 0; - - switch (mode) { - case FILRD: - return (faccessat(AT_FDCWD, nm, R_OK, AT_EACCESS) == 0); - case FILWR: - return (faccessat(AT_FDCWD, nm, W_OK, AT_EACCESS) == 0); - case FILEX: - /* XXX work around eaccess(2) false positives for superuser */ - if (faccessat(AT_FDCWD, nm, X_OK, AT_EACCESS) != 0) - return 0; - if (S_ISDIR(s.st_mode) || geteuid() != 0) - return 1; - return (s.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0; - case FILEXIST: - return (faccessat(AT_FDCWD, nm, F_OK, AT_EACCESS) == 0); - case FILREG: - return S_ISREG(s.st_mode); - case FILDIR: - return S_ISDIR(s.st_mode); - case FILCDEV: - return S_ISCHR(s.st_mode); - case FILBDEV: - return S_ISBLK(s.st_mode); - case FILFIFO: - return S_ISFIFO(s.st_mode); - case FILSOCK: - return S_ISSOCK(s.st_mode); - case FILSYM: - return S_ISLNK(s.st_mode); - case FILSUID: - return (s.st_mode & S_ISUID) != 0; - case FILSGID: - return (s.st_mode & S_ISGID) != 0; - case FILSTCK: - return (s.st_mode & S_ISVTX) != 0; - case FILGZ: - return s.st_size > (off_t)0; - case FILUID: - return s.st_uid == geteuid(); - case FILGID: - return s.st_gid == getegid(); - default: - return 1; - } -} - -static int -find_op_1char(const struct t_op *op, const struct t_op *end, const char *s) -{ - char c; - - c = s[0]; - while (op != end) { - if (c == *op->op_text) - return op->op_num; - op++; - } - return OPERAND; -} - -static int -find_op_2char(const struct t_op *op, const struct t_op *end, const char *s) -{ - while (op != end) { - if (s[0] == op->op_text[0] && s[1] == op->op_text[1]) - return op->op_num; - op++; - } - return OPERAND; -} - -static int -find_op(const char *s) -{ - if (s[0] == '\0') - return OPERAND; - else if (s[1] == '\0') - return find_op_1char(ops1, (&ops1)[1], s); - else if (s[2] == '\0') - return s[0] == '-' ? find_op_1char(opsm1, (&opsm1)[1], s + 1) : - find_op_2char(ops2, (&ops2)[1], s); - else if (s[3] == '\0') - return s[0] == '-' ? find_op_2char(opsm2, (&opsm2)[1], s + 1) : - OPERAND; - else - return OPERAND; -} - -static enum token -t_lex(char *s) -{ - int num; - - if (s == NULL) { - return EOI; - } - num = find_op(s); - if (((TOKEN_TYPE(num) == UNOP || TOKEN_TYPE(num) == BUNOP) - && isunopoperand()) || - (num == LPAREN && islparenoperand()) || - (num == RPAREN && isrparenoperand())) - return OPERAND; - return num; -} - -static int -isunopoperand(void) -{ - char *s; - char *t; - int num; - - if (nargc == 1) - return 1; - s = *(t_wp + 1); - if (nargc == 2) - return parenlevel == 1 && strcmp(s, ")") == 0; - t = *(t_wp + 2); - num = find_op(s); - return TOKEN_TYPE(num) == BINOP && - (parenlevel == 0 || t[0] != ')' || t[1] != '\0'); -} - -static int -islparenoperand(void) -{ - char *s; - int num; - - if (nargc == 1) - return 1; - s = *(t_wp + 1); - if (nargc == 2) - return parenlevel == 1 && strcmp(s, ")") == 0; - if (nargc != 3) - return 0; - num = find_op(s); - return TOKEN_TYPE(num) == BINOP; -} - -static int -isrparenoperand(void) -{ - char *s; - - if (nargc == 1) - return 0; - s = *(t_wp + 1); - if (nargc == 2) - return parenlevel == 1 && strcmp(s, ")") == 0; - return 0; -} - -/* atoi with error detection */ -static int -getn(const char *s) -{ - char *p; - long r; - - errno = 0; - r = strtol(s, &p, 10); - - if (s == p) - error("%s: bad number", s); - - if (errno != 0) - error((errno == EINVAL) ? "%s: bad number" : - "%s: out of range", s); - - while (isspace((unsigned char)*p)) - p++; - - if (*p) - error("%s: bad number", s); - - return (int) r; -} - -/* atoi with error detection and 64 bit range */ -static intmax_t -getq(const char *s) -{ - char *p; - intmax_t r; - - errno = 0; - r = strtoimax(s, &p, 10); - - if (s == p) - error("%s: bad number", s); - - if (errno != 0) - error((errno == EINVAL) ? "%s: bad number" : - "%s: out of range", s); - - while (isspace((unsigned char)*p)) - p++; - - if (*p) - error("%s: bad number", s); - - return r; -} - -static int -intcmp (const char *s1, const char *s2) -{ - intmax_t q1, q2; - - - q1 = getq(s1); - q2 = getq(s2); - - if (q1 > q2) - return 1; - - if (q1 < q2) - return -1; - - return 0; -} - -static int -newerf (const char *f1, const char *f2) -{ - struct stat b1, b2; - - if (stat(f1, &b1) != 0 || stat(f2, &b2) != 0) - return 0; - - if (b1.st_mtimespec.tv_sec > b2.st_mtimespec.tv_sec) - return 1; - if (b1.st_mtimespec.tv_sec < b2.st_mtimespec.tv_sec) - return 0; - - return (b1.st_mtimespec.tv_nsec > b2.st_mtimespec.tv_nsec); -} - -static int -olderf (const char *f1, const char *f2) -{ - return (newerf(f2, f1)); -} - -static int -equalf (const char *f1, const char *f2) -{ - struct stat b1, b2; - - return (stat (f1, &b1) == 0 && - stat (f2, &b2) == 0 && - b1.st_dev == b2.st_dev && - b1.st_ino == b2.st_ino); -} diff --git a/bin/catsh/trap.c b/bin/catsh/trap.c deleted file mode 100644 index 93c063e1..00000000 --- a/bin/catsh/trap.c +++ /dev/null @@ -1,553 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/trap.c 326025 2017-11-20 19:49:47Z pfg $"); - -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> - -#include "shell.h" -#include "main.h" -#include "nodes.h" /* for other headers */ -#include "eval.h" -#include "jobs.h" -#include "show.h" -#include "options.h" -#include "syntax.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "trap.h" -#include "mystring.h" -#include "builtins.h" -#include "myhistedit.h" - - -/* - * Sigmode records the current value of the signal handlers for the various - * modes. A value of zero means that the current handler is not known. - * S_HARD_IGN indicates that the signal was ignored on entry to the shell, - */ - -#define S_DFL 1 /* default signal handling (SIG_DFL) */ -#define S_CATCH 2 /* signal is caught */ -#define S_IGN 3 /* signal is ignored (SIG_IGN) */ -#define S_HARD_IGN 4 /* signal is ignored permanently */ -#define S_RESET 5 /* temporary - to reset a hard ignored sig */ - - -static char sigmode[NSIG]; /* current value of signal */ -volatile sig_atomic_t pendingsig; /* indicates some signal received */ -volatile sig_atomic_t pendingsig_waitcmd; /* indicates wait builtin should be interrupted */ -static int in_dotrap; /* do we execute in a trap handler? */ -static char *volatile trap[NSIG]; /* trap handler commands */ -static volatile sig_atomic_t gotsig[NSIG]; - /* indicates specified signal received */ -static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ -static int last_trapsig; - -static int exiting; /* exitshell() has been called */ -static int exiting_exitstatus; /* value passed to exitshell() */ - -static int getsigaction(int, sig_t *); - - -/* - * Map a string to a signal number. - * - * Note: the signal number may exceed NSIG. - */ -static int -sigstring_to_signum(char *sig) -{ - - if (is_number(sig)) { - int signo; - - signo = atoi(sig); - return ((signo >= 0 && signo < NSIG) ? signo : (-1)); - } else if (strcasecmp(sig, "EXIT") == 0) { - return (0); - } else { - int n; - - if (strncasecmp(sig, "SIG", 3) == 0) - sig += 3; - for (n = 1; n < NSIG; n++) - if (sys_signame[n] && - strcasecmp(sys_signame[n], sig) == 0) - return (n); - } - return (-1); -} - - -/* - * Print a list of valid signal names. - */ -static void -printsignals(void) -{ - int n, outlen; - - outlen = 0; - for (n = 1; n < NSIG; n++) { - if (sys_signame[n]) { - out1fmt("%s", sys_signame[n]); - outlen += strlen(sys_signame[n]); - } else { - out1fmt("%d", n); - outlen += 3; /* good enough */ - } - ++outlen; - if (outlen > 71 || n == NSIG - 1) { - out1str("\n"); - outlen = 0; - } else { - out1c(' '); - } - } -} - - -/* - * The trap builtin. - */ -int -trapcmd(int argc __unused, char **argv) -{ - char *action; - int signo; - int errors = 0; - int i; - - while ((i = nextopt("l")) != '\0') { - switch (i) { - case 'l': - printsignals(); - return (0); - } - } - argv = argptr; - - if (*argv == NULL) { - for (signo = 0 ; signo < NSIG ; signo++) { - if (signo < NSIG && trap[signo] != NULL) { - out1str("trap -- "); - out1qstr(trap[signo]); - if (signo == 0) { - out1str(" EXIT\n"); - } else if (sys_signame[signo]) { - out1fmt(" %s\n", sys_signame[signo]); - } else { - out1fmt(" %d\n", signo); - } - } - } - return 0; - } - action = NULL; - if (*argv && !is_number(*argv)) { - if (strcmp(*argv, "-") == 0) - argv++; - else { - action = *argv; - argv++; - } - } - for (; *argv; argv++) { - if ((signo = sigstring_to_signum(*argv)) == -1) { - warning("bad signal %s", *argv); - errors = 1; - continue; - } - INTOFF; - if (action) - action = savestr(action); - if (trap[signo]) - ckfree(trap[signo]); - trap[signo] = action; - if (signo != 0) - setsignal(signo); - INTON; - } - return errors; -} - - -/* - * Clear traps on a fork. - */ -void -clear_traps(void) -{ - char *volatile *tp; - - for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) { - if (*tp && **tp) { /* trap not NULL or SIG_IGN */ - INTOFF; - ckfree(*tp); - *tp = NULL; - if (tp != &trap[0]) - setsignal(tp - trap); - INTON; - } - } -} - - -/* - * Check if we have any traps enabled. - */ -int -have_traps(void) -{ - char *volatile *tp; - - for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) { - if (*tp && **tp) /* trap not NULL or SIG_IGN */ - return 1; - } - return 0; -} - -/* - * Set the signal handler for the specified signal. The routine figures - * out what it should be set to. - */ -void -setsignal(int signo) -{ - int action; - sig_t sigact = SIG_DFL; - struct sigaction sa; - char *t; - - if ((t = trap[signo]) == NULL) - action = S_DFL; - else if (*t != '\0') - action = S_CATCH; - else - action = S_IGN; - if (action == S_DFL) { - switch (signo) { - case SIGINT: - action = S_CATCH; - break; - case SIGQUIT: -#ifdef DEBUG - { - extern int debug; - - if (debug) - break; - } -#endif - action = S_CATCH; - break; - case SIGTERM: - if (rootshell && iflag) - action = S_IGN; - break; -#if JOBS - case SIGTSTP: - case SIGTTOU: - if (rootshell && mflag) - action = S_IGN; - break; -#endif - } - } - - t = &sigmode[signo]; - if (*t == 0) { - /* - * current setting unknown - */ - if (!getsigaction(signo, &sigact)) { - /* - * Pretend it worked; maybe we should give a warning - * here, but other shells don't. We don't alter - * sigmode, so that we retry every time. - */ - return; - } - if (sigact == SIG_IGN) { - if (mflag && (signo == SIGTSTP || - signo == SIGTTIN || signo == SIGTTOU)) { - *t = S_IGN; /* don't hard ignore these */ - } else - *t = S_HARD_IGN; - } else { - *t = S_RESET; /* force to be set */ - } - } - if (*t == S_HARD_IGN || *t == action) - return; - switch (action) { - case S_DFL: sigact = SIG_DFL; break; - case S_CATCH: sigact = onsig; break; - case S_IGN: sigact = SIG_IGN; break; - } - *t = action; - sa.sa_handler = sigact; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(signo, &sa, NULL); -} - - -/* - * Return the current setting for sig w/o changing it. - */ -static int -getsigaction(int signo, sig_t *sigact) -{ - struct sigaction sa; - - if (sigaction(signo, (struct sigaction *)0, &sa) == -1) - return 0; - *sigact = (sig_t) sa.sa_handler; - return 1; -} - - -/* - * Ignore a signal. - */ -void -ignoresig(int signo) -{ - - if (sigmode[signo] == 0) - setsignal(signo); - if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) { - signal(signo, SIG_IGN); - sigmode[signo] = S_IGN; - } -} - - -int -issigchldtrapped(void) -{ - - return (trap[SIGCHLD] != NULL && *trap[SIGCHLD] != '\0'); -} - - -/* - * Signal handler. - */ -void -onsig(int signo) -{ - - if (signo == SIGINT && trap[SIGINT] == NULL) { - /* - * The !in_dotrap here is safe. The only way we can arrive - * here with in_dotrap set is that a trap handler set SIGINT to - * SIG_DFL and killed itself. - */ - if (suppressint && !in_dotrap) - SET_PENDING_INT; - else - onint(); - return; - } - - /* If we are currently in a wait builtin, prepare to break it */ - if (signo == SIGINT || signo == SIGQUIT) - pendingsig_waitcmd = signo; - - if (trap[signo] != NULL && trap[signo][0] != '\0' && - (signo != SIGCHLD || !ignore_sigchld)) { - gotsig[signo] = 1; - pendingsig = signo; - pendingsig_waitcmd = signo; - } -} - - -/* - * Called to execute a trap. Perhaps we should avoid entering new trap - * handlers while we are executing a trap handler. - */ -void -dotrap(void) -{ - struct stackmark smark; - int i; - int savestatus, prev_evalskip, prev_skipcount; - - in_dotrap++; - for (;;) { - pendingsig = 0; - pendingsig_waitcmd = 0; - for (i = 1; i < NSIG; i++) { - if (gotsig[i]) { - gotsig[i] = 0; - if (trap[i]) { - /* - * Ignore SIGCHLD to avoid infinite - * recursion if the trap action does - * a fork. - */ - if (i == SIGCHLD) - ignore_sigchld++; - - /* - * Backup current evalskip - * state and reset it before - * executing a trap, so that the - * trap is not disturbed by an - * ongoing break/continue/return - * statement. - */ - prev_evalskip = evalskip; - prev_skipcount = skipcount; - evalskip = 0; - - last_trapsig = i; - savestatus = exitstatus; - setstackmark(&smark); - evalstring(stsavestr(trap[i]), 0); - popstackmark(&smark); - - /* - * If such a command was not - * already in progress, allow a - * break/continue/return in the - * trap action to have an effect - * outside of it. - */ - if (evalskip == 0 || - prev_evalskip != 0) { - evalskip = prev_evalskip; - skipcount = prev_skipcount; - exitstatus = savestatus; - } - - if (i == SIGCHLD) - ignore_sigchld--; - } - break; - } - } - if (i >= NSIG) - break; - } - in_dotrap--; -} - - -/* - * Controls whether the shell is interactive or not based on iflag. - */ -void -setinteractive(void) -{ - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); -} - - -/* - * Called to exit the shell. - */ -void -exitshell(int status) -{ - TRACE(("exitshell(%d) pid=%d\n", status, getpid())); - exiting = 1; - exiting_exitstatus = status; - exitshell_savedstatus(); -} - -void -exitshell_savedstatus(void) -{ - struct jmploc loc1, loc2; - char *p; - int sig = 0; - sigset_t sigs; - - if (!exiting) { - if (in_dotrap && last_trapsig) { - sig = last_trapsig; - exiting_exitstatus = sig + 128; - } else - exiting_exitstatus = oexitstatus; - } - exitstatus = oexitstatus = exiting_exitstatus; - if (!setjmp(loc1.loc)) { - handler = &loc1; - if ((p = trap[0]) != NULL && *p != '\0') { - /* - * Reset evalskip, or the trap on EXIT could be - * interrupted if the last command was a "return". - */ - evalskip = 0; - trap[0] = NULL; - FORCEINTON; - evalstring(p, 0); - } - } - if (!setjmp(loc2.loc)) { - handler = &loc2; /* probably unnecessary */ - FORCEINTON; - flushall(); -#if JOBS - setjobctl(0); -#endif - } - if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN && - sig != SIGTTOU) { - signal(sig, SIG_DFL); - sigemptyset(&sigs); - sigaddset(&sigs, sig); - sigprocmask(SIG_UNBLOCK, &sigs, NULL); - kill(getpid(), sig); - /* If the default action is to ignore, fall back to _exit(). */ - } - _exit(exiting_exitstatus); -} diff --git a/bin/catsh/trap.h b/bin/catsh/trap.h deleted file mode 100644 index 2898c594..00000000 --- a/bin/catsh/trap.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)trap.h 8.3 (Berkeley) 6/5/95 - * $FreeBSD: releng/12.0/bin/sh/trap.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -extern volatile sig_atomic_t pendingsig; -extern volatile sig_atomic_t pendingsig_waitcmd; - -void clear_traps(void); -int have_traps(void); -void setsignal(int); -void ignoresig(int); -int issigchldtrapped(void); -void onsig(int); -void dotrap(void); -void setinteractive(void); -void exitshell(int) __dead2; -void exitshell_savedstatus(void) __dead2; diff --git a/bin/catsh/var.c b/bin/catsh/var.c deleted file mode 100644 index 435d3307..00000000 --- a/bin/catsh/var.c +++ /dev/null @@ -1,982 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: releng/12.0/bin/sh/var.c 329221 2018-02-13 16:48:57Z bdrewery $"); - -#include <unistd.h> -#include <stdlib.h> -#include <paths.h> - -/* - * Shell variables. - */ - -#include <locale.h> -#include <langinfo.h> - -#include "shell.h" -#include "output.h" -#include "expand.h" -#include "nodes.h" /* for other headers */ -#include "eval.h" /* defines cmdenviron */ -#include "exec.h" -#include "syntax.h" -#include "options.h" -#include "mail.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "parser.h" -#include "builtins.h" -#ifndef NO_HISTORY -#include "myhistedit.h" -#endif - - -#ifndef VTABSIZE -#define VTABSIZE 39 -#endif - - -struct varinit { - struct var *var; - int flags; - const char *text; - void (*func)(const char *); -}; - - -#ifndef NO_HISTORY -struct var vhistfile; -struct var vhistsize; -struct var vpslit; -struct var vterm; -#endif -struct var venv; -struct var vifs; -struct var vmail; -struct var vmpath; -struct var vpath; -struct var vps0; -struct var vps1; -struct var vps2; -struct var vps4; -struct var vrps1; -struct var vrps2; -static struct var voptind; -struct var vdisvfork; - -struct localvar *localvars; -int forcelocal; - -#define XDG_CONFIG_HOME "${XDG_CONFIG_HOME:-${HOME}/.config}" -#define XDG_DATA_HOME "${XDG_DATA_HOME:-${HOME}/.local/share}" - -static const struct varinit varinit[] = { - { &venv, 0, "ENV=" XDG_CONFIG_HOME "/catsh/env.sh", - NULL }, -#ifndef NO_HISTORY - { &vhistfile, 0, "HISTFILE=" XDG_DATA_HOME "/catsh/history", - sethistfile }, - { &vhistsize, VUNSET, "HISTSIZE=", - sethistsize }, -#endif - { &vifs, 0, "IFS= \t\n", - NULL }, - { &vmail, VUNSET, "MAIL=", - NULL }, - { &vmpath, VUNSET, "MAILPATH=", - NULL }, - { &vpath, 0, "PATH=" _PATH_DEFPATH, - changepath }, - { &vps0, VUNSET, "PS0=", - NULL }, - { &vps1, 0, "PS1=\\$ ", - NULL }, - { &vps2, 0, "PS2=> ", - NULL }, - { &vps4, 0, "PS4=+ ", - NULL }, - { &vrps1, VUNSET, "RPS1=", - NULL }, - { &vrps2, VUNSET, "RPS2=", - NULL }, -#ifndef NO_HISTORY - { &vpslit, VUNSET, "PSlit=", - setpslit }, - { &vterm, VUNSET, "TERM=", - setterm }, -#endif - { &voptind, 0, "OPTIND=1", - getoptsreset }, - { &vdisvfork, VUNSET, "SH_DISABLE_VFORK=", - NULL }, - { NULL, 0, NULL, - NULL } -}; - -static struct var *vartab[VTABSIZE]; - -static const char *const locale_names[7] = { - "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", - "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL -}; -static const int locale_categories[7] = { - LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0 -}; - -static int varequal(const char *, const char *); -static struct var *find_var(const char *, struct var ***, int *); -static int localevar(const char *); -static void setvareq_const(const char *s, int flags); - -extern char **environ; - -/* - * This routine initializes the builtin variables and imports the environment. - * It is called when the shell is initialized. - */ - -void -initvar(void) -{ - char ppid[20]; - const struct varinit *ip; - struct var *vp; - struct var **vpp; - char **envp; - - for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { - if (find_var(ip->text, &vpp, &vp->name_len) != NULL) - continue; - vp->next = *vpp; - *vpp = vp; - vp->text = __DECONST(char *, ip->text); - vp->flags = ip->flags | VSTRFIXED | VTEXTFIXED; - vp->func = ip->func; - } - fmtstr(ppid, sizeof(ppid), "%d", (int)getppid()); - setvarsafe("PPID", ppid, 0); - for (envp = environ ; *envp ; envp++) { - if (strchr(*envp, '=')) { - setvareq(*envp, VEXPORT|VTEXTFIXED); - } - } - setvareq_const("OPTIND=1", 0); - setvareq_const("IFS= \t\n", 0); -} - -/* - * Safe version of setvar, returns 1 on success 0 on failure. - */ - -int -setvarsafe(const char *name, const char *val, int flags) -{ - struct jmploc jmploc; - struct jmploc *const savehandler = handler; - int err = 0; - int inton; - - inton = is_int_on(); - if (setjmp(jmploc.loc)) - err = 1; - else { - handler = &jmploc; - setvar(name, val, flags); - } - handler = savehandler; - SETINTON(inton); - return err; -} - -/* - * Set the value of a variable. The flags argument is stored with the - * flags of the variable. If val is NULL, the variable is unset. - */ - -void -setvar(const char *name, const char *val, int flags) -{ - const char *p; - size_t len; - size_t namelen; - size_t vallen; - char *nameeq; - int isbad; - - isbad = 0; - p = name; - if (! is_name(*p)) - isbad = 1; - p++; - for (;;) { - if (! is_in_name(*p)) { - if (*p == '\0' || *p == '=') - break; - isbad = 1; - } - p++; - } - namelen = p - name; - if (isbad) - error("%.*s: bad variable name", (int)namelen, name); - len = namelen + 2; /* 2 is space for '=' and '\0' */ - if (val == NULL) { - flags |= VUNSET; - vallen = 0; - } else { - vallen = strlen(val); - len += vallen; - } - INTOFF; - nameeq = ckmalloc(len); - memcpy(nameeq, name, namelen); - nameeq[namelen] = '='; - if (val) - memcpy(nameeq + namelen + 1, val, vallen + 1); - else - nameeq[namelen + 1] = '\0'; - setvareq(nameeq, flags); - INTON; -} - -static int -localevar(const char *s) -{ - const char *const *ss; - - if (*s != 'L') - return 0; - if (varequal(s + 1, "ANG")) - return 1; - if (strncmp(s + 1, "C_", 2) != 0) - return 0; - if (varequal(s + 3, "ALL")) - return 1; - for (ss = locale_names; *ss ; ss++) - if (varequal(s + 3, *ss + 3)) - return 1; - return 0; -} - - -/* - * Sets/unsets an environment variable from a pointer that may actually be a - * pointer into environ where the string should not be manipulated. - */ -static void -change_env(const char *s, int set) -{ - char *eqp; - char *ss; - - INTOFF; - ss = savestr(s); - if ((eqp = strchr(ss, '=')) != NULL) - *eqp = '\0'; - if (set && eqp != NULL) - (void) setenv(ss, eqp + 1, 1); - else - (void) unsetenv(ss); - ckfree(ss); - INTON; - - return; -} - - -/* - * Same as setvar except that the variable and value are passed in - * the first argument as name=value. Since the first argument will - * be actually stored in the table, it should not be a string that - * will go away. - */ - -void -setvareq(char *s, int flags) -{ - struct var *vp, **vpp; - int nlen; - - if (aflag) - flags |= VEXPORT; - if (forcelocal && !(flags & (VNOSET | VNOLOCAL))) - mklocal(s); - vp = find_var(s, &vpp, &nlen); - if (vp != NULL) { - if (vp->flags & VREADONLY) { - if ((flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(s); - error("%.*s: is read only", vp->name_len, vp->text); - } - if (flags & VNOSET) { - if ((flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(s); - return; - } - INTOFF; - - if (vp->func && (flags & VNOFUNC) == 0) - (*vp->func)(s + vp->name_len + 1); - - if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(vp->text); - - vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); - vp->flags |= flags; - vp->text = s; - - /* - * We could roll this to a function, to handle it as - * a regular variable function callback, but why bother? - * - * Note: this assumes iflag is not set to 1 initially. - * As part of initvar(), this is called before arguments - * are looked at. - */ - if ((vp == &vmpath || (vp == &vmail && ! mpathset())) && - iflag == 1) - chkmail(1); - if ((vp->flags & VEXPORT) && localevar(s)) { - change_env(s, 1); - (void) setlocale(LC_ALL, ""); - updatecharset(); - } - INTON; - return; - } - /* not found */ - if (flags & VNOSET) { - if ((flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(s); - return; - } - INTOFF; - vp = ckmalloc(sizeof (*vp)); - vp->flags = flags; - vp->text = s; - vp->name_len = nlen; - vp->next = *vpp; - vp->func = NULL; - *vpp = vp; - if ((vp->flags & VEXPORT) && localevar(s)) { - change_env(s, 1); - (void) setlocale(LC_ALL, ""); - updatecharset(); - } - INTON; -} - - -static void -setvareq_const(const char *s, int flags) -{ - setvareq(__DECONST(char *, s), flags | VTEXTFIXED); -} - - -/* - * Process a linked list of variable assignments. - */ - -void -listsetvar(struct arglist *list, int flags) -{ - int i; - - INTOFF; - for (i = 0; i < list->count; i++) - setvareq(savestr(list->args[i]), flags); - INTON; -} - - - -/* - * Find the value of a variable. Returns NULL if not set. - */ - -char * -lookupvar(const char *name) -{ - struct var *v; - - v = find_var(name, NULL, NULL); - if (v == NULL || v->flags & VUNSET) - return NULL; - return v->text + v->name_len + 1; -} - - - -/* - * Search the environment of a builtin command. If the second argument - * is nonzero, return the value of a variable even if it hasn't been - * exported. - */ - -char * -bltinlookup(const char *name, int doall) -{ - struct var *v; - char *result; - int i; - - result = NULL; - if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { - if (varequal(cmdenviron->args[i], name)) - result = strchr(cmdenviron->args[i], '=') + 1; - } - if (result != NULL) - return result; - - v = find_var(name, NULL, NULL); - if (v == NULL || v->flags & VUNSET || - (!doall && (v->flags & VEXPORT) == 0)) - return NULL; - return v->text + v->name_len + 1; -} - - -/* - * Set up locale for a builtin (LANG/LC_* assignments). - */ -void -bltinsetlocale(void) -{ - int act = 0; - char *loc, *locdef; - int i; - - if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { - if (localevar(cmdenviron->args[i])) { - act = 1; - break; - } - } - if (!act) - return; - loc = bltinlookup("LC_ALL", 0); - INTOFF; - if (loc != NULL) { - setlocale(LC_ALL, loc); - INTON; - updatecharset(); - return; - } - locdef = bltinlookup("LANG", 0); - for (i = 0; locale_names[i] != NULL; i++) { - loc = bltinlookup(locale_names[i], 0); - if (loc == NULL) - loc = locdef; - if (loc != NULL) - setlocale(locale_categories[i], loc); - } - INTON; - updatecharset(); -} - -/* - * Undo the effect of bltinlocaleset(). - */ -void -bltinunsetlocale(void) -{ - int i; - - INTOFF; - if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { - if (localevar(cmdenviron->args[i])) { - setlocale(LC_ALL, ""); - updatecharset(); - break; - } - } - INTON; -} - -/* - * Update the localeisutf8 flag. - */ -void -updatecharset(void) -{ - char *charset; - - charset = nl_langinfo(CODESET); - localeisutf8 = !strcmp(charset, "UTF-8"); -} - -void -initcharset(void) -{ - updatecharset(); - initial_localeisutf8 = localeisutf8; -} - -/* - * Generate a list of exported variables. This routine is used to construct - * the third argument to execve when executing a program. - */ - -char ** -environment(void) -{ - int nenv; - struct var **vpp; - struct var *vp; - char **env, **ep; - - nenv = 0; - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - nenv++; - } - ep = env = stalloc((nenv + 1) * sizeof *env); - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - *ep++ = vp->text; - } - *ep = NULL; - return env; -} - - -static int -var_compare(const void *a, const void *b) -{ - const char *const *sa, *const *sb; - - sa = a; - sb = b; - /* - * This compares two var=value strings which creates a different - * order from what you would probably expect. POSIX is somewhat - * ambiguous on what should be sorted exactly. - */ - return strcoll(*sa, *sb); -} - - -/* - * Command to list all variables which are set. This is invoked from the - * set command when it is called without any options or operands. - */ - -int -showvarscmd(int argc __unused, char **argv __unused) -{ - struct var **vpp; - struct var *vp; - const char *s; - const char **vars; - int i, n; - - /* - * POSIX requires us to sort the variables. - */ - n = 0; - for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { - for (vp = *vpp; vp; vp = vp->next) { - if (!(vp->flags & VUNSET)) - n++; - } - } - - INTOFF; - vars = ckmalloc(n * sizeof(*vars)); - i = 0; - for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { - for (vp = *vpp; vp; vp = vp->next) { - if (!(vp->flags & VUNSET)) - vars[i++] = vp->text; - } - } - - qsort(vars, n, sizeof(*vars), var_compare); - for (i = 0; i < n; i++) { - /* - * Skip improper variable names so the output remains usable as - * shell input. - */ - if (!isassignment(vars[i])) - continue; - s = strchr(vars[i], '='); - s++; - outbin(vars[i], s - vars[i], out1); - out1qstr(s); - out1c('\n'); - } - ckfree(vars); - INTON; - - return 0; -} - - - -/* - * The export and readonly commands. - */ - -int -exportcmd(int argc __unused, char **argv) -{ - struct var **vpp; - struct var *vp; - char **ap; - char *name; - char *p; - char *cmdname; - int ch, values; - int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; - - cmdname = argv[0]; - values = 0; - while ((ch = nextopt("p")) != '\0') { - switch (ch) { - case 'p': - values = 1; - break; - } - } - - if (values && *argptr != NULL) - error("-p requires no arguments"); - if (*argptr != NULL) { - for (ap = argptr; (name = *ap) != NULL; ap++) { - if ((p = strchr(name, '=')) != NULL) { - p++; - } else { - vp = find_var(name, NULL, NULL); - if (vp != NULL) { - vp->flags |= flag; - if ((vp->flags & VEXPORT) && localevar(vp->text)) { - change_env(vp->text, 1); - (void) setlocale(LC_ALL, ""); - updatecharset(); - } - continue; - } - } - setvar(name, p, flag); - } - } else { - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) { - if (vp->flags & flag) { - if (values) { - /* - * Skip improper variable names - * so the output remains usable - * as shell input. - */ - if (!isassignment(vp->text)) - continue; - out1str(cmdname); - out1c(' '); - } - if (values && !(vp->flags & VUNSET)) { - outbin(vp->text, - vp->name_len + 1, out1); - out1qstr(vp->text + - vp->name_len + 1); - } else - outbin(vp->text, vp->name_len, - out1); - out1c('\n'); - } - } - } - } - return 0; -} - - -/* - * The "local" command. - */ - -int -localcmd(int argc __unused, char **argv __unused) -{ - char *name; - - nextopt(""); - if (! in_function()) - error("Not in a function"); - while ((name = *argptr++) != NULL) { - mklocal(name); - } - return 0; -} - - -/* - * Make a variable a local variable. When a variable is made local, it's - * value and flags are saved in a localvar structure. The saved values - * will be restored when the shell function returns. We handle the name - * "-" as a special case. - */ - -void -mklocal(char *name) -{ - struct localvar *lvp; - struct var **vpp; - struct var *vp; - - INTOFF; - lvp = ckmalloc(sizeof (struct localvar)); - if (name[0] == '-' && name[1] == '\0') { - lvp->text = ckmalloc(sizeof optval); - memcpy(lvp->text, optval, sizeof optval); - vp = NULL; - } else { - vp = find_var(name, &vpp, NULL); - if (vp == NULL) { - if (strchr(name, '=')) - setvareq(savestr(name), VSTRFIXED | VNOLOCAL); - else - setvar(name, NULL, VSTRFIXED | VNOLOCAL); - vp = *vpp; /* the new variable */ - lvp->text = NULL; - lvp->flags = VUNSET; - } else { - lvp->text = vp->text; - lvp->flags = vp->flags; - vp->flags |= VSTRFIXED|VTEXTFIXED; - if (name[vp->name_len] == '=') - setvareq(savestr(name), VNOLOCAL); - } - } - lvp->vp = vp; - lvp->next = localvars; - localvars = lvp; - INTON; -} - - -/* - * Called after a function returns. - */ - -void -poplocalvars(void) -{ - struct localvar *lvp; - struct var *vp; - int islocalevar; - - INTOFF; - while ((lvp = localvars) != NULL) { - localvars = lvp->next; - vp = lvp->vp; - if (vp == NULL) { /* $- saved */ - memcpy(optval, lvp->text, sizeof optval); - ckfree(lvp->text); - optschanged(); - } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { - vp->flags &= ~VREADONLY; - (void)unsetvar(vp->text); - } else { - islocalevar = (vp->flags | lvp->flags) & VEXPORT && - localevar(lvp->text); - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - vp->flags = lvp->flags; - vp->text = lvp->text; - if (vp->func) - (*vp->func)(vp->text + vp->name_len + 1); - if (islocalevar) { - change_env(vp->text, vp->flags & VEXPORT && - (vp->flags & VUNSET) == 0); - setlocale(LC_ALL, ""); - updatecharset(); - } - } - ckfree(lvp); - } - INTON; -} - - -int -setvarcmd(int argc, char **argv) -{ - if (argc <= 2) - return unsetcmd(argc, argv); - else if (argc == 3) - setvar(argv[1], argv[2], 0); - else - error("too many arguments"); - return 0; -} - - -/* - * The unset builtin command. - */ - -int -unsetcmd(int argc __unused, char **argv __unused) -{ - char **ap; - int i; - int flg_func = 0; - int flg_var = 0; - int ret = 0; - - while ((i = nextopt("vf")) != '\0') { - if (i == 'f') - flg_func = 1; - else - flg_var = 1; - } - if (flg_func == 0 && flg_var == 0) - flg_var = 1; - - INTOFF; - for (ap = argptr; *ap ; ap++) { - if (flg_func) - ret |= unsetfunc(*ap); - if (flg_var) - ret |= unsetvar(*ap); - } - INTON; - return ret; -} - - -/* - * Unset the specified variable. - * Called with interrupts off. - */ - -int -unsetvar(const char *s) -{ - struct var **vpp; - struct var *vp; - - vp = find_var(s, &vpp, NULL); - if (vp == NULL) - return (0); - if (vp->flags & VREADONLY) - return (1); - if (vp->text[vp->name_len + 1] != '\0') - setvar(s, "", 0); - if ((vp->flags & VEXPORT) && localevar(vp->text)) { - change_env(s, 0); - setlocale(LC_ALL, ""); - updatecharset(); - } - vp->flags &= ~VEXPORT; - vp->flags |= VUNSET; - if ((vp->flags & VSTRFIXED) == 0) { - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - *vpp = vp->next; - ckfree(vp); - } - return (0); -} - - - -/* - * Returns true if the two strings specify the same variable. The first - * variable name is terminated by '='; the second may be terminated by - * either '=' or '\0'. - */ - -static int -varequal(const char *p, const char *q) -{ - while (*p == *q++) { - if (*p++ == '=') - return 1; - } - if (*p == '=' && *(q - 1) == '\0') - return 1; - return 0; -} - -/* - * Search for a variable. - * 'name' may be terminated by '=' or a NUL. - * vppp is set to the pointer to vp, or the list head if vp isn't found - * lenp is set to the number of characters in 'name' - */ - -static struct var * -find_var(const char *name, struct var ***vppp, int *lenp) -{ - unsigned int hashval; - int len; - struct var *vp, **vpp; - const char *p = name; - - hashval = 0; - while (*p && *p != '=') - hashval = 2 * hashval + (unsigned char)*p++; - len = p - name; - - if (lenp) - *lenp = len; - vpp = &vartab[hashval % VTABSIZE]; - if (vppp) - *vppp = vpp; - - for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { - if (vp->name_len != len) - continue; - if (memcmp(vp->text, name, len) != 0) - continue; - if (vppp) - *vppp = vpp; - return vp; - } - return NULL; -} diff --git a/bin/catsh/var.h b/bin/catsh/var.h deleted file mode 100644 index 1e6420fd..00000000 --- a/bin/catsh/var.h +++ /dev/null @@ -1,140 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)var.h 8.2 (Berkeley) 5/4/95 - * $FreeBSD: releng/12.0/bin/sh/var.h 326025 2017-11-20 19:49:47Z pfg $ - */ - -/* - * Shell variables. - */ - -/* flags */ -#define VEXPORT 0x01 /* variable is exported */ -#define VREADONLY 0x02 /* variable cannot be modified */ -#define VSTRFIXED 0x04 /* variable struct is statically allocated */ -#define VTEXTFIXED 0x08 /* text is statically allocated */ -#define VSTACK 0x10 /* text is allocated on the stack */ -#define VUNSET 0x20 /* the variable is not set */ -#define VNOFUNC 0x40 /* don't call the callback function */ -#define VNOSET 0x80 /* do not set variable - just readonly test */ -#define VNOLOCAL 0x100 /* ignore forcelocal */ - - -struct var { - struct var *next; /* next entry in hash list */ - int flags; /* flags are defined above */ - int name_len; /* length of name */ - char *text; /* name=value */ - void (*func)(const char *); - /* function to be called when */ - /* the variable gets set/unset */ -}; - - -struct localvar { - struct localvar *next; /* next local variable in list */ - struct var *vp; /* the variable that was made local */ - int flags; /* saved flags */ - char *text; /* saved text */ -}; - - -extern struct localvar *localvars; -extern int forcelocal; - -extern struct var vifs; -extern struct var vmail; -extern struct var vmpath; -extern struct var vpath; -extern struct var vps0; -extern struct var vps1; -extern struct var vps2; -extern struct var vps4; -extern struct var vrps1; -extern struct var vrps2; -extern struct var vdisvfork; -#ifndef NO_HISTORY -extern struct var vhistfile; -extern struct var vhistsize; -extern struct var vterm; -#endif - -extern int localeisutf8; -/* The parser uses the locale that was in effect at startup. */ -extern int initial_localeisutf8; - -/* - * The following macros access the values of the above variables. - * They have to skip over the name. They return the null string - * for unset variables. - */ - -#define ifsval() (vifs.text + 4) -#define ifsset() ((vifs.flags & VUNSET) == 0) -#define mailval() (vmail.text + 5) -#define mpathval() (vmpath.text + 9) -#define pathval() (vpath.text + 5) -#define ps0val() (vps0.text + 4) -#define ps1val() (vps1.text + 4) -#define ps2val() (vps2.text + 4) -#define ps4val() (vps4.text + 4) -#define rps1val() (vrps1.text + 5) -#define rps2val() (vrps2.text + 5) -#define optindval() (voptind.text + 7) -#ifndef NO_HISTORY -#define histfileval() (vhistfile.text + 9) -#define histsizeval() (vhistsize.text + 9) -#define termval() (vterm.text + 5) -#endif - -#define mpathset() ((vmpath.flags & VUNSET) == 0) -#define disvforkset() ((vdisvfork.flags & VUNSET) == 0) - -void initvar(void); -void setvar(const char *, const char *, int); -void setvareq(char *, int); -struct arglist; -void listsetvar(struct arglist *, int); -char *lookupvar(const char *); -char *bltinlookup(const char *, int); -void bltinsetlocale(void); -void bltinunsetlocale(void); -void updatecharset(void); -void initcharset(void); -char **environment(void); -int showvarscmd(int, char **); -void mklocal(char *); -void poplocalvars(void); -int unsetvar(const char *); -int setvarsafe(const char *, const char *, int); |