From nobody@FreeBSD.org  Mon Oct  7 20:52:07 2002
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id D9E6937B406
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 Oct 2002 20:52:07 -0700 (PDT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 90B2843EA3
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 Oct 2002 20:52:07 -0700 (PDT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.6/8.12.6) with ESMTP id g983q77R050254
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 7 Oct 2002 20:52:07 -0700 (PDT)
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.6/8.12.6/Submit) id g983q7bl050253;
	Mon, 7 Oct 2002 20:52:07 -0700 (PDT)
Message-Id: <200210080352.g983q7bl050253@www.freebsd.org>
Date: Mon, 7 Oct 2002 20:52:07 -0700 (PDT)
From: Tim Kientzle <kientzle@acm.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: 'echo' is too big
X-Send-Pr-Version: www-1.0

>Number:         43810
>Category:       bin
>Synopsis:       'echo' is too big
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    njl
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 07 21:00:11 PDT 2002
>Closed-Date:    Sat Nov 23 16:09:25 PST 2002
>Last-Modified:  Sat Nov 23 16:09:25 PST 2002
>Originator:     Tim Kientzle
>Release:        FreeBSD-CURRENT
>Organization:
>Environment:
>Description:
Compiled, statically linked, and stripped, 'echo' is
over 40k!!  A few space-conscious edits reduce that
to just over 5k.

>How-To-Repeat:
ls -l /bin/echo
<gasp in amazement>


>Fix:
Following patch reduces 'echo' to just over 5k
with _no_lost_functionality_ (even that obscure \c
hack still works):

diff --context echo.c-original echo.c
*** echo.c-original     Mon Oct  7 20:44:50 2002
--- echo.c      Mon Oct  7 20:44:15 2002
***************
*** 45,52 ****
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.13 2002/06/30 05:13:53 obrien Exp 
$");
  
- #include <stdio.h>
- #include <stdlib.h>
  #include <string.h>
  
  /* ARGSUSED */
--- 45,50 ----
***************
*** 56,62 ****
        int nflag;      /* if not set, output a trailing newline. */
  
        /* This utility may NOT do getopt(3) option parsing. */
!       if (*++argv && !strcmp(*argv, "-n")) {
                ++argv;
                nflag = 1;
        }
--- 54,60 ----
        int nflag;      /* if not set, output a trailing newline. */
  
        /* This utility may NOT do getopt(3) option parsing. */
!       if (*++argv && argv[0][0]=='-' && argv[0][1]=='n') {
                ++argv;
                nflag = 1;
        }
***************
*** 64,69 ****
--- 62,69 ----
                nflag = 0;
  
        while (argv[0] != NULL) {
+               size_t len;
+               len = strlen(argv[0]);
  
                /*
                 * If the next argument is NULL then this is this
***************
*** 71,93 ****
                 * for a trailing \c.
                 */
                if (argv[1] == NULL) {
-                       size_t len;
- 
-                       len = strlen(argv[0]);
                        /* is there room for a '\c' and is there one? */
                        if (len >= 2 &&
                            argv[0][len - 2] == '\\' &&
                            argv[0][len - 1] == 'c') {
                                /* chop it and set the no-newline flag. */
-                               argv[0][len - 2] = '\0';
                                nflag = 1;
                        }
                }
!               (void)printf("%s", argv[0]);
                if (*++argv)
!                       putchar(' ');
        }
        if (!nflag)
!               putchar('\n');
        return 0;
  }
--- 71,90 ----
                 * for a trailing \c.
                 */
                if (argv[1] == NULL) {
                        /* is there room for a '\c' and is there one? */
                        if (len >= 2 &&
                            argv[0][len - 2] == '\\' &&
                            argv[0][len - 1] == 'c') {
                                /* chop it and set the no-newline flag. */
                                nflag = 1;
+                               len -= 2;
                        }
                }
!               (void)write(1,argv[0],len);
                if (*++argv)
!                       write(1," ",1);
        }
        if (!nflag)
!               write(1,"\n",1);
        return 0;
  }

>Release-Note:
>Audit-Trail:

From: Bruce Evans <bde@zeta.org.au>
To: Tim Kientzle <kientzle@acm.org>
Cc: freebsd-gnats-submit@FreeBSD.ORG
Subject: Re: bin/43810: 'echo' is too big
Date: Tue, 8 Oct 2002 18:04:44 +1000 (EST)

 On Mon, 7 Oct 2002, Tim Kientzle wrote:
 
 > >Description:
 > Compiled, statically linked, and stripped, 'echo' is
 > over 40k!!  A few space-conscious edits reduce that
 > to just over 5k.
 
 I don't approve of hacking on individual utilities to work around
 bloated libraries, but note that sync(1) is enormously bloated in
 -current and this can be "fixed" by writing it in assembler:
 
 %%%
 /* sync.S */
 
 #include <sys/syscall.h>
 
 	.globl	_start
 _start:
 	movl	$SYS_sync,%eax
 	int	$0x80
 	movl	$SYS_exit,%eax
 	int	$0x80
 %%%
 
 Note that this is fully bug for bug compatibile with sync.c: it has the
 same error checking (none).
 
 sync(1) has been bloated from about 6k (?) in RELENG_4 to 16K in -current.
 This compares unfavourably with the 14 bytes for the above version.  Fixing
 the main causes of sync's bloat in libc only reduced it to 3K (still 224
 times larger than the above).  Most of 13K library debloating for sync only
 helps for rare programs that don't use malloc() or sys_errlist[].  Even
 "main() {}" now uses malloc() because atexit() uses it unconditionally and
 crt1 uses atexit() unconditionally (to do nothing for "main() {}").  This
 is recent bloat.  sys_errlist[] is always used for stupider reasons
 (because syscalls reference errno, and sys_errlist[] in in the same
 file as errno).  This bloat came with elf.  errno is in crt0 for aout.
 
 Bruce
 

From: Giorgos Keramidas <keramida@freebsd.org>
To: Tim Kientzle <kientzle@acm.org>
Cc: bug-followup@freebsd.org
Subject: Re: bin/43810: 'echo' is too big
Date: Tue, 8 Oct 2002 12:47:51 +0300

 On 2002-10-07 20:52, Tim Kientzle <kientzle@acm.org> wrote:
 >
 > diff --context echo.c-original echo.c
 > *** echo.c-original     Mon Oct  7 20:44:50 2002
 > --- echo.c      Mon Oct  7 20:44:15 2002
 > ***************
 > *** 45,52 ****
 >   #include <sys/cdefs.h>
 >   __FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.13 2002/06/30 05:13:53 obrien Exp 
 > $");
 >   
 > - #include <stdio.h>
 > - #include <stdlib.h>
 >   #include <string.h>
 >   
 >   /* ARGSUSED */
 > --- 45,50 ----
 > ***************
 > *** 56,62 ****
 >         int nflag;      /* if not set, output a trailing newline. */
 >   
 >         /* This utility may NOT do getopt(3) option parsing. */
 > !       if (*++argv && !strcmp(*argv, "-n")) {
 >                 ++argv;
 >                 nflag = 1;
 >         }
 > --- 54,60 ----
 >         int nflag;      /* if not set, output a trailing newline. */
 >   
 >         /* This utility may NOT do getopt(3) option parsing. */
 > !       if (*++argv && argv[0][0]=='-' && argv[0][1]=='n') {
 >                 ++argv;
 >                 nflag = 1;
 >         }
 
 You're not checking for argv[0][2] == '\0'.  This will make strange
 command lines like work in unexpected ways.
 
 	$ echo -nocheck "foo"
 
 Giorgos.
State-Changed-From-To: open->closed 
State-Changed-By: njl 
State-Changed-When: Sat Nov 23 16:07:54 PST 2002 
State-Changed-Why:  
I committed a patch that removes the getopt and stdio dependencies.  This 
gets echo down to 12820 bytes.  The rest will have to wait on patches to 
atexit() that Tim has submitted. 


Responsible-Changed-From-To: freebsd-bugs->njl 
Responsible-Changed-By: njl 
Responsible-Changed-When: Sat Nov 23 16:07:54 PST 2002 
Responsible-Changed-Why:  
Assign myself to this since I'm working with Tim on size issues. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43810 
>Unformatted:
