[gnu.bash.bug] bash bug report

emil%chem@UCSD.EDU (Emil M. Scoffone) (06/26/89)

GNU program:		Bash 1.01
Machine:		Compaq Deskpro 386/16
Operating System:	System V/386 Release 3.2
			(vendor: Bell Technologies)
Compiler:		GNU C, version 1.35, with GNU as and ld.

I defined a new machine name `i386' in Makefile, for PCs.
The UNIXPC operating system type seems to be for Xenix, so I
used the SYSV-i386 combination for distinguishing a PC based machine
running sysV.
Mail (if needed) to escoffon@ucsd.edu.

****************************************

These are bugs I found while installing bash:

----------------------------------------
in `shell.c':
	SIGVTALRM and SIGPROF are undefined signals under sysv.
Fix:
	used #ifdef's to selectively include the signals.
----------------------------------------
in `general.c':

	in `dup2':
		fDUPFD undeclared
	Fix:
		changed to F_DUPFD

	in `gethostname':
		namelen undeclared
	Fix:
		changed to namlen
----------------------------------------
in `parse.y':	(this is a warning, I think)

	in `decode_prompt_string':
		assignment needs a cast (line 1516)
	Fix:
		added `extern char *index();' declaration.

	Note that people who load with libPW.a should probably redefine
	`index' to `strchr', since there is a `index' routine in that
	library.
----------------------------------------

Note also that I had to change the name `unwind_correct.c' to
`uw_correct.c', since sysV takes at most 14 characters for filenames.
I subscribe to your opinions on the subject.

****************************************

These are bugs I found while running bash:

----------------------------------------
When a command is run that returns a nonzero exit code xxx, bash
prints the message
	Signal xxx (core dumped)
This is because `struct wait' is incorrectly defined in `jobs.h':
the low and high byte of the return value from wait(2) are swapped.

Fix:	rewrote `struct wait' to give the right byte order.
----------------------------------------

****************************************

In addition to the bug fixes, I made some other (convenience) changes:

----------------------------------------
`shell_ulimit' was slightly modified to be more in line with the
description of ulimit(2) on my system.
----------------------------------------
On my computer, ^H by default acts as the `erase' character; bash
uses RUBOUT for this purpose. In order to be consistent, I changed the
keymap for ^H from `rl_backward' to `rl_rubout'.
The macro CTRLH_SAME_AS_RUBOUT (defined in `readline.h') can be used to
turn the new mapping on or off.
----------------------------------------
I use shl(1) in lieu of job control under SysV. This implies that one
cannot turn ISIG off, since the terminal driver interprets the `switch'
character and signals shl. By default, the readline package will turn
ISIG off when NOJOBS is defined, which makes it impossible to switch
out of bash.
The macro WANT_SHL (defined in `readline.h') can be used to turn the
switching on or off under sysV.
----------------------------------------

****************************************

I also made some minor changes here and there, which are not worth
a long-winded report. The rest of the file shows all the differences
between my modified bash files and the 1.01 distribution.

diff dist-bash/FEATURES old-bash/FEATURES
diff dist-bash/LICENSE old-bash/LICENSE
diff dist-bash/Makefile old-bash/Makefile
30c30
< MAINTAINER = '"escoffon@ucsd.edu"'
---
> MAINTAINER = '"bfox@ai.mit.edu"'
34c34
< DESTDIR = /usr/local/bin
---
> DESTDIR = /usr/gnu/bin
39,40c39,40
< # SUN3, SUN4, SUN386i, i386, VAX, SONY, CONVEX, HP, HP9KS300
< TARGET = i386
---
> # SUN3, SUN4, SUN386i, VAX, SONY, CONVEX, HP, HP9KS300
> TARGET = SUN3
45c45
< OS = SYSV
---
> OS = SUNOS4
73c73
< TERMCAP = curses
---
> TERMCAP = termcap
99c99
< SPROMPT = '"${PROGRAM}> "'
---
> SPROMPT = '"${PROGRAM}>"'
112,113c112,113
< #MALLOC = $(ALLOC_SOURCE)malloc-rcheck.o
< MALLOC= $(ALLOC_SOURCE)malloc.o
---
> MALLOC = $(ALLOC_SOURCE)malloc-rcheck.o
> #MALLOC= $(ALLOC_SOURCE)malloc.o
125c125
< 	   uw_protect.c
---
> 	   unwind_protect.c
137c137
< 	   braces.o uw_protect.o	   
---
> 	   braces.o unwind_protect.o	   
diff dist-bash/README old-bash/README
diff dist-bash/alias.c old-bash/alias.c
diff dist-bash/alias.h old-bash/alias.h
diff dist-bash/braces.c old-bash/braces.c
diff dist-bash/builtins.c old-bash/builtins.c
25,26d24
< #if	!(defined(SYSV) && defined(i386))
< #include <sys/resource.h>
27a26
> #include <sys/resource.h>
29d27
< #endif
2424d2421
< #if	!(defined(SYSV) && defined(i386))
2426d2422
< #endif  /* SYSV && i386 */
2439,2441d2434
< #ifdef i386
< 	  return (ulimit (1, 0));
< #else   /* i386 */
2443d2435
< #endif  /* i386 */
diff dist-bash/builtins.h old-bash/builtins.h
diff dist-bash/config.h old-bash/config.h
6,9d5
< #ifdef __GNUC__
< #define alloca __builtin_alloca
< #endif
< 
68a65
> 
diff dist-bash/copy_cmd.c old-bash/copy_cmd.c
diff dist-bash/dispose_cmd.c old-bash/dispose_cmd.c
diff dist-bash/emacs_keymap.c old-bash/emacs_keymap.c
diff dist-bash/execute_cmd.c old-bash/execute_cmd.c
diff dist-bash/flags.c old-bash/flags.c
diff dist-bash/flags.h old-bash/flags.h
diff dist-bash/funmap.c old-bash/funmap.c
diff dist-bash/general.c old-bash/general.c
28,30d27
< #if	defined(SYSV) && defined(i386)
< #include <string.h>
< #else
32d28
< #endif  /* SYSV && i386 */
370c366
< int dup2 (f, t) int f, t; { close (t); return (fcntl (f, F_DUPFD, t)); }
---
> int dup2 (f, t) int f, t; { close (t); return (fcntl (f, fDUPFD, t)); }
382c378
<   name[namlen - 1] = '\0';
---
>   name[namelen - 1] = '\0';
diff dist-bash/general.h old-bash/general.h
diff dist-bash/glob.c old-bash/glob.c
54,56d53
< #ifdef __GNUC__
< #define alloca __builtin_alloca
< #else
58d54
< #endif
diff dist-bash/hash.c old-bash/hash.c
diff dist-bash/hash.h old-bash/hash.h
diff dist-bash/history.c old-bash/history.c
diff dist-bash/history.h old-bash/history.h
diff dist-bash/inform old-bash/inform
diff dist-bash/jobs.c old-bash/jobs.c
diff dist-bash/jobs.h old-bash/jobs.h
9,14c9
< union wait { 
<     struct { 
< 	unsigned char low; unsigned char high; 
<     } bytes; 
<     unsigned short word;
< };
---
> union wait { struct { char high; char low; } bytes; short word; };
17c12
< #define w_termsig bytes.low & ~0200 
---
> #define w_termsig bytes.low
20c15
< #define w_coredump bytes.low & 0200
---
> #define w_coredump w_termsig & 0x7f
110a106
> 
diff dist-bash/keymaps.c old-bash/keymaps.c
diff dist-bash/longest_signal old-bash/longest_signal
diff dist-bash/mail-shell old-bash/mail-shell
diff dist-bash/mailcheck.c old-bash/mailcheck.c
27,30d26
< #ifdef __GNUC__
< #define alloca __builtin_alloca
< #endif
< 
diff dist-bash/make_cmd.c old-bash/make_cmd.c
diff dist-bash/newversion.c old-bash/newversion.c
diff dist-bash/nojobs.c old-bash/nojobs.c
diff dist-bash/parse.y old-bash/parse.y
1404d1403
<   extern char *index ();
diff dist-bash/print_cmd.c old-bash/print_cmd.c
diff dist-bash/readline.c old-bash/readline.c
85d84
< #ifndef WANT_SHL
90d88
< #endif
567,569d566
< #ifdef	CTRLH_SAME_AS_RUBOUT
<   keymap[CTRL('H')] = rl_rubout; 
< #else
571d567
< #endif
diff dist-bash/readline.h old-bash/readline.h
89,101d88
< /* escoffon@ucsd.edu
<    If on, then readline does not turn signal generation off when in SysV.
<    The idea is that ISIG is kept on, and therefore a ^Z will signal the
<    shell layer manager, shl(1). */
< #if	defined(SYSV)
< #define WANT_SHL
< #endif
< 
< /* escoffon@ucsd.edu
<    If on, then readline maps backspaces (^H) and delete to perform
<    the same operation. */
< #define CTRLH_SAME_AS_RUBOUT
< 
diff dist-bash/shell.c old-bash/shell.c
737,742c737
< #ifdef SIGVTALRM
<   SIGVTALRM,
< #endif
< #ifdef SIGPROF
<   SIGPROF,
< #endif
---
>   SIGVTALRM, SIGPROF,
diff dist-bash/shell.h old-bash/shell.h
diff dist-bash/subst.c old-bash/subst.c
diff dist-bash/test.c old-bash/test.c
diff dist-bash/trap.c old-bash/trap.c
diff dist-bash/trap.h old-bash/trap.h
diff dist-bash/uw_protect.c old-bash/uw_protect.c
diff dist-bash/variables.c old-bash/variables.c
28,31d27
< #ifdef __GNUC__
< #define alloca __builtin_alloca
< #endif
< 
diff dist-bash/variables.h old-bash/variables.h
diff dist-bash/version.h old-bash/version.h
diff dist-bash/vi_keymap.c old-bash/vi_keymap.c

emil%chem@UCSD.EDU (Emil M. Scoffone) (07/17/89)

To: bug-bash@ai.mit.edu

BASH version:	1.02
Machine:	Sun 3/160
OpSys:		SunOS 3.2 (4.2BSD)
Compiler:	Sun's native cc

------------------------------------------------------------
Description of bug:

Hitting ^D at the beginning of line results in the
following message:

Segmentation fault (core dumped)

and the shell crashes. This seems to be independent of the
value of 'IGNOREEOF' and 'ignoreeof'.

------------------------------------------------------------
Probable Reason:

I ran BASH in dbx, and found out that 'readline' returns EOF
coerced to a (char *) on its second invocation after it has
seen a valid EOF. On the other hand, 'yy_readline_get' never checks
if the value that 'readline' returns in 'current_readline_line'
is a valid pointer. When it gets to 'strlen' in the 'xrealloc'
call, BASH bombs out.

------------------------------------------------------------
My Fix:

I edited 'parse.y' to include a statement that checks if
'current_readline_line' is (char *) EOF:

08:16:45 pogo(6) diff -c parse.y parse.y~
*** parse.y     Mon Jul 17 08:16:44 1989
--- parse.y~    Mon Jul 17 08:05:13 1989
***************
*** 429,439 ****
        else
        current_readline_line = readline (current_readline_prompt);
  
-       if (current_readline_line == (char *) EOF) {
-                 current_readline_line = (char *)NULL;
-                 return (EOF);
-       }
- 
        current_readline_line_index = 0;
        current_readline_line =
        (char *)xrealloc (current_readline_line,
--- 429,434 ----
08:16:50 pogo(7)

------------------------------------------------------------

I have also seen erratic behaviour on ^D on a Compaq 386 running 
System V, but I haven't had time to look at it in great detail.

emil%chem@UCSD.EDU (Emil M. Scoffone) (07/22/89)

To: bug-bash@ai.mit.edu

GNU program:		Bash 1.02
Machine:		Compaq Deskpro 386/16
Operating System:	System V/386 Release 3.2
			(vendor: Bell Technologies)
Compiler:		GNU C, version 1.35, with GNU as and ld.

****************************************

These are bugs I found while installing bash:

----------------------------------------
in `shell.c':
	on line 305: 'job_control' undefined.
Fix:
	changed line 304 from
#ifndef JOB_CONTROL
	to
#ifndef NOJOBS
----------------------------------------
in `variables.c' and `readline.c':
	`struct pwd' should be `struct passwd'
----------------------------------------
in `readline.c':
	`sigsetmask' is referenced, but there is no such
	system call on my UNIX.
Fix:
	I defined a dummy `sigsetmask' that does nothing. I
	was too lazy to write one that mimicks the behaviour of 
	BSD `sigsetmask'
----------------------------------------
in 'glob.c':
	I added an #ifdef to use the GNU builtin alloca.
----------------------------------------

****************************************

These are bugs I found while running bash:

----------------------------------------
The shell does incorrectly reports exit codes from a killed job.
This is because a couple of masks were defined incorrectly in
`jobs.h'. I also parenthesized two expressions in 'nojobs.h'.
----------------------------------------
I get segmentation violations or memory errors, and the shell
bombs, when I hit ^D. This is the same bug I reported a couple
of days ago on a Sun 3/160, and I fixed it the same way
(added a few lines to 'parse.y').
----------------------------------------

****************************************

The following is a list of modifications to the source files:

------------------------------------------------------------
diff -c shell.c shell.c~

*** shell.c	Tue Jul 11 20:33:11 1989
--- shell.c~	Fri Jul 21 15:01:20 1989
***************
*** 301,307 ****
    else
      {
        interactive = 0;
! #ifndef NOJOBS
        job_control = 0;
  #endif
      }
--- 301,307 ----
    else
      {
        interactive = 0;
! #ifndef JOB_CONTROL
        job_control = 0;
  #endif
      }

------------------------------------------------------------
diff -c variables.c variables.c~

*** variables.c	Tue Jul 11 21:02:14 1989
--- variables.c~	Fri Jul 21 15:01:20 1989
***************
*** 26,31 ****
--- 26,35 ----
  #include "flags.h"
  #include "version.h"
  
+ #ifdef SYSV
+ struct pwd *getpwuid (), *getpwent ();
+ #endif
+ 
  /* The list of shell variables that the user has created, or that came from
     the environment. */
  SHELL_VAR *variable_list;

------------------------------------------------------------
diff -c ./lib/readline.c ./lib/readline.c~

*** ./lib/readline.c	Fri Jul 21 15:07:21 1989
--- ./lib/readline.c~	Fri Jul 21 15:02:42 1989
***************
*** 58,63 ****
--- 58,66 ----
  #include <sys/stat.h>
  
  #include <pwd.h>
+ #ifdef SYSV
+ struct pwd *getpwuid (), *getpwent ();
+ #endif
  
  #define HACK_TERMCAP_MOTION
  
***************
*** 272,284 ****
         		*old_ttou = (Function *)NULL,
         		*old_ttin = (Function *)NULL,
         	 	*old_cont = (Function *)NULL;
- 
- #ifdef SYSV
- void sigsetmask(mask)
- int mask;
- {
- }
- #endif SYSV
    
  /* Handle an interrupt character. */
  static
--- 275,280 ----

------------------------------------------------------------
diff -c jobs.h jobs.h~

*** jobs.h	Mon Jul 17 22:14:14 1989
--- jobs.h~	Fri Jul 21 15:01:20 1989
***************
*** 17,26 ****
  
  #define WSTOPPED 0177
  #define w_status word
! #define w_termsig bytes.low & 0x7f
! #define w_coredump bytes.low & ~0x7f
  #define w_stopsig bytes.high
  #define w_retcode bytes.high
  #define WIFEXITED(wstat) ((wstat).bytes.low == 0)
  #define WIFSTOPPED(wstat) ((wstat).bytes.low == 0177)
  #define WIFTERMINATED(wstat) ((wstat).bytes.high == 0)
--- 17,26 ----
  
  #define WSTOPPED 0177
  #define w_status word
! #define w_termsig bytes.low & ~0x7f
  #define w_stopsig bytes.high
  #define w_retcode bytes.high
+ #define w_coredump w_termsig & 0x7f
  #define WIFEXITED(wstat) ((wstat).bytes.low == 0)
  #define WIFSTOPPED(wstat) ((wstat).bytes.low == 0177)
  #define WIFTERMINATED(wstat) ((wstat).bytes.high == 0)

------------------------------------------------------------
diff -c nojobs.c nojobs.c~

*** nojobs.c	Mon Jul 17 22:14:43 1989
--- nojobs.c~	Fri Jul 21 15:11:22 1989
***************
*** 144,151 ****
    /* Default return value. */
    return_val = status.w_retcode & 0x7f;
  
!   if ((status.w_termsig) != 0 &&
!       (status.w_termsig) != WSTOPPED) {
  #ifndef SYSV
      extern char *sys_siglist[];
      fprintf (stderr, "%s", sys_siglist[status.w_termsig]);
--- 144,151 ----
    /* Default return value. */
    return_val = status.w_retcode & 0x7f;
  
!   if (status.w_termsig != 0 &&
!       status.w_termsig != WSTOPPED) {
  #ifndef SYSV
      extern char *sys_siglist[];
      fprintf (stderr, "%s", sys_siglist[status.w_termsig]);

------------------------------------------------------------
diff -c glob.c glob.c~

*** glob.c	Tue Jul 11 21:35:20 1989
--- glob.c~	Fri Jul 21 15:02:19 1989
***************
*** 51,63 ****
  #ifdef	sparc
  #include <alloca.h>
  #else
- 
- #ifdef __GNUC__
- #define alloca __builtin_alloca
- #else
  extern char *alloca ();
- #endif
- 
  #endif	/* sparc */
  
  extern char *malloc (), *realloc ();
--- 51,57 ----

------------------------------------------------------------
diff -c parse.y parse.y~

*** parse.y	Mon Jul 17 22:19:06 1989
--- parse.y~	Fri Jul 21 15:11:03 1989
***************
*** 429,440 ****
        else
  	current_readline_line = readline (current_readline_prompt);
  
-       if (current_readline_line == (char *) EOF)
-         {
-           current_readline_line = (char *)NULL;
-           return (EOF);
-         }
- 
        current_readline_line_index = 0;
        current_readline_line =
  	(char *)xrealloc (current_readline_line,
--- 429,434 ----

bfox@AUREL.CALTECH.EDU (Brian Fox) (07/22/89)

   Date: Fri, 21 Jul 89 15:14:08 PDT
   From: emil%chem@ucsd.edu (Emil M. Scoffone)
   To: bug-bash@ai.mit.edu

   GNU program:		Bash 1.02
   Machine:		Compaq Deskpro 386/16
   Operating System:	System V/386 Release 3.2
			   (vendor: Bell Technologies)
   Compiler:		GNU C, version 1.35, with GNU as and ld.

   ****************************************

   These are bugs I found while installing bash:

   ----------------------------------------
   The shell does incorrectly reports exit codes from a killed job.
   This is because a couple of masks were defined incorrectly in
   `jobs.h'. I also parenthesized two expressions in 'nojobs.h'.
   ----------------------------------------

Thank you for your clear bug report.

I recently received a fix for the 386 problems.  It has to do with the
byte order defined in the "wait" structure.  Please try using this
jobs.h file, and tell me if it works.

----------------------------------------
File: /usr/gnu/src/bash/jobs.h
----------------------------------------
/* jobs.h -- structures and stuff used by the jobs.c file. */

#if !defined (SYSV) || defined (UNIXPC)
#include <sys/wait.h>
#else

#if defined (i386) || defined (ATT3B) || defined (ATT386)

union wait {
  struct {
    unsigned char low;
    unsigned char high;
  }
  bytes;
  short word;
};

#define WSTOPPED 0177
#define w_status word
#define w_termsig bytes.low & ~0x7f
#define w_stopsig bytes.high
#define w_retcode bytes.high
#define w_coredump w_termsig & 0x7f
#define WIFEXITED(wstat) ((wstat).bytes.low == 0)
#define WIFSTOPPED(wstat) ((wstat).bytes.low == 0177)
#define WIFTERMINATED(wstat) ((wstat).bytes.high == 0)

#else  /* i386 || ATT3B || ATT386 */

#ifdef HPUX
union wait
  {
    int	w_status;		/* used in syscall */

    /* Terminated process status. */
    struct
      {
	unsigned short
	  w_Fill1    : 16,	/* high 16 bits unused */
	  w_Retcode  : 8,	/* exit code if w_termsig==0 */
	  w_Coredump : 1,	/* core dump indicator */
	  w_Termsig  : 7;	/* termination signal */
      } w_T;

    /* Stopped process status.  Returned
       only for traced children unless requested
       with the WUNTRACED option bit. */
    struct
      {
	unsigned short
	  w_Fill2   : 16,	/* high 16 bits unused */
	  w_Stopsig : 8,	/* signal that stopped us */
	  w_Stopval : 8;	/* == W_STOPPED if stopped */
      } w_S;
  };

#define	w_termsig w_T.w_Termsig
#define w_coredump w_T.w_Coredump
#define w_retcode w_T.w_Retcode
#define w_stopval w_S.w_Stopval
#define w_stopsig w_S.w_Stopsig

#define	WSTOPPED 0177
#define WIFSTOPPED(x) (((x) . w_stopval) == WSTOPPED)
#define WIFEXITED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) == 0))
#define WIFSIGNALED(x) ((! (WIFSTOPPED (x))) && (((x) . w_termsig) != 0))

#endif  /* HPUX */
#endif  /* i386 || ATT3B || ATT386 */
#endif  /* !defined (SYSV) || defined (UNIXPC) */

/* I looked it up.  For pretty_print_job ().  The real answer is 24. */
#define LONGEST_SIGNAL_DESC 20

/* We keep an array of jobs.  Each entry in the array is a linked list
   of processes that are piped together.  The first process encountered is
   the group leader. */

/* Each child of the shell is remembered in a STRUCT PROCESS.  A chain of
   such structures is a pipeline.  The chain is circular. */
typedef struct process {
  struct process *next;	/* Next process in the pipeline.  A circular chain. */
  int pid;		/* Process ID. */
  union wait status;	/* The status of this command as returned by wait. */
  int running;		/* Non-zero if this process is running. */
  char *command;	/* The particular program that is running. */
} PROCESS;

/* A description of a pipeline's state. */
typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
#define JOBSTATE(job) (jobs[(job)]->state)

typedef struct job {
  char *wd;		/* The working directory at time of invocation. */
  PROCESS *pipe;	/* The pipeline of processes that make up this job. */
  int pgrp;		/* The process ID of the process group (necessary). */
  int foreground;	/* Non-zero if this is running in the foreground. */
  int notified;		/* Non-zero if already notified about job state. */
  JOB_STATE state;	/* The state that this job is in. */
#ifdef JOB_CONTROL
  COMMAND *deferred;	/* Commands that will execute when this job is done. */
#endif
} JOB;

#define NO_JOB -1	/* An impossible job array index. */
#define DUP_JOB -2	/* A possible return value for get_job_spec (). */

/* Stuff from the jobs.c file. */
extern int last_made_pid;
extern int current_job, previous_job;
extern int asynchronous_notification;
extern JOB **jobs;
extern int job_slots;

----------------------------------------

schene@UUNET.UU.NET (Tony Schene) (07/26/89)

Version: #define VERSION 1.02
Hardware: Sun 4/280
OS: SunOS 4.0.2 with Prisma enhancements and bug fixes
Compiler: Sun cc with Prisma bug fixes and enhancements
Bug:
	bash crashes if ^D is input

Repeat by:
	1) Start up bash
	2) Type ^D

Comments:
	The problem is in yy_readline_get() in line 430 of parse.y,
	on the call to readline().  Readline() returns -1 on EOF, but
	this is not checked for, and the -1 is later passed to
	strlen() on line 435.  Instant death.  I don't have a clue
	as to how to propagate this back up gracefully, but I'm
	sure you do.  Hope this helps.

pwolfe@kailand.kai.com (Patrick Wolfe) (12/03/89)

System:  Sequent Balance B8
OS:      Sequent Dynix (BSD 4.2)
version: 1.04

I picked up and started using bash this week and found a few problems.

First, there appears to be a bug in the malloc routines.  When I compiled bash
with the supplied malloc, it would die with "free: invalid argument" after
the following command sequence was executed:

	$ lf ~partial-username<tab>
	$ lf ~partial-username<tab>

The first command would work, but the second one would kill bash.  When I
recompiled using the system's malloc, everything seems to work okay.

The second problem is that readline seems to trash the command line if the
TERMCAP for the current terminal has the "IC" capability in it.  It is adding
one extra blank for every character inserted (including one for the asterisk at
the beginning of an edited line).

Also, bash allows multi line prompts, but readline has problems when one is
used, since it likes to jump to the begining of the current line and rewrite
the prompt and beginning of the command.

I would like to commend all those who've been working on bash and readline so
far.  I plan to continue using bash, and to try to find and fix any bugs I can.
The "vi mode" simply blows away TCSH.

-- 

        Patrick Wolfe
        System Manager, Kuck & Associates
	work: pwolfe@kailand.kai.com  or  uunet!kailand!pwolfe
	home: pat@pawnix.kai.com  or  uunet!kailand!pawnix!pat

chet@cwns1.CWRU.EDU (Chet Ramey) (12/04/89)

In article <8912030428.AA01426@kailand.kai.com> pwolfe@kailand.kai.com (Patrick Wolfe) writes:

>First, there appears to be a bug in the malloc routines.  When I compiled bash
>with the supplied malloc, it would die with "free: invalid argument" after
>the following command sequence was executed:
>
>	$ lf ~partial-username<tab>
>	$ lf ~partial-username<tab>
>
>The first command would work, but the second one would kill bash.  When I
>recompiled using the system's malloc, everything seems to work okay.

This is a problem with YP (this is just one of many problems with YP) and
the password routines that interact with it.  These YP routines keep a
socket open to the YP server, and close and reopen it when they think they
need to (which is only right *some* of the time).  Based on this
assumption, the routines keep a pointer into the data returned from the YP
server.  When you do a `setpwent', setpwent frees up this storage if it
thinks it needs to.  This isn't always right, and you end up freeing freed
storage.  The Dynix free () allows you to free freed blocks; the bash free ()
doesn't.  I tend to think the fault is with the Dynix free () and the YP
routines. 

Chet Ramey

-- 
Chet Ramey
Network Services Group				"Where's my froggie?"
Case Western Reserve University
chet@ins.CWRU.Edu			

tchrist@convex.COM (Tom Christiansen) (12/08/89)

In article <8912030428.AA01426@kailand.kai.com> pwolfe@kailand.kai.com (Patrick Wolfe) writes:

>I would like to commend all those who've been working on bash and readline so
>far.  I plan to continue using bash, and to try to find and fix any bugs I can.
>The "vi mode" simply blows away TCSH.

Well, it's nice, but it's not as complete a vi as ksh's vi mode, 
which is too bad.

I also like the way tcsh allows ^W to back up to things like / and +,
not just to white space.

And I miss the asynchronous notification of tcsh and csh that's also
lacking in ksh.  

I've been told by devout ksh users that it's missing autoload functions.

--tom

    Tom Christiansen                       {uunet,uiucdcs,sun}!convex!tchrist 
    Convex Computer Corporation                            tchrist@convex.COM
		 "EMACS belongs in <sys/errno.h>: Editor too big!"

trost@reed.bitnet (Bill Trost) (12/09/89)

>I've been told by devout ksh users that it's missing autoload functions.

Hah, you friends just don't know how to write ksh.  I did the same
thing with bash with a few minutes playing.  Presumably, the ksh
mechanism is equivalent.

Anyone know how to do this without a tmp file? ". <<" doesn't work.

autoload() {
	echo $1 \(\) \{ echo . $2 2\>\&1 \; . $2 \} > /tmp/au.$$
	. /tmp/au.$$
	rm /tmp/au.$$
}

Sample use (spam should be defined in ~/spam):

bash% autoload spam ~/spam
bash% type spam
spam is a function
spam() { echo . /u/trost/spam 2>&1 ; . /u/trost/spam }
bash% spam
. /u/trost/spam
/u/trost/spam: No such file or directory


trost%reed@tektronix.tek.com
--
Bill Trost
trost@reed.bitnet, but probably trost%reed@tektronix.tek.com

anders@digre.uio.no (Anders Ellefsrud) (12/14/89)

> >I've been told by devout ksh users that it's missing autoload functions.
> 
> autoload() {
> 	echo $1 \(\) \{ echo . $2 2\>\&1 \; . $2 \} > /tmp/au.$$
> 	. /tmp/au.$$
> 	rm /tmp/au.$$
> }
> 

I see a few problems with that function. I think this is better:

    autoload() {
        eval `echo "$1" "() { args=\$@ ; . $2 ; set -- \$args; $1 \$@ }"`
    }


Note: I said BETTER, not PERFECT! It will not handle funny arguments like
'foo bar'.

Usage:

	autoload foo ~/lib/the_foo_function
	.
	.
	.
	foo bar

... works as expected, but 
	foo 'gaz onk' does not.


---
anders@ifi.uio.no

bfox@sbphy.ai.mit.edu (Brian Fox) (12/14/89)

   Date: 13 Dec 89 17:28:36 GMT
   From: mcsun!sunic!nuug!ifi!digre!anders@uunet.uu.net  (Anders Ellefsrud)
   References: <8912030428.AA01426@kailand.kai.com>, <3749@convex.UUCP>
   Sender: bug-bash-request@prep.ai.mit.edu

   > >I've been told by devout ksh users that it's missing autoload functions.

Please send documentation on "autoload functions".

Brian

chet@cwns1.CWRU.EDU (Chet Ramey) (12/15/89)

In article <8912132157.AA04187@sbphy.Ucsb.EDU> bfox@sbphy.ai.mit.edu (Brian Fox) writes:
>
>   Date: 13 Dec 89 17:28:36 GMT
>   From: mcsun!sunic!nuug!ifi!digre!anders@uunet.uu.net  (Anders Ellefsrud)
>   References: <8912030428.AA01426@kailand.kai.com>, <3749@convex.UUCP>
>   Sender: bug-bash-request@prep.ai.mit.edu
>
>   > >I've been told by devout ksh users that it's missing autoload functions.
>
>Please send documentation on "autoload functions".

When you declare a function `autoload', it is marked as `undefined', and its
definition is deferred until its first use.  When such a function is
referenced for the first time, a search is made of the `FPATH', a 
colon-separated list of directories just like $PATH, for a file whose name
is the same as the function.  If found, the file is then read in as if it
had been the argument to a `.' command, and the function is executed.  This
is, I guess, how you get function libraries for doing shell programming.

`autoload' is really a predefined alias for `typeset -fu'

Here are two functions that will do pretty much the same thing for bash, with
only a couple of differences.  You need two fixes for bash to make this work
`right':  the fix for "$@" and a fix to stop the `.' command from blowing away
the dollar variables unconditionally (ksh assigns extra arguments to `.' to
the dollar variables, but leaves them alone if there are no extra args).

`autoload' does the whole deal: handle multiple arguments, parse $FPATH,
and so on.  It calls `aload', which is a descendent of Bill Trost's
`autoload' function, for each argument that it finds.  An autoloaded
function will be loaded from its source file on first reference, its
definition will be replaced by the one in the source file, then the new
definition will be run.   This is about the best you can do without source
support.

Chet Ramey

#
# An almost ksh-compatible `autoload'.  A function declared as `autoload' will
# be read in from a file the same name as the function found by searching the
# $FPATH (which works the same as $PATH), then that definition will be run.
#
# To do this without source support, we define a dummy function that, when
# executed, will load the file (thereby re-defining the function), then 
# execute that newly-redefined function with the original arguments.
#
# It's not identical to ksh because ksh apparently does lazy evaluation
# and looks for the file to load from only when the function is referenced.
# This one requires that the file exist when the function is declared as
# `autoload'.
#
# usage: autoload func [func...]
#
# The first cut of this was by Bill Trost, trost@reed.bitnet
#
# Chet Ramey
# chet@ins.CWRU.Edu

#
# Declare a function ($1) to be autoloaded from a file ($2) when it is first
# called.  This defines a `temporary' function that will `.' the file 
# containg the real function definition, then execute that new definition with
# the arguments given to this `fake' function.  The autoload function defined
# by the file and the file itself *must* be named identically.
#

aload()
{
	echo $1 \(\) \{  . $2 \; $1 \"\$\@\" \} > /tmp/au.$$
	. /tmp/au.$$
	rm /tmp/au.$$
}

#
# Search $FPATH for a file the same name as the function given as $1, and
# autoload the function from that file.  There is no default $FPATH.
#

autoload()
{
	#
	# save the list of functions; we're going to blow away the arguments
	# in a second
	#

	local args="$*"

	if [ $# -eq 0 ] ; then
		echo "usage: autoload function [function...]"
		return 1
	fi

	#
	# If there is no $FPATH, there is no work to be done
	#

	if [ -z "$FPATH" ] ; then
		echo autoload: FPATH not set
		return 1
	fi

	#
	# This treats FPATH exactly like PATH: a null field anywhere in the
	# FPATH is treated the same as the current directory.
	#
	# The path splitting command is taken from Kernighan and Pike
	#

	fp=$(echo $FPATH | sed 's/^:/.:/
				s/::/:.:/g
				s/:$/:./
				s/:/ /g')

	for FUNC in $args ; do
		#
		# We're blowing away the arguments to autoload here...
		#
		set $fp

		while [ $# -ne 0 ] ; do
			if [ -f $1/$FUNC ] ; then
				break			# found it! 
			fi
			shift
		done

		if [ $# -eq 0 ] ; then
			echo "$FUNC: autoload function not found"
			continue
		fi

#		echo auto-loading $FUNC from $1/$FUNC
		aload $FUNC $1/$FUNC
	done

	return 0
}

-- 
Chet Ramey
Network Services Group				"Where's my froggie?"
Case Western Reserve University
chet@ins.CWRU.Edu			

bfox@sbphy.ai.mit.edu (Brian Fox) (01/05/90)

   Date: 7 Dec 89 17:18:52 GMT
   From: sun-barr!newstop!texsun!convex!tchrist%convex.COM@ames.arc.nasa.gov  (Tom Christiansen)
   Organization: CONVEX Software Development, Richardson, TX
   References: <8912030428.AA01426@kailand.kai.com>
   Sender: bug-bash-request@prep.ai.mit.edu

   In article <8912030428.AA01426@kailand.kai.com> pwolfe@kailand.kai.com (Patrick Wolfe) writes:

   >I would like to commend all those who've been working on bash and readline so
   >far.  I plan to continue using bash, and to try to find and fix any bugs I can.
   >The "vi mode" simply blows away TCSH.

   Well, it's nice, but it's not as complete a vi as ksh's vi mode, 
   which is too bad.

It would be more helpful to tell us what features are missing in Bash.
Then perhaps we could put them in.

   I also like the way tcsh allows ^W to back up to things like / and +,
   not just to white space.

The command <backward-kill-word> operates in this fashion.  You can
set C-w to run this command in your ~/.inputrc file with:

	C-w: backward-kill-word

   And I miss the asynchronous notification of tcsh and csh that's also
   lacking in ksh.

Try putting "notify=" in your ~/.bashrc file.

Brian