diff -Nru ash-1.6.1.orig/alias.c ash-1.6.1/alias.c --- ash-1.6.1.orig/alias.c 2003-08-08 06:04:50.000000000 +0300 +++ ash-1.6.1/alias.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/arith_lex.l ash-1.6.1/arith_lex.l --- ash-1.6.1.orig/arith_lex.l 2003-08-08 06:04:50.000000000 +0300 +++ ash-1.6.1/arith_lex.l 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95"; @@ -54,6 +57,7 @@ result = (*buf = *arith_buf++) ? 1 : YY_NULL; #define YY_NO_UNPUT %} +%option noyywrap %% [ \t\n] { ; } diff -Nru ash-1.6.1.orig/arith.y ash-1.6.1/arith.y --- ash-1.6.1.orig/arith.y 2003-09-19 06:05:43.000000000 +0300 +++ ash-1.6.1/arith.y 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95"; @@ -191,7 +194,6 @@ const char *s; { - yyerrok; yyclearin; arith_lex_reset(); /* reprime lex */ error("arithmetic expression: %s: \"%s\"", s, arith_startbuf); diff -Nru ash-1.6.1.orig/bltin/echo.c ash-1.6.1/bltin/echo.c --- ash-1.6.1.orig/bltin/echo.c 2003-08-08 06:04:53.000000000 +0300 +++ ash-1.6.1/bltin/echo.c 2010-01-08 14:49:49.000000000 +0200 @@ -54,7 +54,7 @@ #define main echocmd -#include "bltin.h" +#include "bltin/bltin.h" int main(int argc, char **argv) diff -Nru ash-1.6.1.orig/bltin/kill.1 ash-1.6.1/bltin/kill.1 --- ash-1.6.1.orig/bltin/kill.1 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/kill.1 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,143 @@ +.\" $NetBSD: kill.1,v 1.17 2003/02/25 10:34:38 wiz Exp $ +.\" +.\" 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 +.\" +.Dd April 28, 1995 +.Dt 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 signal_number +.Nm +.Fl signal_name +.Ar pid +\&... +.Nm +.Fl signal_number +.Ar pid +\&... +.Sh DESCRIPTION +The +.Nm +utility sends a signal to the process(es) specified +by the pid operand(s). +.Pp +Only the super-user may send signals to other users' processes. +.Pp +The options are as follows: +.Pp +.Bl -tag -width Ds +.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 signal_number +If no operand is given, list the signal names; otherwise, write +the signal name corresponding to +.Ar signal_number +provided. +.It Fl signal_name +A symbolic signal name specifying the signal to be sent instead of the +default +.Dv TERM . +.It Fl 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 Ds -compact +.It -1 +If superuser, broadcast the signal to all processes; otherwise broadcast +to all processes belonging to the user. +.It 0 +Broadcast the signal to all processes in the current process group +belonging to the user. +.El +.Pp +Some of the more commonly used signals: +.Bl -tag -width Ds -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 +.Nm +is a built-in to +.Xr csh 1 ; +it allows job specifiers of the form ``%...'' as arguments +so process id's are not as often used as +.Nm +arguments. +See +.Xr csh 1 +for details. +.Sh SEE ALSO +.Xr csh 1 , +.Xr pgrep 1 , +.Xr pkill 1 , +.Xr ps 1 , +.Xr kill 2 , +.Xr sigaction 2 , +.Xr signal 7 +.Sh STANDARDS +The +.Nm +function is expected to be +.St -p1003.2 +compatible. +.Sh HISTORY +A +.Nm +command appeared in +.At v6 . diff -Nru ash-1.6.1.orig/bltin/kill.c ash-1.6.1/bltin/kill.c --- ash-1.6.1.orig/bltin/kill.c 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/kill.c 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,263 @@ +/* $NetBSD: kill.c,v 1.22 2003/08/04 22:31:24 jschauma Exp $ */ + +/* + * 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. + */ + +#include +#ifndef __RCSID +#define __RCSID(arg) +#endif +#ifndef __COPYRIGHT +#define __COPYRIGHT(arg) +#endif +#if !defined(lint) && !defined(SHELL) +__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95"; +#else +__RCSID("$NetBSD: kill.c,v 1.22 2003/08/04 22:31:24 jschauma Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SHELL /* sh (aka ash) builtin */ +#define main killcmd +#include "bltin/bltin.h" +#endif /* SHELL */ + +static void nosig(char *); +static void printsignals(FILE *); +static int signame_to_signum(char *); +static void usage(void); +int main(int, char *[]); + +int +main(int argc, char *argv[]) +{ + int errors, numsig, pid; + char *ep; + +#ifndef SHELL + setprogname(argv[0]); +#endif + setlocale(LC_ALL, ""); + if (argc < 2) + usage(); + + numsig = SIGTERM; + + argc--, argv++; + if (strcmp(*argv, "-l") == 0) { + argc--, argv++; + if (argc > 1) + usage(); + if (argc == 1) { + if (isdigit((unsigned char)**argv) == 0) + usage(); + numsig = strtol(*argv, &ep, 10); + if (*ep != '\0') { + errx(EXIT_FAILURE, "illegal signal number: %s", + *argv); + /* NOTREACHED */ + } + if (numsig >= 128) + numsig -= 128; + if (numsig <= 0 || numsig >= NSIG) + nosig(*argv); +#ifdef _GNU_SOURCE + printf("%s\n", strsignal(numsig)); +#else + printf("%s\n", sys_signame[numsig]); +#endif + exit(0); + } + printsignals(stdout); + exit(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; + if (isalpha((unsigned char)**argv)) { + if ((numsig = signame_to_signum(*argv)) < 0) + nosig(*argv); + } else if (isdigit((unsigned char)**argv)) { + numsig = strtol(*argv, &ep, 10); + if (!*argv || *ep) { + errx(EXIT_FAILURE, "illegal signal number: %s", + *argv); + /* NOTREACHED */ + } + if (numsig < 0 || numsig >= NSIG) + nosig(*argv); + } else + nosig(*argv); + argc--, argv++; + } + + if (argc == 0) + usage(); + + for (errors = 0; argc; argc--, argv++) { +#ifdef SHELL + extern int getjobpgrp(const char *); + if (*argv[0] == '%') { + pid = getjobpgrp(*argv); + if (pid == 0) { + warnx("illegal job id: %s", *argv); + errors = 1; + continue; + } + } else +#endif + { + pid = strtol(*argv, &ep, 10); + if (!**argv || *ep) { + warnx("illegal process id: %s", *argv); + errors = 1; + continue; + } + } + if (kill(pid, numsig) == -1) { + warn("%s", *argv); + errors = 1; + } +#ifdef SHELL + /* Wakeup the process if it was suspended, so it can + exit without an explicit 'fg'. */ + if (numsig == SIGTERM || numsig == SIGHUP) + kill(pid, SIGCONT); +#endif + } + + exit(errors); + /* NOTREACHED */ +} + +static int +signame_to_signum(char *sig) +{ + int n; + + if (strncasecmp(sig, "sig", 3) == 0) + sig += 3; + for (n = 1; n < NSIG; n++) { +#ifdef _GNU_SOURCE + if (!strcasecmp(strsignal(n), sig)) +#else + if (!strcasecmp(sys_signame[n], sig)) +#endif + return (n); + } + return (-1); +} + +static void +nosig(char *name) +{ + + warnx("unknown signal %s; valid signals:", name); + printsignals(stderr); + exit(1); + /* NOTREACHED */ +} + +static void +printsignals(FILE *fp) +{ + int sig; + int len, nl; + const char *name; + int termwidth = 80; + + if (isatty(fileno(fp))) { + struct winsize win; + if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0) + termwidth = win.ws_col; + } + + for (len = 0, sig = 1; sig < NSIG; sig++) { +#ifdef _GNU_SOURCE + name = strsignal(sig); +#else + name = sys_signame[sig]; +#endif + nl = 1 + strlen(name); + + if (len + nl >= termwidth) { + fprintf(fp, "\n"); + len = 0; + } else + if (len != 0) + fprintf(fp, " "); + len += nl; + fprintf(fp, "%s", name); + } + if (len != 0) + fprintf(fp, "\n"); +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: %s [-s signal_name] pid ...\n" + " %s -l [exit_status]\n" + " %s -signal_name pid ...\n" + " %s -signal_number pid ...\n", + getprogname(), getprogname(), getprogname(), getprogname()); + exit(1); + /* NOTREACHED */ +} diff -Nru ash-1.6.1.orig/bltin/printf.1 ash-1.6.1/bltin/printf.1 --- ash-1.6.1.orig/bltin/printf.1 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/printf.1 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,389 @@ +.\" $NetBSD: printf.1,v 1.19 2003/04/28 09:38:19 wiz Exp $ +.\" +.\" 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. +.\" +.\" from: @(#)printf.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd November 5, 1993 +.Dt PRINTF 1 +.Os +.Sh NAME +.Nm printf +.Nd formatted output +.Sh SYNOPSIS +.Nm +.Ar format +.Op Ar arguments ... +.Sh DESCRIPTION +.Nm +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 b , +.Cm B , +.Cm c , +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 +.Tn ASCII +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 +.St -ansiC . +The characters and their meanings are as follows: +.Bl -tag -width Ds -offset indent +.It Cm \ee +Write an +.Aq escape +character. +.It Cm \ea +Write a +.Aq bell +character. +.It Cm \eb +Write a +.Aq backspace +character. +.It Cm \ef +Write a +.Aq form-feed +character. +.It Cm \en +Write a +.Aq new-line +character. +.It Cm \er +Write a +.Aq carriage return +character. +.It Cm \et +Write a +.Aq tab +character. +.It Cm \ev +Write a +.Aq vertical tab +character. +.It Cm \e\' +Write a +.Aq single quote +character. +.It Cm \e" +Write a +.Aq double quote +character. +.It Cm \e\e +Write a backslash character. +.It Cm \e Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit octal number +.Ar num . +.It Cm \ex Ns Ar xx +Write an 8\-bit character whose +.Tn ASCII +value is the 1\- or 2\-digit hexadecimal number +.Ar xx . +.El +.Pp +Each format specification is introduced by the percent character +.Pq Dq \&% . +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 +.Sq # +character specifying that the value should be printed in an +.Dq alternative form . +For +.Cm b , +.Cm c , +.Cm d , +and +.Cm s +formats, this option has no effect. +For the +.Cm o +format 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 e , +.Cm E , +.Cm f , +.Cm 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. +.\" I turned this off - decided it isn't a valid use of '#' +.\" For the +.\" .Cm B +.\" format, backslash-escape sequences are expanded first; +.It Cm \&\- +A minus sign +.Sq \- +which specifies +.Em left adjustment +of the output in the indicated field; +.It Cm \&+ +A +.Sq \&+ +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 +.Sq \&+ +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 +.Sq \- +overrides a +.Sq \&0 +if both are used; +.El +.It Field Width : +An optional digit string specifying a +.Em field width ; +if the output string has fewer characters 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 characters to be printed +from a string +.Sm off +.Pf ( Cm b , +.Sm on +.Cm B , +and +.Cm s +formats); 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 diouxXfwEgGbBcs ) . +.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 f +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]ddd Cm \&. No ddd +.Sm on +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. +.It Cm eE +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd +.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. +An upper-case E is used for an +.Sq E +format. +.It Cm gG +The +.Ar argument +is printed in style +.Cm f +or in style +.Cm e +.Pq Cm E +whichever gives full precision in minimum space. +.It Cm b +Characters from the string +.Ar argument +are printed with backslash-escape sequences expanded. +.br +The following additional backslash-escape sequences are supported: +.Bl -tag -width Ds +.It Cm \ec +Causes +.Nm +to ignore any remaining characters in the string operand containing it, +any remaining string operands, and any additional characters in +the format operand. +.It Cm \e0 Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit +octal number +.Ar num . +.It Cm \e^ Ns Ar c +Write the control character +.Ar c . +Generates characters `\e000' through `\e037`, and `\e177' (from `\e^?'). +.It Cm \eM\- Ns Ar c +Write the character +.Ar c +with the 8th bit set. +Generates characters `\e241' through `\e376`. +.It Cm \eM^ Ns Ar c +Write the control character +.Ar c +with the 8th bit set. +Generates characters `\e000' through `\e037`, and `\e177' (from `\eM^?'). +.El +.It Cm B +Characters from the string +.Ar argument +are printed with unprintable characters backslash-escaped using the +.Sm off +.Pf ` Cm \e Ar c No ', +.Pf ` Cm \e^ Ar c No ', +.Pf ` Cm \eM\- Ar c No ' +or +.Pf ` Cm \eM^ Ar c No ', +.Sm on +formats described above. +.It Cm c +The first character of +.Ar argument +is printed. +.It Cm s +Characters from the string +.Ar argument +are printed until the end is reached or until the number of characters +indicated by the precision specification is reached; if the +precision is omitted, all characters in the string are printed. +.It Cm \&% +Print a `%'; no argument is used. +.El +.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. +.Sh EXIT STATUS +.Nm +exits 0 on success, 1 on failure. +.Sh SEE ALSO +.Xr echo 1 , +.Xr printf 3 , +.Xr vis 3 , +.Xr printf 9 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1-2001 . +.Pp +Support for the floating point formats and `*' as a field width and precision +are optional in POSIX. +.Pp +The behaviour of the %B format and the \e', \e", \exxx, \ee and +\e[M][\-|^]c escape sequences are undefined in POSIX. +.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. +.Pp +Hexadecimal character constants are restricted to, and should be specified +as, two character constants. +This is contrary to the ISO C standard but +does guarantee detection of the end of the constant. diff -Nru ash-1.6.1.orig/bltin/printf.c ash-1.6.1/bltin/printf.c --- ash-1.6.1.orig/bltin/printf.c 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/printf.c 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,662 @@ +/* $NetBSD: printf.c,v 1.28 2003/06/25 12:56:59 dsl Exp $ */ + +/* + * 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. + */ + +#include +#ifndef __RCSID +#define __RCSID(arg) +#endif +#ifndef lint +#if !defined(BUILTIN) && !defined(SHELL) +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif +#endif + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95"; +#else +__RCSID("$NetBSD: printf.c,v 1.28 2003/06/25 12:56:59 dsl Exp $"); +#endif +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define ESCAPE '\e' +#else +#define ESCAPE 033 +#endif + +static void conv_escape_str(char *, void (*)(int)); +static char *conv_escape(char *, char *); +static char *conv_expand(const char *); +static int getchr(void); +static double getdouble(void); +static int getwidth(void); +static intmax_t getintmax(void); +static uintmax_t getuintmax(void); +static char *getstr(void); +static char *mklong(const char *, int); +static void check_conversion(const char *, const char *); +static void usage(void); + +static void b_count(int); +static void b_output(int); +static int b_length; +static char *b_fmt; + +static int rval; +static char **gargv; + +#ifdef BUILTIN /* csh builtin */ +#define main progprintf +#endif + +#ifdef SHELL /* sh (aka ash) builtin */ +#define main printfcmd +#include "bltin/bltin.h" +#endif /* SHELL */ + +#define PF(f, func) { \ + if (fieldwidth != -1) { \ + if (precision != -1) \ + (void)printf(f, fieldwidth, precision, func); \ + else \ + (void)printf(f, fieldwidth, func); \ + } else if (precision != -1) \ + (void)printf(f, precision, func); \ + else \ + (void)printf(f, func); \ +} + +#define APF(cpp, f, func) { \ + if (fieldwidth != -1) { \ + if (precision != -1) \ + (void)asprintf(cpp, f, fieldwidth, precision, func); \ + else \ + (void)asprintf(cpp, f, fieldwidth, func); \ + } else if (precision != -1) \ + (void)asprintf(cpp, f, precision, func); \ + else \ + (void)asprintf(cpp, f, func); \ +} + +int main(int, char **); +int main(int argc, char *argv[]) +{ + char *fmt, *start; + int fieldwidth, precision; + char nextch; + char *format; + int ch; + +#if !defined(SHELL) && !defined(BUILTIN) + (void)setlocale (LC_ALL, ""); +#endif + + while ((ch = getopt(argc, argv, "")) != -1) { + switch (ch) { + case '?': + default: + usage(); + return (1); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + usage(); + return (1); + } + + format = *argv; + gargv = ++argv; + +#define SKIP1 "#-+ 0" +#define SKIP2 "*0123456789" + do { + /* + * 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. + */ + + /* find next format specification */ + for (fmt = format; (ch = *fmt++) ;) { + if (ch == '\\') { + char c_ch; + fmt = conv_escape(fmt, &c_ch); + putchar(c_ch); + continue; + } + if (ch != '%' || (*fmt == '%' && ++fmt)) { + (void)putchar(ch); + continue; + } + + /* Ok - we've found a format specification, + Save its address for a later printf(). */ + start = fmt - 1; + + /* skip to field width */ + fmt += strspn(fmt, SKIP1); + fieldwidth = *fmt == '*' ? getwidth() : -1; + + /* skip to possible '.', get following precision */ + fmt += strspn(fmt, SKIP2); + if (*fmt == '.') + ++fmt; + precision = *fmt == '*' ? getwidth() : -1; + + fmt += strspn(fmt, SKIP2); + + ch = *fmt; + if (!ch) { + warnx("missing format character"); + return (1); + } + /* null terminate format string to we can use it + as an argument to printf. */ + nextch = fmt[1]; + fmt[1] = 0; + switch (ch) { + + case 'B': { + const char *p = conv_expand(getstr()); + *fmt = 's'; + PF(start, p); + break; + } + case 'b': { + /* There has to be a better way to do this, + * but the string we generate might have + * embedded nulls. */ + static char *a, *t; + char *cp = getstr(); + /* Free on entry in case shell longjumped out */ + if (a != NULL) + free(a); + a = NULL; + if (t != NULL) + free(t); + t = NULL; + /* Count number of bytes we want to output */ + b_length = 0; + conv_escape_str(cp, b_count); + t = malloc(b_length + 1); + if (t == NULL) + break; + memset(t, 'x', b_length); + t[b_length] = 0; + /* Get printf to calculate the lengths */ + *fmt = 's'; + APF(&a, start, t); + b_fmt = a; + /* Output leading spaces and data bytes */ + conv_escape_str(cp, b_output); + /* Add any trailing spaces */ + printf("%s", b_fmt); + break; + } + case 'c': { + char p = getchr(); + PF(start, p); + break; + } + case 's': { + char *p = getstr(); + PF(start, p); + break; + } + case 'd': + case 'i': { + intmax_t p = getintmax(); + char *f = mklong(start, ch); + PF(f, p); + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + uintmax_t p = getuintmax(); + char *f = mklong(start, ch); + PF(f, p); + break; + } + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': { + double p = getdouble(); + PF(start, p); + break; + } + default: + warnx("%s: invalid directive", start); + return (1); + } + *fmt++ = ch; + *fmt = nextch; + /* escape if a \c was encountered */ + if (rval & 0x100) + return (rval & ~0x100); + } + } while (gargv != argv && *gargv); + + return (rval); +} + +/* helper functions for conv_escape_str */ + +static void +b_count(int ch) +{ + b_length++; +} + +/* Output one converted character for every 'x' in the 'format' */ + +static void +b_output(int ch) +{ + for (;;) { + switch (*b_fmt++) { + case 0: + b_fmt--; + return; + case ' ': + putchar(' '); + break; + default: + putchar(ch); + return; + } + } +} + + +/* + * Print SysV echo(1) style escape string + * Halts processing string if a \c escape is encountered. + */ +static void +conv_escape_str(char *str, void (*do_putchar)(int)) +{ + int value; + int ch; + char c; + + while ((ch = *str++)) { + if (ch != '\\') { + do_putchar(ch); + continue; + } + + ch = *str++; + if (ch == 'c') { + /* \c as in SYSV echo - abort all processing.... */ + rval |= 0x100; + break; + } + + /* + * %b string octal constants are not like those in C. + * They start with a \0, and are followed by 0, 1, 2, + * or 3 octal digits. + */ + if (ch == '0') { + char octnum[4], *oct_end; + octnum[0] = str[0]; + octnum[1] = str[1]; + octnum[2] = str[2]; + octnum[3] = 0; + do_putchar(strtoul(octnum, &oct_end, 8)); + str += oct_end - octnum; + continue; + } + + /* \[M][^|-]C as defined by vis(3) */ + if (ch == 'M' && *str == '-') { + do_putchar(0200 | str[1]); + str += 2; + continue; + } + if (ch == 'M' && *str == '^') { + str++; + value = 0200; + ch = '^'; + } else + value = 0; + if (ch == '^') { + ch = *str++; + if (ch == '?') + value |= 0177; + else + value |= ch & 037; + do_putchar(value); + continue; + } + + /* Finally test for sequences valid in the format string */ + str = conv_escape(str - 1, &c); + do_putchar(c); + } +} + +/* + * Print "standard" escape characters + */ +static char * +conv_escape(char *str, char *conv_ch) +{ + int value; + int ch; + char num_buf[4], *num_end; + + ch = *str++; + + switch (ch) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + num_buf[0] = ch; + ch = str[0]; + num_buf[1] = ch; + num_buf[2] = ch ? str[1] : 0; + num_buf[3] = 0; + value = strtoul(num_buf, &num_end, 8); + str += num_end - (num_buf + 1); + break; + + case 'x': + /* Hexadecimal character constants are not required to be + supported (by SuS v1) because there is no consistent + way to detect the end of the constant. + Supporting 2 byte constants is a compromise. */ + ch = str[0]; + num_buf[0] = ch; + num_buf[1] = ch ? str[1] : 0; + num_buf[2] = 0; + value = strtoul(num_buf, &num_end, 16); + str += num_end - num_buf; + break; + + case '\\': value = '\\'; break; /* backslash */ + case '\'': value = '\''; break; /* single quote */ + case '"': value = '"'; break; /* double quote */ + case 'a': value = '\a'; break; /* alert */ + case 'b': value = '\b'; break; /* backspace */ + case 'e': value = ESCAPE; break; /* escape */ + case 'f': value = '\f'; break; /* form-feed */ + case 'n': value = '\n'; break; /* newline */ + case 'r': value = '\r'; break; /* carriage-return */ + case 't': value = '\t'; break; /* tab */ + case 'v': value = '\v'; break; /* vertical-tab */ + + default: + warnx("unknown escape sequence `\\%c'", ch); + rval = 1; + value = ch; + break; + } + + *conv_ch = value; + return str; +} + +/* expand a string so that everything is printable */ + +static char * +conv_expand(const char *str) +{ + static char *conv_str; + char *cp; + int ch; + + if (conv_str) + free(conv_str); + /* get a buffer that is definitely large enough.... */ + conv_str = malloc(4 * strlen(str) + 1); + if (!conv_str) + return ""; + cp = conv_str; + + while ((ch = *(unsigned char *)str++)) { + switch (ch) { + /* Use C escapes for expected control characters */ + case '\\': ch = '\\'; break; /* backslash */ + case '\'': ch = '\''; break; /* single quote */ + case '"': ch = '"'; break; /* double quote */ + case '\a': ch = 'a'; break; /* alert */ + case '\b': ch = 'b'; break; /* backspace */ + case ESCAPE: ch = 'e'; break; /* escape */ + case '\f': ch = 'f'; break; /* form-feed */ + case '\n': ch = 'n'; break; /* newline */ + case '\r': ch = 'r'; break; /* carriage-return */ + case '\t': ch = 't'; break; /* tab */ + case '\v': ch = 'v'; break; /* vertical-tab */ + default: + /* Copy anything printable */ + if (isprint(ch)) { + *cp++ = ch; + continue; + } + /* Use vis(3) encodings for the rest */ + *cp++ = '\\'; + if (ch & 0200) { + *cp++ = 'M'; + ch &= ~0200; + } + if (ch == 0177) { + *cp++ = '^'; + *cp++ = '?'; + continue; + } + if (ch < 040) { + *cp++ = '^'; + *cp++ = ch | 0100; + continue; + } + *cp++ = '-'; + *cp++ = ch; + continue; + } + *cp++ = '\\'; + *cp++ = ch; + } + + *cp = 0; + return conv_str; +} + +static char * +mklong(const char *str, int ch) +{ + static char copy[64]; + size_t len; + + len = strlen(str) + 2; + if (len > sizeof copy) { + warnx("format %s too complex\n", str); + len = 4; + } + (void)memmove(copy, str, len - 3); + copy[len - 3] = 'j'; + copy[len - 2] = ch; + copy[len - 1] = '\0'; + return (copy); +} + +static int +getchr(void) +{ + if (!*gargv) + return ('\0'); + return ((int)**gargv++); +} + +static char * +getstr(void) +{ + if (!*gargv) + return (""); + return (*gargv++); +} + +static int +getwidth(void) +{ + long val; + char *s, *ep; + + s = *gargv; + if (!*gargv) + return (0); + gargv++; + + errno = 0; + val = strtoul(s, &ep, 0); + check_conversion(s, ep); + + /* Arbitrarily 'restrict' field widths to 1Mbyte */ + if (val < 0 || val > 1 << 20) { + warnx("%s: invalid field width", s); + return 0; + } + + return val; +} + +static intmax_t +getintmax(void) +{ + intmax_t val; + char *cp, *ep; + + cp = *gargv; + if (cp == NULL) + return 0; + gargv++; + + if (*cp == '\"' || *cp == '\'') + return *(cp+1); + + errno = 0; + val = strtoimax(cp, &ep, 0); + check_conversion(cp, ep); + return val; +} + +static uintmax_t +getuintmax(void) +{ + uintmax_t val; + char *cp, *ep; + + cp = *gargv; + if (cp == NULL) + return 0; + gargv++; + + if (*cp == '\"' || *cp == '\'') + return *(cp+1); + + /* strtoumax won't error -ve values */ + while (isspace(*(unsigned char *)cp)) + cp++; + if (*cp == '-') { + warnx("%s: expected positive numeric value", cp); + rval = 1; + return 0; + } + + errno = 0; + val = strtoumax(cp, &ep, 0); + check_conversion(cp, ep); + return val; +} + +static double +getdouble(void) +{ + double val; + char *ep; + + if (!*gargv) + return (0.0); + + if (**gargv == '\"' || **gargv == '\'') + return (double) *((*gargv++)+1); + + errno = 0; + val = strtod(*gargv, &ep); + check_conversion(*gargv++, ep); + return val; +} + +static void +check_conversion(const char *s, const char *ep) +{ + if (*ep) { + if (ep == s) + warnx("%s: expected numeric value", s); + else + warnx("%s: not completely converted", s); + rval = 1; + } else if (errno == ERANGE) { + warnx("%s: %s", s, strerror(ERANGE)); + rval = 1; + } +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: printf format [arg ...]\n"); +} diff -Nru ash-1.6.1.orig/bltin/test.1 ash-1.6.1/bltin/test.1 --- ash-1.6.1.orig/bltin/test.1 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/test.1 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,309 @@ +.\" $NetBSD: test.1,v 1.18 2002/09/25 15:18:44 wiz Exp $ +.\" +.\" 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 +.\" +.Dd May 31, 1993 +.Dt TEST 1 +.Os +.Sh NAME +.Nm test , +.Nm \&[ +.Nd condition evaluation utility +.Sh SYNOPSIS +.Nm test +.Ar expression +.Nm \&[ +.Ar expression Cm ] +.Sh DESCRIPTION +The +.Nm test +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, test also +returns 1 (false). +.Pp +All operators and flags are separate arguments to the +.Nm test +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. +.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 +.Po Tn FIFO Pc . +.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. +This operator is retained for compatibility with previous versions of +this program. +Do not rely on its existence; use +.Fl h +instead. +.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 \&s\&1 Cm \&= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are identical. +.It Ar \&s\&1 Cm \&!= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are not identical. +.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes before +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes after +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&n\&1 Fl \&eq Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are algebraically +equal. +.It Ar \&n\&1 Fl \&ne Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are not +algebraically equal. +.It Ar \&n\&1 Fl \> Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&ge Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than or equal to the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \< Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&le Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than or equal to the integer +.Ar \&n\&2 . +.El +.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 \&( Ns Ar expression Ns Cm \&) +True if expression is true. +.El +.Pp +The +.Fl a +operator has higher precedence than the +.Fl o +operator. +.Sh GRAMMAR AMBIGUITY +The +.Nm test +grammar is inherently ambiguous. +In order to assure a degree of consistency, the cases described in +.St -p1003.2 +section 4.62.4, +are evaluated consistently according to the rules specified in the +standards document. +All other cases are subject to the ambiguity in the command semantics. +.Sh EXIT STATUS +The +.Nm test +utility exits with one of the following values: +.Bl -tag -width Ds +.It 0 +expression evaluated to true. +.It 1 +expression evaluated to false or expression was +missing. +.It \*[Gt]1 +An error occurred. +.El +.Sh STANDARDS +The +.Nm test +utility implements a superset of the +.St -p1003.2 +specification. diff -Nru ash-1.6.1.orig/bltin/test.c ash-1.6.1/bltin/test.c --- ash-1.6.1.orig/bltin/test.c 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/bltin/test.c 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,486 @@ +/* $NetBSD: test.c,v 1.24 2001/09/16 19:03:26 wiz 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. + */ + +#include +#ifndef __RCSID +#define __RCSID(arg) +#endif +#ifndef lint +__RCSID("$NetBSD: test.c,v 1.24 2001/09/16 19:03:26 wiz Exp $"); +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 ::= +*/ + +enum token { + EOI, + FILRD, + FILWR, + FILEX, + FILEXIST, + FILREG, + FILDIR, + FILCDEV, + FILBDEV, + FILFIFO, + FILSOCK, + FILSYM, + FILGZ, + FILTT, + FILSUID, + FILSGID, + FILSTCK, + FILNT, + FILOT, + FILEQ, + FILUID, + FILGID, + STREZ, + STRNZ, + STREQ, + STRNE, + STRLT, + STRGT, + INTEQ, + INTNE, + INTGE, + INTGT, + INTLE, + INTLT, + UNOT, + BAND, + BOR, + LPAREN, + RPAREN, + OPERAND +}; + +enum token_types { + UNOP, + BINOP, + BUNOP, + BBINOP, + PAREN +}; + +static struct t_op { + const char *op_text; + short op_num, op_type; +} const ops [] = { + {"-r", FILRD, UNOP}, + {"-w", FILWR, UNOP}, + {"-x", FILEX, UNOP}, + {"-e", FILEXIST,UNOP}, + {"-f", FILREG, UNOP}, + {"-d", FILDIR, UNOP}, + {"-c", FILCDEV,UNOP}, + {"-b", FILBDEV,UNOP}, + {"-p", FILFIFO,UNOP}, + {"-u", FILSUID,UNOP}, + {"-g", FILSGID,UNOP}, + {"-k", FILSTCK,UNOP}, + {"-s", FILGZ, UNOP}, + {"-t", FILTT, UNOP}, + {"-z", STREZ, UNOP}, + {"-n", STRNZ, UNOP}, + {"-h", FILSYM, UNOP}, /* for backwards compat */ + {"-O", FILUID, UNOP}, + {"-G", FILGID, UNOP}, + {"-L", FILSYM, UNOP}, + {"-S", FILSOCK,UNOP}, + {"=", STREQ, BINOP}, + {"!=", STRNE, BINOP}, + {"<", STRLT, BINOP}, + {">", STRGT, BINOP}, + {"-eq", INTEQ, BINOP}, + {"-ne", INTNE, BINOP}, + {"-ge", INTGE, BINOP}, + {"-gt", INTGT, BINOP}, + {"-le", INTLE, BINOP}, + {"-lt", INTLT, BINOP}, + {"-nt", FILNT, BINOP}, + {"-ot", FILOT, BINOP}, + {"-ef", FILEQ, BINOP}, + {"!", UNOT, BUNOP}, + {"-a", BAND, BBINOP}, + {"-o", BOR, BBINOP}, + {"(", LPAREN, PAREN}, + {")", RPAREN, PAREN}, + {0, 0, 0} +}; + +static char **t_wp; +static struct t_op const *t_wp_op; + +static void syntax(const char *, const char *); +static int oexpr(enum token); +static int aexpr(enum token); +static int nexpr(enum token); +static int primary(enum token); +static int binop(void); +static int filstat(char *, enum token); +static enum token t_lex(char *); +static int isoperand(void); +static int getn(const char *); +static int newerf(const char *, const char *); +static int olderf(const char *, const char *); +static int equalf(const char *, const char *); + +#if defined(SHELL) +extern void error(const char *, ...) __attribute__((__noreturn__)); +#else +static void error(const char *, ...) __attribute__((__noreturn__)); + +static void +error(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + verrx(2, msg, ap); + /*NOTREACHED*/ + va_end(ap); +} +#endif + +#ifdef SHELL +int testcmd(int, char **); + +int +testcmd(int argc, char **argv) +#else +int main(int, char *[]); + +int +main(int argc, char *argv[]) +#endif +{ + int res; + +#ifndef SHELL + setprogname(argv[0]); +#endif + if (strcmp(argv[0], "[") == 0) { + if (strcmp(argv[--argc], "]")) + error("missing ]"); + argv[argc] = NULL; + } + + if (argc < 2) + return 1; + + t_wp = &argv[1]; + res = !oexpr(t_lex(*t_wp)); + + if (*t_wp != NULL && *++t_wp != NULL) + 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(*++t_wp) == BOR) + return oexpr(t_lex(*++t_wp)) || res; + t_wp--; + return res; +} + +static int +aexpr(enum token n) +{ + int res; + + res = nexpr(n); + if (t_lex(*++t_wp) == BAND) + return aexpr(t_lex(*++t_wp)) && res; + t_wp--; + return res; +} + +static int +nexpr(enum token n) +{ + if (n == UNOT) + return !nexpr(t_lex(*++t_wp)); + return primary(n); +} + +static int +primary(enum token n) +{ + enum token nn; + int res; + + if (n == EOI) + return 0; /* missing expression */ + if (n == LPAREN) { + if ((nn = t_lex(*++t_wp)) == RPAREN) + return 0; /* missing expression */ + res = oexpr(nn); + if (t_lex(*++t_wp) != RPAREN) + syntax(NULL, "closing paren expected"); + return res; + } + if (t_wp_op && t_wp_op->op_type == UNOP) { + /* unary expression */ + if (*++t_wp == NULL) + syntax(t_wp_op->op_text, "argument expected"); + 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); + } + } + + if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { + return binop(); + } + + return strlen(*t_wp) > 0; +} + +static int +binop(void) +{ + const char *opnd1, *opnd2; + struct t_op const *op; + + opnd1 = *t_wp; + (void) t_lex(*++t_wp); + op = t_wp_op; + + if ((opnd2 = *++t_wp) == (char *)0) + syntax(op->op_text, "argument expected"); + + switch (op->op_num) { + 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 getn(opnd1) == getn(opnd2); + case INTNE: + return getn(opnd1) != getn(opnd2); + case INTGE: + return getn(opnd1) >= getn(opnd2); + case INTGT: + return getn(opnd1) > getn(opnd2); + case INTLE: + return getn(opnd1) <= getn(opnd2); + case INTLT: + return getn(opnd1) < getn(opnd2); + 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 access(nm, R_OK) == 0; + case FILWR: + return access(nm, W_OK) == 0; + case FILEX: + return access(nm, X_OK) == 0; + case FILEXIST: + return access(nm, F_OK) == 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 enum token +t_lex(char *s) +{ + struct t_op const *op; + + op = ops; + + if (s == 0) { + t_wp_op = (struct t_op *)0; + return EOI; + } + while (op->op_text) { + if (strcmp(s, op->op_text) == 0) { + if ((op->op_type == UNOP && isoperand()) || + (op->op_num == LPAREN && *(t_wp+1) == 0)) + break; + t_wp_op = op; + return op->op_num; + } + op++; + } + t_wp_op = (struct t_op *)0; + return OPERAND; +} + +static int +isoperand(void) +{ + struct t_op const *op; + char *s, *t; + + op = ops; + if ((s = *(t_wp+1)) == 0) + return 1; + if ((t = *(t_wp+2)) == 0) + return 0; + while (op->op_text) { + if (strcmp(s, op->op_text) == 0) + return op->op_type == BINOP && + (t[0] != ')' || t[1] != '\0'); + op++; + } + return 0; +} + +/* atoi with error detection */ +static int +getn(const char *s) +{ + char *p; + long r; + + errno = 0; + r = strtol(s, &p, 10); + + if (errno != 0) + error("%s: out of range", s); + + while (isspace((unsigned char)*p)) + p++; + + if (*p) + error("%s: bad number", s); + + return (int) r; +} + +static int +newerf (const char *f1, const char *f2) +{ + struct stat b1, b2; + + return (stat (f1, &b1) == 0 && + stat (f2, &b2) == 0 && + b1.st_mtime > b2.st_mtime); +} + +static int +olderf (const char *f1, const char *f2) +{ + struct stat b1, b2; + + return (stat (f1, &b1) == 0 && + stat (f2, &b2) == 0 && + b1.st_mtime < b2.st_mtime); +} + +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 -Nru ash-1.6.1.orig/cd.c ash-1.6.1/cd.c --- ash-1.6.1.orig/cd.c 2003-11-15 05:04:00.000000000 +0200 +++ ash-1.6.1/cd.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95"; @@ -381,7 +384,7 @@ * c implementation of getcwd, that does not open a pipe to * /bin/pwd. */ -#if defined(__NetBSD__) || defined(__SVR4) +#if defined(__NetBSD__) || defined(__SVR4) || defined(__linux__) for (i = MAXPWD;; i *= 2) { pwd = stalloc(i); diff -Nru ash-1.6.1.orig/compat_linux.h ash-1.6.1/compat_linux.h --- ash-1.6.1.orig/compat_linux.h 1970-01-01 02:00:00.000000000 +0200 +++ ash-1.6.1/compat_linux.h 2010-01-08 14:49:49.000000000 +0200 @@ -0,0 +1,23 @@ +/* + * compat.h + * + * Compability functions for Linux / Klibc + */ + +#ifndef _LINUX_COMPAT_H +#define _LINUX_COMPAT_H + +static inline size_t strlcpy ( char * d, + const char * s, + size_t bufsize ) +{ + size_t len = strlen(s); + size_t ret = len; + + if (bufsize <= 0) return 0; + if (len >= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif diff -Nru ash-1.6.1.orig/error.c ash-1.6.1/error.c --- ash-1.6.1.orig/error.c 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/error.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/error.h ash-1.6.1/error.h --- ash-1.6.1.orig/error.h 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/error.h 2010-01-08 14:49:49.000000000 +0200 @@ -111,7 +111,7 @@ * so we use _setjmp instead. */ -#if defined(BSD) && !defined(__SVR4) +#if defined(BSD) && !defined(__SVR4) && !defined(__linux__) #define setjmp(jmploc) _setjmp(jmploc) #define longjmp(jmploc, val) _longjmp(jmploc, val) #endif diff -Nru ash-1.6.1.orig/eval.c ash-1.6.1/eval.c --- ash-1.6.1.orig/eval.c 2003-11-15 05:04:00.000000000 +0200 +++ ash-1.6.1/eval.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; @@ -79,6 +82,9 @@ #include "myhistedit.h" #endif +#ifdef __linux__ +#include "compat_linux.h" +#endif /* flags in argument to evaltree */ #define EV_EXIT 01 /* exit after evaluating tree */ @@ -578,19 +584,25 @@ syspath(void) { static char *sys_path = NULL; +#ifdef _HAVE_SYSCTL static int mib[] = {CTL_USER, USER_CS_PATH}; +#endif size_t len; if (sys_path == NULL) { +#ifdef _HAVE_SYSCTL if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && (sys_path = ckmalloc(len + 5)) != NULL && sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { memcpy(sys_path, "PATH=", 5); } else { +#endif ckfree(sys_path); /* something to keep things happy */ sys_path = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; +#ifdef _HAVE_SYSCTL } +#endif } return sys_path; } @@ -976,7 +988,9 @@ argptr = argv + 1; optptr = NULL; /* and getopt */ +#ifndef __linux__ optreset = 1; +#endif optind = 1; exitstatus = cmdentry.u.bltin(argc, argv); } else { diff -Nru ash-1.6.1.orig/exec.c ash-1.6.1/exec.c --- ash-1.6.1.orig/exec.c 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/exec.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; diff -Nru ash-1.6.1.orig/expand.c ash-1.6.1/expand.c --- ash-1.6.1.orig/expand.c 2003-09-23 06:05:29.000000000 +0300 +++ ash-1.6.1/expand.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; diff -Nru ash-1.6.1.orig/histedit.c ash-1.6.1/histedit.c --- ash-1.6.1.orig/histedit.c 2003-10-28 05:02:11.000000000 +0200 +++ ash-1.6.1/histedit.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95"; @@ -57,9 +60,9 @@ #include "main.h" #include "output.h" #include "mystring.h" -#include "myhistedit.h" #include "error.h" #ifndef SMALL +#include "myhistedit.h" #include "eval.h" #include "memalloc.h" diff -Nru ash-1.6.1.orig/input.c ash-1.6.1/input.c --- ash-1.6.1.orig/input.c 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/input.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; @@ -62,7 +65,9 @@ #include "error.h" #include "alias.h" #include "parser.h" +#ifndef SMALL #include "myhistedit.h" +#endif #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ @@ -104,7 +109,9 @@ int init_editline = 0; /* editline library initialized? */ int whichprompt; /* 1 == PS1, 2 == PS2 */ +#ifndef SMALL EditLine *el; /* cookie for editline package */ +#endif STATIC void pushfile(void); static int preadfd(void); diff -Nru ash-1.6.1.orig/jobs.c ash-1.6.1/jobs.c --- ash-1.6.1.orig/jobs.c 2003-11-28 05:04:07.000000000 +0200 +++ ash-1.6.1/jobs.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; @@ -89,6 +92,9 @@ #if JOBS int initialpgrp; /* pgrp of shell on invocation */ static int curjob = -1; /* current job */ +#ifndef WCOREDUMP +#define WCOREDUMP(status) ((status) & 0x80) +#endif #endif static int ttyfd = -1; diff -Nru ash-1.6.1.orig/mail.c ash-1.6.1/mail.c --- ash-1.6.1.orig/mail.c 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/mail.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/main.c ash-1.6.1/main.c --- ash-1.6.1.orig/main.c 2003-09-15 06:04:26.000000000 +0300 +++ ash-1.6.1/main.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,12 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif +#ifndef __COPYRIGHT +#define __COPYRIGHT(arg) +#endif #ifndef lint __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n"); diff -Nru ash-1.6.1.orig/Makefile ash-1.6.1/Makefile --- ash-1.6.1.orig/Makefile 2003-11-17 05:05:09.000000000 +0200 +++ ash-1.6.1/Makefile 2010-01-08 14:49:49.000000000 +0200 @@ -1,101 +1,105 @@ -# $NetBSD: Makefile,v 1.73 2003/11/16 14:14:18 lukem Exp $ -# @(#)Makefile 8.4 (Berkeley) 5/5/95 +# Makefile.linux -.include - -YHEADER=1 -PROG= sh -SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \ +PROG= ash +SRCS= alias.c arith.c arith_lex.c \ + builtins.c cd.c echo.c error.c eval.c exec.c expand.c \ histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ - mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \ - test.c printf.c kill.c -GENSRCS=arith.c arith_lex.c builtins.c init.c nodes.c syntax.c -GENHDRS=arith.h builtins.h nodes.h syntax.h token.h -SRCS= ${SHSRCS} ${GENSRCS} - -DPSRCS+=${GENHDRS} - -LDADD+= -ll -ledit -ltermcap -DPADD+= ${LIBL} ${LIBEDIT} ${LIBTERMCAP} - -LFLAGS= -8 # 8-bit lex scanner for arithmetic -YFLAGS= -d - -.ifdef CRUNCHEDPROG -LFLAGS+=-L -YFLAGS+=-l -.endif - -CPPFLAGS+=-DSHELL -I. -I${.CURDIR} -#XXX: For testing only. -#CPPFLAGS+=-DDEBUG=1 -#CFLAGS+=-funsigned-char -#TARGET_CHARFLAG?= -DTARGET_CHAR="unsigned char" -funsigned-char - -.ifdef SMALLPROG -CPPFLAGS+=-DSMALL -.endif - -.PATH: ${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test \ - ${NETBSDSRCDIR}/usr.bin/printf \ - ${NETBSDSRCDIR}/bin/kill - -CLEANFILES+= mkinit mkinit.lo mknodes mknodes.lo mksyntax mksyntax.lo -CLEANFILES+= ${GENSRCS} ${GENHDRS} y.tab.h -CLEANFILES+= trace + mystring.c nodes.c options.c parser.c printf.c redir.c \ + show.c syntax.c trap.c output.c var.c test.c kill.c + +OBJ1 = init.o +OBJ2 = alias.o arith.o arith_lex.o \ + builtins.o cd.o echo.o error.o eval.o exec.o expand.o \ + histedit.o input.o jobs.o mail.o main.o memalloc.o miscbltin.o \ + mystring.o nodes.o options.o parser.o printf.o redir.o \ + show.o syntax.o trap.o output.o var.o test.o kill.o + +OBJS = $(OBJ1) $(OBJ2) + +YACC = bison -y +LEX = flex -l + +SHELL_DEFS = -DSHELL -DSMALL +SRC_DEFS = -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D__BIT_TYPES_DEFINED__ +OPTFLAGS = -g -O2 -pipe +INCLUDES = -I. +CFLAGS = $(SHELL_DEFS) $(SRC_DEFS) $(OPTFLAGS) $(INCLUDES) +LDFLAGS = + +CLEANFILES =\ + builtins.c builtins.h init.c mkinit mknodes mksyntax \ + nodes.c nodes.h syntax.c syntax.h signames.c token.h \ + arith.c arith.h arith_lex.c \ + printf.c test.c echo.c kill.c + +all: $(OBJS) + $(CC) -o $(PROG) $(OBJS) $(LDFLAGS) + $(CC) -static -o $(PROG).static $(OBJS) $(LDFLAGS) + +install: all + install -d $(DESTDIR)/bin + install $(PROG) $(DESTDIR)/bin/$(PROG) + install $(PROG).static $(DESTDIR)/bin/$(PROG).static + install -d $(DESTDIR)/usr/share/man/man1 + install -m 644 sh.1 $(DESTDIR)/usr/share/man/man1/ash.1 + +parser.o: token.h token.h: mktokens - ${_MKTARGET_CREATE} - ${HOST_SH} ${.ALLSRC} + sh ./mktokens + +builtins.h builtins.c: mkbuiltins shell.h builtins.def + sh ./mkbuiltins shell.h builtins.def . "$(CFLAGS)" + +init.c: mkinit $(SRCS) + ./mkinit $(SRCS) + touch init.c + +mkinit: mkinit.c + $(CC) $(CFLAGS) $(LDFLAGS) mkinit.c -o $@ $(LDADD) + +nodes.c nodes.h: mknodes nodetypes nodes.c.pat + ./mknodes nodetypes nodes.c.pat + +mknodes: mknodes.c + $(CC) $(CFLAGS) $(LDFLAGS) mknodes.c -o $@ $(LDADD) + +syntax.c syntax.h: mksyntax + ./mksyntax + +mksyntax: mksyntax.c parser.h + $(CC) $(CFLAGS) $(LDFLAGS) mksyntax.c -o $@ $(LDADD) + +signames.c: mksignames + ./mksignames + +echo.c: bltin/echo.c + ln -s $< $@ + +test.c: bltin/test.c + ln -s $< $@ + +kill.c: bltin/kill.c + ln -s $< $@ + +printf.c: bltin/printf.c + ln -s $< $@ + +arith.c: arith.y + $(YACC) $< + mv y.tab.c $@ + +arith_lex.o: arith_lex.c arith.h + +arith_yylex.o: arith_yylex.c arith.h + +arith_lex.c: arith_lex.l + $(LEX) $< + mv lex.yy.c $@ -builtins.h: builtins.c - ${_MKTARGET_CREATE} +arith.h: arith.c + sed -n '/^#define ARITH/p' $< > $@ -builtins.c: mkbuiltins shell.h builtins.def - ${_MKTARGET_CREATE} - ${HOST_SH} ${.ALLSRC} ${.OBJDIR} - [ -f builtins.h ] - -init.c: mkinit ${SHSRCS} - ${_MKTARGET_CREATE} - ./${.ALLSRC} - -nodes.h: nodes.c - -nodes.c: mknodes nodetypes nodes.c.pat - ${_MKTARGET_CREATE} - ./${.ALLSRC} - [ -f nodes.h ] - -syntax.h: syntax.c - -syntax.c: mksyntax - ${_MKTARGET_CREATE} - ./${.ALLSRC} - [ -f syntax.h ] - -.if ${USETOOLS} == "yes" -COMPATOBJDIR!= cd ${NETBSDSRCDIR}/tools/compat && ${PRINTOBJDIR} -NBCOMPATLIB= -L${COMPATOBJDIR} -lnbcompat -.endif - -mkinit: mkinit.lo - ${_MKTARGET_LINK} - ${HOST_LINK.c} -o ${.TARGET} ${.ALLSRC} ${NBCOMPATLIB} - -mknodes: mknodes.lo - ${_MKTARGET_LINK} - ${HOST_LINK.c} -o ${.TARGET} ${.ALLSRC} ${NBCOMPATLIB} - -.if (${MACHINE_ARCH} == "powerpc") || \ - (${MACHINE_CPU} == "arm") -TARGET_CHARFLAG?= -DTARGET_CHAR="unsigned char" -.else -TARGET_CHARFLAG?= -DTARGET_CHAR="signed char" -.endif - -mksyntax: mksyntax.lo - ${_MKTARGET_LINK} - ${HOST_LINK.c} ${TARGET_CHARFLAG} -o ${.TARGET} ${.ALLSRC} ${NBCOMPATLIB} +clean: + rm -f core $(CLEANFILES) $(PROG) $(PROG).static $(OBJS) -.include diff -Nru ash-1.6.1.orig/memalloc.c ash-1.6.1/memalloc.c --- ash-1.6.1.orig/memalloc.c 2003-08-08 06:04:51.000000000 +0300 +++ ash-1.6.1/memalloc.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/miscbltin.c ash-1.6.1/miscbltin.c --- ash-1.6.1.orig/miscbltin.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/miscbltin.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; @@ -222,6 +225,7 @@ } while (*++ap != '\0'); umask(mask); } else { +#ifdef _HAVE_SETMODE void *set; INTOFF; @@ -231,9 +235,11 @@ } INTON; if (!set) +#endif error("Illegal mode: %s", ap); - +#ifdef _HAVE_SETMODE umask(~mask & 0777); +#endif } } return 0; diff -Nru ash-1.6.1.orig/mkinit.c ash-1.6.1/mkinit.c --- ash-1.6.1.orig/mkinit.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/mkinit.c 2010-01-08 14:49:49.000000000 +0200 @@ -65,6 +65,9 @@ #include #include +#ifdef __linux__ +#include "compat_linux.h" +#endif /* * OUTFILE is the name of the output file. Output is initially written diff -Nru ash-1.6.1.orig/mystring.c ash-1.6.1/mystring.c --- ash-1.6.1.orig/mystring.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/mystring.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/options.c ash-1.6.1/options.c --- ash-1.6.1.orig/options.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/options.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/output.c ash-1.6.1/output.c --- ash-1.6.1.orig/output.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/output.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; @@ -68,7 +71,6 @@ #include "memalloc.h" #include "error.h" - #define OUTBUFSIZ BUFSIZ #define BLOCK_OUT -2 /* output to a fixed block of memory */ #define MEM_OUT -3 /* output to dynamically allocated memory */ @@ -228,6 +230,7 @@ va_end(ap); } +#ifndef __linux__ void dprintf(const char *fmt, ...) { @@ -238,6 +241,7 @@ va_end(ap); flushout(out2); } +#endif void fmtstr(char *outbuf, size_t length, const char *fmt, ...) diff -Nru ash-1.6.1.orig/output.h ash-1.6.1/output.h --- ash-1.6.1.orig/output.h 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/output.h 2010-01-08 14:49:49.000000000 +0200 @@ -65,8 +65,10 @@ __attribute__((__format__(__printf__,2,3))); void out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2))); +#ifndef __linux__ void dprintf(const char *, ...) __attribute__((__format__(__printf__,1,2))); +#endif void fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4))); void doformat(struct output *, const char *, va_list); diff -Nru ash-1.6.1.orig/parser.c ash-1.6.1/parser.c --- ash-1.6.1.orig/parser.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/parser.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; diff -Nru ash-1.6.1.orig/redir.c ash-1.6.1/redir.c --- ash-1.6.1.orig/redir.c 2003-08-08 06:04:52.000000000 +0300 +++ ash-1.6.1/redir.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/show.c ash-1.6.1/show.c --- ash-1.6.1.orig/show.c 2003-11-15 05:04:01.000000000 +0200 +++ ash-1.6.1/show.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; diff -Nru ash-1.6.1.orig/trap.c ash-1.6.1/trap.c --- ash-1.6.1.orig/trap.c 2003-08-27 06:01:40.000000000 +0300 +++ ash-1.6.1/trap.c 2010-01-08 14:49:49.000000000 +0200 @@ -33,6 +33,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; @@ -100,7 +103,11 @@ p += 3; for (i = 0; i < NSIG; ++i) +#ifdef _GNU_SOURCE + if (strcasecmp (p, strsignal(i)) == 0) +#else if (strcasecmp (p, sys_signame[i]) == 0) +#endif return i; return -1; } @@ -116,7 +123,11 @@ out1str("EXIT "); for (n = 1; n < NSIG; n++) { +#ifdef _GNU_SOURCE + out1fmt("%s", strsignal(n)); +#else out1fmt("%s", sys_signame[n]); +#endif if ((n == NSIG/2) || n == (NSIG - 1)) out1str("\n"); else @@ -138,8 +149,13 @@ if (argc <= 1) { for (signo = 0 ; signo <= NSIG ; signo++) { if (trap[signo] != NULL) +#ifdef _GNU_SOURCE + out1fmt("trap -- '%s' %s\n", trap[signo], + (signo) ? strsignal(signo) : "EXIT"); +#else out1fmt("trap -- '%s' %s\n", trap[signo], (signo) ? sys_signame[signo] : "EXIT"); +#endif } return 0; } diff -Nru ash-1.6.1.orig/var.c ash-1.6.1/var.c --- ash-1.6.1.orig/var.c 2003-08-27 06:01:40.000000000 +0300 +++ ash-1.6.1/var.c 2010-01-08 14:49:49.000000000 +0200 @@ -34,6 +34,9 @@ */ #include +#ifndef __RCSID +#define __RCSID(arg) +#endif #ifndef lint #if 0 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";