dfenyes@thesis1.med.uth.tmc.edu (David Fenyes) (04/24/91)
Hello, I'm working on a small shell and I'd like it to have much of the functionality of ksh and bash without taking up as much space. If I want the code itself to fit in 64K, I've got about 8K code space to implement a history mechanism. I figure the approach would be to have the shell simply store the lines, and offer access to them in a meaningful way. All processing & re-execution, etc. can then be done with shell funcs. (The shell is based on Kenneth Almquist's ash) What is the best way to approach a history mechanism? Since the way we think of commands typed into a shell is in 'blocks' of one 'major' prompt (PS1) and the subsequent continuations (PS2's), This might be one way for the shell to think about chunks of history. Here are my thoughts for a low-level shell history support: - implement history as a dynamically resizable list. - Mark each line as major or minor prompt (ps1 or ps2) - history command is basically a lister. - A load command (which is already implemented in the shell) allows a line to be pre-fed to the editor, so a line is already in the buffer when the editor is invoked. If 'load' is invoked with a line already in the buffer, the previous line is saved in the history and the new line is stored in the buffer. - `load' command would contain an option to load as minor prompt line, loading as a major prompt line as default. - The history command contains options to list from <line> to <line>, where <line> could be relative or absolute, or can list 'blocks' from the nth back major prompt to the n+1st, etc. History options would allow lines to be listed either plain, or with appropriate prefixed option to the 'load' command to allow it to read in the line as either a major or minor prompt line. Using these tools, history can be saved in a file either wholesale with a trap 0, or the most recent chunk before each prompt via the EVERY variable, which is executed before a PS1. At logout, the file can be truncated to HISTSIZE with /bin/tail, and at login, the file can be read in with a function that precedes each line with the word 'load' and executes the result. Re-executing a command or block could be accomplished via something like : eval $(history options args...) (done in a shell function.) substitution could be done with something like eval $(subst $1 $2 "$(history opts args)"), where subst() is a shell function using builtin expr. These are just some rough thoughts, so I thought I'd ask this group for input, since most of us do some thinking about shells. Thanks, David. ---- David Fenyes dfenyes@thesis1.hsch.utexas.edu University of Texas Medical School Houston, Texas
alex@am.sublink.org (Alex Martelli) (04/26/91)
I've also hacked a simple mechanism into ash for history processing via external commands (mostly for Minix and Coherent, actually); the credit for the idea must go, at least 3/4ths of it, to my friend and colleague Lanfranco Albani, albani@cadlab.sublink.org, although I was the one that did most of the implementation. 1. the shell just appends each logical-line to a history-file; this is how any history-like external command accesses the history; 2. if, when the shell is about to emit a primary-prompt to terminal, it finds that a file named $HOME/..dothis exists, it opens, unlinks, and then sources it; this is how the shell accesses the results of any history-like external command. Several enhancements suggest themselves (have both history-file and doit-file named by environment variables, and so on) - and the best thing is that, far from needing 8K of codespace, both of these changes will fit in just a few bytes... another one of this class, if you like csh-like history-expansion as well as interactive one, is to have an environment variable HISTORY-WHEN whose syntax is a colon-separated list of pairs regular-expression//program-name: if a logical line matches a regular expression, then it is passed to the standard input of the associated program name (at a quite early stage of the processing) - the program can emit the commands to be performed to standard output and/or to the doit-file as before. For example, an HISTORY-WHEN of '/^^|[^\\]!/cshclone' would strictly imitate csh's behavior (assuming cshclone does so) - the /'s are just arbitrary separators, the regular expression means 'a caret at line start or a non-backslash followed by a bang' (...the heavy overloading of the caret sign makes it LOOK more complex that it is...:-). As you can probably tell, this last suggestion is one I have not implemented, nor even fully finalized in design [what exactly should be the difference between the history-filter emitting to stdout versus putting commands into the doit-file, and what if it does both, what *should* be put into the history-file, etc, to keep it reasonably simple and usable]. Notice that ash already has regexps, as a part of the expr/test builtin, so their price in codesize has been paid already... As is typical of good ideas, these simple tricks have many uses - the doit-file, for example, allows not only history-like mechanisms but all sorts of external mechanisms able to set the shell's environment, change its current-directory, and so on. Together with the "executable prompt string" that we already discussed, these ideas work well in my ash ('mash'). I would of course be honored if any shell author felt it worth his or her while to use or elaborate them in another shell... -- Alex Martelli - (home snailmail:) v. Barontini 27, 40138 Bologna, ITALIA Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).
jmason@gpu.utcs.utoronto.ca (Jamie Mason) (04/28/91)
In article <1991Apr25.212431.1109@am.sublink.org> alex@am.sublink.org (Alex Martelli) writes: >2. if, when the shell is about to emit a primary-prompt to terminal, it > finds that a file named $HOME/..dothis exists, it opens, unlinks, > and then sources it; this is how the shell accesses the results of > any history-like external command. SECURITY HOLE!! Someone else could easlily write this file, and the shell would execute their commands. The shell should *at least* enforce that ~/.doit be a) owned by the effective uid of the shell and b) of mode 600 (or 700, since it *is* being executed, sort of). Jamie ... Segmentation fault (core dumped) Written On Sunday, April 28, 1991 at 12:27:03am EDT
alex@am.sublink.org (Alex Martelli) (05/05/91)
jmason@gpu.utcs.utoronto.ca (Jamie Mason) writes: ... :In article <1991Apr25.212431.1109@am.sublink.org> alex@am.sublink.org (Alex Martelli) writes: :>2. if, when the shell is about to emit a primary-prompt to terminal, it :> finds that a file named $HOME/..dothis exists, it opens, unlinks, :> and then sources it; this is how the shell accesses the results of :> any history-like external command. : : SECURITY HOLE!! Someone else could easlily write this file, and :the shell would execute their commands. The shell should *at least* :enforce that ~/.doit be a) owned by the effective uid of the shell and b) :of mode 600 (or 700, since it *is* being executed, sort of). 'easily'? ALL dot files in your home directory can be thought of as "security holes" in this way - if you leave them writable (in general, if you leave your home directory writable!), you're already asking for big trouble, and, no, I don't think such mode-600ness is enforced today for .profile, .exrc, .cshrc, .login, .rhosts, whatever $ENV points at in ksh, and so on! -- Alex Martelli - (home snailmail:) v. Barontini 27, 40138 Bologna, ITALIA Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).
meissner@osf.org (Michael Meissner) (05/08/91)
In article <1991May05.003216.300@am.sublink.org> alex@am.sublink.org (Alex Martelli) writes: | 'easily'? ALL dot files in your home directory can be thought of as | "security holes" in this way - if you leave them writable (in general, | if you leave your home directory writable!), you're already asking | for big trouble, and, no, I don't think such mode-600ness is enforced | today for .profile, .exrc, .cshrc, .login, .rhosts, whatever $ENV | points at in ksh, and so on! Of the files listed, only .rhosts should (and in fact must) be protected by 0600. I see no point in making the rest world unreadable. It helps newbies if I can point them to existing dot files for examples of how to customize things (though of course my personel dot files have been overcustomized over the years, and tend to overwhelm). -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Considering the flames and intolerance, shouldn't USENET be spelled ABUSENET?