Subject: bin/1454: ulimit builtin in /bin/sh broken & mkinit improvements
To: None <gnats-bugs@gnats.netbsd.org>
From: Mike Long <mike.long@analog.com>
List: netbsd-bugs
Date: 09/08/1995 00:21:02
>Number:         1454
>Category:       bin
>Synopsis:       ulimit builtin in /bin/sh broken & mkinit improvements
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Sep 11 23:35:05 1995
>Last-Modified:
>Originator:     I am Root--hear me roar
>Organization:
	Easily Distracted Anonym
>Release:        950907
>Environment:
System: NetBSD azathoth 1.0A NetBSD 1.0A (AZATHOTH) #4: Sun Sep 3 01:37:38 EDT 1995 root@azathoth:/usr/src/sys/arch/i386/compile/AZATHOTH i386

>Description:

The command 'sh -c "ulimit -a"' produces the following:

time(seconds)        unlimited
file(blocks)         unlimited
data(kbytes)         qd
stack(kbytes)        qd
coredump(blocks)     unlimited
memory(kbytes)       qd
locked memory(kbytes) qd
process(processes)   qd
nofiles(descriptors) qd

The problem is that the shell's internal doutput() routine does not
support %qd.  The patch for output.c below fixes this.

I noticed while testing my doutput() fix that 'make' relinked the
shell even when I didn't change the sources.  The reason is that
src/bin/sh/mkinit.c compiles the init.c that it creates, which is
unecessary (that's why we have make).  mkinit leaves init.c unaltered
if it doesn't change, but always touches init.o regardless.  As a
result, sh is relinked every time it is made.  I've included a patch
to fix this, too.

>How-To-Repeat:
	sh -c "ulimit -a"	# see bogus output
	cd /usr/src/bin/sh
	make clean
	make			# sh is compiled and linked
	make			# mkinit runs and sh is linked AGAIN?

>Fix:

*** /usr/src/bin/sh/output.c.orig       Fri May 12 06:47:25 1995
--- /usr/src/bin/sh/output.c    Thu Sep  7 23:20:37 1995
***************
*** 56,59 ****
--- 56,60 ----
   */
  
+ #include <sys/types.h>        /* quad_t */
  #include <sys/ioctl.h>
  
***************
*** 342,346 ****
   * - Formats supported: d, u, o, X, s, and c.
   * - The x format is also accepted but is treated like X.
!  * - The l modifier is accepted.
   * - The - and # flags are accepted; # only works with the o format.
   * - Width and precision may be specified with any format except c.
--- 343,347 ----
   * - Formats supported: d, u, o, X, s, and c.
   * - The x format is also accepted but is treated like X.
!  * - The l and q modifiers are accepted.
   * - The - and # flags are accepted; # only works with the o format.
   * - Width and precision may be specified with any format except c.
***************
*** 373,380 ****
        int prec;
        int islong;
        char *p;
        int sign;
!       long l;
!       unsigned long num;
        unsigned base;
        int len;
--- 374,382 ----
        int prec;
        int islong;
+       int isquad;
        char *p;
        int sign;
!       quad_t l;
!       u_quad_t num;
        unsigned base;
        int len;
***************
*** 392,395 ****
--- 394,398 ----
                prec = -1;
                islong = 0;
+               isquad = 0;
                for (;;) {
                        if (*f == '-')
***************
*** 424,430 ****
                        f++;
                }
                switch (*f) {
                case 'd':
!                       if (islong)
                                l = va_arg(ap, long);
                        else
--- 427,439 ----
                        f++;
                }
+               else if (*f == 'q') {
+                       isquad++;
+                       f++;
+               }
                switch (*f) {
                case 'd':
!                       if (isquad)
!                               l = va_arg(ap, quad_t);
!                       else if (islong)
                                l = va_arg(ap, long);
                        else
***************
*** 450,454 ****
  uns_number:     /* an unsigned number */
                        sign = 0;
!                       if (islong)
                                num = va_arg(ap, unsigned long);
                        else
--- 459,465 ----
  uns_number:     /* an unsigned number */
                        sign = 0;
!                       if (isquad)
!                               num = va_arg(ap, u_quad_t);
!                       else if (islong)
                                num = va_arg(ap, unsigned long);
                        else

*** /usr/src/bin/sh/mkinit.c.orig       Fri May 12 06:47:20 1995
--- /usr/src/bin/sh/mkinit.c    Thu Sep  7 00:38:13 1995
***************
*** 56,63 ****
   * improves the structure of the program since there is no need for
   * anyone outside of a module to know that that module performs special
!  * operations on particular events.  The command is executed iff init.c
!  * is actually changed.
   *
!  * Usage:  mkinit command sourcefile...
   */
  
--- 56,62 ----
   * improves the structure of the program since there is no need for
   * anyone outside of a module to know that that module performs special
!  * operations on particular events.
   *
!  * Usage:  mkinit sourcefile...
   */
  
***************
*** 80,84 ****
  #define OUTFILE "init.c"
  #define OUTTEMP "init.c.new"
- #define OUTOBJ "init.o"
  
  
--- 79,82 ----
***************
*** 165,169 ****
  void output __P((void));
  int file_changed __P((void));
- int touch __P((char *));
  void addstr __P((char *, struct text *));
  void addchar __P((int, struct text *));
--- 163,166 ----
***************
*** 183,191 ****
        char **ap;
  
-       if (argc < 2)
-               error("Usage:  mkinit command file...");
        header_files[0] = "\"shell.h\"";
        header_files[1] = "\"mystring.h\"";
!       for (ap = argv + 2 ; *ap ; ap++)
                readfile(*ap);
        output();
--- 180,186 ----
        char **ap;
  
        header_files[0] = "\"shell.h\"";
        header_files[1] = "\"mystring.h\"";
!       for (ap = argv + 1 ; *ap ; ap++)
                readfile(*ap);
        output();
***************
*** 196,207 ****
        } else {
                unlink(OUTTEMP);
-               if (touch(OUTOBJ))
-                       exit(0);                /* no compilation necessary */
        }
!       printf("%s\n", argv[1]);
!       execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
!       error("Can't exec shell");
! 
!       exit(1);
  }
  
--- 191,196 ----
        } else {
                unlink(OUTTEMP);
        }
!       exit(0);
  }
  
***************
*** 439,467 ****
        return 1;
  }
- 
- 
- /*
-  * Touch a file.  Returns 0 on failure, 1 on success.
-  */
- 
- int
- touch(file)
-       char *file;
- {
-       int fd;
-       char c;
- 
-       if ((fd = open(file, O_RDWR)) < 0)
-               return 0;
-       if (read(fd, &c, 1) != 1) {
-               close(fd);
-               return 0;
-       }
-       lseek(fd, (off_t)0, 0);
-       write(fd, &c, 1);
-       close(fd);
-       return 1;
- }
- 
  
  
--- 428,431 ----

*** /usr/src/bin/sh/Makefile.orig       Tue Jun 20 06:23:09 1995
--- /usr/src/bin/sh/Makefile    Sat Aug 19 00:29:36 1995
***************
*** 25,32 ****
  
  init.c: mkinit ${SRCS}
!       ./mkinit '${CC} -c ${CFLAGS} init.c' ${.ALLSRC:S/^mkinit$//}
  
  mkinit: ${.CURDIR}/mkinit.c
        ${CC} ${CFLAGS} ${.CURDIR}/mkinit.c -o $@
  
  nodes.c nodes.h: mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat
--- 25,33 ----
  
  init.c: mkinit ${SRCS}
!       ./mkinit ${.ALLSRC:S/^mkinit$//}
  
  mkinit: ${.CURDIR}/mkinit.c
        ${CC} ${CFLAGS} ${.CURDIR}/mkinit.c -o $@
+       rm -f init.c
  
  nodes.c nodes.h: mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat

>Audit-Trail:
>Unformatted: