rc

[fork] interactive rc shell
Log | Files | Refs | README | LICENSE

commit c68ac7eedea03d0c21cbfbb57704fda65a1c9cc3
parent a8699a58d8632f21e897ea5c4900a15483a9a8ca
Author: Toby Goodwin <toby@paccrat.org>
Date:   Tue, 21 Apr 2015 21:39:24 +0100

release: rc-1.7.3

Diffstat:
MAUTHORS | 6++++--
MCOPYING | 48+++++++++++++++++++++++-------------------------
MChangeLog | 36++++++++++++++++++++++++++++++++++++
MMakefile.am | 6++----
MNEWS | 22++++++++++++----------
MREADME | 4++--
MReleaseTime | 1-
Macinclude.m4 | 13++++++++-----
Mconfigure.ac | 34++++++++++++++++++++++------------
Aedit-edit.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aedit-editline.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aedit-readline.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aedit-vrl.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minput.c | 1+
Mlex.c | 2+-
Mprint.c | 12++++++------
Mproto.h | 10+++++-----
Mrc.1 | 9++++++++-
Mrc.h | 2--
Mrc.spec | 10++++++----
20 files changed, 518 insertions(+), 80 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -1,5 +1,7 @@ -The current maintainer of rc is Toby Goodwin <toby@paccrat.org>. Please -send all bug reports to him. +The current maintainer of rc is Toby Goodwin <toby@paccrat.org>. Please +send all bug reports to him, or via github: + + https://github.com/rakitzis/rc/issues This shell was written by me, Byron Rakitzis, but kudos go to Paul Haahr for letting me know what a shell should do and for contributing certain diff --git a/COPYING b/COPYING @@ -1,26 +1,24 @@ /* - * Copyright 1991, 2001, 2002 by Byron Rakitzis. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * - * 1. The author is not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * - * 4. This notice may not be removed or altered. - * - * [this copyright notice is adapted from Henry Spencer's - * "awf" copyright notice.] - */ +Copyright (c) 1991, 1999, 2001-2003, 2014, 2015 Byron Rakitzis + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment (see the following) in the product +documentation is required. + + Portions Copyright (c) 1991, 1999, 2001-2003, 2014, 2015 Byron Rakitzis + +2. Altered source versions must be plainly marked as such, and must not +be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ diff --git a/ChangeLog b/ChangeLog @@ -854,3 +854,39 @@ Changes since rc-1.5b2 Zekoll). Feature: allow $"x as a synonym for $^x + + Release: rc-1.7.2. + +2015-04-03 + + Packaging: the rc.spec file was very out-of-date. + +2015-04-04 + + Portability: the comment from 1999-08-19 may well have been true at + the time, but the final version of the C99 standard called varargs + copying macro va_copy(). + +2015-04-07 + + Portability: look in -ltinfo for tgetent. + + Packaging: various autoconf / automake updates and tweaks. + +2015-04-14 + + Bug: in initinput(), the call ugchar(EOF) used the ungetcount member + of the top Input structure without initializing it. Thanks to Jeff + Johnson for finding this, Robert Scheck for reporting it, and Uli + Drepper for implementing MALLOC_PERTURB_, a cheap way to find uses of + uninitialized memory. + +2015-04-18 + + Licensing: tweaked to match exactly the "zlib with acknowledgement" + license which is used by nunit and is already approved by various + distros. + +2015-04-20 + + Release: rc-1.7.3. diff --git a/Makefile.am b/Makefile.am @@ -24,7 +24,7 @@ noinst_PROGRAMS = mksignal mkstatval tripping $(HISTORY) rc_SOURCES = builtins.c except.c exec.c fn.c footobar.c getopt.c glob.c glom.c hash.c heredoc.c input.c lex.c list.c main.c match.c nalloc.c open.c parse.c print.c redir.c signal.c status.c tree.c utils.c var.c wait.c walk.c which.c -EXTRA_rc_SOURCES = addon.c edit-bsd.c edit-gnu.c edit-null.c execve.c system.c system-bsd.c +EXTRA_rc_SOURCES = addon.c edit-edit.c edit-editline.c edit-null.c edit-readline.c edit-vrl.c execve.c system.c system-bsd.c rc_DEPENDENCIES = sigmsgs.o $(ADDON) $(EDIT) $(EXECVE) $(SYSTEM) rc_LDADD = sigmsgs.o $(ADDON) $(EDIT) $(EXECVE) $(SYSTEM) @@ -33,7 +33,7 @@ noinst_HEADERS = edit.h getgroups.h input.h jbwrap.h parse.h proto.h rc.h rlimit BUILT_SOURCES = sigmsgs.c -EXTRA_DIST = EXAMPLES RELDATE addon.c addon.h history.1 parse.y rc.1 trip.rc +EXTRA_DIST = EXAMPLES addon.c addon.h history.1 parse.y rc.1 trip.rc sigmsgs.c sigmsgs.h: mksignal ./mksignal @@ -45,8 +45,6 @@ status.o: statval.h statval.h: mkstatval ./mkstatval > statval.h -CONFIGURE_DEPENDENCIES = RELDATE - DISTCLEANFILES = sigmsgs.c sigmsgs.h statval.h # Of course, parse.c and parse.h depend on parse.y. However, unless diff --git a/NEWS b/NEWS @@ -7,17 +7,19 @@ was removed, as this causes indigestion on file systems that don't support sparse files (the configuration and implementation of large file support is still present of course). -Bug fixes. Fix for CVE-2014-1936. Broken symlinks now glob correctly. -The variables $prompt and $version are now exported if they are -inherited from the environment when rc starts. EIO handling is now -enabled for readline too. A few bogosities in the history program were -fixed. A regression introduced by the fix for the $(a.b) quoting bug was -fixed, and that bug was correctly fixed. +Bug fixes. Fix a use of uninitialized memory. Fix for CVE-2014-1936. +Broken symlinks now glob correctly. The variables $prompt and $version +are now exported if they are inherited from the environment when rc +starts. EIO handling is now enabled for readline too. A few bogosities +in the history program were fixed. A regression introduced by the fix +for the $(a.b) quoting bug was fixed, and that bug was correctly fixed. -New features. Filename completion with GNU readline now quotes special -characters. +New features. Added $"x as a synonym for $^x. Minimal support for +various alternative line editing libraries. Filename completion with GNU +readline now quotes special characters. -Documentation. Minor updates only. +Documentation. Licence updated to use exactly the text of the zlib- +with-acknowledgement licence. Toby Goodwin -2014-09-01 +2015-04-20 diff --git a/README b/README @@ -1,8 +1,8 @@ -This is release rc-1.7.2. +This is release rc-1.7.3. See COPYING for copying information. All files are - Copyright 1991, 2001, 2002, 2003, 2014 Byron Rakitzis. + Copyright 1991, 1999, 2001-2003, 2014, 2015 Byron Rakitzis. See INSTALL for build and installation information. diff --git a/ReleaseTime b/ReleaseTime @@ -2,6 +2,5 @@ ChangeLog NEWS README -RELDATE configure.ac rc.1 diff --git a/acinclude.m4 b/acinclude.m4 @@ -197,11 +197,14 @@ main() { dnl Where is tgetent()? AC_DEFUN([RC_LIB_TGETENT], [ - AC_CHECK_LIB(termcap, tgetent, - rc_lib_tgetent=-ltermcap, - AC_CHECK_LIB(ncurses, tgetent, - rc_lib_tgetent=-lncurses, - AC_MSG_ERROR(tgetent not found) + AC_CHECK_LIB(tinfo, tgetent, + rc_lib_tgetent=-ltinfo, + AC_CHECK_LIB(termcap, tgetent, + rc_lib_tgetent=-ltermcap, + AC_CHECK_LIB(ncurses, tgetent, + rc_lib_tgetent=-lncurses, + AC_MSG_ERROR(tgetent not found) + ) ) ) ]) diff --git a/configure.ac b/configure.ac @@ -1,5 +1,5 @@ dnl Our package name, version, ... -AC_INIT([rc], [1.7.2]) +AC_INIT([rc], [1.7.3]) dnl ... and release date RELDATE=`date -I` @@ -9,11 +9,10 @@ dnl Get things going... AC_CONFIG_SRCDIR([rc.h]) AM_INIT_AUTOMAKE -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS(config.h) dnl Find a standard C compiler AC_PROG_CC -AM_PROG_CC_STDC dnl If we're using gcc, specify `-Wall'. I've also checked the code dnl with `-pedantic -W -Wall -Wpointer-arith -Wstrict-prototypes @@ -170,21 +169,30 @@ AC_SUBST(ADDON) EDIT=edit-null.o -AC_ARG_WITH(edit, [ --with-edit=(bsd,edit,gnu,vrl) Command line editing library], [ +AC_ARG_WITH(edit, [ --with-edit=(edit,editline,readline,vrl) Command line editing library], [ case $withval in yes) AC_MSG_ERROR(must specify which library) # might consider searching ;; - bsd) - EDIT=edit-bsd.o + no|null) + ;; + edit|bsd) + EDIT=edit-edit.o RC_LIB_TGETENT AC_CHECK_LIB(edit, el_init, [ LIBS="$LIBS -ledit $rc_lib_tgetent" + ], AC_MSG_ERROR(edit library not found), $rc_lib_tgetent) + ;; + editline) + EDIT=edit-editline.o + RC_LIB_TGETENT + AC_CHECK_LIB(editline, el_ring_bell, [ + LIBS="$LIBS -leditline $rc_lib_tgetent" ], AC_MSG_ERROR(editline library not found), $rc_lib_tgetent) ;; - gnu) - EDIT=edit-gnu.o + readline|gnu) + EDIT=edit-readline.o RC_LIB_TGETENT AC_CHECK_LIB(readline, readline, [ LIBS="$LIBS -lreadline $rc_lib_tgetent" @@ -196,10 +204,12 @@ AC_ARG_WITH(edit, [ --with-edit=(bsd,edit,gnu,vrl) Command line editing librar rl_catch_signals = 0; ], [], AC_MSG_ERROR(readline >= 4.0 not found)) ;; - no|null) - ;; - edit|vrl) - EDIT=edit-$withval.o + vrl) + EDIT=edit-vrl.o + RC_LIB_TGETENT + AC_CHECK_LIB(vrl, iline_peekch, [ + LIBS="$LIBS -lvrl $rc_lib_tgetent" + ], AC_MSG_ERROR(vrl library not found), $rc_lib_tgetent) ;; *) AC_MSG_ERROR(unknown editing library $withval) diff --git a/edit-edit.c b/edit-edit.c @@ -0,0 +1,91 @@ +#include "rc.h" + +#include <stdio.h> + +#include <histedit.h> + +#include "edit.h" + +bool editing = 1; + +struct cookie { + EditLine *el; + History *hist; +}; + +static char *prompt; + +void *edit_begin(int fd) { + FILE *f; + HistEvent he; + struct cookie *c; + + c = ealloc(sizeof *c); + if (fd == 0) + f = stdin; + else + f = fdopen(fd, "r"); + c->el = el_init("rc", f, stdout, stderr); + el_set(c->el, EL_SIGNAL, 0); + el_source(c->el, NULL); + + c->hist = history_init(); + history(c->hist, &he, H_SETSIZE, 20); + el_set(c->el, EL_HIST, history, c->hist); + + return c; +} + + +static void edit_catcher(int sig) { + write(2, "\n", 1); + rc_raise(eError); +} + +char *edit_alloc(void *cookie, size_t *count) { + const char *r; + HistEvent he; + struct cookie *c = cookie; + void (*oldint)(int), (*oldquit)(int); + + oldint = sys_signal(SIGINT, edit_catcher); + oldquit = sys_signal(SIGQUIT, edit_catcher); + + r = el_gets(c->el, count); + + sys_signal(SIGINT, oldint); + sys_signal(SIGQUIT, oldquit); + + if (r) + history(c->hist, &he, H_ENTER, r); + return (char *)r; /* cast to avoid gcc warning */ +} + +static char *edit_prompter(EditLine *e) { + return prompt; +} + +void edit_prompt(void *cookie, char *pr) { + struct cookie *c = cookie; + + prompt = pr; + el_set(c->el, EL_PROMPT, edit_prompter); +} + +void edit_free(void *cookie) { + /* this function deliberately left blank */ +} + +void edit_end(void *cookie) { + struct cookie *c = cookie; + + el_end(c->el); + history_end(c->hist); + efree(c); +} + +void edit_reset(void *cookie) { + struct cookie *c = cookie; + + el_set(c->el, EL_TERMINAL, NULL); +} diff --git a/edit-editline.c b/edit-editline.c @@ -0,0 +1,100 @@ +#include "rc.h" + +#include <errno.h> +#include <stdio.h> + +#include "editline.h" + +bool editing = 1; + +struct cookie { + char *buffer; +}; + +static char *prompt; + +void *edit_begin(int fd) { + List *hist; + struct cookie *c; + + hist = varlookup("history"); + if (hist != NULL) + if (read_history(hist->w) != 0 && + errno != ENOENT) /* ignore if missing */ + uerror(hist->w); + + c = ealloc(sizeof *c); + c->buffer = NULL; + return c; +} + +/* +static void edit_catcher(int sig) { + write(2, "\n", 1); + rc_raise(eError); +} + +*/ + +char *edit_alloc(void *cookie, size_t *count) { + struct cookie *c = cookie; +/* + const char *r; + HistEvent he; + struct cookie *c = cookie; + void (*oldint)(int), (*oldquit)(int); + + oldint = sys_signal(SIGINT, edit_catcher); + oldquit = sys_signal(SIGQUIT, edit_catcher); + + r = el_gets(c->el, count); + + sys_signal(SIGINT, oldint); + sys_signal(SIGQUIT, oldquit); + + if (r) + history(c->hist, &he, H_ENTER, r); +*/ + + c->buffer = readline(prompt); + if (c->buffer) { + *count = strlen(c->buffer); + c->buffer[*count] = '\n'; + ++*count; + } + return c->buffer; +} + +/* +static char *edit_prompter(ne *e) { + return prompt; +} +*/ + +void edit_prompt(void *cookie, char *pr) { + //struct cookie *c = cookie; + + prompt = pr; + //el_set(c->el, EL_PROMPT, edit_prompter); +} + +void edit_free(void *cookie) { + struct cookie *c = cookie; + + efree(c->buffer); + c->buffer = NULL; /* allow "overfrees" */ +} + +void edit_end(void *cookie) { + //struct cookie *c = cookie; + + //el_end(c->el); + //history_end(c->hist); + //efree(c); +} + +void edit_reset(void *cookie) { + //struct cookie *c = cookie; + + //el_set(c->el, EL_TERMINAL, NULL); +} diff --git a/edit-readline.c b/edit-readline.c @@ -0,0 +1,87 @@ +#include "rc.h" + +#include <errno.h> +#include <stdio.h> +#include <readline/readline.h> +#include <readline/history.h> +#include <readline/rltypedefs.h> + +#include "edit.h" + +bool editing = 1; + +struct cookie { + char *buffer; +}; + +void *edit_begin(int fd) { + List *hist; + struct cookie *c; + + rl_catch_signals = 0; + rl_completer_quote_characters = "'"; + rl_filename_quote_characters = "\t\n !#$&'()*;<=>?@[\\]^`{|}~"; + + hist = varlookup("history"); + if (hist != NULL) + if (read_history(hist->w) != 0 && errno != ENOENT) /* ignore if missing */ + uerror(hist->w); + + c = ealloc(sizeof *c); + c->buffer = NULL; + return c; +} + +static void edit_catcher(int sig) { + write(2, "\n", 1); + rc_raise(eError); +} + +static char *prompt; + +char *edit_alloc(void *cookie, size_t *count) { + struct cookie *c = cookie; + void (*oldint)(int), (*oldquit)(int); + + oldint = sys_signal(SIGINT, edit_catcher); + oldquit = sys_signal(SIGQUIT, edit_catcher); + + c->buffer = readline(prompt); + + sys_signal(SIGINT, oldint); + sys_signal(SIGQUIT, oldquit); + + if (c->buffer) { + *count = strlen(c->buffer); + if (*count) + add_history(c->buffer); + c->buffer[*count] = '\n'; + ++*count; /* include the \n */ + } + return c->buffer; +} + +void edit_prompt(void *cookie, char *pr) { + prompt = pr; +} + +void edit_free(void *cookie) { + struct cookie *c = cookie; + + efree(c->buffer); + /* Set c->buffer to NULL, allowing us to "overfree" it. This + is a bit of a kludge, but it's otherwise hard to deal with + the case where a signal causes an early return from + readline. */ + c->buffer = NULL; +} + +void edit_end(void *cookie) { + struct cookie *c = cookie; + + efree(c); +} + +void edit_reset(void *cookie) { + rl_reset_terminal(NULL); +} diff --git a/edit-vrl.c b/edit-vrl.c @@ -0,0 +1,104 @@ +#include "rc.h" + +#include <errno.h> +#include <stdio.h> + +#include "edit.h" + +extern char *readline(char *); +extern void add_history(char *); + +bool editing = 1; + +struct cookie { + char *buffer; +}; + +static char *prompt; + +void *edit_begin(int fd) { + List *hist; + struct cookie *c; + + + hist = varlookup("history"); + if (hist != NULL) + ; + /* XXX will need to loop calling add_history() */ + + c = ealloc(sizeof *c); + c->buffer = NULL; + return c; +} + +/* +static void edit_catcher(int sig) { + write(2, "\n", 1); + rc_raise(eError); +} + +*/ + +char *edit_alloc(void *cookie, size_t *count) { + struct cookie *c = cookie; +/* + const char *r; + HistEvent he; + struct cookie *c = cookie; + void (*oldint)(int), (*oldquit)(int); + + oldint = sys_signal(SIGINT, edit_catcher); + oldquit = sys_signal(SIGQUIT, edit_catcher); + + r = el_gets(c->el, count); + + sys_signal(SIGINT, oldint); + sys_signal(SIGQUIT, oldquit); + + if (r) + history(c->hist, &he, H_ENTER, r); +*/ + + c->buffer = readline(prompt); + if (c->buffer) { + add_history(c->buffer); + *count = strlen(c->buffer); + c->buffer[*count] = '\n'; + ++*count; + } + return c->buffer; +} + +/* +static char *edit_prompter(ne *e) { + return prompt; +} +*/ + +void edit_prompt(void *cookie, char *pr) { + //struct cookie *c = cookie; + + prompt = pr; + //el_set(c->el, EL_PROMPT, edit_prompter); +} + +void edit_free(void *cookie) { + struct cookie *c = cookie; + + efree(c->buffer); + c->buffer = NULL; /* allow "overfrees" */ +} + +void edit_end(void *cookie) { + //struct cookie *c = cookie; + + //el_end(c->el); + //history_end(c->hist); + //efree(c); +} + +void edit_reset(void *cookie) { + //struct cookie *c = cookie; + + //el_set(c->el, EL_TERMINAL, NULL); +} diff --git a/input.c b/input.c @@ -163,6 +163,7 @@ void termchange(void) { extern void initinput() { istack = itop = ealloc(istacksize = 256 * sizeof (Input)); + istack->ungetcount = 0; ugchar(EOF); } diff --git a/lex.c b/lex.c @@ -349,7 +349,7 @@ extern void yyerror(const char *s) { } extern void scanerror(char *s) { - skiptonl(); /* flush upto newline */ + skiptonl(); /* flush up to newline */ yyerror(s); errset = prerror = TRUE; } diff --git a/print.c b/print.c @@ -285,11 +285,11 @@ extern int fmtprint(Format *format, const char *fmt,...) { va_list ap, saveargs; va_start(ap, fmt); - __va_copy(saveargs, format->args); - __va_copy(format->args, ap); + va_copy(saveargs, format->args); + va_copy(format->args, ap); n += printfmt(format, fmt); va_end(format->args); - __va_copy(format->args, saveargs); + va_copy(format->args, saveargs); return n + format->flushed; } @@ -316,7 +316,7 @@ extern int fprint(int fd, const char *fmt,...) { format.u.n = fd; va_start(ap, fmt); - __va_copy(format.args, ap); + va_copy(format.args, ap); printfmt(&format, fmt); va_end(format.args); @@ -361,7 +361,7 @@ extern char *mprint(const char *fmt,...) { format.u.n = 1; va_start(ap, fmt); - __va_copy(format.args, ap); + va_copy(format.args, ap); result = memprint(&format, fmt, ealloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); va_end(format.args); return result; @@ -374,7 +374,7 @@ extern char *nprint(const char *fmt,...) { format.u.n = 0; va_start(ap, fmt); - __va_copy(format.args, ap); + va_copy(format.args, ap); result = memprint(&format, fmt, nalloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); va_end(format.args); return result; diff --git a/proto.h b/proto.h @@ -23,11 +23,11 @@ typedef long align_t; #include <stdarg.h> -/* C 9x specifies a __va_copy() macro which should be used for copying -objects of type va_list. Of course, most places don't have this yet, -but where it does exist we need to use it. */ -#ifndef __va_copy -#define __va_copy(x,y) (x)=(y) +/* C 99 specifies a va_copy() macro to be used for copying +objects of type va_list. If this doesn't exist, hope that simple +assignment works. */ +#ifndef va_copy +#define va_copy(x,y) (x)=(y) #endif #if STDC_HEADERS diff --git a/rc.1 b/rc.1 @@ -161,7 +161,7 @@ .if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" .if "\\$4"" \\$3\fR\s10 .. -.TH RC 1 "2014-09-01" +.TH RC 1 "2015-04-20" .SH NAME rc \- shell .SH SYNOPSIS @@ -1142,6 +1142,13 @@ use: .Ds .Cr "echo $^path." .De +.PP +For compability with the Plan 9 rc, +.Ds +.Cr $"var +.De +.PP +is accepted as a synonym for dollar-caret. .SS "Backquote Substitution" A list may be formed from the output of a command by using backquote substitution: diff --git a/rc.h b/rc.h @@ -6,8 +6,6 @@ #define RC "rc: " -#include <assert.h> - /* datatypes */ #define ENV_SEP '\001' diff --git a/rc.spec b/rc.spec @@ -1,6 +1,6 @@ %define name rc -%define version 1.7.1 -%define release 1 +%define version 1.7.2 +%define release 3 Summary: rc - the Plan 9 and Tenth Edition shell Name: %name @@ -8,8 +8,10 @@ Version: %version Release: %release Group: Shells License: distributable -Source0: http://www.libra-aries-books.co.uk/software/rc/release/%name-%version.tar.gz +Source0: http://static.tobold.org/rc/rc-1.7.2.tar.gz Buildroot: /var/tmp/%{name}-rpmroot +BuildRequires: autoconf +BuildRequires: readline-devel %description This is a reimplementation for Unix, by Byron Rakitzis, of the Plan 9 @@ -20,7 +22,7 @@ shell, but with a much cleaner syntax. %setup %build -sh configure --with-readline --prefix "$RPM_BUILD_ROOT" --mandir "$RPM_BUILD_ROOT/usr/share/man" +sh configure --with-edit=gnu --prefix "$RPM_BUILD_ROOT" --mandir "$RPM_BUILD_ROOT/usr/share/man" make %install