]> git.saurik.com Git - apple/shell_cmds.git/commitdiff
shell_cmds-116.tar.gz mac-os-x-105 mac-os-x-1051 v116
authorApple <opensource@apple.com>
Mon, 17 Sep 2007 22:07:53 +0000 (22:07 +0000)
committerApple <opensource@apple.com>
Mon, 17 Sep 2007 22:07:53 +0000 (22:07 +0000)
142 files changed:
Makefile
Makefile.postamble
Manpages/alloc.1 [deleted file]
Manpages/bindkey.1 [deleted file]
Manpages/break.1 [deleted file]
Manpages/breaksw.1 [deleted file]
Manpages/builtin.1
Manpages/builtins.1 [deleted file]
Manpages/case.1 [deleted file]
Manpages/chdir.1 [deleted file]
Manpages/complete.1 [deleted file]
Manpages/continue.1 [deleted file]
Manpages/default.1 [deleted file]
Manpages/dirs.1 [deleted file]
Manpages/do.1 [deleted file]
Manpages/done.1 [deleted file]
Manpages/echotc.1 [deleted file]
Manpages/elif.1 [deleted file]
Manpages/else.1 [deleted file]
Manpages/end.1 [deleted file]
Manpages/endif.1 [deleted file]
Manpages/endsw.1 [deleted file]
Manpages/esac.1 [deleted file]
Manpages/eval.1 [deleted file]
Manpages/exec.1 [deleted file]
Manpages/exit.1 [deleted file]
Manpages/export.1 [deleted file]
Manpages/fi.1 [deleted file]
Manpages/filetest.1 [deleted file]
Manpages/foreach.1 [deleted file]
Manpages/glob.1 [deleted file]
Manpages/goto.1 [deleted file]
Manpages/hashstat.1 [deleted file]
Manpages/history.1 [deleted file]
Manpages/hup.1 [deleted file]
Manpages/if.1 [deleted file]
Manpages/jobid.1 [deleted file]
Manpages/limit.1 [deleted file]
Manpages/log.1 [deleted file]
Manpages/logout.1 [deleted file]
Manpages/ls-F.1 [deleted file]
Manpages/notify.1 [deleted file]
Manpages/onintr.1 [deleted file]
Manpages/popd.1 [deleted file]
Manpages/pushd.1 [deleted file]
Manpages/readonly.1 [deleted file]
Manpages/rehash.1 [deleted file]
Manpages/repeat.1 [deleted file]
Manpages/sched.1 [deleted file]
Manpages/set.1 [deleted file]
Manpages/setenv.1 [deleted file]
Manpages/settc.1 [deleted file]
Manpages/setty.1 [deleted file]
Manpages/setvar.1 [deleted file]
Manpages/shift.1 [deleted file]
Manpages/source.1 [deleted file]
Manpages/stop.1 [deleted file]
Manpages/suspend.1 [deleted file]
Manpages/switch.1 [deleted file]
Manpages/telltc.1 [deleted file]
Manpages/then.1 [deleted file]
Manpages/trap.1 [deleted file]
Manpages/uncomplete.1 [deleted file]
Manpages/unhash.1 [deleted file]
Manpages/unlimit.1 [deleted file]
Manpages/unset.1 [deleted file]
Manpages/unsetenv.1 [deleted file]
Manpages/until.1 [deleted file]
Manpages/where.1 [deleted file]
Manpages/while.1 [deleted file]
alias/Makefile.postamble
alias/generic.sh
date/Makefile
date/date.1
date/date.c
date/extern.h
date/netdate.c
date/vary.c [new file with mode: 0644]
date/vary.h [new file with mode: 0644]
echo/Makefile
echo/echo.1
echo/echo.c
expr/expr.c
find/Makefile
find/extern.h
find/find.1
find/find.c
find/find.h
find/function.c
find/getdate.y [new file with mode: 0644]
find/ls.c
find/main.c
find/misc.c
find/operator.c
find/option.c
find/y.tab.c [deleted file]
id/Makefile
id/groups.1
id/id.1
id/id.c
id/whoami.1
killall/Makefile
killall/killall.1
killall/killall.c
locate/locate/updatedb.sh
nohup/nohup.c
printf/printf.1
pwd/Makefile
pwd/pwd.1
pwd/pwd.c
renice/renice.8
script/Makefile
script/script.1
script/script.c
su/su.1
su/su.c
test/test.1
test/test.c
uname/uname.1
uname/uname.c
users/users.1
users/users.c
w/Makefile
w/extern.h
w/fmt.c
w/pr_time.c
w/proc_compare.c
w/uptime.1
w/w.1
w/w.c
which/Makefile
which/Makefile.preamble
which/which.1
which/which.c [new file with mode: 0644]
which/which.csh [deleted file]
who/who.1
who/who.c
xargs/Makefile
xargs/pathnames.h
xargs/strnsubst.c
xargs/xargs.1
xargs/xargs.c

index e9fc42f53bbb3a8f8e58593ad4e28687becec957..936206befb50bda92da2eb2ef70e5988ceeefec9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@ TOOLS = alias apply basename chroot date dirname echo env expr false\
         nice nohup printenv printf pwd renice script shlock sleep su\
         tee test time true uname users w whereis which who xargs yes
 
-OTHERSRCS = PROJECT Makefile.preamble Makefile Makefile.postamble Manpages/*.1
+OTHERSRCS = PROJECT Makefile.preamble Makefile Makefile.postamble Manpages/builtin.1
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
@@ -29,7 +29,7 @@ DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
 
-NEXTSTEP_PB_CFLAGS = -Wall 
+NEXTSTEP_PB_CFLAGS = -Wall -mdynamic-no-pic
 
 
 NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(NAME)/Build
index f2fd4e959d647d4f3654cb860822519e58795478..b60b7ed4e8ae720e7a69894d87e13a13f49773d2 100644 (file)
@@ -1,4 +1,94 @@
 include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
 
+BUILTIN_LINKS = alias.1 \
+       alloc.1 \
+       bg.1 \
+       bind.1 \
+       bindkey.1 \
+       break.1 \
+       breaksw.1 \
+       builtins.1 \
+       case.1 \
+       cd.1 \
+       chdir.1 \
+       command.1 \
+       complete.1 \
+       continue.1 \
+       default.1 \
+       dirs.1 \
+       do.1 \
+       done.1 \
+       echotc.1 \
+       elif.1 \
+       else.1 \
+       end.1 \
+       endif.1 \
+       endsw.1 \
+       esac.1 \
+       eval.1 \
+       exec.1 \
+       exit.1 \
+       export.1 \
+       fc.1 \
+       fg.1 \
+       fi.1 \
+       filetest.1 \
+       for.1 \
+       foreach.1 \
+       getopts.1 \
+       glob.1 \
+       goto.1 \
+       hash.1 \
+       hashstat.1 \
+       history.1 \
+       hup.1 \
+       if.1 \
+       jobid.1 \
+       jobs.1 \
+       limit.1 \
+       log.1 \
+       logout.1 \
+       ls-F.1 \
+       notify.1 \
+       onintr.1 \
+       popd.1 \
+       pushd.1 \
+       read.1 \
+       readonly.1 \
+       rehash.1 \
+       repeat.1 \
+       return.1 \
+       sched.1 \
+       set.1 \
+       setenv.1 \
+       settc.1 \
+       setty.1 \
+       setvar.1 \
+       shift.1 \
+       source.1 \
+       stop.1 \
+       suspend.1 \
+       switch.1 \
+       telltc.1 \
+       then.1 \
+       times.1 \
+       trap.1 \
+       type.1 \
+       ulimit.1 \
+       umask.1 \
+       unalias.1 \
+       uncomplete.1 \
+       unhash.1 \
+       unlimit.1 \
+       unset.1 \
+       unsetenv.1 \
+       until.1 \
+       wait.1 \
+       where.1 \
+       while.1
+
 after_install::
-       $(INSTALL_FILE) $(SRCROOT)/Manpages/*.1 $(DSTROOT)/usr/share/man/man1
+       @echo Installing manpage links...
+       @for manpage in $(BUILTIN_LINKS); do \
+               $(LN) -f $(DSTROOT)/usr/share/man/man1/builtin.1 $(DSTROOT)/usr/share/man/man1/$${manpage}; \
+       done
diff --git a/Manpages/alloc.1 b/Manpages/alloc.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/bindkey.1 b/Manpages/bindkey.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/break.1 b/Manpages/break.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/breaksw.1 b/Manpages/breaksw.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
index bc53b39cea255116bae161816108f46c5dbaf905..f452c910457d4de3590922ffc511d41f4d4f6d37 100644 (file)
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"    $FreeBSD: src/share/man/man1/builtin.1,v 1.20 2002/07/23 14:38:07 tjr Exp $
+.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man1/builtin.1,v 1.25 2005/09/09 17:02:08 garys Exp $
 .\"
-.Dd September 1, 1999
+.Dd February 23, 2005
 .Dt BUILTIN 1
 .Os
 .Sh NAME
 .Nm builtin ,
+.Nm \&! ,
+.Nm \&% ,
+.Nm \&. ,
+.Nm \&: ,
+.Nm \&@ ,
+.Nm \&{ ,
+.Nm \&} ,
 .Nm alias ,
 .Nm alloc ,
 .Nm bg ,
@@ -80,6 +87,7 @@
 .Nm jobs ,
 .Nm kill ,
 .Nm limit ,
+.Nm local ,
 .Nm log ,
 .Nm login ,
 .Nm logout ,
 .Nm readonly ,
 .Nm rehash ,
 .Nm repeat ,
+.Nm return ,
 .Nm sched ,
 .Nm set ,
 .Nm setenv ,
 .Nm test ,
 .Nm then ,
 .Nm time ,
+.Nm times ,
 .Nm trap ,
 .Nm true ,
 .Nm type ,
 .Nm where ,
 .Nm which ,
 .Nm while
-.Nd shell builtin commands
+.Nd shell built-in commands
 .Sh SYNOPSIS
 .Nm
 .Op Fl options
@@ -147,11 +157,12 @@ of the specified command matches the name of a builtin command.
 Thus, while specifying
 .Dq Ic echo
 causes a builtin command to be executed under shells that support the
-builtin echo command,
+.Nm echo
+builtin command,
 specifying
-.Dq Pa /bin/echo
+.Dq Ic /bin/echo
 or
-.Dq Pa ./echo
+.Dq Ic ./echo
 does not.
 .Pp
 While some builtin commands may exist in more than one shell, their
@@ -164,26 +175,48 @@ Only builtin commands for the
 and
 .Xr sh 1
 shells are listed here.
-Consult the appropriate manual page for
-details on the operation of any given builtin command under those shells.
-Users of other shells will need to consult the documentation supplied
-with the other shells.
+Consult a shell's manual page for
+details on the operation its builtin commands.
+Beware that the
+.Xr sh 1
+manual page, at least, calls some of these commands
+.Dq built-in commands
+and some of them
+.Dq reserved words .
+Users of other shells may need to consult an
+.Xr info 1
+page or other sources of documentation.
+.Pp
+Commands marked
+.Dq Li No**
+under
+.Em External
+do exist externally,
+but are implemented as scripts using a builtin command of the same name.
 .Bl -column ".Ic uncomplete" ".Em External" ".Xr csh 1" ".Xr sh 1" -offset indent
 .It Xo
 .Em "Command   External" Ta Xr csh 1 Ta Xr sh 1
 .Xc
-.It Ic alias Ta Yes Ta Yes Ta Yes
+.It Ic ! Ta \&No Ta \&No Ta \&Yes
+.It Ic % Ta \&No Ta Yes Ta \&No
+.It Ic . Ta \&No Ta \&No Ta Yes
+.It Ic : Ta \&No Ta Yes Ta Yes
+.It Ic @ Ta \&No Ta Yes Ta Yes
+.It Ic { Ta \&No Ta \&No Ta \&Yes
+.It Ic } Ta \&No Ta \&No Ta \&Yes
+.It Ic alias Ta \&No** Ta Yes Ta Yes
 .It Ic alloc Ta \&No Ta Yes Ta \&No
-.It Ic bg Ta Yes Ta Yes Ta Yes
+.It Ic bg Ta No** Ta Yes Ta Yes
 .It Ic bind Ta \&No Ta \&No Ta Yes
 .It Ic bindkey Ta \&No Ta Yes Ta \&No
 .It Ic break Ta \&No Ta Yes Ta \&Yes
 .It Ic breaksw Ta \&No Ta Yes Ta \&No
+.It Ic builtin Ta \&No Ta \&No Ta Yes
 .It Ic builtins Ta \&No Ta Yes Ta \&No
 .It Ic case Ta \&No Ta Yes Ta Yes
-.It Ic cd Ta Yes Ta Yes Ta Yes
-.It Ic chdir Ta \&No Ta Yes Ta \&No
-.It Ic command Ta Yes Ta \&No Ta Yes
+.It Ic cd Ta \&No** Ta Yes Ta Yes
+.It Ic chdir Ta \&No Ta Yes Ta \&Yes
+.It Ic command Ta \&No** Ta \&No Ta Yes
 .It Ic complete Ta \&No Ta Yes Ta \&No
 .It Ic continue Ta \&No Ta Yes Ta \&Yes
 .It Ic default Ta \&No Ta Yes Ta \&No
@@ -203,13 +236,13 @@ with the other shells.
 .It Ic exit Ta \&No Ta Yes Ta Yes
 .It Ic export Ta \&No Ta \&No Ta Yes
 .It Ic false Ta Yes Ta \&No Ta Yes
-.It Ic fc Ta Yes Ta \&No Ta Yes
-.It Ic fg Ta Yes Ta Yes Ta Yes
+.It Ic fc Ta \&No** Ta \&No Ta Yes
+.It Ic fg Ta \&No** Ta Yes Ta Yes
 .It Ic filetest Ta \&No Ta Yes Ta \&No
 .It Ic fi Ta \&No Ta \&No Ta Yes
 .It Ic for Ta \&No Ta \&No Ta Yes
 .It Ic foreach Ta \&No Ta Yes Ta \&No
-.It Ic getopts Ta Yes Ta \&No Ta Yes
+.It Ic getopts Ta \&No** Ta \&No Ta Yes
 .It Ic glob Ta \&No Ta Yes Ta \&No
 .It Ic goto Ta \&No Ta Yes Ta \&No
 .It Ic hash Ta \&No Ta \&No Ta Yes
@@ -218,9 +251,10 @@ with the other shells.
 .It Ic hup Ta \&No Ta Yes Ta \&No
 .It Ic if Ta \&No Ta Yes Ta \&Yes
 .It Ic jobid Ta \&No Ta \&No Ta Yes
-.It Ic jobs Ta Yes Ta Yes Ta Yes
+.It Ic jobs Ta \&No** Ta Yes Ta Yes
 .It Ic kill Ta Yes Ta Yes Ta \&No
 .It Ic limit Ta \&No Ta Yes Ta \&No
+.It Ic local Ta \&No Ta \&No Ta Yes
 .It Ic log Ta \&No Ta Yes Ta \&No
 .It Ic login Ta Yes Ta Yes Ta \&No
 .It Ic logout Ta \&No Ta Yes Ta \&No
@@ -233,10 +267,11 @@ with the other shells.
 .It Ic printenv Ta Yes Ta Yes Ta \&No
 .It Ic pushd Ta \&No Ta Yes Ta \&No
 .It Ic pwd Ta Yes Ta \&No Ta Yes
-.It Ic read Ta Yes Ta \&No Ta Yes
+.It Ic read Ta \&No** Ta \&No Ta Yes
 .It Ic readonly Ta \&No Ta \&No Ta Yes
 .It Ic rehash Ta \&No Ta Yes Ta \&No
 .It Ic repeat Ta \&No Ta Yes Ta \&No
+.It Ic return Ta \&No Ta \&No Ta Yes
 .It Ic sched Ta \&No Ta Yes Ta \&No
 .It Ic set Ta \&No Ta Yes Ta \&Yes
 .It Ic setenv Ta \&No Ta Yes Ta \&No
@@ -252,19 +287,20 @@ with the other shells.
 .It Ic test Ta Yes Ta \&No Ta Yes
 .It Ic then Ta \&No Ta \&No Ta Yes
 .It Ic time Ta Yes Ta Yes Ta \&No
+.It Ic times Ta \&No Ta \&No Ta Yes
 .It Ic trap Ta \&No Ta \&No Ta Yes
 .It Ic true Ta Yes Ta \&No Ta Yes
 .It Ic type Ta \&No Ta \&No Ta Yes
 .It Ic ulimit Ta \&No Ta \&No Ta Yes
-.It Ic umask Ta Yes Ta Yes Ta Yes
-.It Ic unalias Ta Yes Ta Yes Ta Yes
+.It Ic umask Ta \&No** Ta Yes Ta Yes
+.It Ic unalias Ta \&No** Ta Yes Ta Yes
 .It Ic uncomplete Ta \&No Ta Yes Ta \&No
 .It Ic unhash Ta \&No Ta Yes Ta \&No
 .It Ic unlimit Ta \&No Ta Yes Ta \&No
 .It Ic unset Ta \&No Ta Yes Ta Yes
 .It Ic unsetenv Ta \&No Ta Yes Ta \&No
 .It Ic until Ta \&No Ta \&No Ta Yes
-.It Ic wait Ta Yes Ta Yes Ta Yes
+.It Ic wait Ta \&No** Ta Yes Ta Yes
 .It Ic where Ta \&No Ta Yes Ta \&No
 .It Ic which Ta Yes Ta Yes Ta \&No
 .It Ic while Ta \&No Ta Yes Ta \&Yes
@@ -273,6 +309,7 @@ with the other shells.
 .Xr csh 1 ,
 .Xr echo 1 ,
 .Xr false 1 ,
+.Xr info 1 ,
 .Xr kill 1 ,
 .Xr login 1 ,
 .Xr nice 1 ,
diff --git a/Manpages/builtins.1 b/Manpages/builtins.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/case.1 b/Manpages/case.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/chdir.1 b/Manpages/chdir.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/complete.1 b/Manpages/complete.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/continue.1 b/Manpages/continue.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/default.1 b/Manpages/default.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/dirs.1 b/Manpages/dirs.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/do.1 b/Manpages/do.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/done.1 b/Manpages/done.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/echotc.1 b/Manpages/echotc.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/elif.1 b/Manpages/elif.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/else.1 b/Manpages/else.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/end.1 b/Manpages/end.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/endif.1 b/Manpages/endif.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/endsw.1 b/Manpages/endsw.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/esac.1 b/Manpages/esac.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/eval.1 b/Manpages/eval.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/exec.1 b/Manpages/exec.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/exit.1 b/Manpages/exit.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/export.1 b/Manpages/export.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/fi.1 b/Manpages/fi.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/filetest.1 b/Manpages/filetest.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/foreach.1 b/Manpages/foreach.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/glob.1 b/Manpages/glob.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/goto.1 b/Manpages/goto.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/hashstat.1 b/Manpages/hashstat.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/history.1 b/Manpages/history.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/hup.1 b/Manpages/hup.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/if.1 b/Manpages/if.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/jobid.1 b/Manpages/jobid.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/limit.1 b/Manpages/limit.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/log.1 b/Manpages/log.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/logout.1 b/Manpages/logout.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/ls-F.1 b/Manpages/ls-F.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/notify.1 b/Manpages/notify.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/onintr.1 b/Manpages/onintr.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/popd.1 b/Manpages/popd.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/pushd.1 b/Manpages/pushd.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/readonly.1 b/Manpages/readonly.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/rehash.1 b/Manpages/rehash.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/repeat.1 b/Manpages/repeat.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/sched.1 b/Manpages/sched.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/set.1 b/Manpages/set.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/setenv.1 b/Manpages/setenv.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/settc.1 b/Manpages/settc.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/setty.1 b/Manpages/setty.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/setvar.1 b/Manpages/setvar.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/shift.1 b/Manpages/shift.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/source.1 b/Manpages/source.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/stop.1 b/Manpages/stop.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/suspend.1 b/Manpages/suspend.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/switch.1 b/Manpages/switch.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/telltc.1 b/Manpages/telltc.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/then.1 b/Manpages/then.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/trap.1 b/Manpages/trap.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/uncomplete.1 b/Manpages/uncomplete.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/unhash.1 b/Manpages/unhash.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/unlimit.1 b/Manpages/unlimit.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/unset.1 b/Manpages/unset.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/unsetenv.1 b/Manpages/unsetenv.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/until.1 b/Manpages/until.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/where.1 b/Manpages/where.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
diff --git a/Manpages/while.1 b/Manpages/while.1
deleted file mode 100644 (file)
index 5a811f4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/builtin.1
index 25b1a3a3b3dedcfaf5d20f8dee43f56bfa974acd..0e72ad28838960ec5e7dd0644393d1f0eccaedb5 100644 (file)
@@ -2,7 +2,7 @@ include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
 
 after_install::
        mkdir -p "$(DSTROOT)$(INSTALLDIR)"
-       install -c -m 555 ./generic.sh $(DSTROOT)$(INSTALLDIR)/alias
+       $(INSTALL_PROGRAM) generic.sh $(DSTROOT)$(INSTALLDIR)/alias
 
        $(LINKPRODUCT) $(DSTROOT)$(INSTALLDIR)/bg
        $(LINKPRODUCT) $(DSTROOT)$(INSTALLDIR)/cd
index ebc2b8550fbf02e9f1a9b19496780c511a704018..b47956d099863dcb53f102ef425ae43e17f177d7 100644 (file)
@@ -1,4 +1,4 @@
 #!/bin/sh
-# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.1 2002/07/16 22:16:03 wollman Exp $
+# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
 # This file is in the public domain.
-${0##*/} ${1+"$@"}
+builtin ${0##*/} ${1+"$@"}
index a7632ac5859de67457151f7c205913bb97c7566f..5fb3ba6838f7f6d657ed3717300d00ed99b1810b 100644 (file)
@@ -12,12 +12,13 @@ NAME = date
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Tool
 
-HFILES = extern.h
+HFILES = extern.h vary.h
 
-CFILES = date.c netdate.c
+CFILES = date.c netdate.c vary.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble date.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index e5962fe4e83f2e1ff702136477c86168a4d74920..e176c35a478d899c7f208be7c1cb7093b7817194 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $NetBSD: date.1,v 1.22 1998/06/08 09:07:13 lukem Exp $
-.\"
+.\"-
 .\" Copyright (c) 1980, 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
@@ -35,8 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)date.1     8.3 (Berkeley) 4/28/95
+.\" $FreeBSD: src/bin/date/date.1,v 1.72 2005/02/13 22:25:09 ru Exp $
 .\"
-.Dd September 22, 2004
+.Dd August 16, 2007
 .Dt DATE 1
 .Os
 .Sh NAME
 .Nd display or set date and time
 .Sh SYNOPSIS
 .Nm
-.Op Fl nu
+.Op Fl ju
 .Op Fl r Ar seconds
-.Op Cm + Ns Ar format
+.Oo
+.Fl v
+.Sm off
+.Op Cm + | -
+.Ar val Op Ar ymwdHMS
+.Sm on
+.Oc
+.Ar ...
+.Op Cm + Ns Ar output_fmt
+.Nm
+.Op Fl jnu
+.Sm off
+.Op Oo Oo Ar mm Oc Ar dd Oc Ar HH
+.Ar MM Oo Oo Ar cc Oc Ar yy Oc Op Ar .ss
+.Sm on
+.Nm
+.Op Fl jnu
+.Fl f Ar input_fmt new_date
+.Op Cm + Ns Ar output_fmt
 .Nm
-.Op Fl u
-.Ar mmddhhmm[[cc]yy]
+.Op Fl d Ar dst
+.Op Fl t Ar minutes_west
 .Sh DESCRIPTION
+When invoked without arguments, the
 .Nm
-displays the current date and time when invoked without arguments.
-Providing arguments will format the date and time in a user-defined
-way or set the date.  Only the superuser may set the date.
+utility displays the current date and time.
+Otherwise, depending on the options specified,
+.Nm
+will set the date and time or print it in a user-defined way.
+.Pp
+The
+.Nm
+utility displays the date and time read from the kernel clock.
+When used to set the date and time,
+both the kernel clock and the hardware clock are updated.
+.Pp
+Only the superuser may set the date,
+and if the system securelevel (see
+.Xr securelevel 8 )
+is greater than 1,
+the time may not be changed by more than 1 second.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
+.It Fl d Ar dst
+Set the kernel's value for daylight saving time.
+If
+.Ar dst
+is non-zero, future calls
+to
+.Xr gettimeofday 2
+will return a non-zero for
+.Fa tz_dsttime .
+.It Fl f
+Use
+.Ar input_fmt
+as the format string to parse the
+.Ar new_date
+provided rather than using the default
+.Sm off
+.Oo Oo Oo 
+.Ar mm Oc
+.Ar dd Oc
+.Ar HH Oc
+.Ar MM 
+.Oo Oo
+.Ar cc Oc
+.Ar yy Oc Oo 
+.Ar .ss Oc 
+.Sm on
+format.
+Parsing is done using
+.Xr strptime 3 .
+.It Fl j
+Do not try to set the date.
+This allows you to use the
+.Fl f
+flag in addition to the
+.Cm +
+option to convert one date format to another.
 .It Fl n
-The utility
+By default, if the
 .Xr timed 8
-is used to synchronize the clocks on groups of machines.
-By default, if
-timed
-is running,
+daemon is running,
 .Nm
-will set the time on all of the machines in the local group.
+sets the time on all of the machines in the local group.
 The
 .Fl n
-option stops
-.Nm
-from setting the time for other than the current machine.
-.It Fl r
-Print out the date and time that is
+option suppresses this behavior and causes the time to be set only on the
+current machine.
+.It Fl r Ar seconds
+Print the date and time represented by
+.Ar seconds ,
+where
 .Ar seconds
-from the Epoch.
+is the number of seconds since the Epoch
+(00:00:00 UTC, January 1, 1970;
+see
+.Xr time 3 ) ,
+and can be specified in decimal, octal, or hex.
+.It Fl t Ar minutes_west
+Set the system's value for minutes west of
+.Tn GMT .
+.Ar minutes_west
+specifies the number of minutes returned in
+.Fa tz_minuteswest
+by future calls to
+.Xr gettimeofday 2 .
 .It Fl u
 Display or set the date in
 .Tn UTC
-(universal) time.
+(Coordinated Universal) time.
+.It Fl v
+Adjust (i.e., take the current date and display the result of the
+adjustment; not actually set the date) the second, minute, hour, month
+day, week day, month or year according to
+.Ar val .
+If
+.Ar val
+is preceded with a plus or minus sign,
+the date is adjusted forwards or backwards according to the remaining string,
+otherwise the relevant part of the date is set.
+The date can be adjusted as many times as required using these flags.
+Flags are processed in the order given.
+.Pp
+When setting values
+(rather than adjusting them),
+seconds are in the range 0-59, minutes are in the range 0-59, hours are
+in the range 0-23, month days are in the range 1-31, week days are in the
+range 0-6 (Sun-Sat),
+months are in the range 1-12 (Jan-Dec)
+and years are in the range 80-38 or 1980-2038.
+.Pp
+If
+.Ar val
+is numeric, one of either
+.Ar y ,
+.Ar m ,
+.Ar w ,
+.Ar d ,
+.Ar H ,
+.Ar M
+or
+.Ar S
+must be used to specify which part of the date is to be adjusted.
+.Pp
+The week day or month may be specified using a name rather than a
+number.
+If a name is used with the plus
+(or minus)
+sign, the date will be put forwards
+(or backwards)
+to the next
+(previous)
+date that matches the given week day or month.
+This will not adjust the date,
+if the given week day or month is the same as the current one.
+.Pp
+When a date is adjusted to a specific value or in units greater than hours,
+daylight savings time considerations are ignored.
+Adjustments in units of hours or less honor daylight saving time.
+So, assuming the current date is March 26, 0:30 and that the DST adjustment
+means that the clock goes forward at 01:00 to 02:00, using
+.Fl v No +1H
+will adjust the date to March 26, 2:30.
+Likewise, if the date is October 29, 0:30 and the DST adjustment means that
+the clock goes back at 02:00 to 01:00, using
+.Fl v No +3H
+will be necessary to reach October 29, 2:30.
+.Pp
+When the date is adjusted to a specific value that does not actually exist
+(for example March 26, 1:30 BST 2000 in the Europe/London timezone),
+the date will be silently adjusted forwards in units of one hour until it
+reaches a valid time.
+When the date is adjusted to a specific value that occurs twice
+(for example October 29, 1:30 2000),
+the resulting timezone will be set so that the date matches the earlier of
+the two times.
+.Pp
+Adjusting the date by months is inherently ambiguous because
+a month is a unit of variable length depending on the current date.
+This kind of date adjustment is applied in the most intuitive way.
+First of all,
+.Nm
+tries to preserve the day of the month.
+If it is impossible because the target month is shorter than the present one,
+the last day of the target month will be the result.
+For example, using
+.Fl v No +1m
+on May 31 will adjust the date to June 30, while using the same option
+on January 30 will result in the date adjusted to the last day of February.
+This approach is also believed to make the most sense for shell scripting.
+Nevertheless, be aware that going forth and back by the same number of
+months may take you to a different date.
+.Pp
+Refer to the examples below for further details.
 .El
 .Pp
-An operand with a leading plus (``+'') sign signals a user-defined format
-string which specifies the format in which to display the date and time.
-The format string may contain any of the conversion specifications described
-in the 
+An operand with a leading plus
+.Pq Sq +
+sign signals a user-defined format string
+which specifies the format in which to display the date and time.
+The format string may contain any of the conversion specifications
+described in the
 .Xr strftime 3
 manual page, as well as any arbitrary text.
-A <newline> character is always output after the characters specified by
+A newline
+.Pq Ql \en
+character is always output after the characters specified by
 the format string.
-The format string for the default display is:
-.Bd -literal -offset indent
-``%a %b %e %H:%M:%S %Z %Y''.
-.Ed
+The format string for the default display is
+.Dq +%+ .
 .Pp
 If an operand does not have a leading plus sign, it is interpreted as
 a value for setting the system's notion of the current date and time.
@@ -101,90 +261,136 @@ The canonical representation for setting the date and time is:
 .Pp
 .Bl -tag -width Ds -compact -offset indent
 .It Ar cc
-The first two digits of the year (the century).
+Century
+(either 19 or 20)
+prepended to the abbreviated year.
 .It Ar yy
-The second two digits of the year.  If
-.Dq yy
-is specified, but
-.Dq cc
-is not, a value for
-.Dq yy
-between 69 and 99 results in a
-.Dq cc
-value of 19.  Otherwise, a
-.Dq cc
-value of 20 is used.
+Year in abbreviated form
+(e.g., 89 for 1989, 06 for 2006).
 .It Ar mm
-The month of the year, from 1 to 12.
+Numeric month, a number from 1 to 12.
 .It Ar dd
-The day of the month, from 1 to 31.
-.It Ar hh
-The hour of the day, from 0 to 23.
-.It Ar mm
-The minute of the hour, from 0 to 59.
+Day, a number from 1 to 31.
+.It Ar HH
+Hour, a number from 0 to 23.
+.It Ar MM
+Minutes, a number from 0 to 59.
 .It Ar ss
-The second of the minute, from 0 to 61.
+Seconds, a number from 0 to 61
+(59 plus a maximum of two leap seconds).
 .El
 .Pp
 Everything but the minutes is optional.
 .Pp
-Time changes for Daylight Saving and Standard time and leap seconds
-and years are handled automatically.
-.Sh ENVIRONMENT VARIABLES
+Time changes for Daylight Saving Time, standard time, leap seconds,
+and leap years are handled automatically.
+.Sh ENVIRONMENT
 The following environment variables affect the execution of
-.Nm
-:
-.Bl -tag -width TZ
+.Nm :
+.Bl -tag -width Ds
 .It Ev TZ
 The timezone to use when displaying dates.
+The normal format is a pathname relative to
+.Pa /usr/share/zoneinfo .
+For example, the command
+.Dq TZ=America/Los_Angeles date
+displays the current time in California.
 See
 .Xr environ 7
 for more information.
 .El
 .Sh FILES
 .Bl -tag -width /var/log/messages -compact
-.It Pa /var/log/wtmp
-A record of date resets and time changes.
 .It Pa /var/log/messages
-A record of the user setting the time.
+record of the user setting the time
 .El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success, 1 if unable to set the date, and 2
+if able to set the local date, but unable to set it globally.
 .Sh EXAMPLES
 The command:
-.Bd -literal -offset indent
-date "+DATE: %m/%d/%y%nTIME: %H:%M:%S"
-.Ed
+.Pp
+.Dl "date ""+DATE: %Y-%m-%d%nTIME: %H:%M:%S"""
 .Pp
 will display:
 .Bd -literal -offset indent
-DATE: 11/21/87
+DATE: 1987-11-21
 TIME: 13:36:16
 .Ed
 .Pp
+In the Europe/London timezone, the command:
+.Pp
+.Dl "date -v1m -v+1y"
+.Pp
+will display:
+.Pp
+.Dl "Sun Jan  4 04:15:24 GMT 1998"
+.Pp
+where it is currently
+.Li "Mon Aug  4 04:15:24 BST 1997" .
+.Pp
+The command:
+.Pp
+.Dl "date -v1d -v3m -v0y -v-1d"
+.Pp
+will display the last day of February in the year 2000:
+.Pp
+.Dl "Tue Feb 29 03:18:00 GMT 2000"
+.Pp
+So will do the command:
+.Pp
+.Dl "date -v30d -v3m -v0y -v-1m"
+.Pp
+because there is no such date as the 30th of February.
+.Pp
 The command:
-.Bd -literal -offset indent
-date 061316271985
-.Ed
+.Pp
+.Dl "date -v1d -v+1m -v-1d -v-fri"
+.Pp
+will display the last Friday of the month:
+.Pp
+.Dl "Fri Aug 29 04:31:11 BST 1997"
+.Pp
+where it is currently
+.Li "Mon Aug  4 04:31:11 BST 1997" .
+.Pp
+The command:
+.Pp
+.Dl "date 0613162785"
 .Pp
 sets the date to
 .Dq Li "June 13, 1985, 4:27 PM" .
 .Pp
+.Dl "date ""+%Y%m%d%H%M.%S"""
+.Pp
+may be used on one machine to print out the date
+suitable for setting on another.
+.Qq ( Li "+%m%d%H%M%Y.%S"
+for use on
+.Tn Linux . )
+.Pp
 The command:
-.Bd -literal -offset indent
-date 1432
-.Ed
+.Pp
+.Dl "date 1432"
 .Pp
 sets the time to
 .Li "2:32 PM" ,
 without modifying the date.
-.Sh DIAGNOSTICS
-The following exit values are returned:
- 0    The date was written successfully (either locally or globally)
- >0   An error occurred.
 .Pp
+Finally the command:
+.Pp
+.Dl "date -j -f ""%a %b %d %T %Z %Y"" ""`date`"" ""+%s"""
+.Pp
+can be used to parse the output from
+.Nm
+and express it in Epoch time.
+.Sh DIAGNOSTICS
 Occasionally, when
 .Xr timed 8
-synchronizes the time on many hosts, the setting of a new time value
-may require more than a few seconds.
+synchronizes the time on many hosts, the setting of a new time value may
+require more than a few seconds.
 On these occasions,
 .Nm
 prints:
@@ -194,26 +400,33 @@ The message
 occurs when the communication
 between
 .Nm
-and timed fails.
+and
+.Xr timed 8
+fails.
 .Sh LEGACY SYNOPSIS
-.Nm
-.Op Fl nu
-.Op Fl r Ar seconds
-.Op Cm + Ns Ar format
+As above, except for the second line, which is:
 .Pp
-.Nm "    "
-.Ar [[[[[cc]yy]mm]dd]hh]mm[\&.ss]
+.Nm
+.Op Fl jnu
+.Sm off
+.Op Oo Oo Oo Oo Ar cc Oc Ar yy Oc Ar mm Oc Ar dd Oc Ar HH
+.Ar MM Op Ar .ss
+.Sm on
 .Sh LEGACY DIAGNOSTICS
-.Pp
-When invoked in legacy mode the following exit values are returned:
- 0    The date was written successfully
- 1    Unable to set the date
- 2    Able to set the local date, but unable to set it globally
+When invoked in legacy mode, the following exit values are returned:
+.Bl -tag -width X -compact
+.It 0
+The date was written successfully
+.It 1
+Unable to set the date
+.It 2
+Able to set the local date, but unable to set it globally
+.El
 .Sh SEE ALSO
 .Xr gettimeofday 2 ,
 .Xr strftime 3 ,
-.Xr compat 5 ,
-.Xr utmp 5 ,
+.Xr strptime 3 ,
+.Xr utmpx 5 ,
 .Xr timed 8
 .Rs
 .%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
@@ -223,7 +436,10 @@ When invoked in legacy mode the following exit values are returned:
 .Sh STANDARDS
 The
 .Nm
-utility supports the
-.St -susv3 .
-It is also expected to be compatible with
+utility is expected to be compatible with
 .St -p1003.2 .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
index fc456f8d1e1b1a5c399b47c809f16e25055b2421..64b4496de670d41bc514393ce9231191c3170b6d 100644 (file)
@@ -1,6 +1,4 @@
-/*     $NetBSD: date.c,v 1.25 1998/07/28 11:41:47 mycroft Exp $        */
-
-/*
+/*-
  * Copyright (c) 1985, 1987, 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
 #ifndef lint
-__COPYRIGHT(
+static char const copyright[] =
 "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
-       The Regents of the University of California.  All rights reserved.\n");
+       The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)date.c     8.2 (Berkeley) 4/28/95";
-#else
-__RCSID("$NetBSD: date.c,v 1.25 1998/07/28 11:41:47 mycroft Exp $");
-#endif
 #endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/date/date.c,v 1.47 2005/01/10 08:39:21 imp Exp $");
 
 #include <sys/param.h>
 #include <sys/time.h>
 
 #include <ctype.h>
 #include <err.h>
-#include <fcntl.h>
+#include <locale.h>
+#ifndef __APPLE__
+#include <libutil.h>
+#endif /* !__APPLE__ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <locale.h>
 #include <syslog.h>
-#include <time.h>
-#include <tzfile.h>
 #include <unistd.h>
-#include <util.h>
+#include <utmpx.h>
 
-#include "get_compat.h"
+#ifdef __APPLE__
+#include <get_compat.h>
+#include <util.h>
+#else
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
 
 #include "extern.h"
+#include "vary.h"
 
-time_t tval;
-int nflag;
-int retval = 0;
-int  unix2003_std = 0;         /* to determine legacy vs std mode */
+#ifndef        TM_YEAR_BASE
+#define        TM_YEAR_BASE    1900
+#endif
+
+static time_t tval;
+int retval;
+int unix2003_std = 0;  /* to determine legacy vs std mode */
 
-int main __P((int, char *[]));
-static void setthetime __P((char *));
-static void badformat __P((void));
-static void badtime __P((void));
-static void usage __P((void));
+static void setthetime(const char *, const char *, int, int);
+static void badformat(void);
+static void usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char *argv[])
 {
-       extern int optind;
-       extern char *optarg;
+       struct timezone tz;
        int ch, rflag;
-       char *format, buf[1024];
-
-       (void)setlocale(LC_ALL, "");
-
-       if (compat_mode("bin/date", "unix2003"))        /* Determine the STD */
-               unix2003_std = 1;
-       else
-               unix2003_std = 0;
-
+       int jflag, nflag;
+       const char *format;
+       char buf[1024];
+       char *endptr, *fmt;
+       char *tmp;
+       int set_timezone;
+       struct vary *v;
+       const struct vary *badv;
+       struct tm lt;
+
+       unix2003_std = COMPAT_MODE("bin/date", "unix2003");     /* Determine the STD */
+
+       v = NULL;
+       fmt = NULL;
+       (void) setlocale(LC_TIME, "");
+       tz.tz_dsttime = tz.tz_minuteswest = 0;
        rflag = 0;
-       while ((ch = getopt(argc, argv, "nr:u")) != -1)
+       jflag = nflag = 0;
+       set_timezone = 0;
+       while ((ch = getopt(argc, argv, "d:f:jnr:t:uv:")) != -1)
                switch((char)ch) {
+               case 'd':               /* daylight savings time */
+                       tz.tz_dsttime = strtol(optarg, &endptr, 10) ? 1 : 0;
+                       if (endptr == optarg || *endptr != '\0')
+                               usage();
+                       set_timezone = 1;
+                       break;
+               case 'f':
+                       fmt = optarg;
+                       break;
+               case 'j':
+                       jflag = 1;      /* don't set time */
+                       break;
                case 'n':               /* don't set network */
                        nflag = 1;
                        break;
                case 'r':               /* user specified seconds */
                        rflag = 1;
-                       tval = atol(optarg);
+                       tval = strtoq(optarg, &tmp, 0);
+                       if (*tmp != 0)
+                               usage();
+                       break;
+               case 't':               /* minutes west of UTC */
+                                       /* error check; don't allow "PST" */
+                       tz.tz_minuteswest = strtol(optarg, &endptr, 10);
+                       if (endptr == optarg || *endptr != '\0')
+                               usage();
+                       set_timezone = 1;
+                       break;
+               case 'u':               /* do everything in UTC */
+                       (void)setenv("TZ", "UTC0", 1);
                        break;
-               case 'u':               /* do everything in GMT */
-                       (void)setenv("TZ", "GMT0", 1);
+               case 'v':
+                       v = vary_append(v, optarg);
                        break;
                default:
                        usage();
@@ -115,10 +146,17 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
+       /*
+        * If -d or -t, set the timezone or daylight savings time; this
+        * doesn't belong here; the kernel should not know about either.
+        */
+       if (set_timezone && settimeofday((struct timeval *)NULL, &tz))
+               err(1, "settimeofday (timezone)");
+
        if (!rflag && time(&tval) == -1)
                err(1, "time");
 
-       format = "%a %b %e %H:%M:%S %Z %Y";
+       format = "%+";
 
        /* allow the operands in any order */
        if (*argv && **argv == '+') {
@@ -127,169 +165,171 @@ main(argc, argv)
        }
 
        if (*argv) {
-               setthetime(*argv);
+               setthetime(fmt, *argv, jflag, nflag);
                ++argv;
-       }
+       } else if (fmt != NULL)
+               usage();
 
        if (*argv && **argv == '+')
                format = *argv + 1;
 
-       (void)strftime(buf, sizeof(buf), format, localtime(&tval));
+       lt = *localtime(&tval);
+       badv = vary_apply(v, &lt);
+       if (badv) {
+               fprintf(stderr, "%s: Cannot apply date adjustment\n",
+                       badv->arg);
+               vary_destroy(v);
+               usage();
+       }
+       vary_destroy(v);
+       (void)strftime(buf, sizeof(buf), format, &lt);
        (void)printf("%s\n", buf);
-
-       /* if date/time could not be set/notified in the other hosts as
-          determined by netsetval() a return value 2 is set, which is
-          to be propogated back to shell in the legacy mode.
-       */
-       if( unix2003_std )
-               exit(0);        /* set/notify time thru NTPD isn't stds */
-       else
-               exit(retval);   /* Propogate the error condition set, if any */
+       if (fflush(stdout))
+               err(1, "stdout");
+       /*
+        * If date/time could not be set/notified in the other hosts as
+        * determined by netsetval(), a return value 2 is set, which is
+        * only propagated back to shell in legacy mode.
+        */
+       if (unix2003_std)
+               exit(0);
+       exit(retval);
 }
 
 #define        ATOI2(s)        ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
+#define        ATOI2_OFFSET(s, o)      (((s)[o] - '0') * 10 + ((s)[o + 1] - '0'))
 
-void
-setthetime(p)
-       char *p;
+static void
+setthetime(const char *fmt, const char *p, int jflag, int nflag)
 {
-
        struct tm *lt;
-       struct timeval tv;
        const char *dot, *t;
-       int yearset, len;
-
-       char tmp1_p[5] = "";            /* to hold ccyy and reformat */
-       char tmp2_p[16] = "";           /* ccyyMMddhhmm.ss is 15 chars */
-
-       for (t = p, dot = NULL; *t; ++t) {
-               if (isdigit(*t))
-                       continue;
-               if (*t == '.' && dot == NULL) {
-                       dot = t;
-                       continue;
-               }
-               badformat();
-       }
-
-       lt = localtime(&tval);
-
-       lt->tm_isdst = -1;                      /* Divine correct DST */
-
-       if (dot != NULL) {                      /* .ss */
-               len = strlen(dot);
-               if (len != 3)
+       int century;
+       size_t length;
+
+       if (fmt != NULL) {
+               lt = localtime(&tval);
+               t = strptime(p, fmt, lt);
+               if (t == NULL) {
+                       fprintf(stderr, "Failed conversion of ``%s''"
+                               " using format ``%s''\n", p, fmt);
                        badformat();
-               ++dot;
-               lt->tm_sec = ATOI2(dot);
+               } else if (*t != '\0')
+                       fprintf(stderr, "Warning: Ignoring %ld extraneous"
+                               " characters in date string (%s)\n",
+                               (long) strlen(t), t);
        } else {
-               len = 0;
-               lt->tm_sec = 0;
-       }
-
-       yearset = 0;
-
-       switch (strlen(p) - len) {
-       case 12:                                /* cc */
-               if(unix2003_std) {
-                       /* The last 4 chars are ccyy;
-                          reformat it to be in the first */
-                       strncpy(tmp1_p, &p[8], 4);
-                       tmp1_p[4] = '\0';
-                       p[8] = '\0';    /* .ss already processed; so no harm */
-                       strcpy(tmp2_p, p);
-                       strcpy(p, tmp1_p);
-                       strcat(p, tmp2_p);
-               }
-
-               lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
-               yearset = 1;
-               /* FALLTHROUGH */
-       case 10:                                /* yy */
-               if(unix2003_std) {
-                       /* The last 2 chars are yy; reformat it to be in the
-                          first, only if already not done. */
-                       if (tmp1_p[0] == '\0') {
-                               strncpy(tmp1_p, &p[8], 2);
-                               tmp1_p[2] = '\0';
-                               p[8] = '\0';    /* .ss done; so no harm */
-                               strcpy(tmp2_p, p);
-                               strcpy(p, tmp1_p);
-                               strcat(p, tmp2_p);
-                       } else
-                               ;  /* do nothing, already reformatted */
+               for (t = p, dot = NULL; *t; ++t) {
+                       if (isdigit(*t))
+                               continue;
+                       if (*t == '.' && dot == NULL) {
+                               dot = t;
+                               continue;
+                       }
+                       badformat();
                }
 
-               if (yearset) {
-                       lt->tm_year += ATOI2(p);
-               } else {
-                       yearset = ATOI2(p);
-                       if (yearset < 69)
-                               lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
-                       else
-                               lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
+               lt = localtime(&tval);
+
+               if (dot != NULL) {                      /* .ss */
+                       dot++; /* *dot++ = '\0'; */
+                       if (strlen(dot) != 2)
+                               badformat();
+                       lt->tm_sec = ATOI2(dot);
+                       if (lt->tm_sec > 61)
+                               badformat();
+               } else
+                       lt->tm_sec = 0;
+
+               century = 0;
+               /* if p has a ".ss" field then let's pretend it's not there */
+               switch (length = strlen(p) - ((dot != NULL) ? 3 : 0)) {
+               case 12:                                /* cc */
+                       lt->tm_year = (unix2003_std ? ATOI2_OFFSET(p, length - 4) : ATOI2(p)) * 100 - TM_YEAR_BASE;
+                       century = 1;
+                       /* FALLTHROUGH */
+               case 10:                                /* yy */
+                       if (century)
+                               lt->tm_year += (unix2003_std ? ATOI2_OFFSET(p, length - 2) : ATOI2(p));
+                       else {
+                               lt->tm_year = (unix2003_std ? ATOI2_OFFSET(p, length - 2) : ATOI2(p));
+                               if (lt->tm_year < 69)   /* hack for 2000 ;-} */
+                                       lt->tm_year += 2000 - TM_YEAR_BASE;
+                               else
+                                       lt->tm_year += 1900 - TM_YEAR_BASE;
+                       }
+                       /* FALLTHROUGH */
+               case 8:                                 /* mm */
+                       lt->tm_mon = ATOI2(p);
+                       if (lt->tm_mon > 12)
+                               badformat();
+                       --lt->tm_mon;           /* time struct is 0 - 11 */
+                       /* FALLTHROUGH */
+               case 6:                                 /* dd */
+                       lt->tm_mday = ATOI2(p);
+                       if (lt->tm_mday > 31)
+                               badformat();
+                       /* FALLTHROUGH */
+               case 4:                                 /* HH */
+                       lt->tm_hour = ATOI2(p);
+                       if (lt->tm_hour > 23)
+                               badformat();
+                       /* FALLTHROUGH */
+               case 2:                                 /* MM */
+                       lt->tm_min = ATOI2(p);
+                       if (lt->tm_min > 59)
+                               badformat();
+                       break;
+               default:
+                       badformat();
                }
-               /* FALLTHROUGH */
-       case 8:                                 /* mm */
-               lt->tm_mon = ATOI2(p);
-               --lt->tm_mon;                   /* time struct is 0 - 11 */
-               /* FALLTHROUGH */
-       case 6:                                 /* dd */
-               lt->tm_mday = ATOI2(p);
-               /* FALLTHROUGH */
-       case 4:                                 /* hh */
-               lt->tm_hour = ATOI2(p);
-               /* FALLTHROUGH */
-       case 2:                                 /* mm */
-               lt->tm_min = ATOI2(p);
-               break;
-       default:
-               badformat();
        }
 
+       /* Let mktime() decide whether summer time is in effect. */
+       lt->tm_isdst = -1;
+
        /* convert broken-down time to GMT clock time */
        if ((tval = mktime(lt)) == -1)
-               badtime();
-
-       /* set the time */
-       if (nflag || netsettime(tval)) {
-               logwtmp("|", "date", "");
-               tv.tv_sec = tval;
-               tv.tv_usec = 0;
-               if (settimeofday(&tv, NULL)) {
-                       perror("date: settimeofday");
-                       exit(1);
+               errx(1, "nonexistent time");
+
+       if (!jflag) {
+               /* set the time */
+               if (nflag || netsettime(tval)) {
+                       struct utmpx ut;
+                       bzero(&ut, sizeof(ut));
+                       ut.ut_type = OLD_TIME;
+                       (void)gettimeofday(&ut.ut_tv, NULL);
+                       pututxline(&ut);
+                       ut.ut_tv.tv_sec = tval;
+                       ut.ut_tv.tv_usec = 0;
+                       if (settimeofday(&ut.ut_tv, NULL))
+                               err(1, "settimeofday (timeval)");
+                       ut.ut_type = NEW_TIME;
+                       pututxline(&ut);
                }
-               logwtmp("{", "date", "");
-       }
 
-       if ((p = getlogin()) == NULL)
-               p = "???";
-       syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
+               if ((p = getlogin()) == NULL)
+                       p = "???";
+               syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
+       }
 }
 
 static void
-badformat()
+badformat(void)
 {
        warnx("illegal time format");
        usage();
 }
 
 static void
-badtime()
-{
-       errx(1, "illegal time");
-}
-
-static void
-usage()
+usage(void)
 {
-       (void)fprintf(stderr,
-           "usage: date [-nu] [-r seconds] [+format]\n");
-       if (unix2003_std)
-               (void)fprintf(stderr, "       date [-u] mmddhhmm[[cc]yy]\n");
-       else
-               (void)fprintf(stderr, "       date [[[[[cc]yy]mm]dd]hh]mm[.ss]\n");
+       (void)fprintf(stderr, "%s\n%s\n",
+           "usage: date [-jnu] [-d dst] [-r seconds] [-t west] "
+           "[-v[+|-]val[ymwdHMS]] ... ",
+               unix2003_std ? "            "
+           "[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]" :
+           "            "
+           "[-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format]");
        exit(1);
-       /* NOTREACHED */
 }
index c0d7fbe5163d9bea1c073b0481f489e6d094a615..fe2baee4effc88f88b83d65f0d0fc51abb3b75e3 100644 (file)
@@ -1,5 +1,3 @@
-/*     $NetBSD: extern.h,v 1.3 1995/03/21 09:03:52 cgd Exp $   */
-
 /*-
  * Copyright (c) 1993
  *     The Regents of the University of California.  All rights reserved.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -33,6 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)extern.h    8.1 (Berkeley) 5/31/93
+ * $FreeBSD: src/bin/date/extern.h,v 1.7 2004/04/06 20:06:45 markm Exp $
  */
 
-int    netsettime __P((time_t));
+int    netsettime(time_t);
index ee7b8ff75abd1df0142197c64a52b442c5c83378..4f7852a492ee9a9123f8f90d1170122b72c8bba5 100644 (file)
@@ -1,5 +1,3 @@
-/*     $NetBSD: netdate.c,v 1.16 1998/07/28 03:47:15 mycroft Exp $     */
-
 /*-
  * Copyright (c) 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#ifndef lint
 #if 0
-static char sccsid[] = "@(#)netdate.c  8.2 (Berkeley) 4/28/95";
-#else
-__RCSID("$NetBSD: netdate.c,v 1.16 1998/07/28 03:47:15 mycroft Exp $");
-#endif
+#ifndef lint
+static char sccsid[] = "@(#)netdate.c  8.1 (Berkeley) 5/31/93";
 #endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/date/netdate.c,v 1.18 2004/04/06 20:06:45 markm Exp $");
 
 #include <sys/param.h>
 #include <sys/time.h>
@@ -53,7 +47,6 @@ __RCSID("$NetBSD: netdate.c,v 1.16 1998/07/28 03:47:15 mycroft Exp $");
 
 #include <err.h>
 #include <errno.h>
-#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -72,31 +65,26 @@ extern int retval;
  * Returns 0 on success.  Returns > 0 on failure, setting retval to 2;
  */
 int
-netsettime(tval)
-       time_t tval;
+netsettime(time_t tval)
 {
        struct timeval tout;
        struct servent *sp;
        struct tsp msg;
-       struct sockaddr_in sin, dest, from;
+       struct sockaddr_in lsin, dest, from;
        fd_set ready;
        long waittime;
-       int s, length, timed_ack, found, error;
-#ifdef IP_PORTRANGE
-       int on;
-#endif
-       char hostname[MAXHOSTNAMELEN + 1];
+       int s, port, timed_ack, found, lerr;
+       socklen_t length;
+       char hostname[MAXHOSTNAMELEN];
 
        if ((sp = getservbyname("timed", "udp")) == NULL) {
-               warnx("udp/timed: unknown service");
+               warnx("timed/udp: unknown service");
                return (retval = 2);
        }
 
-       (void)memset(&dest, 0, sizeof(dest));
-       dest.sin_len = sizeof(struct sockaddr_in);
-       dest.sin_family = AF_INET;
        dest.sin_port = sp->s_port;
-       dest.sin_addr.s_addr = htonl(INADDR_ANY);
+       dest.sin_family = AF_INET;
+       dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
        s = socket(AF_INET, SOCK_DGRAM, 0);
        if (s < 0) {
                if (errno != EPROTONOSUPPORT)
@@ -104,30 +92,30 @@ netsettime(tval)
                return (retval = 2);
        }
 
-#ifdef IP_PORTRANGE
-       on = IP_PORTRANGE_LOW;
-       if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on)) < 0) {
-               warn("setsockopt");
+       memset(&lsin, 0, sizeof(lsin));
+       lsin.sin_family = AF_INET;
+       for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
+               lsin.sin_port = htons((u_short)port);
+               if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0)
+                       break;
+               if (errno == EADDRINUSE)
+                       continue;
+               if (errno != EADDRNOTAVAIL)
+                       warn("bind");
                goto bad;
        }
-#endif
-
-       (void)memset(&sin, 0, sizeof(sin));
-       sin.sin_len = sizeof(struct sockaddr_in);
-       sin.sin_family = AF_INET;
-       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-               warn("bind");
+       if (port == IPPORT_RESERVED / 2) {
+               warnx("all ports in use");
                goto bad;
        }
-
        msg.tsp_type = TSP_SETDATE;
        msg.tsp_vers = TSPVERSION;
        if (gethostname(hostname, sizeof(hostname))) {
                warn("gethostname");
                goto bad;
        }
-       hostname[sizeof(hostname) - 1] = '\0';
-       (void)strncpy(msg.tsp_name, hostname, sizeof(hostname));
+       (void)strncpy(msg.tsp_name, hostname, sizeof(msg.tsp_name) - 1);
+       msg.tsp_name[sizeof(msg.tsp_name) - 1] = '\0';
        msg.tsp_seq = htons((u_short)0);
        msg.tsp_time.tv_sec = htonl((u_long)tval);
        msg.tsp_time.tv_usec = htonl((u_long)0);
@@ -152,11 +140,11 @@ loop:
        FD_SET(s, &ready);
        found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
 
-       length = sizeof(error);
+       length = sizeof(lerr);
        if (!getsockopt(s,
-           SOL_SOCKET, SO_ERROR, (char *)&error, &length) && error) {
-               if (error != ECONNREFUSED)
-                       warn("send (delayed error)");
+           SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) {
+               if (lerr != ECONNREFUSED)
+                       warnc(lerr, "send (delayed error)");
                goto bad;
        }
 
@@ -180,7 +168,7 @@ loop:
                        (void)close(s);
                        return (0);
                default:
-                       warnx("wrong ack received from timed: %s", 
+                       warnx("wrong ack received from timed: %s",
                            tsptype[msg.tsp_type]);
                        timed_ack = -1;
                        break;
diff --git a/date/vary.c b/date/vary.c
new file mode 100644 (file)
index 0000000..82a6cea
--- /dev/null
@@ -0,0 +1,506 @@
+/*-
+ * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/date/vary.c,v 1.16 2004/08/09 13:43:39 yar Exp $");
+
+#include <err.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include "vary.h"
+
+struct trans {
+  int val;
+  const char *str;
+};
+
+static struct trans trans_mon[] = {
+  { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
+  { 5, "may"}, { 6, "june" }, { 7, "july" }, { 8, "august" },
+  { 9, "september" }, { 10, "october" }, { 11, "november" }, { 12, "december" },
+  { -1, NULL }
+};
+
+static struct trans trans_wday[] = {
+  { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" },
+  { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" },
+  { -1, NULL }
+};
+
+static char digits[] = "0123456789";
+static int adjhour(struct tm *, char, int, int);
+
+static int
+domktime(struct tm *t, char type)
+{
+  time_t ret;
+
+  while ((ret = mktime(t)) == -1 && t->tm_year > 68 && t->tm_year < 138)
+    /* While mktime() fails, adjust by an hour */
+    adjhour(t, type == '-' ? type : '+', 1, 0);
+
+  return ret;
+}
+
+static int
+trans(const struct trans t[], const char *arg)
+{
+  int f;
+
+  for (f = 0; t[f].val != -1; f++)
+    if (!strncasecmp(t[f].str, arg, 3) ||
+        !strncasecmp(t[f].str, arg, strlen(t[f].str)))
+      return t[f].val;
+
+  return -1;
+}
+
+struct vary *
+vary_append(struct vary *v, char *arg)
+{
+  struct vary *result, **nextp;
+
+  if (v) {
+    result = v;
+    while (v->next)
+      v = v->next;
+    nextp = &v->next;
+  } else
+    nextp = &result;
+
+  if ((*nextp = (struct vary *)malloc(sizeof(struct vary))) == NULL)
+    err(1, "malloc");
+  (*nextp)->arg = arg;
+  (*nextp)->next = NULL;
+  return result;
+}
+
+static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static int
+daysinmonth(const struct tm *t)
+{
+  int year;
+
+  year = t->tm_year + 1900;
+
+  if (t->tm_mon == 1)
+    if (!(year % 400))
+      return 29;
+    else if (!(year % 100))
+      return 28;
+    else if (!(year % 4))
+      return 29;
+    else
+      return 28;
+  else if (t->tm_mon >= 0 && t->tm_mon < 12)
+    return mdays[t->tm_mon];
+
+  return 0;
+}
+
+
+static int
+adjyear(struct tm *t, char type, int val, int mk)
+{
+  switch (type) {
+    case '+':
+      t->tm_year += val;
+      break;
+    case '-':
+      t->tm_year -= val;
+      break;
+    default:
+      t->tm_year = val;
+      if (t->tm_year < 69)
+       t->tm_year += 100;              /* as per date.c */
+      else if (t->tm_year > 1900)
+        t->tm_year -= 1900;             /* struct tm holds years since 1900 */
+      break;
+  }
+  return !mk || domktime(t, type) != -1;
+}
+
+static int
+adjmon(struct tm *t, char type, int val, int istext, int mk)
+{
+  int lmdays;
+
+  if (val < 0)
+    return 0;
+
+  switch (type) {
+    case '+':
+      if (istext) {
+        if (val <= t->tm_mon)
+          val += 11 - t->tm_mon;       /* early next year */
+        else
+          val -= t->tm_mon + 1;                /* later this year */
+      }
+      if (val) {
+        if (!adjyear(t, '+', (t->tm_mon + val) / 12, 0))
+          return 0;
+        val %= 12;
+        t->tm_mon += val;
+        if (t->tm_mon > 11)
+          t->tm_mon -= 12;
+      }
+      break;
+
+    case '-':
+      if (istext) {
+        if (val-1 > t->tm_mon)
+          val = 13 - val + t->tm_mon;  /* later last year */
+        else
+          val = t->tm_mon - val + 1;   /* early this year */
+      }
+      if (val) {
+        if (!adjyear(t, '-', val / 12, 0))
+          return 0;
+        val %= 12;
+        if (val > t->tm_mon) {
+          if (!adjyear(t, '-', 1, 0))
+            return 0;
+          val -= 12;
+        }
+        t->tm_mon -= val;
+      }
+      break;
+
+    default:
+      if (val > 12 || val < 1)
+        return 0;
+      t->tm_mon = --val;
+  }
+
+  /* e.g., -v-1m on March, 31 is the last day of February in common sense */
+  lmdays = daysinmonth(t);
+  if (t->tm_mday > lmdays)
+    t->tm_mday = lmdays;
+
+  return !mk || domktime(t, type) != -1;
+}
+
+static int
+adjday(struct tm *t, char type, int val, int mk)
+{
+  int lmdays;
+
+  switch (type) {
+    case '+':
+      while (val) {
+        lmdays = daysinmonth(t);
+        if (val > lmdays - t->tm_mday) {
+          val -= lmdays - t->tm_mday + 1;
+          t->tm_mday = 1;
+          if (!adjmon(t, '+', 1, 0, 0))
+            return 0;
+        } else {
+          t->tm_mday += val;
+          val = 0;
+        }
+      }
+      break;
+    case '-':
+      while (val)
+        if (val >= t->tm_mday) {
+          val -= t->tm_mday;
+          t->tm_mday = 1;
+          if (!adjmon(t, '-', 1, 0, 0))
+            return 0;
+          t->tm_mday = daysinmonth(t);
+        } else {
+          t->tm_mday -= val;
+          val = 0;
+        }
+      break;
+    default:
+      if (val > 0 && val <= daysinmonth(t))
+        t->tm_mday = val;
+      else
+        return 0;
+      break;
+  }
+
+  return !mk || domktime(t, type) != -1;
+}
+
+static int
+adjwday(struct tm *t, char type, int val, int istext, int mk)
+{
+  if (val < 0)
+    return 0;
+
+  switch (type) {
+    case '+':
+      if (istext)
+        if (val < t->tm_wday)
+          val = 7 - t->tm_wday + val;  /* early next week */
+        else
+          val -= t->tm_wday;           /* later this week */
+      else
+        val *= 7;                      /* "-v+5w" == "5 weeks in the future" */
+      return !val || adjday(t, '+', val, mk);
+    case '-':
+      if (istext) {
+        if (val > t->tm_wday)
+          val = 7 - val + t->tm_wday;  /* later last week */
+        else
+          val = t->tm_wday - val;      /* early this week */
+      } else
+        val *= 7;                      /* "-v-5w" == "5 weeks ago" */
+      return !val || adjday(t, '-', val, mk);
+    default:
+      if (val < t->tm_wday)
+        return adjday(t, '-', t->tm_wday - val, mk);
+      else if (val > 6)
+        return 0;
+      else if (val > t->tm_wday)
+        return adjday(t, '+', val - t->tm_wday, mk);
+  }
+  return 1;
+}
+
+static int
+adjhour(struct tm *t, char type, int val, int mk)
+{
+  if (val < 0)
+    return 0;
+
+  switch (type) {
+    case '+':
+      if (val) {
+        int days;
+
+        days = (t->tm_hour + val) / 24;
+        val %= 24;
+        t->tm_hour += val;
+        t->tm_hour %= 24;
+        if (!adjday(t, '+', days, 0))
+          return 0;
+      }
+      break;
+
+    case '-':
+      if (val) {
+        int days;
+
+        days = val / 24;
+        val %= 24;
+        if (val > t->tm_hour) {
+          days++;
+          val -= 24;
+        }
+        t->tm_hour -= val;
+        if (!adjday(t, '-', days, 0))
+          return 0;
+      }
+      break;
+
+    default:
+      if (val > 23)
+        return 0;
+      t->tm_hour = val;
+  }
+
+  return !mk || domktime(t, type) != -1;
+}
+
+static int
+adjmin(struct tm *t, char type, int val, int mk)
+{
+  if (val < 0)
+    return 0;
+
+  switch (type) {
+    case '+':
+      if (val) {
+        if (!adjhour(t, '+', (t->tm_min + val) / 60, 0))
+          return 0;
+        val %= 60;
+        t->tm_min += val;
+        if (t->tm_min > 59)
+          t->tm_min -= 60;
+      }
+      break;
+
+    case '-':
+      if (val) {
+        if (!adjhour(t, '-', val / 60, 0))
+          return 0;
+        val %= 60;
+        if (val > t->tm_min) {
+          if (!adjhour(t, '-', 1, 0))
+            return 0;
+          val -= 60;
+        }
+        t->tm_min -= val;
+      }
+      break;
+
+    default:
+      if (val > 59)
+        return 0;
+      t->tm_min = val;
+  }
+
+  return !mk || domktime(t, type) != -1;
+}
+
+static int
+adjsec(struct tm *t, char type, int val, int mk)
+{
+  if (val < 0)
+    return 0;
+
+  switch (type) {
+    case '+':
+      if (val) {
+        if (!adjmin(t, '+', (t->tm_sec + val) / 60, 0))
+          return 0;
+        val %= 60;
+        t->tm_sec += val;
+        if (t->tm_sec > 59)
+          t->tm_sec -= 60;
+      }
+      break;
+
+    case '-':
+      if (val) {
+        if (!adjmin(t, '-', val / 60, 0))
+          return 0;
+        val %= 60;
+        if (val > t->tm_sec) {
+          if (!adjmin(t, '-', 1, 0))
+            return 0;
+          val -= 60;
+        }
+        t->tm_sec -= val;
+      }
+      break;
+
+    default:
+      if (val > 59)
+        return 0;
+      t->tm_sec = val;
+  }
+
+  return !mk || domktime(t, type) != -1;
+}
+
+const struct vary *
+vary_apply(const struct vary *v, struct tm *t)
+{
+  char type;
+  char which;
+  char *arg;
+  size_t len;
+  int val;
+
+  for (; v; v = v->next) {
+    type = *v->arg;
+    arg = v->arg;
+    if (type == '+' || type == '-')
+      arg++;
+    else
+      type = '\0';
+    len = strlen(arg);
+    if (len < 2)
+      return v;
+
+    if (type == '\0')
+      t->tm_isdst = -1;
+
+    if (strspn(arg, digits) != len-1) {
+      val = trans(trans_wday, arg);
+      if (val != -1) {
+          if (!adjwday(t, type, val, 1, 1))
+            return v;
+      } else {
+        val = trans(trans_mon, arg);
+        if (val != -1) {
+          if (!adjmon(t, type, val, 1, 1))
+            return v;
+        } else
+          return v;
+      }
+    } else {
+      val = atoi(arg);
+      which = arg[len-1];
+      
+      switch (which) {
+        case 'S':
+          if (!adjsec(t, type, val, 1))
+            return v;
+          break;
+        case 'M':
+          if (!adjmin(t, type, val, 1))
+            return v;
+          break;
+        case 'H':
+          if (!adjhour(t, type, val, 1))
+            return v;
+          break;
+        case 'd':
+          t->tm_isdst = -1;
+          if (!adjday(t, type, val, 1))
+            return v;
+          break;
+        case 'w':
+          t->tm_isdst = -1;
+          if (!adjwday(t, type, val, 0, 1))
+            return v;
+          break;
+        case 'm':
+          t->tm_isdst = -1;
+          if (!adjmon(t, type, val, 0, 1))
+            return v;
+          break;
+        case 'y':
+          t->tm_isdst = -1;
+          if (!adjyear(t, type, val, 1))
+            return v;
+          break;
+        default:
+          return v;
+      }
+    }
+  }
+  return 0;
+}
+
+void
+vary_destroy(struct vary *v)
+{
+  struct vary *n;
+
+  while (v) {
+    n = v->next;
+    free(v);
+    v = n;
+  }
+}
diff --git a/date/vary.h b/date/vary.h
new file mode 100644 (file)
index 0000000..27eddf7
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/bin/date/vary.h,v 1.4 1999/08/27 23:14:00 peter Exp $
+ */
+
+struct vary {
+  char *arg;
+  struct vary *next;
+};
+
+extern struct vary *vary_append(struct vary *v, char *arg);
+extern const struct vary *vary_apply(const struct vary *v, struct tm *t);
+extern void vary_destroy(struct vary *v);
index f2346d373f40e908e615aed328fd04f1aab1c3b6..bd0e4372beb16c8c1e0a33e24ed018186c92f603 100644 (file)
@@ -16,6 +16,7 @@ CFILES = echo.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble echo.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 9e08e2305d066412e90839e6c17e81fd9afa0885..87bcc34b516c8b09e819410ac373853d9e42d5ce 100644 (file)
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
@@ -33,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)echo.1      8.1 (Berkeley) 7/22/93
-.\" $FreeBSD: src/bin/echo/echo.1,v 1.13 2001/08/15 09:09:35 ru Exp $
+.\" $FreeBSD: src/bin/echo/echo.1,v 1.19 2005/01/16 16:41:56 ru Exp $
 .\"
-.Dd July 22, 1993
+.Dd April 12, 2003
 .Dt ECHO 1
 .Os
 .Sh NAME
@@ -58,20 +55,38 @@ output.
 The following option is available:
 .Bl -tag -width flag
 .It Fl n
-Do not print the trailing newline character.  This may also be
-achieved by appending
+Do not print the trailing newline character.
+This may also be achieved by appending
 .Ql \ec
 to the end of the string, as is done
 by iBCS2 compatible systems.
+Note that this option as well as the effect of
+.Ql \ec
+are implementation-defined in
+.St -p1003.1-2001
+as amended by Cor.\& 1-2002.
+Applications aiming for maximum
+portability are strongly encouraged to use
+.Xr printf 1
+to suppress the newline character.
 .El
 .Pp
 Some shells may provide a builtin
 .Nm
 command which is similar or identical to this utility.
+.\" 4874742
+Most notably, the builtin
+.Nm
+in
+.Xr sh 1
+does not accept the
+.Fl n
+option.
+.\" 4874742
 Consult the
 .Xr builtin 1
 manual page.
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
 .Xr builtin 1 ,
@@ -81,6 +96,6 @@ manual page.
 .Sh STANDARDS
 The
 .Nm
-utility is expected to be
-.St -p1003.2
-compatible.
+utility conforms to
+.St -p1003.1-2001
+as amended by Cor.\& 1-2002.
index bbb05396f650890dc74b3227bdba881c82d4e013..629e22f1e09d8fe15ae8d1bc7f45202f78f79c18 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1989, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -31,6 +27,7 @@
  * SUCH DAMAGE.
  */
 
+#if 0
 #ifndef lint
 static char const copyright[] =
 "@(#) Copyright (c) 1989, 1993\n\
@@ -38,32 +35,66 @@ static char const copyright[] =
 #endif /* not lint */
 
 #ifndef lint
-#if 0
 static char sccsid[] = "@(#)echo.c     8.1 (Berkeley) 5/31/93";
-#endif
 #endif /* not lint */
+#endif
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/bin/echo/echo.c,v 1.13 2002/06/30 05:13:53 obrien Exp $");
+__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.18 2005/01/10 08:39:22 imp Exp $");
 
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
-/* ARGSUSED */
+/*
+ * Report an error and exit.
+ * Use it instead of err(3) to avoid linking-in stdio.
+ */
+static void
+errexit(const char *prog, const char *reason)
+{
+       char *errstr = strerror(errno);
+       write(STDERR_FILENO, prog, strlen(prog));
+       write(STDERR_FILENO, ": ", 2);
+       write(STDERR_FILENO, reason, strlen(reason));
+       write(STDERR_FILENO, ": ", 2);
+       write(STDERR_FILENO, errstr, strlen(errstr));
+       write(STDERR_FILENO, "\n", 1);
+       exit(1);
+}
+       
 int
 main(int argc, char *argv[])
 {
        int nflag;      /* if not set, output a trailing newline. */
+       int veclen;     /* number of writev arguments. */
+       struct iovec *iov, *vp; /* Elements to write, current element. */
+       char space[] = " ";
+       char newline[] = "\n";
+       char *progname = argv[0];
 
        /* This utility may NOT do getopt(3) option parsing. */
        if (*++argv && !strcmp(*argv, "-n")) {
                ++argv;
+               --argc;
                nflag = 1;
-       }
-       else
+       } else
                nflag = 0;
 
+       veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
+
+       if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
+               errexit(progname, "malloc");
+
        while (argv[0] != NULL) {
+               size_t len;
+               
+               len = strlen(argv[0]);
 
                /*
                 * If the next argument is NULL then this is this
@@ -71,23 +102,36 @@ main(int argc, char *argv[])
                 * 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';
+                               len -= 2;
                                nflag = 1;
                        }
                }
-               (void)printf("%s", argv[0]);
-               if (*++argv)
-                       putchar(' ');
+               vp->iov_base = *argv;
+               vp++->iov_len = len;
+               if (*++argv) {
+                       vp->iov_base = space;
+                       vp++->iov_len = 1;
+               }
+       }
+       if (!nflag) {
+               veclen++;
+               vp->iov_base = newline;
+               vp++->iov_len = 1;
+       }
+       /* assert(veclen == (vp - iov)); */
+       while (veclen) {
+               int nwrite;
+
+               nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
+               if (writev(STDOUT_FILENO, iov, nwrite) == -1)
+                       errexit(progname, "write");
+               iov += nwrite;
+               veclen -= nwrite;
        }
-       if (!nflag)
-               putchar('\n');
        return 0;
 }
index 36b998f6f4146091c170a05ffc7e3fccaab7ccb0..590608c8941472f1d9b3b5b03c53393f6270fc1d 100644 (file)
@@ -254,7 +254,7 @@ error()
 struct val *
 eval6()
 {
-       struct val     *v;
+       struct val *v;
 
        if (token == OPERAND) {
                nexttoken();
@@ -265,11 +265,73 @@ eval6()
                v = eval0();
 
                if (token != LP)
-                       error();
+                       error();
+                 
                nexttoken();
                return v;
        } else {
-               error();
+          
+               switch (token) {
+               case DIV:
+                        nexttoken();
+                        tokval = make_str("/");
+                        break;
+               case MUL: 
+                        nexttoken();
+                        tokval = make_str("*");
+                        break;
+               case OR: 
+                        nexttoken();
+                        tokval = make_str("|");
+                        break;
+               case AND: 
+                        nexttoken();
+                        tokval = make_str("&");
+                        break;
+               case EQ: 
+                        nexttoken();
+                        tokval = make_str("=");
+                        break;
+               case LT: 
+                        nexttoken();
+                        tokval = make_str("<");
+                        break;
+               case GT: 
+                        nexttoken();
+                        tokval = make_str(">");
+                        break;
+               case ADD: 
+                        nexttoken();
+                        tokval = make_str("+");
+                        break;
+               case SUB: 
+                        nexttoken();
+                        tokval = make_str("-");
+                        break;
+               case MOD: 
+                        nexttoken();
+                        tokval = make_str("%");
+                        break;
+               case NE: 
+                        nexttoken();
+                        tokval = make_str("!=");
+                        break;
+               case LE: 
+                        nexttoken();
+                        tokval = make_str("<=");
+                        break;
+               case MATCH:
+                        nexttoken();
+                        tokval = make_str(":");
+                        break;
+               case GE: 
+                        nexttoken();
+                        tokval = make_str(">=");
+                        break;
+               case EOI:
+                        error();
+               }
+               return tokval;
        }
        /* NOTREACHED */
 }
@@ -550,7 +612,7 @@ main(argc, argv)
 
        (void) setlocale(LC_ALL, "");
        av = argv + 1;
-       if (!strcmp(*av, "--"))
+       if (*av && !strcmp(*av, "--"))
            av++;
        nexttoken();
        vp = eval0();
index c0cb27652d8670e168822f11013314a1de6b158a..4e13a44cb18ef3551a12fa68a147137688f79d1f 100644 (file)
@@ -14,10 +14,14 @@ PROJECT_TYPE = Tool
 
 HFILES = extern.h find.h
 
-CFILES = find.c function.c ls.c main.c misc.c operator.c option.c y.tab.c
+CFILES = find.c function.c ls.c main.c misc.c operator.c option.c
+
+OTHERLINKED = getdate.y
+OTHERLINKEDOFILES = getdate.o
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble find.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID -D_DARWIN_USE_64_BIT_INODE
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index d909f1e617dc8ffc13f1b95ddfb920f3b72c1dc7..945b5575dc86f554c9930505154994d1e0bb1767 100644 (file)
  * SUCH DAMAGE.
  *
  *     @(#)extern.h    8.3 (Berkeley) 4/16/94
- *     $FreeBSD: src/usr.bin/find/extern.h,v 1.9.2.4 2001/05/06 09:53:22 phk Exp $
+ *     $FreeBSD: src/usr.bin/find/extern.h,v 1.23 2006/05/14 20:23:00 krion Exp $
  */
 
 #include <sys/cdefs.h>
 
-void    brace_subst __P((char *, char **, char *, int));
-void   *emalloc __P((unsigned int));
-PLAN   *find_create __P((char ***));
-int     find_execute __P((PLAN *, char **));
-PLAN   *find_formplan __P((char **));
-PLAN   *not_squish __P((PLAN *));
-PLAN   *or_squish __P((PLAN *));
-PLAN   *paren_squish __P((PLAN *));
+void    brace_subst(char *, char **, char *, int);
+PLAN   *find_create(char ***);
+int     find_execute(PLAN *, char **);
+PLAN   *find_formplan(char **);
+PLAN   *not_squish(PLAN *);
+PLAN   *or_squish(PLAN *);
+PLAN   *paren_squish(PLAN *);
+struct timeb;
+time_t  get_date(char *, struct timeb *);
 struct stat;
-void    printlong __P((char *, char *, struct stat *));
-int     queryuser __P((char **));
-OPTION *option __P((char *));
+void    printlong(char *, char *, struct stat *);
+int     queryuser(char **);
+OPTION *lookup_option(const char *);
+void    finish_execplus(void);
 
 creat_f        c_Xmin;
 creat_f        c_Xtime;
+creat_f        c_acl;
 creat_f        c_and;
 creat_f        c_delete;
 creat_f        c_depth;
@@ -58,9 +61,7 @@ creat_f       c_empty;
 creat_f        c_exec;
 creat_f        c_flags;
 creat_f        c_follow;
-#if !defined(__NetBSD__)
 creat_f        c_fstype;
-#endif
 creat_f        c_group;
 creat_f        c_inum;
 creat_f        c_links;
@@ -81,9 +82,11 @@ creat_f      c_xdev;
 
 exec_f f_Xmin;
 exec_f f_Xtime;
+exec_f f_acl;
 exec_f f_always_true;
 exec_f f_closeparen;
 exec_f f_delete;
+exec_f f_depth;
 exec_f f_empty;
 exec_f f_exec;
 exec_f f_expr;
@@ -113,3 +116,6 @@ exec_f      f_user;
 extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs;
 extern int mindepth, maxdepth;
 extern int regexp_flags;
+extern time_t now;
+extern int dotfd;
+extern FTS *tree;
index 5a3ad9619d97b989f37d36395db87be5cb9f5530..a20f4504b8faf78545de607eea4a5d7cb742dc82 100644 (file)
@@ -1,3 +1,4 @@
+.\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" This code is derived from software contributed to Berkeley by
@@ -32,9 +33,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)find.1      8.7 (Berkeley) 5/9/95
-.\" $FreeBSD: src/usr.bin/find/find.1,v 1.23.2.14 2001/12/14 15:53:30 ru Exp $
+.\" $FreeBSD: src/usr.bin/find/find.1,v 1.81 2006/12/13 17:02:50 ru Exp $
 .\"
-.Dd May 3, 2001
+.Dd December 13, 2006
 .Dt FIND 1
 .Os
 .Sh NAME
 .Op Fl H | Fl L | Fl P
 .Op Fl EXdsx
 .Op Fl f Ar pathname
+.Ar pathname ...
+.Ar expression
+.Nm
+.Op Fl H | Fl L | Fl P
+.Op Fl EXdsx
+.Fl f Ar pathname
 .Op Ar pathname ...
 .Ar expression
 .Sh DESCRIPTION
-.Nm Find
-recursively descends the directory tree for each
+The
+.Nm
+utility recursively descends the directory tree for each
 .Ar pathname
 listed, evaluating an
 .Ar expression
@@ -73,9 +81,7 @@ The
 .Xr re_format 7
 manual page fully describes both formats.
 .It Fl H
-The
-.Fl H
-option causes the file information and file type (see
+Cause the file information and file type (see
 .Xr stat 2 )
 returned for each symbolic link specified on the command line to be
 those of the file referenced by the link, not the link itself.
@@ -84,25 +90,23 @@ be for the link itself.
 File information of all symbolic links not on
 the command line is that of the link itself.
 .It Fl L
-The
-.Fl L
-option causes the file information and file type (see
+Cause the file information and file type (see
 .Xr stat 2 )
 returned for each symbolic link to be those of the file referenced by the
 link, not the link itself.
 If the referenced file does not exist, the file information and type will
 be for the link itself.
+.Pp
+This option is equivalent to the deprecated
+.Ic -follow
+primary.
 .It Fl P
-The
-.Fl P
-option causes the file information and file type (see
+Cause the file information and file type (see
 .Xr stat 2 )
 returned for each symbolic link to be those of the link itself.
 This is the default.
 .It Fl X
-The
-.Fl X
-option is a modification to permit
+Permit
 .Nm
 to be safely used in conjunction with
 .Xr xargs 1 .
@@ -117,32 +121,45 @@ and double
 quotes, backslash
 .Pq Dq Li \e ,
 space, tab and newline characters.
+.Pp
+However, you may wish to consider the
+.Fl print0
+primary in conjunction with
+.Dq Nm xargs Fl 0
+as an effective alternative.
 .It Fl d
-The
-.Fl d
-option causes
+Cause
 .Nm
-to perform a depth\-first traversal, i.e., directories
-are visited in post\-order and all entries in a directory will be acted
+to perform a depth-first traversal, i.e., directories
+are visited in post-order and all entries in a directory will be acted
 on before the directory itself.
 By default,
 .Nm
-visits directories in pre\-order, i.e., before their contents.
+visits directories in pre-order, i.e., before their contents.
 Note, the default is
 .Em not
-a breadth\-first traversal.
+a breadth-first traversal.
+.Pp
+This option is equivalent to the
+.Ic -depth
+primary of
+.St -p1003.1-2001 .
+.Fl d
+can be useful when
+.Nm
+is used with
+.Xr cpio 1
+to process files that are contained in directories with unusual permissions.
+It ensures that you have write permission while you are placing files in a
+directory, then sets the directory's permissions as the last thing.
 .It Fl f
-The
-.Fl f
-option specifies a file hierarchy for
+Specify a file hierarchy for
 .Nm
 to traverse.
 File hierarchies may also be specified as the operands immediately
 following the options.
 .It Fl s
-The
-.Fl s
-option causes
+Cause
 .Nm
 to traverse the file hierarchies in lexicographical order,
 i.e., alphabetical order within each directory.
@@ -152,15 +169,52 @@ and
 .Ql "find | sort"
 may give different results.
 .It Fl x
-The
-.Fl x
-option prevents
+Prevent
 .Nm
 from descending into directories that have a device number different
 than that of the file from which the descent began.
+.Pp
+This option is equivalent to the deprecated
+.Ic -xdev
+primary.
 .El
 .Sh PRIMARIES
 .Bl -tag -width indent
+.It Ic -Bmin Ar n
+True if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started, rounded up to the next full minute, is
+.Ar n
+minutes.
+.It Ic -Bnewer Ar file
+Same as
+.Ic -newerBm .
+.It Ic -Btime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
+.\" .It Ic -acl
+.\" May be used in conjunction with other options to locate
+.\" files with extended ACLs.
+.\" See
+.\" .Xr acl 3
+.\" for more information.
 .It Ic -amin Ar n
 True if the difference between the file last access time and the time
 .Nm
@@ -170,12 +224,44 @@ minutes.
 .It Ic -anewer Ar file
 Same as
 .Ic -neweram .
-.It Ic -atime Ar n
-True if the difference between the file last access time and the time
+.It Ic -atime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the file last access time and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the file last access time and the time
 .Nm
-was started, rounded up to the next full 24\-hour period, is
+was started is exactly
 .Ar n
-24\-hour periods.
+units.
+Possible time units are as follows:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm s
+second
+.It Cm m
+minute (60 seconds)
+.It Cm h
+hour (60 minutes)
+.It Cm d
+day (24 hours)
+.It Cm w
+week (7 days)
+.El
+.Pp
+Any number of units may be combined in one
+.Ic -atime
+argument, for example,
+.Dq Li "-atime -1h30m" .
+Units are probably only useful when used in conjunction with the
+.Cm +
+or
+.Cm -
+modifier.
 .It Ic -cmin Ar n
 True if the difference between the time of last change of file status
 information and the time
@@ -186,13 +272,25 @@ minutes.
 .It Ic -cnewer Ar file
 Same as
 .Ic -newercm .
-.It Ic -ctime Ar n
-True if the difference between the time of last change of file status
+.It Ic -ctime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the time of last change of file status
 information and the time
 .Nm
-was started, rounded up to the next full 24\-hour period, is
+was started, rounded up to the next full 24-hour period, is
 .Ar n
-24\-hour periods.
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the time of last change of file status
+information and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
 .It Ic -delete
 Delete found files and/or directories.
 Always returns true.
@@ -205,23 +303,19 @@ It will not attempt to delete a filename with a
 character in its pathname relative to
 .Dq Pa \&.
 for security reasons.
-Depth\-first traversal processing is implied by this option.
+Depth-first traversal processing is implied by this option.
 .It Ic -depth
 Always true;
 same as the
 .Fl d
 option.
-.Ic -depth
-can be useful when
-.Nm
-is used with
-.Xr cpio 1
-to process files that are contained in directories with unusual permissions.
-It enures that you have write permission while you are placing files in a
-directory, then sets the directory's permissions as the last thing.
+.It Ic -depth Ar n
+True if the depth of the file relative to the starting point of the traversal
+is
+.Ar n .
 .It Ic -empty
 True if the current file or directory is empty.
-.It Ic -exec Ar utility Op Ar argument ... ;
+.It Ic -exec Ar utility Oo Ar argument ... Oc Li \&;
 True if the program named
 .Ar utility
 returns a zero value as its exit status.
@@ -230,6 +324,10 @@ Optional
 may be passed to the utility.
 The expression must be terminated by a semicolon
 .Pq Dq Li \&; .
+If you invoke
+.Nm
+from a shell you may need to quote the semicolon if the shell would
+otherwise treat it as a control operator.
 If the string
 .Dq Li {}
 appears anywhere in the utility name or the
@@ -243,7 +341,16 @@ and
 .Ar arguments
 are not subject to the further expansion of shell patterns
 and constructs.
-.It Ic -execdir Ar utility Op Ar argument ... ;
+.It Ic -exec Ar utility Oo Ar argument ... Oc Li {} +
+Same as
+.Ic -exec ,
+except that
+.Dq Li {}
+is replaced with as many pathnames as possible for each invocation of
+.Ar utility .
+This behaviour is similar to that of
+.Xr xargs 1 .
+.It Ic -execdir Ar utility Oo Ar argument ... Oc Li \&;
 The
 .Ic -execdir
 primary is identical to the
@@ -305,7 +412,7 @@ True if the file is contained in a file system of type
 .Ar type .
 The
 .Xr sysctl 8
-command can be used to find out the types of filesystems
+command can be used to find out the types of file systems
 that are available on the system:
 .Pp
 .Dl "sysctl vfs"
@@ -349,11 +456,11 @@ links.
 .It Ic -ls
 This primary always evaluates to true.
 The following information for the current file is written to standard output:
-its inode number, size in 512\-byte blocks, file permissions, number of hard
+its inode number, size in 512-byte blocks, file permissions, number of hard
 links, owner, group, size in bytes, last modification time, and pathname.
 If the file is a block or character special file, the major and minor numbers
 will be displayed instead of the size in bytes.
-If the file is a symbolic link, the pathname of the linked\-to file will be
+If the file is a symbolic link, the pathname of the linked-to file will be
 displayed preceded by
 .Dq Li -> .
 The format is identical to that produced by
@@ -361,11 +468,24 @@ The format is identical to that produced by
 .Nm ls Fl dgils .
 .Ek
 .It Ic -maxdepth Ar n
-True if the depth of the current file into the tree is less than or equal to
-.Ar n .
+Always true; descend at most
+.Ar n
+directory levels below the command line arguments.
+If any
+.Ic -maxdepth
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
+.Ic -maxdepth Li 0
+limits the whole search to the command line arguments.
 .It Ic -mindepth Ar n
-True if the depth of the current file into the tree is greater than or equal to
+Always true; do not apply any tests or actions at levels less than
 .Ar n .
+If any
+.Ic -mindepth
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
+.Ic -mindepth Li 1
+processes all but the command line arguments.
 .It Ic -mmin Ar n
 True if the difference between the file last modification time and the time
 .Nm
@@ -375,12 +495,23 @@ minutes.
 .It Ic -mnewer Ar file
 Same as
 .Ic -newer .
-.It Ic -mtime Ar n
-True if the difference between the file last modification time and the time
+.It Ic -mtime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the file last modification time and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the file last modification time and the time
 .Nm
-was started, rounded up to the next full 24\-hour period, is
+was started is exactly
 .Ar n
-24\-hour periods.
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
 .It Ic -name Ar pattern
 True if the last component of the pathname being examined matches
 .Ar pattern .
@@ -401,12 +532,16 @@ True if the current file has a more recent last modification time than
 .It Ic -newer Ns Ar X Ns Ar Y Ar file
 True if the current file has a more recent last access time
 .Ar ( X Ns = Ns Cm a ) ,
+inode creation time
+.Ar ( X Ns = Ns Cm B ) ,
 change time
 .Ar ( X Ns = Ns Cm c ) ,
 or modification time
 .Ar ( X Ns = Ns Cm m )
 than the last access time
 .Ar ( Y Ns = Ns Cm a ) ,
+inode creation time
+.Ar ( Y Ns = Ns Cm B ) ,
 change time
 .Ar ( Y Ns = Ns Cm c ) ,
 or modification time
@@ -428,7 +563,7 @@ is equivalent to
 True if the file belongs to an unknown group.
 .It Ic -nouser
 True if the file belongs to an unknown user.
-.It Ic -ok Ar utility Op Ar argument ... ;
+.It Ic -ok Ar utility Oo Ar argument ... Oc Li \&;
 The
 .Ic -ok
 primary is identical to the
@@ -439,13 +574,16 @@ requests user affirmation for the execution of the
 .Ar utility
 by printing
 a message to the terminal and reading a response.
-If the response is other than
-.Dq Li y
+If the response is not affirmative
+.Ql ( y
+in the
+.Dq Li POSIX
+locale),
 the command is not executed and the
 value of the
 .Ic -ok
 expression is false.
-.It Ic -okdir Ar utility Op Ar argument ... ;
+.It Ic -okdir Ar utility Oo Ar argument ... Oc Li \&;
 The
 .Ic -okdir
 primary is identical to the
@@ -515,7 +653,8 @@ Note, the first character of a symbolic mode may not be a dash
 This primary always evaluates to true.
 It prints the pathname of the current file to standard output.
 If none of
-.Ic -exec , -ls , -print0 ,
+.\" 4772561
+.Ic -exec , -ls , -print , -print0 ,
 or
 .Ic -ok
 is specified, the given expression shall be effectively replaced by
@@ -523,7 +662,8 @@ is specified, the given expression shall be effectively replaced by
 .It Ic -print0
 This primary always evaluates to true.
 It prints the pathname of the current file to standard output, followed by an
-.Tn ASCII NUL
+.Tn ASCII
+.Dv NUL
 character (character code 0).
 .It Ic -prune
 This primary always evaluates to true.
@@ -549,8 +689,8 @@ but not
 .Dq Li xyzzy
 or
 .Dq Li /foo/ .
-.It Ic -size Ar n Ns Op Cm c
-True if the file's size, rounded up, in 512\-byte blocks is
+.It Ic -size Ar n Ns Op Cm ckMGTP
+True if the file's size, rounded up, in 512-byte blocks is
 .Ar n .
 If
 .Ar n
@@ -560,6 +700,25 @@ then the primary is true if the
 file's size is
 .Ar n
 bytes (characters).
+Similarly if
+.Ar n
+is followed by a scale indicator then the file's size is compared to
+.Ar n
+scaled as:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm k
+kilobytes (1024 bytes)
+.It Cm M
+megabytes (1024 kilobytes)
+.It Cm G
+gigabytes (1024 megabytes)
+.It Cm T
+terabytes (1024 gigabytes)
+.It Cm P
+petabytes (1024 terabytes)
+.El
+.Pp
 .It Ic -type Ar t
 True if the file is of the specified type.
 Possible file types are as follows:
@@ -610,7 +769,7 @@ The operators are listed in order of decreasing precedence.
 This evaluates to true if the parenthesized expression evaluates to
 true.
 .Pp
-.It Cm \&! Ar expression 
+.It Cm \&! Ar expression
 .It Cm -false Ar expression
 .It Cm -not Ar expression
 This is the unary
@@ -646,6 +805,15 @@ All operands and primaries must be separate arguments to
 Primaries which themselves take arguments expect each argument
 to be a separate argument to
 .Nm .
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_COLLATE , LC_CTYPE , LC_MESSAGES
+and
+.Ev LC_TIME
+environment variables affect the execution of the
+.Nm
+utility as described in
+.Xr environ 7 .
 .Sh EXAMPLES
 The following examples are shown as given to the shell:
 .Bl -tag -width indent
@@ -668,10 +836,34 @@ Print out a list of all the files that are either owned by
 .Dq wnj
 or that are newer than
 .Pa ttt .
-.It Li "find . -newerct '1 minute ago' -print"
+.It Li "find / -newerct '1 minute ago' -print"
 Print out a list of all the files whose inode change time is more
 recent than the current time minus one minute.
+.It Li "find / -type f -exec echo {} \e;"
+Use the
+.Xr echo 1
+command to print out a list of all the files.
+.It Li "find -L /usr/ports/packages -type l -delete"
+Delete all broken symbolic links in
+.Pa /usr/ports/packages .
+.It Li "find /usr/src -name CVS -prune -o -depth +6 -print"
+Find files and directories that are at least seven levels deep
+in the working directory
+.Pa /usr/src .
+.It Li "find /usr/src -name CVS -prune -o -mindepth 7 -print"
+Is not equivalent to the previous example, since
+.Ic -prune
+is not evaluated below level seven.
 .El
+.Sh COMPATIBILITY
+The
+.Ic -follow
+primary is deprecated; the
+.Fl L
+option should be used instead.
+See the
+.Sx STANDARDS
+section below for details.
 .Sh SEE ALSO
 .Xr chflags 1 ,
 .Xr chmod 1 ,
@@ -679,7 +871,9 @@ recent than the current time minus one minute.
 .Xr locate 1 ,
 .Xr whereis 1 ,
 .Xr which 1 ,
+.Xr xargs 1 ,
 .Xr stat 2 ,
+.\" .Xr acl 3 ,
 .Xr fts 3 ,
 .Xr getgrent 3 ,
 .Xr getpwent 3 ,
@@ -690,18 +884,24 @@ recent than the current time minus one minute.
 The
 .Nm
 utility syntax is a superset of the syntax specified by the
-.St -p1003.2
+.St -p1003.1-2001
 standard.
 .Pp
-All the single character options as well as the
-.Ic -iname , -inum , -iregex , -print0 , -delete , -ls ,
+All the single character options except
+.Ic -H
 and
-.Ic -regex
-primaries are extensions to
-.St -p1003.2 .
+.Ic -L
+as well as
+.Ic -amin , -anewer , -cmin , -cnewer , -delete , -empty , -fstype ,
+.Ic -iname , -inum , -iregex , -ls , -maxdepth , -mindepth , -mmin ,
+.Ic -path , -print0 , -regex
+and all of the
+.Ic -B
+birthtime related primaries are extensions to
+.St -p1003.1-2001 .
 .Pp
 Historically, the
-.Fl d , h
+.Fl d , L
 and
 .Fl x
 options were implemented using the primaries
@@ -743,10 +943,16 @@ it appears.
 .Pp
 The
 .Fl E
-option was implemented on the analogy of
+option was inspired by the equivalent
 .Xr grep 1
 and
-.Xr sed 1 .
+.Xr sed 1
+options.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
 .Sh BUGS
 The special characters used by
 .Nm
@@ -780,10 +986,13 @@ construct.
 .Pp
 The
 .Ic -delete
-primary does not interact well with other options that cause the filesystem
+primary does not interact well with other options that cause the file system
 tree traversal options to be changed.
-.Sh HISTORY
-A
-.Nm
-command appeared in
-.At v1 .
+.Pp
+The
+.Ic -mindepth
+and
+.Ic -maxdepth
+primaries are actually global options (as documented above).
+They should
+probably be replaced by options which look like options.
index 9f5db7d1c62049d55dda28d78193bb88ff66bf5a..35f800664aded9b3a074be559cc8bbad7154ad82 100644 (file)
 #if 0
 static char sccsid[] = "@(#)find.c     8.5 (Berkeley) 8/5/94";
 #else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/find.c,v 1.7.6.3 2001/05/06 09:53:22 phk Exp $";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/find.c,v 1.18 2006/05/14 20:23:00 krion Exp $");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -51,19 +52,19 @@ static const char rcsid[] =
 #include <fts.h>
 #include <regex.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
 
 #ifdef __APPLE__
-#include "get_compat.h"
+#include <get_compat.h>
+#include <unistd.h>
 #else
 #define COMPAT_MODE(func, mode) 1
 #endif
 
 #include "find.h"
 
-static int     find_compare __P((const FTSENT **s1, const FTSENT **s2));
+static int find_compare(const FTSENT * const *s1, const FTSENT * const *s2);
 
 /*
  * find_compare --
@@ -72,8 +73,7 @@ static int    find_compare __P((const FTSENT **s1, const FTSENT **s2));
  *     order within each directory.
  */
 static int
-find_compare(s1, s2)
-       const FTSENT **s1, **s2;
+find_compare(const FTSENT * const *s1, const FTSENT * const *s2)
 {
 
        return (strcoll((*s1)->fts_name, (*s2)->fts_name));
@@ -85,8 +85,7 @@ find_compare(s1, s2)
  *     command arguments.
  */
 PLAN *
-find_formplan(argv)
-       char **argv;
+find_formplan(char *argv[])
 {
        PLAN *plan, *tail, *new;
 
@@ -124,23 +123,23 @@ find_formplan(argv)
         */
        if (!isoutput) {
                OPTION *p;
-               char **argv = 0;
+               char **argv1 = 0;
 
                if (plan == NULL) {
-                       p = option("-print");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("-print");
+                       new = (p->create)(p, &argv1);
                        tail = plan = new;
                } else {
-                       p = option("(");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("(");
+                       new = (p->create)(p, &argv1);
                        new->next = plan;
                        plan = new;
-                       p = option(")");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option(")");
+                       new = (p->create)(p, &argv1);
                        tail->next = new;
                        tail = new;
-                       p = option("-print");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("-print");
+                       new = (p->create)(p, &argv1);
                        tail->next = new;
                        tail = new;
                }
@@ -207,16 +206,14 @@ FTS *tree;                        /* pointer to top of FTS hierarchy */
  *     over all FTSENT's returned for the given search paths.
  */
 int
-find_execute(plan, paths)
-       PLAN *plan;             /* search plan */
-       char **paths;           /* array of pathnames to traverse */
+find_execute(PLAN *plan, char *paths[])
 {
-       register FTSENT *entry;
+       FTSENT *entry;
        PLAN *p;
        int rval;
-       char    **myPaths;
-       int     nonSearchableDirFound = 0;
-       int                     pathIndex;
+       char **myPaths;
+       int nonSearchableDirFound = 0;
+       int pathIndex;
        struct stat statInfo;
 
        /* special-case directories specified on command line - explicitly examine
@@ -265,6 +262,11 @@ find_execute(plan, paths)
                err(1, "ftsopen");
 
        for (rval = nonSearchableDirFound; (entry = fts_read(tree)) != NULL;) {
+               if (maxdepth != -1 && entry->fts_level >= maxdepth) {
+                       if (fts_set(tree, entry, FTS_SKIP))
+                               err(1, "%s", entry->fts_path);
+               }
+
                switch (entry->fts_info) {
                case FTS_D:
                        if (isdepth)
@@ -304,20 +306,11 @@ find_execute(plan, paths)
                 * the work specified by the user on the command line.
                 */
                for (p = plan; p && (p->execute)(p, entry); p = p->next);
-
-               if (maxdepth != -1 && entry->fts_level >= maxdepth) {
-                       if (fts_set(tree, entry, FTS_SKIP))
-                       err(1, "%s", entry->fts_path);
-                       continue;
-               }
        }
+       free (myPaths);
+       finish_execplus();
        if (errno)
                err(1, "fts_read");
-
-       for (p = plan; p; p = p->next) {
-           if (p->flags & F_CLEANUP) (p->execute)(p, NULL);
-       }
-
-       free (myPaths);
+       fts_close(tree);
        return (rval);
 }
index 24eaa55542f0f8e1bead9fbf7716010540a24ae9..6a8bc437f129dd90a4426a907e705a003c04c9a9 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)find.h      8.1 (Berkeley) 6/6/93
- *     $FreeBSD: src/usr.bin/find/find.h,v 1.6.2.6 2001/09/19 09:44:24 ru Exp $
+ *     $FreeBSD: src/usr.bin/find/find.h,v 1.19 2006/05/14 20:23:01 krion Exp $
  */
 
 #include <regex.h>
@@ -44,7 +44,7 @@ struct _plandata;
 struct _option;
 
 /* execute function */
-typedef int exec_f __P((struct _plandata *, FTSENT *));
+typedef int exec_f(struct _plandata *, FTSENT *);
 /* create function */
 typedef        struct _plandata *creat_f(struct _option *, char ***);
 
@@ -57,6 +57,7 @@ typedef       struct _plandata *creat_f(struct _option *, char ***);
 #define        F_TIME2_C       0x00000020      /* one of -newer?c */
 #define        F_TIME2_T       0x00000040      /* one of -newer?t */
 #define F_MAXDEPTH     F_TIME_A        /* maxdepth vs. mindepth */
+#define F_DEPTH                F_TIME_A        /* -depth n vs. -d */
 /* command line function modifiers */
 #define        F_EQUAL         0x00000000      /* [acm]min [acm]time inum links size */
 #define        F_LESSTHAN      0x00000100
@@ -67,8 +68,12 @@ typedef      struct _plandata *creat_f(struct _option *, char ***);
 #define        F_MTMASK        0x00003000
 #define        F_MTFLAG        0x00000000      /* fstype */
 #define        F_MTTYPE        0x00001000
+#define        F_MTUNKNOWN     0x00002000
 #define        F_IGNCASE       0x00010000      /* iname ipath iregex */
-#define F_CLEANUP      0x00020000      /* need an extra cleanup call at the end*/
+#define        F_EXACTTIME     F_IGNCASE       /* -[acm]time units syntax */
+#define F_EXECPLUS     0x00020000      /* -exec ... {} + */
+#define        F_TIME_B        0x00040000      /* one of -Btime, -Bnewer, -newerB* */
+#define        F_TIME2_B       0x00080000      /* one of -newer?B */
 
 /* node definition */
 typedef struct _plandata {
@@ -84,6 +89,7 @@ typedef struct _plandata {
                        u_long _f_notflags;
                } fl;
                nlink_t _l_data;                /* link count */
+               short _d_data;                  /* level depth (-1 to N) */
                off_t _o_data;                  /* file size */
                time_t _t_data;                 /* time value */
                uid_t _u_data;                  /* uid */
@@ -93,6 +99,13 @@ typedef struct _plandata {
                        char **_e_argv;         /* argv array */
                        char **_e_orig;         /* original strings */
                        int *_e_len;            /* allocated length */
+                       int _e_pbnum;           /* base num. of args. used */
+                       int _e_ppos;            /* number of arguments used */
+                       int _e_pnummax;         /* max. number of arguments */
+                       int _e_psize;           /* number of bytes of args. */
+                       int _e_pbsize;          /* base num. of bytes of args */
+                       int _e_psizemax;        /* max num. of bytes of args */
+                       struct _plandata *_e_next;/* next F_EXECPLUS in tree */
                } ex;
                char *_a_data[2];               /* array of char pointers */
                char *_c_data;                  /* char pointer */
@@ -101,6 +114,7 @@ typedef struct _plandata {
 } PLAN;
 #define        a_data  p_un._a_data
 #define        c_data  p_un._c_data
+#define        d_data  p_un._d_data
 #define fl_flags       p_un.fl._f_flags
 #define fl_notflags    p_un.fl._f_notflags
 #define        g_data  p_un._g_data
@@ -116,9 +130,16 @@ typedef struct _plandata {
 #define        e_argv  p_un.ex._e_argv
 #define        e_orig  p_un.ex._e_orig
 #define        e_len   p_un.ex._e_len
+#define e_pbnum        p_un.ex._e_pbnum
+#define e_ppos p_un.ex._e_ppos
+#define e_pnummax p_un.ex._e_pnummax
+#define e_psize p_un.ex._e_psize
+#define e_pbsize p_un.ex._e_pbsize
+#define e_psizemax p_un.ex._e_psizemax
+#define e_next p_un.ex._e_next
 
 typedef struct _option {
-       char *name;                     /* option name */
+       const char *name;               /* option name */
        creat_f *create;                /* create function */
        exec_f *execute;                /* execute function */
        int flags;
index eb2c65ad5baf823cff5cb1d71e4f1863661ebc41..0e6028e9b8cf046b5acf0c3e828f5abc16e818df 100644 (file)
 
 #ifndef lint
 #if 0
-static const char sccsid[] = "@(#)function.c  8.10 (Berkeley) 5/4/95";
-#else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/function.c,v 1.22.2.9 2001/09/19 09:44:24 ru Exp $";
+static const char sccsid[] = "@(#)function.c   8.10 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.58 2006/05/27 18:27:41 krion Exp $");
+
 #include <sys/param.h>
 #include <sys/ucred.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/acl.h>
 #include <sys/wait.h>
 #include <sys/mount.h>
 #include <sys/timeb.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
 
 #include <dirent.h>
 #include <err.h>
@@ -58,24 +58,34 @@ static const char rcsid[] =
 #include <fnmatch.h>
 #include <fts.h>
 #include <grp.h>
+#include <limits.h>
 #include <pwd.h>
 #include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include "find.h"
 
 #ifdef __APPLE__
-#include "get_compat.h"
+#include <sys/sysctl.h>
+#include <get_compat.h>
 #else
 #define COMPAT_MODE(func, mode) 1
 #endif
 
-time_t get_date __P((char *date, struct timeb *now));
+static PLAN *palloc(OPTION *);
+static long long find_parsenum(PLAN *, const char *, char *, char *);
+static long long find_parsetime(PLAN *, const char *, char *);
+static char *nextarg(OPTION *, char ***);
+
+extern char **environ;
+
+static PLAN *lastexecplus = NULL;
 
-#define        COMPARE(a, b) {                                                 \
+#define        COMPARE(a, b) do {                                              \
        switch (plan->flags & F_ELG_MASK) {                             \
        case F_EQUAL:                                                   \
                return (a == b);                                        \
@@ -86,11 +96,10 @@ time_t get_date __P((char *date, struct timeb *now));
        default:                                                        \
                abort();                                                \
        }                                                               \
-}
+} while(0)
 
 static PLAN *
-palloc(option)
-       OPTION *option;
+palloc(OPTION *option)
 {
        PLAN *new;
 
@@ -107,9 +116,7 @@ palloc(option)
  *     Parse a string of the form [+-]# and return the value.
  */
 static long long
-find_parsenum(plan, option, vp, endch)
-       PLAN *plan;
-       char *option, *vp, *endch;
+find_parsenum(PLAN *plan, const char *option, char *vp, char *endch)
 {
        long long value;
        char *endchar, *str;    /* Pointer to character ending conversion. */
@@ -138,22 +145,94 @@ find_parsenum(plan, option, vp, endch)
        value = strtoq(str, &endchar, 10);
        if (value == 0 && endchar == str)
                errx(1, "%s: %s: illegal numeric value", option, vp);
-       if (endchar[0] && (endch == NULL || endchar[0] != *endch))
+       if (endchar[0] && endch == NULL)
                errx(1, "%s: %s: illegal trailing character", option, vp);
        if (endch)
                *endch = endchar[0];
        return value;
 }
 
+/*
+ * find_parsetime --
+ *     Parse a string of the form [+-]([0-9]+[smhdw]?)+ and return the value.
+ */
+static long long
+find_parsetime(PLAN *plan, const char *option, char *vp)
+{
+       long long secs, value;
+       char *str, *unit;       /* Pointer to character ending conversion. */
+
+       /* Determine comparison from leading + or -. */
+       str = vp;
+       switch (*str) {
+       case '+':
+               ++str;
+               plan->flags |= F_GREATER;
+               break;
+       case '-':
+               ++str;
+               plan->flags |= F_LESSTHAN;
+               break;
+       default:
+               plan->flags |= F_EQUAL;
+               break;
+       }
+
+       value = strtoq(str, &unit, 10);
+       if (value == 0 && unit == str) {
+               errx(1, "%s: %s: illegal time value", option, vp);
+               /* NOTREACHED */
+       }
+       if (*unit == '\0')
+               return value;
+
+       /* Units syntax. */
+       secs = 0;
+       for (;;) {
+               switch(*unit) {
+               case 's':       /* seconds */
+                       secs += value;
+                       break;
+               case 'm':       /* minutes */
+                       secs += value * 60;
+                       break;
+               case 'h':       /* hours */
+                       secs += value * 3600;
+                       break;
+               case 'd':       /* days */
+                       secs += value * 86400;
+                       break;
+               case 'w':       /* weeks */
+                       secs += value * 604800;
+                       break;
+               default:
+                       errx(1, "%s: %s: bad unit '%c'", option, vp, *unit);
+                       /* NOTREACHED */
+               }
+               str = unit + 1;
+               if (*str == '\0')       /* EOS */
+                       break;
+               value = strtoq(str, &unit, 10);
+               if (value == 0 && unit == str) {
+                       errx(1, "%s: %s: illegal time value", option, vp);
+                       /* NOTREACHED */
+               }
+               if (*unit == '\0') {
+                       errx(1, "%s: %s: missing trailing unit", option, vp);
+                       /* NOTREACHED */
+               }
+       }
+       plan->flags |= F_EXACTTIME;
+       return secs;
+}
+
 /*
  * nextarg --
  *     Check that another argument still exists, return a pointer to it,
  *     and increment the argument vector pointer.
  */
 static char *
-nextarg(option, argvp)
-       OPTION *option;
-       char ***argvp;
+nextarg(OPTION *option, char ***argvp)
 {
        char *arg;
 
@@ -164,10 +243,10 @@ nextarg(option, argvp)
 } /* nextarg() */
 
 /*
- * The value of n for the inode times (atime, ctime, and mtime) is a range,
- * i.e. n matches from (n - 1) to n 24 hour periods.  This interacts with
- * -n, such that "-mtime -1" would be less than 0 days, which isn't what the
- * user wanted.  Correct so that -1 is "less than 1".
+ * The value of n for the inode times (atime, birthtime, ctime, mtime) is a
+ * range, i.e. n matches from (n - 1) to n 24 hour periods.  This interacts
+ * with -n, such that "-mtime -1" would be less than 0 days, which isn't what
+ * the user wanted.  Correct so that -1 is "less than 1".
  */
 #define        TIME_CORRECT(p) \
        if (((p)->flags & F_ELG_MASK) == F_LESSTHAN) \
@@ -178,23 +257,23 @@ nextarg(option, argvp)
  *
  *    True if the difference between the
  *             file access time (-amin)
+ *             file birth time (-Bmin)
  *             last change of file status information (-cmin)
  *             file modification time (-mmin)
  *    and the current time is n min periods.
  */
 int
-f_Xmin(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_Xmin(PLAN *plan, FTSENT *entry)
 {
-       extern time_t now;
-
        if (plan->flags & F_TIME_C) {
                COMPARE((now - entry->fts_statp->st_ctime +
                    60 - 1) / 60, plan->t_data);
        } else if (plan->flags & F_TIME_A) {
                COMPARE((now - entry->fts_statp->st_atime +
                    60 - 1) / 60, plan->t_data);
+       } else if (plan->flags & F_TIME_B) {
+               COMPARE((now - entry->fts_statp->st_birthtime +
+                   60 - 1) / 60, plan->t_data);
        } else {
                COMPARE((now - entry->fts_statp->st_mtime +
                    60 - 1) / 60, plan->t_data);
@@ -202,9 +281,7 @@ f_Xmin(plan, entry)
 }
 
 PLAN *
-c_Xmin(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_Xmin(OPTION *option, char ***argvp)
 {
        char *nmins;
        PLAN *new;
@@ -223,46 +300,45 @@ c_Xmin(option, argvp)
  *
  *     True if the difference between the
  *             file access time (-atime)
+ *             file birth time (-Btime)
  *             last change of file status information (-ctime)
  *             file modification time (-mtime)
  *     and the current time is n 24 hour periods.
  */
 
 int
-f_Xtime(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_Xtime(PLAN *plan, FTSENT *entry)
 {
-       extern time_t now;
-
-       int fudge = COMPAT_MODE("bin/find", "unix2003") ? 0 : 86400 - 1;
+       time_t xtime;
+
+       if (plan->flags & F_TIME_A)
+               xtime = entry->fts_statp->st_atime;
+       else if (plan->flags & F_TIME_B)
+               xtime = entry->fts_statp->st_birthtime;
+       else if (plan->flags & F_TIME_C)
+               xtime = entry->fts_statp->st_ctime;
+       else
+               xtime = entry->fts_statp->st_mtime;
 
-       if (plan->flags & F_TIME_C) {
-               COMPARE((now - entry->fts_statp->st_ctime +
-                   fudge) / 86400, plan->t_data);
-       } else if (plan->flags & F_TIME_A) {
-               COMPARE((now - entry->fts_statp->st_atime +
-                   fudge) / 86400, plan->t_data);
-       } else {
-               COMPARE((now - entry->fts_statp->st_mtime +
-                   fudge) / 86400, plan->t_data);
-       }
+       if (COMPAT_MODE("bin/find", "unix2003") || plan->flags & F_EXACTTIME)
+               COMPARE((now - xtime) / 86400, plan->t_data);
+       else
+               COMPARE((now - xtime + 86400 - 1) / 86400, plan->t_data);
 }
 
 PLAN *
-c_Xtime(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_Xtime(OPTION *option, char ***argvp)
 {
-       char *ndays;
+       char *value;
        PLAN *new;
 
-       ndays = nextarg(option, argvp);
+       value = nextarg(option, argvp);
        ftsoptions &= ~FTS_NOSTAT;
 
        new = palloc(option);
-       new->t_data = find_parsenum(new, option->name, ndays, NULL);
-       TIME_CORRECT(new);
+       new->t_data = find_parsetime(new, option->name, value);
+       if (!(new->flags & F_EXACTTIME))
+               TIME_CORRECT(new);
        return new;
 }
 
@@ -276,9 +352,7 @@ c_Xtime(option, argvp)
  *        find_execute() so their f_* functions are set to f_always_true().
  */
 PLAN *
-c_mXXdepth(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_mXXdepth(OPTION *option, char ***argvp)
 {
        char *dstr;
        PLAN *new;
@@ -296,15 +370,64 @@ c_mXXdepth(option, argvp)
        return new;
 }
 
+#ifndef __APPLE__
+/*
+ * -acl function --
+ *
+ *     Show files with EXTENDED ACL attributes.
+ */
+int
+f_acl(PLAN *plan __unused, FTSENT *entry)
+{
+       int match, entries;
+       acl_entry_t ae;
+       acl_t facl;
+
+       if (S_ISLNK(entry->fts_statp->st_mode))
+               return 0;
+       if ((match = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED)) <= 0) {
+               if (match < 0 && errno != EINVAL)
+                       warn("%s", entry->fts_accpath);
+       else
+               return 0;
+       }
+       match = 0;
+       if ((facl = acl_get_file(entry->fts_accpath,ACL_TYPE_ACCESS)) != NULL) {
+               if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) {
+                       /*
+                        * POSIX.1e requires that ACLs of type ACL_TYPE_ACCESS
+                        * must have at least three entries (owner, group,
+                        * other).
+                        */
+                       entries = 1;
+                       while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1) {
+                               if (++entries > 3) {
+                                       match = 1;
+                                       break;
+                               }
+                       }
+               }
+               acl_free(facl);
+       } else
+               warn("%s", entry->fts_accpath);
+       return match;
+}
+
+PLAN *
+c_acl(OPTION *option, char ***argvp __unused)
+{
+       ftsoptions &= ~FTS_NOSTAT;
+       return (palloc(option));
+}
+#endif /* !__APPLE__ */
+
 /*
  * -delete functions --
  *
  *     True always.  Makes its best shot and continues on regardless.
  */
 int
-f_delete(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_delete(PLAN *plan __unused, FTSENT *entry)
 {
        /* ignore these from fts */
        if (strcmp(entry->fts_accpath, ".") == 0 ||
@@ -344,9 +467,7 @@ f_delete(plan, entry)
 }
 
 PLAN *
-c_delete(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_delete(OPTION *option, char ***argvp __unused)
 {
 
        ftsoptions &= ~FTS_NOSTAT;      /* no optimise */
@@ -360,39 +481,72 @@ c_delete(option, argvp)
 
 
 /*
- * -depth functions --
+ * always_true --
  *
- *     Always true, causes descent of the directory hierarchy to be done
- *     so that all entries in a directory are acted on before the directory
- *     itself.
+ *     Always true, used for -maxdepth, -mindepth, -xdev and -follow
  */
 int
-f_always_true(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_always_true(PLAN *plan __unused, FTSENT *entry __unused)
 {
        return 1;
 }
 
+/*
+ * -depth functions --
+ *
+ *     With argument: True if the file is at level n.
+ *     Without argument: Always true, causes descent of the directory hierarchy
+ *     to be done so that all entries in a directory are acted on before the
+ *     directory itself.
+ */
+int
+f_depth(PLAN *plan, FTSENT *entry)
+{
+       if (plan->flags & F_DEPTH)
+               COMPARE(entry->fts_level, plan->d_data);
+       else
+               return 1;
+}
+
 PLAN *
-c_depth(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_depth(OPTION *option, char ***argvp)
 {
-       isdepth = 1;
+       PLAN *new;
+       char *str;
 
-       return palloc(option);
-}
+       new = palloc(option);
+
+       str = **argvp;
+       if (str && !(new->flags & F_DEPTH)) {
+               /* skip leading + or - */
+               if (*str == '+' || *str == '-')
+                       str++;
+               /* skip sign */
+               if (*str == '+' || *str == '-')
+                       str++;
+               if (isdigit(*str))
+                       new->flags |= F_DEPTH;
+       }
 
+       if (new->flags & F_DEPTH) {     /* -depth n */
+               char *ndepth;
+
+               ndepth = nextarg(option, argvp);
+               new->d_data = find_parsenum(new, option->name, ndepth, NULL);
+       } else {                        /* -d */
+               isdepth = 1;
+       }
+
+       return new;
+}
 /*
  * -empty functions --
  *
  *     True if the file or directory is empty
  */
 int
-f_empty(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_empty(PLAN *plan __unused, FTSENT *entry)
 {
        if (S_ISREG(entry->fts_statp->st_mode) &&
            entry->fts_statp->st_size == 0)
@@ -420,9 +574,7 @@ f_empty(plan, entry)
 }
 
 PLAN *
-c_empty(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_empty(OPTION *option, char ***argvp __unused)
 {
        ftsoptions &= ~FTS_NOSTAT;
 
@@ -445,94 +597,45 @@ c_empty(option, argvp)
  *     of the user before executing the utility.
  */
 int
-f_exec(plan, entry)
-       register PLAN *plan;
-       FTSENT *entry;
+f_exec(PLAN *plan, FTSENT *entry)
 {
-       extern int dotfd;
-       register int cnt;
+       int cnt;
        pid_t pid;
        int status;
-       char *file = NULL;
-       static char **plus_path = NULL;
-       static int plus_path_cnt = 0;
-       static unsigned long exec_after = 0;
-       static unsigned long path_so_far = 0;
-       struct _ex saved_ex;
-
-       if (entry) {
-           /* XXX - if file/dir ends in '/' this will not work -- can it? */
-           if ((plan->flags & F_EXECDIR) && 
-             (file = strrchr(entry->fts_path, '/'))) {
+       char *file;
+
+       if (entry == NULL && plan->flags & F_EXECPLUS) {
+               if (plan->e_ppos == plan->e_pbnum)
+                       return (1);
+               plan->e_argv[plan->e_ppos] = NULL;
+               goto doexec;
+       }
+
+       /* XXX - if file/dir ends in '/' this will not work -- can it? */
+       if ((plan->flags & F_EXECDIR) && \
+           (file = strrchr(entry->fts_path, '/')))
                file++;
-           } else {
+       else
                file = entry->fts_path;
-           }
-
-           if (plan->flags & F_CLEANUP) {
-               plus_path = realloc(plus_path, sizeof(char *) * ++plus_path_cnt);
-               if (!plus_path) errx(1, "out of memory");
-               plus_path[plus_path_cnt -1] = strdup(file);
-               if (!plus_path[plus_path_cnt -1]) errx(1, "out of memory");
-
-               path_so_far += sizeof(char *) + strlen(file);
-
-               if (!exec_after) {
-                   size_t l = sizeof(exec_after);
-                   int rc = 
-                     sysctlbyname("kern.argmax", &exec_after, &l, NULL, NULL);
-                   if (rc < 0) {
-                       /* Something conservitave */
-                       exec_after = 16 * 1024;
-                   }
-               }
-               if (path_so_far >= exec_after) {
-                   return f_exec(plan, NULL);
-               }
 
-               return 1;
-           }
+       if (plan->flags & F_EXECPLUS) {
+               if ((plan->e_argv[plan->e_ppos] = strdup(file)) == NULL)
+                       err(1, NULL);
+               plan->e_len[plan->e_ppos] = strlen(file);
+               plan->e_psize += plan->e_len[plan->e_ppos];
+               if (++plan->e_ppos < plan->e_pnummax &&
+                   plan->e_psize < plan->e_psizemax)
+                       return (1);
+               plan->e_argv[plan->e_ppos] = NULL;
        } else {
-           if (!plus_path) return 1;
-           saved_ex = plan->p_un.ex;
-           int new_len = 0;
-           int ocnt;
-           for(cnt = 0; plan->e_argv[cnt]; ++cnt) {
-               if (plan->e_len[cnt]) {
-                   new_len += plus_path_cnt;
-               } else {
-                   new_len++;
-               }
-           }
-           new_len++;
-
-           plan->e_argv = malloc(sizeof(char *) * new_len);
-           if (!plan->e_argv) errx(1, "out of memory");
-
-           for(ocnt = cnt = 0; saved_ex._e_argv[ocnt]; ++ocnt) {
-               if (saved_ex._e_len[ocnt]) {
-                   int ppi;
-                   for(ppi = 0; ppi < plus_path_cnt; ++ppi) {
-                       plan->e_argv[cnt++] = plus_path[ppi];
-                   }
-#if 0
-                   memmove(plan->e_argv + cnt, *plus_path,
-                     sizeof(char *) * plus_path_cnt);
-                   cnt += plus_path_cnt;
-#endif
-               } else {
-                   plan->e_argv[cnt++] = saved_ex._e_argv[ocnt];
-               }
-           }
-           plan->e_argv[cnt++] = NULL;
+               for (cnt = 0; plan->e_argv[cnt]; ++cnt)
+                       if (plan->e_len[cnt])
+                               brace_subst(plan->e_orig[cnt],
+                                   &plan->e_argv[cnt], file,
+                                   plan->e_len[cnt]);
        }
 
-       if (!(plan->flags & F_CLEANUP)) for (cnt = 0; plan->e_argv[cnt]; ++cnt)
-               if (plan->e_len[cnt])
-                       brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt],
-                           file, plan->e_len[cnt]);
-
-       if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
+doexec:        if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
                return 0;
 
        /* make sure find output is interspersed correctly with subprocesses */
@@ -553,21 +656,15 @@ f_exec(plan, entry)
                warn("%s", plan->e_argv[0]);
                _exit(1);
        }
-       pid = waitpid(pid, &status, 0);
-       if (plus_path) {
-           int i;
-           for(i = 0; i < plus_path_cnt; ++i) {
-               free(plus_path[i]);
-           }
-           free(plus_path);
-           plus_path = NULL;
-           plus_path_cnt = 0;
-           plan->p_un.ex = saved_ex;
-           path_so_far = 0;
-           if (WIFEXITED(status) && WEXITSTATUS(status)) {
-               exit(WEXITSTATUS(status));
-           }
+       if (plan->flags & F_EXECPLUS) {
+               while (--plan->e_ppos >= plan->e_pbnum)
+                       free(plan->e_argv[plan->e_ppos]);
+               plan->e_ppos = plan->e_pbnum;
+               plan->e_psize = plan->e_pbsize;
        }
+       pid = waitpid(pid, &status, 0);
+       if (plan->flags & F_EXECPLUS && WIFEXITED(status) && WEXITSTATUS(status))
+               _exit(WEXITSTATUS(status));
        return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
 }
 
@@ -579,14 +676,12 @@ f_exec(plan, entry)
  *     strings, but also flags meaning that the string has to be massaged.
  */
 PLAN *
-c_exec(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_exec(OPTION *option, char ***argvp)
 {
        PLAN *new;                      /* node returned */
-       register int cnt;
-       register char **argv, **ap, *p;
-       int plus_armed = 0;
+       long argmax;
+       int cnt, i;
+       char **argv, **ap, **ep, *p;
 
        /* XXX - was in c_execdir, but seems unnecessary!?
        ftsoptions &= ~FTS_NOSTAT;
@@ -599,31 +694,56 @@ c_exec(option, argvp)
        for (ap = argv = *argvp;; ++ap) {
                if (!*ap)
                        errx(1,
-                           "%s: no terminating \";\"", option->name);
-               if (**ap == '{' && ap[0][1] == '}' && ap[0][2] == '\0') {
-                   plus_armed = COMPAT_MODE("bin/find", "unix2003");
-                   continue;
-               }
-               if (**ap == ';') {
+                           "%s: no terminating \";\" or \"+\"", option->name);
+               if (**ap == ';')
                        break;
-               }
-               if (plus_armed && **ap == '+') {
-                       new->flags |= F_CLEANUP;
+               if (**ap == '+' && ap != argv && strcmp(*(ap - 1), "{}") == 0) {
+                       new->flags |= F_EXECPLUS;
                        break;
                }
-               plus_armed = 0;
        }
 
+       if (ap == argv)
+               errx(1, "%s: no command specified", option->name);
+
        cnt = ap - *argvp + 1;
-       new->e_argv = (char **)emalloc((u_int)cnt * sizeof(char *));
-       new->e_orig = (char **)emalloc((u_int)cnt * sizeof(char *));
-       new->e_len = (int *)emalloc((u_int)cnt * sizeof(int));
+       if (new->flags & F_EXECPLUS) {
+               new->e_ppos = new->e_pbnum = cnt - 2;
+               if ((argmax = sysconf(_SC_ARG_MAX)) == -1) {
+                       warn("sysconf(_SC_ARG_MAX)");
+                       argmax = _POSIX_ARG_MAX;
+               }
+               argmax -= 1024;
+               for (ep = environ; *ep != NULL; ep++)
+                       argmax -= strlen(*ep) + 1 + sizeof(*ep);
+               argmax -= 1 + sizeof(*ep);
+               new->e_pnummax = argmax / 16;
+               argmax -= sizeof(char *) * new->e_pnummax;
+               if (argmax <= 0)
+                       errx(1, "no space for arguments");
+               new->e_psizemax = argmax;
+               new->e_pbsize = 0;
+               cnt += new->e_pnummax + 1;
+               new->e_next = lastexecplus;
+               lastexecplus = new;
+       }
+       if ((new->e_argv = malloc(cnt * sizeof(char *))) == NULL)
+               err(1, NULL);
+       if ((new->e_orig = malloc(cnt * sizeof(char *))) == NULL)
+               err(1, NULL);
+       if ((new->e_len = malloc(cnt * sizeof(int))) == NULL)
+               err(1, NULL);
 
        for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
                new->e_orig[cnt] = *argv;
+               if (new->flags & F_EXECPLUS)
+                       new->e_pbsize += strlen(*argv) + 1;
                for (p = *argv; *p; ++p)
-                       if (p[0] == '{' && p[1] == '}') {
-                               new->e_argv[cnt] = emalloc((u_int)MAXPATHLEN);
+                       if (!(new->flags & F_EXECPLUS) && p[0] == '{' &&
+                           p[1] == '}') {
+                               if ((new->e_argv[cnt] =
+                                   malloc(MAXPATHLEN)) == NULL)
+                                       err(1, NULL);
                                new->e_len[cnt] = MAXPATHLEN;
                                break;
                        }
@@ -632,16 +752,38 @@ c_exec(option, argvp)
                        new->e_len[cnt] = 0;
                }
        }
+       if (new->flags & F_EXECPLUS) {
+               new->e_psize = new->e_pbsize;
+               cnt--;
+               for (i = 0; i < new->e_pnummax; i++) {
+                       new->e_argv[cnt] = NULL;
+                       new->e_len[cnt] = 0;
+                       cnt++;
+               }
+               argv = ap;
+               goto done;
+       }
        new->e_argv[cnt] = new->e_orig[cnt] = NULL;
 
-       *argvp = argv + 1;
+done:  *argvp = argv + 1;
        return new;
 }
 
+/* Finish any pending -exec ... {} + functions. */
+void
+finish_execplus()
+{
+       PLAN *p;
+
+       p = lastexecplus;
+       while (p != NULL) {
+               (p->execute)(p, NULL);
+               p = p->e_next;
+       }
+}
+
 int
-f_flags(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_flags(PLAN *plan, FTSENT *entry)
 {
        u_long flags;
 
@@ -658,9 +800,7 @@ f_flags(plan, entry)
 }
 
 PLAN *
-c_flags(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_flags(OPTION *option, char ***argvp)
 {
        char *flags_str;
        PLAN *new;
@@ -693,9 +833,7 @@ c_flags(option, argvp)
  *     basis.
  */
 PLAN *
-c_follow(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_follow(OPTION *option, char ***argvp __unused)
 {
        ftsoptions &= ~FTS_PHYSICAL;
        ftsoptions |= FTS_LOGICAL;
@@ -709,22 +847,23 @@ c_follow(option, argvp)
  *     True if the file is of a certain type.
  */
 int
-f_fstype(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_fstype(PLAN *plan, FTSENT *entry)
 {
        static dev_t curdev;    /* need a guaranteed illegal dev value */
        static int first = 1;
        struct statfs sb;
        static int val_type, val_flags;
-       char *p, save[2];
+       char *p, save[2] = {0,0};
+
+       if ((plan->flags & F_MTMASK) == F_MTUNKNOWN)
+               return 0;
 
        /* Only check when we cross mount point. */
        if (first || curdev != entry->fts_statp->st_dev) {
                curdev = entry->fts_statp->st_dev;
 
                /*
-                * Statfs follows symlinks; find wants the link's file system,
+                * Statfs follows symlinks; find wants the link's filesystem,
                 * not where it points.
                 */
                if (entry->fts_info == FTS_SL ||
@@ -759,22 +898,19 @@ f_fstype(plan, entry)
        }
        switch (plan->flags & F_MTMASK) {
        case F_MTFLAG:
-               return (val_flags & plan->mt_data) != 0;
+               return val_flags & plan->mt_data;
        case F_MTTYPE:
-               return (val_type == plan->mt_data);
+               return val_type == plan->mt_data;
        default:
                abort();
        }
 }
 
-#if !defined(__NetBSD__)
 PLAN *
-c_fstype(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_fstype(OPTION *option, char ***argvp)
 {
        char *fsname;
-       register PLAN *new;
+       PLAN *new;
        struct vfsconf vfc;
 
        fsname = nextarg(option, argvp);
@@ -808,10 +944,14 @@ c_fstype(option, argvp)
                break;
        }
 
-       errx(1, "%s: unknown file type", fsname);
-       /* NOTREACHED */
+       /*
+        * We need to make filesystem checks for filesystems
+        * that exists but aren't in the kernel work.
+        */
+       fprintf(stderr, "Warning: Unknown filesystem type %s\n", fsname);
+       new->flags |= F_MTUNKNOWN;
+       return new;
 }
-#endif /* __NetBSD__ */
 
 /*
  * -group gname functions --
@@ -821,17 +961,13 @@ c_fstype(option, argvp)
  *     name, gname is taken as a group ID.
  */
 int
-f_group(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_group(PLAN *plan, FTSENT *entry)
 {
-       return entry->fts_statp->st_gid == plan->g_data;
+       COMPARE(entry->fts_statp->st_gid, plan->g_data);
 }
 
 PLAN *
-c_group(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_group(OPTION *option, char ***argvp)
 {
        char *gname;
        PLAN *new;
@@ -841,15 +977,19 @@ c_group(option, argvp)
        gname = nextarg(option, argvp);
        ftsoptions &= ~FTS_NOSTAT;
 
+       new = palloc(option);
        g = getgrnam(gname);
        if (g == NULL) {
+               char* cp = gname;
+               if( gname[0] == '-' || gname[0] == '+' )
+                       gname++;
                gid = atoi(gname);
                if (gid == 0 && gname[0] != '0')
                        errx(1, "%s: %s: no such group", option->name, gname);
+               gid = find_parsenum(new, option->name, cp, NULL);
        } else
                gid = g->gr_gid;
 
-       new = palloc(option);
        new->g_data = gid;
        return new;
 }
@@ -860,17 +1000,13 @@ c_group(option, argvp)
  *     True if the file has inode # n.
  */
 int
-f_inum(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_inum(PLAN *plan, FTSENT *entry)
 {
        COMPARE(entry->fts_statp->st_ino, plan->i_data);
 }
 
 PLAN *
-c_inum(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_inum(OPTION *option, char ***argvp)
 {
        char *inum_str;
        PLAN *new;
@@ -889,17 +1025,13 @@ c_inum(option, argvp)
  *     True if the file has n links.
  */
 int
-f_links(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_links(PLAN *plan, FTSENT *entry)
 {
        COMPARE(entry->fts_statp->st_nlink, plan->l_data);
 }
 
 PLAN *
-c_links(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_links(OPTION *option, char ***argvp)
 {
        char *nlinks;
        PLAN *new;
@@ -918,18 +1050,14 @@ c_links(option, argvp)
  *     Always true - prints the current entry to stdout in "ls" format.
  */
 int
-f_ls(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_ls(PLAN *plan __unused, FTSENT *entry)
 {
        printlong(entry->fts_path, entry->fts_accpath, entry->fts_statp);
        return 1;
 }
 
 PLAN *
-c_ls(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_ls(OPTION *option, char ***argvp __unused)
 {
        ftsoptions &= ~FTS_NOSTAT;
        isoutput = 1;
@@ -944,18 +1072,14 @@ c_ls(option, argvp)
  *     matches pattern using Pattern Matching Notation S3.14
  */
 int
-f_name(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_name(PLAN *plan, FTSENT *entry)
 {
        return !fnmatch(plan->c_data, entry->fts_name,
            plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
 }
 
 PLAN *
-c_name(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_name(OPTION *option, char ***argvp)
 {
        char *pattern;
        PLAN *new;
@@ -974,22 +1098,20 @@ c_name(option, argvp)
  *     file.
  */
 int
-f_newer(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_newer(PLAN *plan, FTSENT *entry)
 {
        if (plan->flags & F_TIME_C)
                return entry->fts_statp->st_ctime > plan->t_data;
        else if (plan->flags & F_TIME_A)
                return entry->fts_statp->st_atime > plan->t_data;
+       else if (plan->flags & F_TIME_B)
+               return entry->fts_statp->st_birthtime > plan->t_data;
        else
                return entry->fts_statp->st_mtime > plan->t_data;
 }
 
 PLAN *
-c_newer(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_newer(OPTION *option, char ***argvp)
 {
        char *fn_or_tspec;
        PLAN *new;
@@ -1024,17 +1146,13 @@ c_newer(option, argvp)
  *     of the getgrnam() 9.2.1 [POSIX.1] function returns NULL.
  */
 int
-f_nogroup(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_nogroup(PLAN *plan __unused, FTSENT *entry)
 {
        return group_from_gid(entry->fts_statp->st_gid, 1) == NULL;
 }
 
 PLAN *
-c_nogroup(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_nogroup(OPTION *option, char ***argvp __unused)
 {
        ftsoptions &= ~FTS_NOSTAT;
 
@@ -1048,17 +1166,13 @@ c_nogroup(option, argvp)
  *     of the getpwuid() 9.2.2 [POSIX.1] function returns NULL.
  */
 int
-f_nouser(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_nouser(PLAN *plan __unused, FTSENT *entry)
 {
        return user_from_uid(entry->fts_statp->st_uid, 1) == NULL;
 }
 
 PLAN *
-c_nouser(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_nouser(OPTION *option, char ***argvp __unused)
 {
        ftsoptions &= ~FTS_NOSTAT;
 
@@ -1072,9 +1186,7 @@ c_nouser(option, argvp)
  *     matches pattern using Pattern Matching Notation S3.14
  */
 int
-f_path(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_path(PLAN *plan, FTSENT *entry)
 {
        return !fnmatch(plan->c_data, entry->fts_path,
            plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
@@ -1090,9 +1202,7 @@ f_path(plan, entry)
  *     symbolic mode.
  */
 int
-f_perm(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_perm(PLAN *plan, FTSENT *entry)
 {
        mode_t mode;
 
@@ -1108,9 +1218,7 @@ f_perm(plan, entry)
 }
 
 PLAN *
-c_perm(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_perm(OPTION *option, char ***argvp)
 {
        char *perm;
        PLAN *new;
@@ -1125,7 +1233,7 @@ c_perm(option, argvp)
                new->flags |= F_ATLEAST;
                ++perm;
        } else if (*perm == '+') {
-               if ((set = setmode(perm +1)) != NULL) {
+               if ((set = setmode(perm + 1)) != NULL) {
                    new->flags |= F_ANY;
                    ++perm;
                    free(set);
@@ -1143,22 +1251,18 @@ c_perm(option, argvp)
 /*
  * -print functions --
  *
- *     Always true, causes the current pathame to be written to
+ *     Always true, causes the current pathname to be written to
  *     standard output.
  */
 int
-f_print(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_print(PLAN *plan __unused, FTSENT *entry)
 {
        (void)puts(entry->fts_path);
        return 1;
 }
 
 PLAN *
-c_print(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_print(OPTION *option, char ***argvp __unused)
 {
        isoutput = 1;
 
@@ -1168,13 +1272,11 @@ c_print(option, argvp)
 /*
  * -print0 functions --
  *
- *     Always true, causes the current pathame to be written to
+ *     Always true, causes the current pathname to be written to
  *     standard output followed by a NUL character
  */
 int
-f_print0(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_print0(PLAN *plan __unused, FTSENT *entry)
 {
        fputs(entry->fts_path, stdout);
        fputc('\0', stdout);
@@ -1189,12 +1291,8 @@ f_print0(plan, entry)
  *     Prune a portion of the hierarchy.
  */
 int
-f_prune(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_prune(PLAN *plan __unused, FTSENT *entry)
 {
-       extern FTS *tree;
-
        if (fts_set(tree, entry, FTS_SKIP))
                err(1, "%s", entry->fts_path);
        return 1;
@@ -1209,12 +1307,10 @@ f_prune(plan, entry)
  *     regular expression.
  */
 int
-f_regex(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_regex(PLAN *plan, FTSENT *entry)
 {
        char *str;
-       size_t len;
+       int len;
        regex_t *pre;
        regmatch_t pmatch;
        int errcode;
@@ -1244,9 +1340,7 @@ f_regex(plan, entry)
 }
 
 PLAN *
-c_regex(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_regex(OPTION *option, char ***argvp)
 {
        PLAN *new;
        char *pattern;
@@ -1276,9 +1370,7 @@ c_regex(option, argvp)
 /* c_simple covers c_prune, c_openparen, c_closeparen, c_not, c_or */
 
 PLAN *
-c_simple(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_simple(OPTION *option, char ***argvp __unused)
 {
        return palloc(option);
 }
@@ -1288,15 +1380,14 @@ c_simple(option, argvp)
  *
  *     True if the file size in bytes, divided by an implementation defined
  *     value and rounded up to the next integer, is n.  If n is followed by
- *     a c, the size is in bytes.
+ *      one of c k M G T P, the size is in bytes, kilobytes,
+ *      megabytes, gigabytes, terabytes or petabytes respectively.
  */
 #define        FIND_SIZE       512
 static int divsize = 1;
 
 int
-f_size(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_size(PLAN *plan, FTSENT *entry)
 {
        off_t size;
 
@@ -1306,13 +1397,12 @@ f_size(plan, entry)
 }
 
 PLAN *
-c_size(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_size(OPTION *option, char ***argvp)
 {
        char *size_str;
        PLAN *new;
        char endch;
+       off_t scale;
 
        size_str = nextarg(option, argvp);
        ftsoptions &= ~FTS_NOSTAT;
@@ -1320,8 +1410,38 @@ c_size(option, argvp)
        new = palloc(option);
        endch = 'c';
        new->o_data = find_parsenum(new, option->name, size_str, &endch);
-       if (endch == 'c')
+       if (endch != '\0') {
                divsize = 0;
+
+               switch (endch) {
+               case 'c':                       /* characters */
+                       scale = 0x1LL;
+                       break;
+               case 'k':                       /* kilobytes 1<<10 */
+                       scale = 0x400LL;
+                       break;
+               case 'M':                       /* megabytes 1<<20 */
+                       scale = 0x100000LL;
+                       break;
+               case 'G':                       /* gigabytes 1<<30 */
+                       scale = 0x40000000LL;
+                       break;
+               case 'T':                       /* terabytes 1<<40 */
+                       scale = 0x1000000000LL;
+                       break;
+               case 'P':                       /* petabytes 1<<50 */
+                       scale = 0x4000000000000LL;
+                       break;
+               default:
+                       errx(1, "%s: %s: illegal trailing character",
+                               option->name, size_str);
+                       break;
+               }
+               if (new->o_data > QUAD_MAX / scale)
+                       errx(1, "%s: %s: value too large",
+                               option->name, size_str);
+               new->o_data *= scale;
+       }
        return new;
 }
 
@@ -1333,17 +1453,13 @@ c_size(option, argvp)
  *     regular file or whiteout respectively.
  */
 int
-f_type(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_type(PLAN *plan, FTSENT *entry)
 {
        return (entry->fts_statp->st_mode & S_IFMT) == plan->m_data;
 }
 
 PLAN *
-c_type(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_type(OPTION *option, char ***argvp)
 {
        char *typestring;
        PLAN *new;
@@ -1397,17 +1513,13 @@ c_type(option, argvp)
  *     return a valid user name, uname is taken as a user ID.
  */
 int
-f_user(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_user(PLAN *plan, FTSENT *entry)
 {
-       return entry->fts_statp->st_uid == plan->u_data;
+       COMPARE(entry->fts_statp->st_uid, plan->u_data);
 }
 
 PLAN *
-c_user(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_user(OPTION *option, char ***argvp)
 {
        char *username;
        PLAN *new;
@@ -1417,15 +1529,19 @@ c_user(option, argvp)
        username = nextarg(option, argvp);
        ftsoptions &= ~FTS_NOSTAT;
 
+       new = palloc(option);
        p = getpwnam(username);
        if (p == NULL) {
+               char* cp = username;
+               if( username[0] == '-' || username[0] == '+' )
+                       username++;
                uid = atoi(username);
                if (uid == 0 && username[0] != '0')
                        errx(1, "%s: %s: no such user", option->name, username);
+               uid = find_parsenum(new, option->name, cp, NULL);
        } else
                uid = p->pw_uid;
 
-       new = palloc(option);
        new->u_data = uid;
        return new;
 }
@@ -1433,13 +1549,11 @@ c_user(option, argvp)
 /*
  * -xdev functions --
  *
- *     Always true, causes find not to decend past directories that have a
+ *     Always true, causes find not to descend past directories that have a
  *     different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
  */
 PLAN *
-c_xdev(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_xdev(OPTION *option, char ***argvp __unused)
 {
        ftsoptions |= FTS_XDEV;
 
@@ -1452,12 +1566,10 @@ c_xdev(option, argvp)
  *     True if expression is true.
  */
 int
-f_expr(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_expr(PLAN *plan, FTSENT *entry)
 {
-       register PLAN *p;
-       register int state = 0;
+       PLAN *p;
+       int state = 0;
 
        for (p = plan->p_data[0];
            p && (state = (p->execute)(p, entry)); p = p->next);
@@ -1472,17 +1584,13 @@ f_expr(plan, entry)
  */
 
 int
-f_openparen(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_openparen(PLAN *plan __unused, FTSENT *entry __unused)
 {
        abort();
 }
 
 int
-f_closeparen(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_closeparen(PLAN *plan __unused, FTSENT *entry __unused)
 {
        abort();
 }
@@ -1494,9 +1602,7 @@ f_closeparen(plan, entry)
  * AND operator. Since AND is implicit, no node is allocated.
  */
 PLAN *
-c_and(option, argvp)
-       OPTION *option;
-       char ***argvp;
+c_and(OPTION *option __unused, char ***argvp __unused)
 {
        return NULL;
 }
@@ -1507,12 +1613,10 @@ c_and(option, argvp)
  *     Negation of a primary; the unary NOT operator.
  */
 int
-f_not(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_not(PLAN *plan, FTSENT *entry)
 {
-       register PLAN *p;
-       register int state = 0;
+       PLAN *p;
+       int state = 0;
 
        for (p = plan->p_data[0];
            p && (state = (p->execute)(p, entry)); p = p->next);
@@ -1528,12 +1632,10 @@ f_not(plan, entry)
  * not evaluated if the first expression is true.
  */
 int
-f_or(plan, entry)
-       PLAN *plan;
-       FTSENT *entry;
+f_or(PLAN *plan, FTSENT *entry)
 {
-       register PLAN *p;
-       register int state = 0;
+       PLAN *p;
+       int state = 0;
 
        for (p = plan->p_data[0];
            p && (state = (p->execute)(p, entry)); p = p->next);
diff --git a/find/getdate.y b/find/getdate.y
new file mode 100644 (file)
index 0000000..c68de33
--- /dev/null
@@ -0,0 +1,970 @@
+%{
+/*
+**  Originally written by Steven M. Bellovin <smb@research.att.com> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+**  This grammar has 10 shift/reduce conflicts.
+**
+**  This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/getdate.y,v 1.4 2005/08/25 13:44:02 roberto Exp $");
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* The code at the top of get_date which figures out the offset of the
+   current time zone checks various CPP symbols to see if special
+   tricks are need, but defaults to using the gettimeofday system call.
+   Include <sys/time.h> if that will be used.  */
+
+#if    defined(vms)
+# include <types.h>
+#else /* defined(vms) */
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/timeb.h>
+#endif /* !defined(vms) */
+
+#if defined (__STDC__) || defined (USG)
+#include <string.h>
+#endif
+
+/* Some old versions of bison generate parsers that use bcopy.
+   That loses on systems that don't provide the function, so we have
+   to redefine it here.  */
+#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#endif
+
+#if defined (__STDC__)
+#include <stdlib.h>
+#endif
+
+/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
+   releases):
+
+   We don't want to mess with all the portability hassles of alloca.
+   In particular, most (all?) versions of bison will use alloca in
+   their parser.  If bison works on your system (e.g. it should work
+   with gcc), then go ahead and use it, but the more general solution
+   is to use byacc instead of bison, which should generate a portable
+   parser.  I played with adding "#define alloca dont_use_alloca", to
+   give an error if the parser generator uses alloca (and thus detect
+   unportable getdate.c's), but that seems to cause as many problems
+   as it solves.  */
+
+#include <time.h>
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yyparse(void);
+static int yylex(void);
+static int yyerror(const char *);
+
+time_t get_date(char *, struct timeb *);
+
+#define EPOCH          1970
+#define HOUR(x)                ((time_t)(x) * 60)
+#define SECSPERDAY     (24L * 60L * 60L)
+
+
+/*
+**  An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+    const char *name;
+    int                type;
+    time_t     value;
+} TABLE;
+
+
+/*
+**  Daylight-savings mode:  on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+    DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+**  Meridian:  am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+    MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+**  Global variables.  We could get rid of most of these by using a good
+**  union as the yacc stack.  (This routine was originally written before
+**  yacc had the %union construct.)  Maybe someday; right now we only use
+**  the %union very rarely.
+*/
+static char    *yyInput;
+static DSTMODE yyDSTmode;
+static time_t  yyDayOrdinal;
+static time_t  yyDayNumber;
+static int     yyHaveDate;
+static int     yyHaveDay;
+static int     yyHaveRel;
+static int     yyHaveTime;
+static int     yyHaveZone;
+static time_t  yyTimezone;
+static time_t  yyDay;
+static time_t  yyHour;
+static time_t  yyMinutes;
+static time_t  yyMonth;
+static time_t  yySeconds;
+static time_t  yyYear;
+static MERIDIAN        yyMeridian;
+static time_t  yyRelMonth;
+static time_t  yyRelSeconds;
+
+%}
+
+%union {
+    time_t             Number;
+    enum _MERIDIAN     Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type  <Number>        tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type  <Number>        tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type  <Meridian>      tMERIDIAN o_merid
+
+%%
+
+spec   : /* NULL */
+       | spec item
+       ;
+
+item   : time {
+           yyHaveTime++;
+       }
+       | zone {
+           yyHaveZone++;
+       }
+       | date {
+           yyHaveDate++;
+       }
+       | day {
+           yyHaveDay++;
+       }
+       | rel {
+           yyHaveRel++;
+       }
+       | number
+       ;
+
+time   : tUNUMBER tMERIDIAN {
+           yyHour = $1;
+           yyMinutes = 0;
+           yySeconds = 0;
+           yyMeridian = $2;
+       }
+       | tUNUMBER ':' tUNUMBER o_merid {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = 0;
+           yyMeridian = $4;
+       }
+       | tUNUMBER ':' tUNUMBER tSNUMBER {
+           yyHour = $1;
+           yyMinutes = $3;
+           yyMeridian = MER24;
+           yyDSTmode = DSToff;
+           yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+       }
+       | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = $5;
+           yyMeridian = $6;
+       }
+       | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = $5;
+           yyMeridian = MER24;
+           yyDSTmode = DSToff;
+           yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+       }
+       ;
+
+zone   : tZONE {
+           yyTimezone = $1;
+           yyDSTmode = DSToff;
+       }
+       | tDAYZONE {
+           yyTimezone = $1;
+           yyDSTmode = DSTon;
+       }
+       |
+         tZONE tDST {
+           yyTimezone = $1;
+           yyDSTmode = DSTon;
+       }
+       ;
+
+day    : tDAY {
+           yyDayOrdinal = 1;
+           yyDayNumber = $1;
+       }
+       | tDAY ',' {
+           yyDayOrdinal = 1;
+           yyDayNumber = $1;
+       }
+       | tUNUMBER tDAY {
+           yyDayOrdinal = $1;
+           yyDayNumber = $2;
+       }
+       ;
+
+date   : tUNUMBER '/' tUNUMBER {
+           yyMonth = $1;
+           yyDay = $3;
+       }
+       | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+           if ($1 >= 100) {
+               yyYear = $1;
+               yyMonth = $3;
+               yyDay = $5;
+           } else {
+               yyMonth = $1;
+               yyDay = $3;
+               yyYear = $5;
+           }
+       }
+       | tUNUMBER tSNUMBER tSNUMBER {
+           /* ISO 8601 format.  yyyy-mm-dd.  */
+           yyYear = $1;
+           yyMonth = -$2;
+           yyDay = -$3;
+       }
+       | tUNUMBER tMONTH tSNUMBER {
+           /* e.g. 17-JUN-1992.  */
+           yyDay = $1;
+           yyMonth = $2;
+           yyYear = -$3;
+       }
+       | tMONTH tUNUMBER {
+           yyMonth = $1;
+           yyDay = $2;
+       }
+       | tMONTH tUNUMBER ',' tUNUMBER {
+           yyMonth = $1;
+           yyDay = $2;
+           yyYear = $4;
+       }
+       | tUNUMBER tMONTH {
+           yyMonth = $2;
+           yyDay = $1;
+       }
+       | tUNUMBER tMONTH tUNUMBER {
+           yyMonth = $2;
+           yyDay = $1;
+           yyYear = $3;
+       }
+       ;
+
+rel    : relunit tAGO {
+           yyRelSeconds = -yyRelSeconds;
+           yyRelMonth = -yyRelMonth;
+       }
+       | relunit
+       ;
+
+relunit        : tUNUMBER tMINUTE_UNIT {
+           yyRelSeconds += $1 * $2 * 60L;
+       }
+       | tSNUMBER tMINUTE_UNIT {
+           yyRelSeconds += $1 * $2 * 60L;
+       }
+       | tMINUTE_UNIT {
+           yyRelSeconds += $1 * 60L;
+       }
+       | tSNUMBER tSEC_UNIT {
+           yyRelSeconds += $1;
+       }
+       | tUNUMBER tSEC_UNIT {
+           yyRelSeconds += $1;
+       }
+       | tSEC_UNIT {
+           yyRelSeconds++;
+       }
+       | tSNUMBER tMONTH_UNIT {
+           yyRelMonth += $1 * $2;
+       }
+       | tUNUMBER tMONTH_UNIT {
+           yyRelMonth += $1 * $2;
+       }
+       | tMONTH_UNIT {
+           yyRelMonth += $1;
+       }
+       ;
+
+number : tUNUMBER {
+           if (yyHaveTime && yyHaveDate && !yyHaveRel)
+               yyYear = $1;
+           else {
+               if($1>10000) {
+                   yyHaveDate++;
+                   yyDay= ($1)%100;
+                   yyMonth= ($1/100)%100;
+                   yyYear = $1/10000;
+               }
+               else {
+                   yyHaveTime++;
+                   if ($1 < 100) {
+                       yyHour = $1;
+                       yyMinutes = 0;
+                   }
+                   else {
+                       yyHour = $1 / 100;
+                       yyMinutes = $1 % 100;
+                   }
+                   yySeconds = 0;
+                   yyMeridian = MER24;
+               }
+           }
+       }
+       ;
+
+o_merid        : /* NULL */ {
+           $$ = MER24;
+       }
+       | tMERIDIAN {
+           $$ = $1;
+       }
+       ;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+    { "january",       tMONTH,  1 },
+    { "february",      tMONTH,  2 },
+    { "march",         tMONTH,  3 },
+    { "april",         tMONTH,  4 },
+    { "may",           tMONTH,  5 },
+    { "june",          tMONTH,  6 },
+    { "july",          tMONTH,  7 },
+    { "august",                tMONTH,  8 },
+    { "september",     tMONTH,  9 },
+    { "sept",          tMONTH,  9 },
+    { "october",       tMONTH, 10 },
+    { "november",      tMONTH, 11 },
+    { "december",      tMONTH, 12 },
+    { "sunday",                tDAY, 0 },
+    { "monday",                tDAY, 1 },
+    { "tuesday",       tDAY, 2 },
+    { "tues",          tDAY, 2 },
+    { "wednesday",     tDAY, 3 },
+    { "wednes",                tDAY, 3 },
+    { "thursday",      tDAY, 4 },
+    { "thur",          tDAY, 4 },
+    { "thurs",         tDAY, 4 },
+    { "friday",                tDAY, 5 },
+    { "saturday",      tDAY, 6 },
+    { NULL,            0, 0 }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+    { "year",          tMONTH_UNIT,    12 },
+    { "month",         tMONTH_UNIT,    1 },
+    { "fortnight",     tMINUTE_UNIT,   14 * 24 * 60 },
+    { "week",          tMINUTE_UNIT,   7 * 24 * 60 },
+    { "day",           tMINUTE_UNIT,   1 * 24 * 60 },
+    { "hour",          tMINUTE_UNIT,   60 },
+    { "minute",                tMINUTE_UNIT,   1 },
+    { "min",           tMINUTE_UNIT,   1 },
+    { "second",                tSEC_UNIT,      1 },
+    { "sec",           tSEC_UNIT,      1 },
+    { NULL,            0,              0 }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+    { "tomorrow",      tMINUTE_UNIT,   1 * 24 * 60 },
+    { "yesterday",     tMINUTE_UNIT,   -1 * 24 * 60 },
+    { "today",         tMINUTE_UNIT,   0 },
+    { "now",           tMINUTE_UNIT,   0 },
+    { "last",          tUNUMBER,       -1 },
+    { "this",          tMINUTE_UNIT,   0 },
+    { "next",          tUNUMBER,       2 },
+    { "first",         tUNUMBER,       1 },
+/*  { "second",                tUNUMBER,       2 }, */
+    { "third",         tUNUMBER,       3 },
+    { "fourth",                tUNUMBER,       4 },
+    { "fifth",         tUNUMBER,       5 },
+    { "sixth",         tUNUMBER,       6 },
+    { "seventh",       tUNUMBER,       7 },
+    { "eighth",                tUNUMBER,       8 },
+    { "ninth",         tUNUMBER,       9 },
+    { "tenth",         tUNUMBER,       10 },
+    { "eleventh",      tUNUMBER,       11 },
+    { "twelfth",       tUNUMBER,       12 },
+    { "ago",           tAGO,           1 },
+    { NULL,            0,              0 }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+    { "gmt",   tZONE,     HOUR( 0) },  /* Greenwich Mean */
+    { "ut",    tZONE,     HOUR( 0) },  /* Universal (Coordinated) */
+    { "utc",   tZONE,     HOUR( 0) },
+    { "wet",   tZONE,     HOUR( 0) },  /* Western European */
+    { "bst",   tDAYZONE,  HOUR( 0) },  /* British Summer */
+    { "wat",   tZONE,     HOUR( 1) },  /* West Africa */
+    { "at",    tZONE,     HOUR( 2) },  /* Azores */
+#if    0
+    /* For completeness.  BST is also British Summer, and GST is
+     * also Guam Standard. */
+    { "bst",   tZONE,     HOUR( 3) },  /* Brazil Standard */
+    { "gst",   tZONE,     HOUR( 3) },  /* Greenland Standard */
+#endif
+#if 0
+    { "nft",   tZONE,     HOUR(3.5) }, /* Newfoundland */
+    { "nst",   tZONE,     HOUR(3.5) }, /* Newfoundland Standard */
+    { "ndt",   tDAYZONE,  HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+    { "ast",   tZONE,     HOUR( 4) },  /* Atlantic Standard */
+    { "adt",   tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
+    { "est",   tZONE,     HOUR( 5) },  /* Eastern Standard */
+    { "edt",   tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
+    { "cst",   tZONE,     HOUR( 6) },  /* Central Standard */
+    { "cdt",   tDAYZONE,  HOUR( 6) },  /* Central Daylight */
+    { "mst",   tZONE,     HOUR( 7) },  /* Mountain Standard */
+    { "mdt",   tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
+    { "pst",   tZONE,     HOUR( 8) },  /* Pacific Standard */
+    { "pdt",   tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
+    { "yst",   tZONE,     HOUR( 9) },  /* Yukon Standard */
+    { "ydt",   tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
+    { "hst",   tZONE,     HOUR(10) },  /* Hawaii Standard */
+    { "hdt",   tDAYZONE,  HOUR(10) },  /* Hawaii Daylight */
+    { "cat",   tZONE,     HOUR(10) },  /* Central Alaska */
+    { "ahst",  tZONE,     HOUR(10) },  /* Alaska-Hawaii Standard */
+    { "nt",    tZONE,     HOUR(11) },  /* Nome */
+    { "idlw",  tZONE,     HOUR(12) },  /* International Date Line West */
+    { "cet",   tZONE,     -HOUR(1) },  /* Central European */
+    { "met",   tZONE,     -HOUR(1) },  /* Middle European */
+    { "mewt",  tZONE,     -HOUR(1) },  /* Middle European Winter */
+    { "mest",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
+    { "swt",   tZONE,     -HOUR(1) },  /* Swedish Winter */
+    { "sst",   tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
+    { "fwt",   tZONE,     -HOUR(1) },  /* French Winter */
+    { "fst",   tDAYZONE,  -HOUR(1) },  /* French Summer */
+    { "eet",   tZONE,     -HOUR(2) },  /* Eastern Europe, USSR Zone 1 */
+    { "bt",    tZONE,     -HOUR(3) },  /* Baghdad, USSR Zone 2 */
+#if 0
+    { "it",    tZONE,     -HOUR(3.5) },/* Iran */
+#endif
+    { "zp4",   tZONE,     -HOUR(4) },  /* USSR Zone 3 */
+    { "zp5",   tZONE,     -HOUR(5) },  /* USSR Zone 4 */
+#if 0
+    { "ist",   tZONE,     -HOUR(5.5) },/* Indian Standard */
+#endif
+    { "zp6",   tZONE,     -HOUR(6) },  /* USSR Zone 5 */
+#if    0
+    /* For completeness.  NST is also Newfoundland Stanard, and SST is
+     * also Swedish Summer. */
+    { "nst",   tZONE,     -HOUR(6.5) },/* North Sumatra */
+    { "sst",   tZONE,     -HOUR(7) },  /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+    { "wast",  tZONE,     -HOUR(7) },  /* West Australian Standard */
+    { "wadt",  tDAYZONE,  -HOUR(7) },  /* West Australian Daylight */
+#if 0
+    { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+    { "cct",   tZONE,     -HOUR(8) },  /* China Coast, USSR Zone 7 */
+    { "jst",   tZONE,     -HOUR(9) },  /* Japan Standard, USSR Zone 8 */
+#if 0
+    { "cast",  tZONE,     -HOUR(9.5) },/* Central Australian Standard */
+    { "cadt",  tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+    { "east",  tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
+    { "eadt",  tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
+    { "gst",   tZONE,     -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+    { "nzt",   tZONE,     -HOUR(12) }, /* New Zealand */
+    { "nzst",  tZONE,     -HOUR(12) }, /* New Zealand Standard */
+    { "nzdt",  tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
+    { "idle",  tZONE,     -HOUR(12) }, /* International Date Line East */
+    {  NULL,   0,         0 }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+    { "a",     tZONE,  HOUR(  1) },
+    { "b",     tZONE,  HOUR(  2) },
+    { "c",     tZONE,  HOUR(  3) },
+    { "d",     tZONE,  HOUR(  4) },
+    { "e",     tZONE,  HOUR(  5) },
+    { "f",     tZONE,  HOUR(  6) },
+    { "g",     tZONE,  HOUR(  7) },
+    { "h",     tZONE,  HOUR(  8) },
+    { "i",     tZONE,  HOUR(  9) },
+    { "k",     tZONE,  HOUR( 10) },
+    { "l",     tZONE,  HOUR( 11) },
+    { "m",     tZONE,  HOUR( 12) },
+    { "n",     tZONE,  HOUR(- 1) },
+    { "o",     tZONE,  HOUR(- 2) },
+    { "p",     tZONE,  HOUR(- 3) },
+    { "q",     tZONE,  HOUR(- 4) },
+    { "r",     tZONE,  HOUR(- 5) },
+    { "s",     tZONE,  HOUR(- 6) },
+    { "t",     tZONE,  HOUR(- 7) },
+    { "u",     tZONE,  HOUR(- 8) },
+    { "v",     tZONE,  HOUR(- 9) },
+    { "w",     tZONE,  HOUR(-10) },
+    { "x",     tZONE,  HOUR(-11) },
+    { "y",     tZONE,  HOUR(-12) },
+    { "z",     tZONE,  HOUR(  0) },
+    { NULL,    0,      0 }
+};
+
+\f
+
+
+/* ARGSUSED */
+static int
+yyerror(const char *s __unused)
+{
+  return 0;
+}
+
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+{
+    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+       return -1;
+    switch (Meridian) {
+    case MER24:
+       if (Hours < 0 || Hours > 23)
+           return -1;
+       return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERam:
+       if (Hours < 1 || Hours > 12)
+           return -1;
+       if (Hours == 12)
+           Hours = 0;
+       return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERpm:
+       if (Hours < 1 || Hours > 12)
+           return -1;
+       if (Hours == 12)
+           Hours = 0;
+       return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+    default:
+       abort ();
+    }
+    /* NOTREACHED */
+}
+
+
+/* Year is either
+   * A negative number, which means to use its absolute value (why?)
+   * A number from 0 to 99, which means a year from 1900 to 1999, or
+   * The actual year (>=100).  */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year,
+       time_t Hours, time_t Minutes, time_t Seconds,
+       MERIDIAN Meridian, DSTMODE DSTmode)
+{
+    static int DaysInMonth[12] = {
+       31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    time_t     tod;
+    time_t     Julian;
+    int                i;
+
+    if (Year < 0)
+       Year = -Year;
+    if (Year < 69)
+       Year += 2000;
+    else if (Year < 100)
+       Year += 1900;
+    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+                   ? 29 : 28;
+    /* Checking for 2038 bogusly assumes that time_t is 32 bits.  But
+       I'm too lazy to try to check for time_t overflow in another way.  */
+    if (Year < EPOCH || Year > 2038
+     || Month < 1 || Month > 12
+     /* Lint fluff:  "conversion from long may lose accuracy" */
+     || Day < 1 || Day > DaysInMonth[(int)--Month])
+       return -1;
+
+    for (Julian = Day - 1, i = 0; i < Month; i++)
+       Julian += DaysInMonth[i];
+    for (i = EPOCH; i < Year; i++)
+       Julian += 365 + (i % 4 == 0);
+    Julian *= SECSPERDAY;
+    Julian += yyTimezone * 60L;
+    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+       return -1;
+    Julian += tod;
+    if (DSTmode == DSTon
+     || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+       Julian -= 60 * 60;
+    return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+    time_t     StartDay;
+    time_t     FutureDay;
+
+    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+    struct tm  *tm;
+    time_t     now;
+
+    now = Start;
+    tm = localtime(&now);
+    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+    return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+    struct tm  *tm;
+    time_t     Month;
+    time_t     Year;
+
+    if (RelMonth == 0)
+       return 0;
+    tm = localtime(&Start);
+    Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+    Year = Month / 12;
+    Month = Month % 12 + 1;
+    return DSTcorrect(Start,
+           Convert(Month, (time_t)tm->tm_mday, Year,
+               (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+               MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(char *buff)
+{
+    char       *p;
+    char       *q;
+    const TABLE        *tp;
+    int                i;
+    int                abbrev;
+
+    /* Make it lowercase. */
+    for (p = buff; *p; p++)
+       if (isupper(*p))
+           *p = tolower(*p);
+
+    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+       yylval.Meridian = MERam;
+       return tMERIDIAN;
+    }
+    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+       yylval.Meridian = MERpm;
+       return tMERIDIAN;
+    }
+
+    /* See if we have an abbreviation for a month. */
+    if (strlen(buff) == 3)
+       abbrev = 1;
+    else if (strlen(buff) == 4 && buff[3] == '.') {
+       abbrev = 1;
+       buff[3] = '\0';
+    }
+    else
+       abbrev = 0;
+
+    for (tp = MonthDayTable; tp->name; tp++) {
+       if (abbrev) {
+           if (strncmp(buff, tp->name, 3) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       }
+       else if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+    }
+
+    for (tp = TimezoneTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    if (strcmp(buff, "dst") == 0) 
+       return tDST;
+
+    for (tp = UnitsTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    /* Strip off any plural and try the units table again. */
+    i = strlen(buff) - 1;
+    if (buff[i] == 's') {
+       buff[i] = '\0';
+       for (tp = UnitsTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       buff[i] = 's';          /* Put back for "this" in OtherTable. */
+    }
+
+    for (tp = OtherTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    /* Military timezones. */
+    if (buff[1] == '\0' && isalpha(*buff)) {
+       for (tp = MilitaryTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+    }
+
+    /* Drop out any periods and try the timezone table again. */
+    for (i = 0, p = q = buff; *q; q++)
+       if (*q != '.')
+           *p++ = *q;
+       else
+           i++;
+    *p = '\0';
+    if (i)
+       for (tp = TimezoneTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+
+    return tID;
+}
+
+
+static int
+yylex(void)
+{
+    char       c;
+    char       *p;
+    char       buff[20];
+    int                Count;
+    int                sign;
+
+    for ( ; ; ) {
+       while (isspace(*yyInput))
+           yyInput++;
+
+       if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+           if (c == '-' || c == '+') {
+               sign = c == '-' ? -1 : 1;
+               if (!isdigit(*++yyInput))
+                   /* skip the '-' sign */
+                   continue;
+           }
+           else
+               sign = 0;
+           for (yylval.Number = 0; isdigit(c = *yyInput++); )
+               yylval.Number = 10 * yylval.Number + c - '0';
+           yyInput--;
+           if (sign < 0)
+               yylval.Number = -yylval.Number;
+           return sign ? tSNUMBER : tUNUMBER;
+       }
+       if (isalpha(c)) {
+           for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+               if (p < &buff[sizeof buff - 1])
+                   *p++ = c;
+           *p = '\0';
+           yyInput--;
+           return LookupWord(buff);
+       }
+       if (c != '(')
+           return *yyInput++;
+       Count = 0;
+       do {
+           c = *yyInput++;
+           if (c == '\0')
+               return c;
+           if (c == '(')
+               Count++;
+           else if (c == ')')
+               Count--;
+       } while (Count > 0);
+    }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds.  */
+static long
+difftm (struct tm *a, struct tm *b)
+{
+  int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+  int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+  int days = (
+             /* difference in day of year */
+             a->tm_yday - b->tm_yday
+             /* + intervening leap days */
+             +  ((ay >> 2) - (by >> 2))
+             -  (ay/100 - by/100)
+             +  ((ay/100 >> 2) - (by/100 >> 2))
+             /* + difference in years * 365 */
+             +  (long)(ay-by) * 365
+             );
+  return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+             + (a->tm_min - b->tm_min))
+         + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(char *p, struct timeb *now)
+{
+    struct tm          *tm, gmt;
+    struct timeb       ftz;
+    time_t             Start;
+    time_t             tod;
+    time_t nowtime;
+
+    bzero (&gmt, sizeof(struct tm));
+    yyInput = p;
+    if (now == NULL) {
+       struct tm *gmt_ptr;
+
+        now = &ftz;
+       (void)time (&nowtime);
+
+       gmt_ptr = gmtime (&nowtime);
+       if (gmt_ptr != NULL)
+       {
+           /* Make a copy, in case localtime modifies *tm (I think
+              that comment now applies to *gmt_ptr, but I am too
+              lazy to dig into how gmtime and locatime allocate the
+              structures they return pointers to).  */
+           gmt = *gmt_ptr;
+       }
+
+       if (! (tm = localtime (&nowtime)))
+           return -1;
+
+       if (gmt_ptr != NULL)
+           ftz.timezone = difftm (&gmt, tm) / 60;
+       else
+           /* We are on a system like VMS, where the system clock is
+              in local time and the system has no concept of timezones.
+              Hopefully we can fake this out (for the case in which the
+              user specifies no timezone) by just saying the timezone
+              is zero.  */
+           ftz.timezone = 0;
+
+       if(tm->tm_isdst)
+           ftz.timezone += 60;
+    }
+    else
+    {
+       nowtime = now->time;
+    }
+
+    tm = localtime(&nowtime);
+    yyYear = tm->tm_year + 1900;
+    yyMonth = tm->tm_mon + 1;
+    yyDay = tm->tm_mday;
+    yyTimezone = now->timezone;
+    yyDSTmode = DSTmaybe;
+    yyHour = 0;
+    yyMinutes = 0;
+    yySeconds = 0;
+    yyMeridian = MER24;
+    yyRelSeconds = 0;
+    yyRelMonth = 0;
+    yyHaveDate = 0;
+    yyHaveDay = 0;
+    yyHaveRel = 0;
+    yyHaveTime = 0;
+    yyHaveZone = 0;
+
+    if (yyparse()
+     || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+       return -1;
+
+    if (yyHaveDate || yyHaveTime || yyHaveDay) {
+       Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+                   yyMeridian, yyDSTmode);
+       if (Start < 0)
+           return -1;
+    }
+    else {
+       Start = nowtime;
+       if (!yyHaveRel)
+           Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+    }
+
+    Start += yyRelSeconds;
+    Start += RelativeMonth(Start, yyRelMonth);
+
+    if (yyHaveDay && !yyHaveDate) {
+       tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+       Start += tod;
+    }
+
+    /* Have to do *something* with a legitimate -1 so it's distinguishable
+     * from the error return value.  (Alternately could set errno on error.) */
+    return Start == -1 ? 0 : Start;
+}
+
+
+#if    defined(TEST)
+
+/* ARGSUSED */
+int
+main(int ac, char *av[])
+{
+    char       buff[128];
+    time_t     d;
+
+    (void)printf("Enter date, or blank line to exit.\n\t> ");
+    (void)fflush(stdout);
+    while (gets(buff) && buff[0]) {
+       d = get_date(buff, (struct timeb *)NULL);
+       if (d == -1)
+           (void)printf("Bad format - couldn't convert.\n");
+       else
+           (void)printf("%s", ctime(&d));
+       (void)printf("\t> ");
+       (void)fflush(stdout);
+    }
+    exit(0);
+    /* NOTREACHED */
+}
+#endif /* defined(TEST) */
index d05002910d582a4606399364ecd9c0124e16e372..5a42be2aea2e95ee5722da8c8fb2194a18222b27 100644 (file)
--- a/find/ls.c
+++ b/find/ls.c
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)ls.c       8.1 (Berkeley) 6/6/93";
-#else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/ls.c,v 1.5.6.2 2001/05/06 09:53:22 phk Exp $";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/ls.c,v 1.17 2004/01/20 09:27:03 des Exp $");
+
 #include <sys/param.h>
 #include <sys/stat.h>
 
 #include <err.h>
 #include <errno.h>
+#include <fts.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <langinfo.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#ifdef __APPLE__
 #include <utmp.h>
+#endif /* __APPLE__ */
+
+#include "find.h"
 
 /* Derived from the print routines in the ls(1) source code. */
 
-static void printlink __P((char *));
-static void printtime __P((time_t));
+static void printlink(char *);
+static void printtime(time_t);
 
 void
-printlong(name, accpath, sb)
-       char *name;                     /* filename to print */
-       char *accpath;                  /* current valid path to filename */
-       struct stat *sb;                /* stat buffer */
+printlong(char *name, char *accpath, struct stat *sb)
 {
-       char modep[15], *user_from_uid(), *group_from_gid();
+       char modep[15];
 
-       (void)printf("%6lu %4qd ", (u_long) sb->st_ino, sb->st_blocks);
+       (void)printf("%6lu %8"PRId64" ", (u_long) sb->st_ino, sb->st_blocks);
        (void)strmode(sb->st_mode, modep);
+#ifdef __APPLE__
        (void)printf("%s %3u %-*s %-*s ", modep, sb->st_nlink, UT_NAMESIZE,
            user_from_uid(sb->st_uid, 0), UT_NAMESIZE,
+#else /* !__APPLE__ */
+       (void)printf("%s %3u %-*s %-*s ", modep, sb->st_nlink, MAXLOGNAME - 1,
+           user_from_uid(sb->st_uid, 0), MAXLOGNAME - 1,
+#endif /* __APPLE__ */
            group_from_gid(sb->st_gid, 0));
 
        if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
                (void)printf("%3d, %3d ", major(sb->st_rdev),
                    minor(sb->st_rdev));
        else
-               (void)printf("%8qd ", sb->st_size);
+               (void)printf("%8"PRId64" ", sb->st_size);
        printtime(sb->st_mtime);
        (void)printf("%s", name);
        if (S_ISLNK(sb->st_mode))
@@ -83,34 +94,34 @@ printlong(name, accpath, sb)
 }
 
 static void
-printtime(ftime)
-       time_t ftime;
+printtime(time_t ftime)
 {
-       int i;
        char longstring[80];
+       static time_t lnow;
+       const char *format;
+       static int d_first = -1;
 
-       strftime(longstring, sizeof(longstring), "%c", localtime(&ftime));
-       for (i = 4; i < 11; ++i)
-               (void)putchar(longstring[i]);
+       if (d_first < 0)
+               d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+       if (lnow == 0)
+               lnow = time(NULL);
 
 #define        SIXMONTHS       ((365 / 2) * 86400)
-       if (ftime + SIXMONTHS > time((time_t *)NULL))
-               for (i = 11; i < 16; ++i)
-                       (void)putchar(longstring[i]);
-       else {
-               (void)putchar(' ');
-               for (i = 20; i < 24; ++i)
-                       (void)putchar(longstring[i]);
-       }
-       (void)putchar(' ');
+       if (ftime + SIXMONTHS > lnow && ftime < lnow + SIXMONTHS)
+               /* mmm dd hh:mm || dd mmm hh:mm */
+               format = d_first ? "%e %b %R " : "%b %e %R ";
+       else
+               /* mmm dd  yyyy || dd mmm  yyyy */
+               format = d_first ? "%e %b  %Y " : "%b %e  %Y ";
+       strftime(longstring, sizeof(longstring), format, localtime(&ftime));
+       fputs(longstring, stdout);
 }
 
 static void
-printlink(name)
-       char *name;
+printlink(char *name)
 {
        int lnklen;
-       char path[MAXPATHLEN + 1];
+       char path[MAXPATHLEN];
 
        if ((lnklen = readlink(name, path, MAXPATHLEN - 1)) == -1) {
                warn("%s", name);
index bad04a212ed6dc698a0b884921416f89f0699668..b1f22332658ad7e7fe05551a58200071dc5b6fa3 100644 (file)
@@ -43,12 +43,12 @@ char copyright[] =
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)main.c     8.4 (Berkeley) 5/4/95";
-#else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/main.c,v 1.9.6.2 2001/02/25 21:56:59 knu Exp $";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/main.c,v 1.15 2003/06/14 13:00:21 markm Exp $");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -76,14 +76,12 @@ int isxargs;                        /* don't permit xargs delimiting chars */
 int mindepth = -1, maxdepth = -1; /* minimum and maximum depth */
 int regexp_flags = REG_BASIC;  /* use the "basic" regexp by default*/
 
-static void usage __P((void));
+static void usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char *argv[])
 {
-       register char **p, **start;
+       char **p, **start;
        int Hflag, Lflag, ch;
 
        (void)setlocale(LC_ALL, "");
@@ -163,7 +161,7 @@ main(argc, argv)
 }
 
 static void
-usage()
+usage(void)
 {
        (void)fprintf(stderr,
 "usage: find [-H | -L | -P] [-EXdsx] [-f file] [file ...] [expression]\n");
index 2ad2ace83f8e987530d017196343fd0a4552b826..ced8cfbf569b821d5dff02d1b5aa455bda86bd29 100644 (file)
 #if 0
 static char sccsid[] = "@(#)misc.c     8.2 (Berkeley) 4/1/94";
 #else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/misc.c,v 1.2.12.1 2000/06/23 18:38:46 roberto Exp $";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/misc.c,v 1.8 2005/04/02 07:44:12 tjr Exp $");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -60,12 +61,10 @@ static const char rcsid[] =
  *     Replace occurrences of {} in s1 with s2 and return the result string.
  */
 void
-brace_subst(orig, store, path, len)
-       char *orig, **store, *path;
-       int len;
+brace_subst(char *orig, char **store, char *path, int len)
 {
-       register int plen;
-       register char ch, *p;
+       int plen;
+       char ch, *p;
 
        plen = strlen(path);
        for (p = *store; (ch = *orig) != '\0'; ++orig)
@@ -84,13 +83,13 @@ brace_subst(orig, store, path, len)
 /*
  * queryuser --
  *     print a message to standard error and then read input from standard
- *     input. If the input is 'y' then 1 is returned.
+ *     input. If the input is an affirmative response (according to the
+ *     current locale) then 1 is returned.
  */
 int
-queryuser(argv)
-       register char **argv;
+queryuser(char *argv[])
 {
-       int ch, first, nl;
+       char *p, resp[256];
 
        (void)fprintf(stderr, "\"%s", *argv);
        while (*++argv)
@@ -98,35 +97,17 @@ queryuser(argv)
        (void)fprintf(stderr, "\"? ");
        (void)fflush(stderr);
 
-       first = ch = getchar();
-       for (nl = 0;;) {
-               if (ch == '\n') {
-                       nl = 1;
-                       break;
-               }
-               if (ch == EOF)
-                       break;
-               ch = getchar();
-       }
-
-       if (!nl) {
+       if (fgets(resp, sizeof(resp), stdin) == NULL)
+               *resp = '\0';
+       if ((p = strchr(resp, '\n')) != NULL)
+               *p = '\0';
+       else {
                (void)fprintf(stderr, "\n");
                (void)fflush(stderr);
        }
-        return (first == 'y');
-}
-
-/*
- * emalloc --
- *     malloc with error checking.
- */
-void *
-emalloc(len)
-       u_int len;
-{
-       void *p;
-
-       if ((p = malloc(len)) == NULL)
-               err(1, NULL);
-       return (p);
+#ifdef __APPLE__
+        return (resp[0] == 'y');
+#else
+        return (rpmatch(resp) == 1);
+#endif
 }
index a8feb8e3322e16c6d919adfeb8d39497e1c9fff7..f04d12adaffd32ff295c54286987cb61d66d5317 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.bin/find/operator.c,v 1.5.6.1 2001/05/06 09:53:22 phk Exp $
  */
 
 #ifndef lint
+#if 0
 static char sccsid[] = "@(#)operator.c 8.1 (Berkeley) 6/6/93";
+#endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/operator.c,v 1.14 2003/06/14 13:00:21 markm Exp $");
+
 #include <sys/types.h>
 
 #include <err.h>
@@ -48,13 +51,15 @@ static char sccsid[] = "@(#)operator.c      8.1 (Berkeley) 6/6/93";
 
 #include "find.h"
 
+static PLAN *yanknode(PLAN **);
+static PLAN *yankexpr(PLAN **);
+
 /*
  * yanknode --
  *     destructively removes the top from the plan
  */
 static PLAN *
-yanknode(planp)
-       PLAN **planp;           /* pointer to top of plan (modified) */
+yanknode(PLAN **planp)
 {
        PLAN *node;             /* top node removed from the plan */
 
@@ -72,10 +77,9 @@ yanknode(planp)
  *     simple node or a f_expr node containing a list of simple nodes.
  */
 static PLAN *
-yankexpr(planp)
-       PLAN **planp;           /* pointer to top of plan (modified) */
+yankexpr(PLAN **planp)
 {
-       register PLAN *next;    /* temp node holding subexpression results */
+       PLAN *next;             /* temp node holding subexpression results */
        PLAN *node;             /* pointer to returned node or expression */
        PLAN *tail;             /* pointer to tail of subplan */
        PLAN *subplan;          /* pointer to head of ( ) expression */
@@ -93,7 +97,7 @@ yankexpr(planp)
        if (node->execute == f_openparen)
                for (tail = subplan = NULL;;) {
                        if ((next = yankexpr(planp)) == NULL)
-                               err(1, "(: missing closing ')'");
+                               errx(1, "(: missing closing ')'");
                        /*
                         * If we find a closing ')' we store the collected
                         * subplan in our '(' node and convert the node to
@@ -122,14 +126,13 @@ yankexpr(planp)
 
 /*
  * paren_squish --
- *     replaces "parentheisized" plans in our search plan with "expr" nodes.
+ *     replaces "parenthesized" plans in our search plan with "expr" nodes.
  */
 PLAN *
-paren_squish(plan)
-       PLAN *plan;             /* plan with ( ) nodes */
+paren_squish(PLAN *plan)
 {
-       register PLAN *expr;    /* pointer to next expression */
-       register PLAN *tail;    /* pointer to tail of result plan */
+       PLAN *expr;             /* pointer to next expression */
+       PLAN *tail;             /* pointer to tail of result plan */
        PLAN *result;           /* pointer to head of result plan */
 
        result = tail = NULL;
@@ -163,17 +166,16 @@ paren_squish(plan)
  *     compresses "!" expressions in our search plan.
  */
 PLAN *
-not_squish(plan)
-       PLAN *plan;             /* plan to process */
+not_squish(PLAN *plan)
 {
-       register PLAN *next;    /* next node being processed */
-       register PLAN *node;    /* temporary node used in f_not processing */
-       register PLAN *tail;    /* pointer to tail of result plan */
+       PLAN *next;             /* next node being processed */
+       PLAN *node;             /* temporary node used in f_not processing */
+       PLAN *tail;             /* pointer to tail of result plan */
        PLAN *result;           /* pointer to head of result plan */
 
        tail = result = NULL;
 
-       while (next = yanknode(&plan)) {
+       while ((next = yanknode(&plan))) {
                /*
                 * if we encounter a ( expression ) then look for nots in
                 * the expr subplan.
@@ -227,11 +229,10 @@ not_squish(plan)
  *     compresses -o expressions in our search plan.
  */
 PLAN *
-or_squish(plan)
-       PLAN *plan;             /* plan with ors to be squished */
+or_squish(PLAN *plan)
 {
-       register PLAN *next;    /* next node being processed */
-       register PLAN *tail;    /* pointer to tail of result plan */
+       PLAN *next;             /* next node being processed */
+       PLAN *tail;             /* pointer to tail of result plan */
        PLAN *result;           /* pointer to head of result plan */
 
        tail = result = next = NULL;
index a0abc8be07592bb375ec994cacd8442667ce5290..004d5500326ea53fb5bfe6f80336183cb28cf94f 100644 (file)
 /*
 static char sccsid[] = "@(#)option.c   8.2 (Berkeley) 4/16/94";
 */
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/option.c,v 1.9.2.4 2001/05/06 09:53:22 phk Exp $";
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/option.c,v 1.25 2006/04/05 23:06:11 ceri Exp $");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -54,12 +55,20 @@ static const char rcsid[] =
 
 #include "find.h"
 
+int typecompare(const void *, const void *);
+
 /* NB: the following table must be sorted lexically. */
 static OPTION const options[] = {
        { "!",          c_simple,       f_not,          0 },
        { "(",          c_simple,       f_openparen,    0 },
        { ")",          c_simple,       f_closeparen,   0 },
+       { "-Bmin",      c_Xmin,         f_Xmin,         F_TIME_B },
+       { "-Bnewer",    c_newer,        f_newer,        F_TIME_B },
+       { "-Btime",     c_Xtime,        f_Xtime,        F_TIME_B },
        { "-a",         c_and,          NULL,           0 },
+#ifndef __APPLE__
+       { "-acl",       c_acl,          f_acl,          0 },
+#endif /* !__APPLE__ */
        { "-amin",      c_Xmin,         f_Xmin,         F_TIME_A },
        { "-and",       c_and,          NULL,           0 },
        { "-anewer",    c_newer,        f_newer,        F_TIME_A },
@@ -68,20 +77,14 @@ static OPTION const options[] = {
        { "-cnewer",    c_newer,        f_newer,        F_TIME_C },
        { "-ctime",     c_Xtime,        f_Xtime,        F_TIME_C },
        { "-delete",    c_delete,       f_delete,       0 },
-       { "-depth",     c_depth,        f_always_true,  0 },
+       { "-depth",     c_depth,        f_depth,        0 },
        { "-empty",     c_empty,        f_empty,        0 },
        { "-exec",      c_exec,         f_exec,         0 },
        { "-execdir",   c_exec,         f_exec,         F_EXECDIR },
        { "-false",     c_simple,       f_not,          0 },
        { "-flags",     c_flags,        f_flags,        0 },
        { "-follow",    c_follow,       f_always_true,  0 },
-/*
- * NetBSD doesn't provide a getvfsbyname(), so this option
- * is not available if using a NetBSD kernel.
- */
-#if !defined(__NetBSD__)
        { "-fstype",    c_fstype,       f_fstype,       0 },
-#endif
        { "-group",     c_group,        f_group,        0 },
        { "-iname",     c_name,         f_name,         F_IGNCASE },
        { "-inum",      c_inum,         f_inum,         0 },
@@ -96,14 +99,22 @@ static OPTION const options[] = {
        { "-mtime",     c_Xtime,        f_Xtime,        0 },
        { "-name",      c_name,         f_name,         0 },
        { "-newer",     c_newer,        f_newer,        0 },
+       { "-newerBB",   c_newer,        f_newer,        F_TIME_B | F_TIME2_B },
+       { "-newerBa",   c_newer,        f_newer,        F_TIME_B | F_TIME2_A },
+       { "-newerBc",   c_newer,        f_newer,        F_TIME_B | F_TIME2_C },
+       { "-newerBm",   c_newer,        f_newer,        F_TIME_B },
+       { "-newerBt",   c_newer,        f_newer,        F_TIME_B | F_TIME2_T },
+       { "-neweraB",   c_newer,        f_newer,        F_TIME_A | F_TIME2_B },
        { "-neweraa",   c_newer,        f_newer,        F_TIME_A | F_TIME2_A },
        { "-newerac",   c_newer,        f_newer,        F_TIME_A | F_TIME2_C },
        { "-neweram",   c_newer,        f_newer,        F_TIME_A },
        { "-newerat",   c_newer,        f_newer,        F_TIME_A | F_TIME2_T },
+       { "-newercB",   c_newer,        f_newer,        F_TIME_C | F_TIME2_B },
        { "-newerca",   c_newer,        f_newer,        F_TIME_C | F_TIME2_A },
        { "-newercc",   c_newer,        f_newer,        F_TIME_C | F_TIME2_C },
        { "-newercm",   c_newer,        f_newer,        F_TIME_C },
        { "-newerct",   c_newer,        f_newer,        F_TIME_C | F_TIME2_T },
+       { "-newermB",   c_newer,        f_newer,        F_TIME2_B },
        { "-newerma",   c_newer,        f_newer,        F_TIME2_A },
        { "-newermc",   c_newer,        f_newer,        F_TIME2_C },
        { "-newermm",   c_newer,        f_newer,        0 },
@@ -136,17 +147,16 @@ static OPTION const options[] = {
  *     this switch stuff.
  */
 PLAN *
-find_create(argvp)
-       char ***argvp;
+find_create(char ***argvp)
 {
-       register OPTION *p;
+       OPTION *p;
        PLAN *new;
        char **argv;
 
        argv = *argvp;
 
-       if ((p = option(*argv)) == NULL)
-               errx(1, "%s: unknown expression primary", *argv);
+       if ((p = lookup_option(*argv)) == NULL)
+               errx(1, "%s: unknown option", *argv);
        ++argv;
 
        new = (p->create)(p, &argv);
@@ -155,11 +165,9 @@ find_create(argvp)
 }
 
 OPTION *
-option(name)
-       char *name;
+lookup_option(const char *name)
 {
        OPTION tmp;
-       int typecompare __P((const void *, const void *));
 
        tmp.name = name;
        return ((OPTION *)bsearch(&tmp, options,
@@ -167,8 +175,7 @@ option(name)
 }
 
 int
-typecompare(a, b)
-       const void *a, *b;
+typecompare(const void *a, const void *b)
 {
-       return (strcmp(((OPTION *)a)->name, ((OPTION *)b)->name));
+       return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
 }
diff --git a/find/y.tab.c b/find/y.tab.c
deleted file mode 100644 (file)
index 573e775..0000000
+++ /dev/null
@@ -1,1542 +0,0 @@
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char yysccsid[] = "@(#)yaccpar  1.9 (Berkeley) 02/21/93";
-#else
-__IDSTRING(yyrcsid, "$NetBSD: skeleton.c,v 1.14 1997/10/20 03:41:16 lukem Exp $");
-#endif
-#endif
-#include <stdlib.h>
-#define YYBYACC 1
-#define YYMAJOR 1
-#define YYMINOR 9
-#define YYLEX yylex()
-#define YYEMPTY -1
-#define yyclearin (yychar=(YYEMPTY))
-#define yyerrok (yyerrflag=0)
-#define YYRECOVERING (yyerrflag!=0)
-#define YYPREFIX "yy"
-#line 2 "getdate.y"
-/*
-**  Originally written by Steven M. Bellovin <smb@research.att.com> while
-**  at the University of North Carolina at Chapel Hill.  Later tweaked by
-**  a couple of people on Usenet.  Completely overhauled by Rich $alz
-**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
-**
-**  This grammar has 10 shift/reduce conflicts.
-**
-**  This code is in the public domain and has no copyright.
-*/
-/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
-/* SUPPRESS 288 on yyerrlab *//* Label unused */
-
-#ifdef HAVE_CONFIG_H
-#if defined (emacs) || defined (CONFIG_BROKETS)
-#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
-/* Since the code of getdate.y is not included in the Emacs executable
-   itself, there is no need to #define static in this file.  Even if
-   the code were included in the Emacs executable, it probably
-   wouldn't do any harm to #undef it here; this will only cause
-   problems if we try to write to a static variable, which I don't
-   think this code needs to do.  */
-#ifdef emacs
-#undef static
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-/* The code at the top of get_date which figures out the offset of the
-   current time zone checks various CPP symbols to see if special
-   tricks are need, but defaults to using the gettimeofday system call.
-   Include <sys/time.h> if that will be used.  */
-
-#if    defined(vms)
-# include <types.h>
-#else /* defined(vms) */
-# include <sys/types.h>
-/* don't need xtime.h */
-# include <sys/time.h>
-# include <time.h>
-#endif /* !defined(vms) */
-
-#include <sys/timeb.h>
-
-#if defined (STDC_HEADERS) || defined (USG)
-#include <string.h>
-#endif
-
-/* Some old versions of bison generate parsers that use bcopy.
-   That loses on systems that don't provide the function, so we have
-   to redefine it here.  */
-#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
-#define bcopy(from, to, len) memcpy ((to), (from), (len))
-#endif
-
-#if defined (STDC_HEADERS)
-#include <stdlib.h>
-#endif
-
-/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
-   releases):
-
-   We don't want to mess with all the portability hassles of alloca.
-   In particular, most (all?) versions of bison will use alloca in
-   their parser.  If bison works on your system (e.g. it should work
-   with gcc), then go ahead and use it, but the more general solution
-   is to use byacc instead of bison, which should generate a portable
-   parser.  I played with adding "#define alloca dont_use_alloca", to
-   give an error if the parser generator uses alloca (and thus detect
-   unportable getdate.c's), but that seems to cause as many problems
-   as it solves.  */
-
-extern struct tm       *gmtime();
-extern struct tm       *localtime();
-
-#define yyparse getdate_yyparse
-#define yylex getdate_yylex
-#define yyerror getdate_yyerror
-
-static int yyparse ();
-static int yylex ();
-static int yyerror ();
-
-#define EPOCH          1970
-#define HOUR(x)                ((time_t)(x) * 60)
-#define SECSPERDAY     (24L * 60L * 60L)
-
-
-/*
-**  An entry in the lexical lookup table.
-*/
-typedef struct _TABLE {
-    char       *name;
-    int                type;
-    time_t     value;
-} TABLE;
-
-
-/*
-**  Daylight-savings mode:  on, off, or not yet known.
-*/
-typedef enum _DSTMODE {
-    DSTon, DSToff, DSTmaybe
-} DSTMODE;
-
-/*
-**  Meridian:  am, pm, or 24-hour style.
-*/
-typedef enum _MERIDIAN {
-    MERam, MERpm, MER24
-} MERIDIAN;
-
-
-/*
-**  Global variables.  We could get rid of most of these by using a good
-**  union as the yacc stack.  (This routine was originally written before
-**  yacc had the %union construct.)  Maybe someday; right now we only use
-**  the %union very rarely.
-*/
-static char    *yyInput;
-static DSTMODE yyDSTmode;
-static time_t  yyDayOrdinal;
-static time_t  yyDayNumber;
-static int     yyHaveDate;
-static int     yyHaveDay;
-static int     yyHaveRel;
-static int     yyHaveTime;
-static int     yyHaveZone;
-static time_t  yyTimezone;
-static time_t  yyDay;
-static time_t  yyHour;
-static time_t  yyMinutes;
-static time_t  yyMonth;
-static time_t  yySeconds;
-static time_t  yyYear;
-static MERIDIAN        yyMeridian;
-static time_t  yyRelMonth;
-static time_t  yyRelSeconds;
-
-#line 150 "getdate.y"
-typedef union {
-    time_t             Number;
-    enum _MERIDIAN     Meridian;
-} YYSTYPE;
-#line 172 "y.tab.c"
-#define tAGO 257
-#define tDAY 258
-#define tDAYZONE 259
-#define tID 260
-#define tMERIDIAN 261
-#define tMINUTE_UNIT 262
-#define tMONTH 263
-#define tMONTH_UNIT 264
-#define tSEC_UNIT 265
-#define tSNUMBER 266
-#define tUNUMBER 267
-#define tZONE 268
-#define tDST 269
-#define YYERRCODE 256
-short yylhs[] = {                                        -1,
-    0,    0,    2,    2,    2,    2,    2,    2,    3,    3,
-    3,    3,    3,    4,    4,    4,    6,    6,    6,    5,
-    5,    5,    5,    5,    5,    5,    5,    7,    7,    9,
-    9,    9,    9,    9,    9,    9,    9,    9,    8,    1,
-    1,
-};
-short yylen[] = {                                         2,
-    0,    2,    1,    1,    1,    1,    1,    1,    2,    4,
-    4,    6,    6,    1,    1,    2,    1,    2,    2,    3,
-    5,    3,    3,    2,    4,    2,    3,    2,    1,    2,
-    2,    1,    2,    2,    1,    2,    2,    1,    1,    0,
-    1,
-};
-short yydefred[] = {                                      1,
-    0,    0,   15,   32,    0,   38,   35,    0,    0,    0,
-    2,    3,    4,    5,    6,    7,    8,    0,   18,    0,
-   31,   36,   33,   19,    9,   30,    0,   37,   34,    0,
-    0,    0,   16,   28,    0,   23,   27,   22,    0,    0,
-   25,   41,   11,    0,   10,    0,    0,   21,   13,   12,
-};
-short yydgoto[] = {                                       1,
-   45,   11,   12,   13,   14,   15,   16,   17,   18,
-};
-short yysindex[] = {                                      0,
- -249,  -38,    0,    0, -260,    0,    0, -240,  -47, -248,
-    0,    0,    0,    0,    0,    0,    0, -237,    0,  -18,
-    0,    0,    0,    0,    0,    0, -262,    0,    0, -239,
- -238, -236,    0,    0, -235,    0,    0,    0,  -56,  -19,
-    0,    0,    0, -234,    0, -232, -258,    0,    0,    0,
-};
-short yyrindex[] = {                                      0,
-    0,    1,    0,    0,    0,    0,    0,    0,   69,   12,
-    0,    0,    0,    0,    0,    0,    0,   23,    0,   34,
-    0,    0,    0,    0,    0,    0,   67,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,   56,   45,
-    0,    0,    0,    0,    0,    0,   56,    0,    0,    0,
-};
-short yygindex[] = {                                      0,
-  -17,    0,    0,    0,    0,    0,    0,    0,    0,
-};
-#define YYTABLESIZE 337
-short yytable[] = {                                      32,
-   17,   44,   42,   36,   37,   19,   20,   49,    2,    3,
-   31,   14,    4,    5,    6,    7,    8,    9,   10,   34,
-   33,   21,   29,   22,   23,   35,   38,   46,   39,   50,
-   40,   41,   47,   24,   48,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,   20,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,   40,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,   26,    0,   39,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,   42,    0,    0,    0,    0,   43,
-   24,    0,    0,   25,   26,   27,   28,   29,   30,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,   17,   17,
-    0,    0,   17,   17,   17,   17,   17,   17,   17,   14,
-   14,    0,    0,   14,   14,   14,   14,   14,   14,   14,
-   29,   29,    0,    0,   29,   29,   29,   29,   29,   29,
-   29,   24,   24,    0,    0,   24,   24,   24,   24,   24,
-   24,   24,   20,   20,    0,    0,   20,   20,   20,   20,
-   20,   20,   20,   40,   40,    0,    0,   40,   40,   40,
-   40,    0,   40,   40,   26,   26,    0,   39,   26,   26,
-   26,   26,    0,    0,   26,   39,   39,
-};
-short yycheck[] = {                                      47,
-    0,   58,  261,  266,  267,   44,  267,  266,  258,  259,
-   58,    0,  262,  263,  264,  265,  266,  267,  268,  257,
-  269,  262,    0,  264,  265,   44,  266,   47,  267,   47,
-  267,  267,  267,    0,  267,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,    0,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,  261,   -1,   -1,   -1,   -1,  266,
-  258,   -1,   -1,  261,  262,  263,  264,  265,  266,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  258,  259,
-   -1,   -1,  262,  263,  264,  265,  266,  267,  268,  258,
-  259,   -1,   -1,  262,  263,  264,  265,  266,  267,  268,
-  258,  259,   -1,   -1,  262,  263,  264,  265,  266,  267,
-  268,  258,  259,   -1,   -1,  262,  263,  264,  265,  266,
-  267,  268,  258,  259,   -1,   -1,  262,  263,  264,  265,
-  266,  267,  268,  258,  259,   -1,   -1,  262,  263,  264,
-  265,   -1,  267,  268,  258,  259,   -1,  259,  262,  263,
-  264,  265,   -1,   -1,  268,  267,  268,
-};
-#define YYFINAL 1
-#ifndef YYDEBUG
-#define YYDEBUG 0
-#endif
-#define YYMAXTOKEN 269
-#if YYDEBUG
-char *yyname[] = {
-"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,"','",0,0,"'/'",0,0,0,0,0,0,0,0,0,0,"':'",0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tAGO","tDAY",
-"tDAYZONE","tID","tMERIDIAN","tMINUTE_UNIT","tMONTH","tMONTH_UNIT","tSEC_UNIT",
-"tSNUMBER","tUNUMBER","tZONE","tDST",
-};
-char *yyrule[] = {
-"$accept : spec",
-"spec :",
-"spec : spec item",
-"item : time",
-"item : zone",
-"item : date",
-"item : day",
-"item : rel",
-"item : number",
-"time : tUNUMBER tMERIDIAN",
-"time : tUNUMBER ':' tUNUMBER o_merid",
-"time : tUNUMBER ':' tUNUMBER tSNUMBER",
-"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
-"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
-"zone : tZONE",
-"zone : tDAYZONE",
-"zone : tZONE tDST",
-"day : tDAY",
-"day : tDAY ','",
-"day : tUNUMBER tDAY",
-"date : tUNUMBER '/' tUNUMBER",
-"date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
-"date : tUNUMBER tSNUMBER tSNUMBER",
-"date : tUNUMBER tMONTH tSNUMBER",
-"date : tMONTH tUNUMBER",
-"date : tMONTH tUNUMBER ',' tUNUMBER",
-"date : tUNUMBER tMONTH",
-"date : tUNUMBER tMONTH tUNUMBER",
-"rel : relunit tAGO",
-"rel : relunit",
-"relunit : tUNUMBER tMINUTE_UNIT",
-"relunit : tSNUMBER tMINUTE_UNIT",
-"relunit : tMINUTE_UNIT",
-"relunit : tSNUMBER tSEC_UNIT",
-"relunit : tUNUMBER tSEC_UNIT",
-"relunit : tSEC_UNIT",
-"relunit : tSNUMBER tMONTH_UNIT",
-"relunit : tUNUMBER tMONTH_UNIT",
-"relunit : tMONTH_UNIT",
-"number : tUNUMBER",
-"o_merid :",
-"o_merid : tMERIDIAN",
-};
-#endif
-#ifdef YYSTACKSIZE
-#undef YYMAXDEPTH
-#define YYMAXDEPTH YYSTACKSIZE
-#else
-#ifdef YYMAXDEPTH
-#define YYSTACKSIZE YYMAXDEPTH
-#else
-#define YYSTACKSIZE 10000
-#define YYMAXDEPTH 10000
-#endif
-#endif
-#define YYINITSTACKSIZE 200
-int yydebug;
-int yynerrs;
-int yyerrflag;
-int yychar;
-short *yyssp;
-YYSTYPE *yyvsp;
-YYSTYPE yyval;
-YYSTYPE yylval;
-short *yyss;
-short *yysslim;
-YYSTYPE *yyvs;
-int yystacksize;
-#line 369 "getdate.y"
-
-/* Month and day table. */
-static TABLE const MonthDayTable[] = {
-    { "january",       tMONTH,  1 },
-    { "february",      tMONTH,  2 },
-    { "march",         tMONTH,  3 },
-    { "april",         tMONTH,  4 },
-    { "may",           tMONTH,  5 },
-    { "june",          tMONTH,  6 },
-    { "july",          tMONTH,  7 },
-    { "august",                tMONTH,  8 },
-    { "september",     tMONTH,  9 },
-    { "sept",          tMONTH,  9 },
-    { "october",       tMONTH, 10 },
-    { "november",      tMONTH, 11 },
-    { "december",      tMONTH, 12 },
-    { "sunday",                tDAY, 0 },
-    { "monday",                tDAY, 1 },
-    { "tuesday",       tDAY, 2 },
-    { "tues",          tDAY, 2 },
-    { "wednesday",     tDAY, 3 },
-    { "wednes",                tDAY, 3 },
-    { "thursday",      tDAY, 4 },
-    { "thur",          tDAY, 4 },
-    { "thurs",         tDAY, 4 },
-    { "friday",                tDAY, 5 },
-    { "saturday",      tDAY, 6 },
-    { NULL }
-};
-
-/* Time units table. */
-static TABLE const UnitsTable[] = {
-    { "year",          tMONTH_UNIT,    12 },
-    { "month",         tMONTH_UNIT,    1 },
-    { "fortnight",     tMINUTE_UNIT,   14 * 24 * 60 },
-    { "week",          tMINUTE_UNIT,   7 * 24 * 60 },
-    { "day",           tMINUTE_UNIT,   1 * 24 * 60 },
-    { "hour",          tMINUTE_UNIT,   60 },
-    { "minute",                tMINUTE_UNIT,   1 },
-    { "min",           tMINUTE_UNIT,   1 },
-    { "second",                tSEC_UNIT,      1 },
-    { "sec",           tSEC_UNIT,      1 },
-    { NULL }
-};
-
-/* Assorted relative-time words. */
-static TABLE const OtherTable[] = {
-    { "tomorrow",      tMINUTE_UNIT,   1 * 24 * 60 },
-    { "yesterday",     tMINUTE_UNIT,   -1 * 24 * 60 },
-    { "today",         tMINUTE_UNIT,   0 },
-    { "now",           tMINUTE_UNIT,   0 },
-    { "last",          tUNUMBER,       -1 },
-    { "this",          tMINUTE_UNIT,   0 },
-    { "next",          tUNUMBER,       2 },
-    { "first",         tUNUMBER,       1 },
-/*  { "second",                tUNUMBER,       2 }, */
-    { "third",         tUNUMBER,       3 },
-    { "fourth",                tUNUMBER,       4 },
-    { "fifth",         tUNUMBER,       5 },
-    { "sixth",         tUNUMBER,       6 },
-    { "seventh",       tUNUMBER,       7 },
-    { "eighth",                tUNUMBER,       8 },
-    { "ninth",         tUNUMBER,       9 },
-    { "tenth",         tUNUMBER,       10 },
-    { "eleventh",      tUNUMBER,       11 },
-    { "twelfth",       tUNUMBER,       12 },
-    { "ago",           tAGO,   1 },
-    { NULL }
-};
-
-/* The timezone table. */
-/* Some of these are commented out because a time_t can't store a float. */
-static TABLE const TimezoneTable[] = {
-    { "gmt",   tZONE,     HOUR( 0) },  /* Greenwich Mean */
-    { "ut",    tZONE,     HOUR( 0) },  /* Universal (Coordinated) */
-    { "utc",   tZONE,     HOUR( 0) },
-    { "wet",   tZONE,     HOUR( 0) },  /* Western European */
-    { "bst",   tDAYZONE,  HOUR( 0) },  /* British Summer */
-    { "wat",   tZONE,     HOUR( 1) },  /* West Africa */
-    { "at",    tZONE,     HOUR( 2) },  /* Azores */
-#if    0
-    /* For completeness.  BST is also British Summer, and GST is
-     * also Guam Standard. */
-    { "bst",   tZONE,     HOUR( 3) },  /* Brazil Standard */
-    { "gst",   tZONE,     HOUR( 3) },  /* Greenland Standard */
-#endif
-#if 0
-    { "nft",   tZONE,     HOUR(3.5) }, /* Newfoundland */
-    { "nst",   tZONE,     HOUR(3.5) }, /* Newfoundland Standard */
-    { "ndt",   tDAYZONE,  HOUR(3.5) }, /* Newfoundland Daylight */
-#endif
-    { "ast",   tZONE,     HOUR( 4) },  /* Atlantic Standard */
-    { "adt",   tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
-    { "est",   tZONE,     HOUR( 5) },  /* Eastern Standard */
-    { "edt",   tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
-    { "cst",   tZONE,     HOUR( 6) },  /* Central Standard */
-    { "cdt",   tDAYZONE,  HOUR( 6) },  /* Central Daylight */
-    { "mst",   tZONE,     HOUR( 7) },  /* Mountain Standard */
-    { "mdt",   tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
-    { "pst",   tZONE,     HOUR( 8) },  /* Pacific Standard */
-    { "pdt",   tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
-    { "yst",   tZONE,     HOUR( 9) },  /* Yukon Standard */
-    { "ydt",   tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
-    { "hst",   tZONE,     HOUR(10) },  /* Hawaii Standard */
-    { "hdt",   tDAYZONE,  HOUR(10) },  /* Hawaii Daylight */
-    { "cat",   tZONE,     HOUR(10) },  /* Central Alaska */
-    { "ahst",  tZONE,     HOUR(10) },  /* Alaska-Hawaii Standard */
-    { "nt",    tZONE,     HOUR(11) },  /* Nome */
-    { "idlw",  tZONE,     HOUR(12) },  /* International Date Line West */
-    { "cet",   tZONE,     -HOUR(1) },  /* Central European */
-    { "met",   tZONE,     -HOUR(1) },  /* Middle European */
-    { "mewt",  tZONE,     -HOUR(1) },  /* Middle European Winter */
-    { "mest",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
-    { "swt",   tZONE,     -HOUR(1) },  /* Swedish Winter */
-    { "sst",   tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
-    { "fwt",   tZONE,     -HOUR(1) },  /* French Winter */
-    { "fst",   tDAYZONE,  -HOUR(1) },  /* French Summer */
-    { "eet",   tZONE,     -HOUR(2) },  /* Eastern Europe, USSR Zone 1 */
-    { "bt",    tZONE,     -HOUR(3) },  /* Baghdad, USSR Zone 2 */
-#if 0
-    { "it",    tZONE,     -HOUR(3.5) },/* Iran */
-#endif
-    { "zp4",   tZONE,     -HOUR(4) },  /* USSR Zone 3 */
-    { "zp5",   tZONE,     -HOUR(5) },  /* USSR Zone 4 */
-#if 0
-    { "ist",   tZONE,     -HOUR(5.5) },/* Indian Standard */
-#endif
-    { "zp6",   tZONE,     -HOUR(6) },  /* USSR Zone 5 */
-#if    0
-    /* For completeness.  NST is also Newfoundland Stanard, and SST is
-     * also Swedish Summer. */
-    { "nst",   tZONE,     -HOUR(6.5) },/* North Sumatra */
-    { "sst",   tZONE,     -HOUR(7) },  /* South Sumatra, USSR Zone 6 */
-#endif /* 0 */
-    { "wast",  tZONE,     -HOUR(7) },  /* West Australian Standard */
-    { "wadt",  tDAYZONE,  -HOUR(7) },  /* West Australian Daylight */
-#if 0
-    { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
-#endif
-    { "cct",   tZONE,     -HOUR(8) },  /* China Coast, USSR Zone 7 */
-    { "jst",   tZONE,     -HOUR(9) },  /* Japan Standard, USSR Zone 8 */
-#if 0
-    { "cast",  tZONE,     -HOUR(9.5) },/* Central Australian Standard */
-    { "cadt",  tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
-#endif
-    { "east",  tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
-    { "eadt",  tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
-    { "gst",   tZONE,     -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
-    { "nzt",   tZONE,     -HOUR(12) }, /* New Zealand */
-    { "nzst",  tZONE,     -HOUR(12) }, /* New Zealand Standard */
-    { "nzdt",  tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
-    { "idle",  tZONE,     -HOUR(12) }, /* International Date Line East */
-    {  NULL  }
-};
-
-/* Military timezone table. */
-static TABLE const MilitaryTable[] = {
-    { "a",     tZONE,  HOUR(  1) },
-    { "b",     tZONE,  HOUR(  2) },
-    { "c",     tZONE,  HOUR(  3) },
-    { "d",     tZONE,  HOUR(  4) },
-    { "e",     tZONE,  HOUR(  5) },
-    { "f",     tZONE,  HOUR(  6) },
-    { "g",     tZONE,  HOUR(  7) },
-    { "h",     tZONE,  HOUR(  8) },
-    { "i",     tZONE,  HOUR(  9) },
-    { "k",     tZONE,  HOUR( 10) },
-    { "l",     tZONE,  HOUR( 11) },
-    { "m",     tZONE,  HOUR( 12) },
-    { "n",     tZONE,  HOUR(- 1) },
-    { "o",     tZONE,  HOUR(- 2) },
-    { "p",     tZONE,  HOUR(- 3) },
-    { "q",     tZONE,  HOUR(- 4) },
-    { "r",     tZONE,  HOUR(- 5) },
-    { "s",     tZONE,  HOUR(- 6) },
-    { "t",     tZONE,  HOUR(- 7) },
-    { "u",     tZONE,  HOUR(- 8) },
-    { "v",     tZONE,  HOUR(- 9) },
-    { "w",     tZONE,  HOUR(-10) },
-    { "x",     tZONE,  HOUR(-11) },
-    { "y",     tZONE,  HOUR(-12) },
-    { "z",     tZONE,  HOUR(  0) },
-    { NULL }
-};
-
-\f
-
-
-/* ARGSUSED */
-static int
-yyerror(s)
-    char       *s;
-{
-  return 0;
-}
-
-
-static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-{
-    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
-       return -1;
-    switch (Meridian) {
-    case MER24:
-       if (Hours < 0 || Hours > 23)
-           return -1;
-       return (Hours * 60L + Minutes) * 60L + Seconds;
-    case MERam:
-       if (Hours < 1 || Hours > 12)
-           return -1;
-       if (Hours == 12)
-           Hours = 0;
-       return (Hours * 60L + Minutes) * 60L + Seconds;
-    case MERpm:
-       if (Hours < 1 || Hours > 12)
-           return -1;
-       if (Hours == 12)
-           Hours = 0;
-       return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
-    default:
-       abort ();
-    }
-    /* NOTREACHED */
-}
-
-
-/* Year is either
-   * A negative number, which means to use its absolute value (why?)
-   * A number from 0 to 99, which means a year from 1900 to 1999, or
-   * The actual year (>=100).  */
-static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
-    time_t     Month;
-    time_t     Day;
-    time_t     Year;
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-    DSTMODE    DSTmode;
-{
-    static int DaysInMonth[12] = {
-       31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-    };
-    time_t     tod;
-    time_t     Julian;
-    int                i;
-
-    if (Year < 0)
-       Year = -Year;
-    if (Year < 69)
-       Year += 2000;
-    else if (Year < 100)
-       Year += 1900;
-    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
-                   ? 29 : 28;
-    /* Checking for 2038 bogusly assumes that time_t is 32 bits.  But
-       I'm too lazy to try to check for time_t overflow in another way.  */
-    if (Year < EPOCH || Year > 2038
-     || Month < 1 || Month > 12
-     /* Lint fluff:  "conversion from long may lose accuracy" */
-     || Day < 1 || Day > DaysInMonth[(int)--Month])
-       return -1;
-
-    for (Julian = Day - 1, i = 0; i < Month; i++)
-       Julian += DaysInMonth[i];
-    for (i = EPOCH; i < Year; i++)
-       Julian += 365 + (i % 4 == 0);
-    Julian *= SECSPERDAY;
-    Julian += yyTimezone * 60L;
-    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
-       return -1;
-    Julian += tod;
-    if (DSTmode == DSTon
-     || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
-       Julian -= 60 * 60;
-    return Julian;
-}
-
-
-static time_t
-DSTcorrect(Start, Future)
-    time_t     Start;
-    time_t     Future;
-{
-    time_t     StartDay;
-    time_t     FutureDay;
-
-    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
-    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
-    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
-}
-
-
-static time_t
-RelativeDate(Start, DayOrdinal, DayNumber)
-    time_t     Start;
-    time_t     DayOrdinal;
-    time_t     DayNumber;
-{
-    struct tm  *tm;
-    time_t     now;
-
-    now = Start;
-    tm = localtime(&now);
-    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
-    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
-    return DSTcorrect(Start, now);
-}
-
-
-static time_t
-RelativeMonth(Start, RelMonth)
-    time_t     Start;
-    time_t     RelMonth;
-{
-    struct tm  *tm;
-    time_t     Month;
-    time_t     Year;
-
-    if (RelMonth == 0)
-       return 0;
-    tm = localtime(&Start);
-    Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
-    Year = Month / 12;
-    Month = Month % 12 + 1;
-    return DSTcorrect(Start,
-           Convert(Month, (time_t)tm->tm_mday, Year,
-               (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
-               MER24, DSTmaybe));
-}
-
-
-static int
-LookupWord(buff)
-    char               *buff;
-{
-    register char      *p;
-    register char      *q;
-    register const TABLE       *tp;
-    int                        i;
-    int                        abbrev;
-
-    /* Make it lowercase. */
-    for (p = buff; *p; p++)
-       if (isupper(*p))
-           *p = tolower(*p);
-
-    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
-       yylval.Meridian = MERam;
-       return tMERIDIAN;
-    }
-    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
-       yylval.Meridian = MERpm;
-       return tMERIDIAN;
-    }
-
-    /* See if we have an abbreviation for a month. */
-    if (strlen(buff) == 3)
-       abbrev = 1;
-    else if (strlen(buff) == 4 && buff[3] == '.') {
-       abbrev = 1;
-       buff[3] = '\0';
-    }
-    else
-       abbrev = 0;
-
-    for (tp = MonthDayTable; tp->name; tp++) {
-       if (abbrev) {
-           if (strncmp(buff, tp->name, 3) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-       }
-       else if (strcmp(buff, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-    }
-
-    for (tp = TimezoneTable; tp->name; tp++)
-       if (strcmp(buff, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-
-    if (strcmp(buff, "dst") == 0) 
-       return tDST;
-
-    for (tp = UnitsTable; tp->name; tp++)
-       if (strcmp(buff, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-
-    /* Strip off any plural and try the units table again. */
-    i = strlen(buff) - 1;
-    if (buff[i] == 's') {
-       buff[i] = '\0';
-       for (tp = UnitsTable; tp->name; tp++)
-           if (strcmp(buff, tp->name) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-       buff[i] = 's';          /* Put back for "this" in OtherTable. */
-    }
-
-    for (tp = OtherTable; tp->name; tp++)
-       if (strcmp(buff, tp->name) == 0) {
-           yylval.Number = tp->value;
-           return tp->type;
-       }
-
-    /* Military timezones. */
-    if (buff[1] == '\0' && isalpha(*buff)) {
-       for (tp = MilitaryTable; tp->name; tp++)
-           if (strcmp(buff, tp->name) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-    }
-
-    /* Drop out any periods and try the timezone table again. */
-    for (i = 0, p = q = buff; *q; q++)
-       if (*q != '.')
-           *p++ = *q;
-       else
-           i++;
-    *p = '\0';
-    if (i)
-       for (tp = TimezoneTable; tp->name; tp++)
-           if (strcmp(buff, tp->name) == 0) {
-               yylval.Number = tp->value;
-               return tp->type;
-           }
-
-    return tID;
-}
-
-
-static int
-yylex()
-{
-    register char      c;
-    register char      *p;
-    char               buff[20];
-    int                        Count;
-    int                        sign;
-
-    for ( ; ; ) {
-       while (isspace(*yyInput))
-           yyInput++;
-
-       if (isdigit(c = *yyInput) || c == '-' || c == '+') {
-           if (c == '-' || c == '+') {
-               sign = c == '-' ? -1 : 1;
-               if (!isdigit(*++yyInput))
-                   /* skip the '-' sign */
-                   continue;
-           }
-           else
-               sign = 0;
-           for (yylval.Number = 0; isdigit(c = *yyInput++); )
-               yylval.Number = 10 * yylval.Number + c - '0';
-           yyInput--;
-           if (sign < 0)
-               yylval.Number = -yylval.Number;
-           return sign ? tSNUMBER : tUNUMBER;
-       }
-       if (isalpha(c)) {
-           for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
-               if (p < &buff[sizeof buff - 1])
-                   *p++ = c;
-           *p = '\0';
-           yyInput--;
-           return LookupWord(buff);
-       }
-       if (c != '(')
-           return *yyInput++;
-       Count = 0;
-       do {
-           c = *yyInput++;
-           if (c == '\0')
-               return c;
-           if (c == '(')
-               Count++;
-           else if (c == ')')
-               Count--;
-       } while (Count > 0);
-    }
-}
-
-#define TM_YEAR_ORIGIN 1900
-
-/* Yield A - B, measured in seconds.  */
-static long
-difftm (a, b)
-     struct tm *a, *b;
-{
-  int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
-  int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
-  int days = (
-             /* difference in day of year */
-             a->tm_yday - b->tm_yday
-             /* + intervening leap days */
-             +  ((ay >> 2) - (by >> 2))
-             -  (ay/100 - by/100)
-             +  ((ay/100 >> 2) - (by/100 >> 2))
-             /* + difference in years * 365 */
-             +  (long)(ay-by) * 365
-             );
-  return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
-             + (a->tm_min - b->tm_min))
-         + (a->tm_sec - b->tm_sec));
-}
-
-time_t
-get_date(p, now)
-    char               *p;
-    struct timeb       *now;
-{
-    struct tm          *tm, gmt;
-    struct timeb       ftz;
-    time_t             Start;
-    time_t             tod;
-    time_t nowtime;
-
-    yyInput = p;
-    if (now == NULL) {
-       struct tm *gmt_ptr;
-
-        now = &ftz;
-       (void)time (&nowtime);
-
-       gmt_ptr = gmtime (&nowtime);
-       if (gmt_ptr != NULL)
-       {
-           /* Make a copy, in case localtime modifies *tm (I think
-              that comment now applies to *gmt_ptr, but I am too
-              lazy to dig into how gmtime and locatime allocate the
-              structures they return pointers to).  */
-           gmt = *gmt_ptr;
-       }
-
-       if (! (tm = localtime (&nowtime)))
-           return -1;
-
-       if (gmt_ptr != NULL)
-           ftz.timezone = difftm (&gmt, tm) / 60;
-       else
-           /* We are on a system like VMS, where the system clock is
-              in local time and the system has no concept of timezones.
-              Hopefully we can fake this out (for the case in which the
-              user specifies no timezone) by just saying the timezone
-              is zero.  */
-           ftz.timezone = 0;
-
-       if(tm->tm_isdst)
-           ftz.timezone += 60;
-    }
-    else
-    {
-       nowtime = now->time;
-    }
-
-    tm = localtime(&nowtime);
-    yyYear = tm->tm_year + 1900;
-    yyMonth = tm->tm_mon + 1;
-    yyDay = tm->tm_mday;
-    yyTimezone = now->timezone;
-    yyDSTmode = DSTmaybe;
-    yyHour = 0;
-    yyMinutes = 0;
-    yySeconds = 0;
-    yyMeridian = MER24;
-    yyRelSeconds = 0;
-    yyRelMonth = 0;
-    yyHaveDate = 0;
-    yyHaveDay = 0;
-    yyHaveRel = 0;
-    yyHaveTime = 0;
-    yyHaveZone = 0;
-
-    if (yyparse()
-     || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
-       return -1;
-
-    if (yyHaveDate || yyHaveTime || yyHaveDay) {
-       Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
-                   yyMeridian, yyDSTmode);
-       if (Start < 0)
-           return -1;
-    }
-    else {
-       Start = nowtime;
-       if (!yyHaveRel)
-           Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
-    }
-
-    Start += yyRelSeconds;
-    Start += RelativeMonth(Start, yyRelMonth);
-
-    if (yyHaveDay && !yyHaveDate) {
-       tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
-       Start += tod;
-    }
-
-    /* Have to do *something* with a legitimate -1 so it's distinguishable
-     * from the error return value.  (Alternately could set errno on error.) */
-    return Start == -1 ? 0 : Start;
-}
-
-
-#if    defined(TEST)
-
-/* ARGSUSED */
-int
-main(ac, av)
-    int                ac;
-    char       *av[];
-{
-    char       buff[128];
-    time_t     d;
-
-    (void)printf("Enter date, or blank line to exit.\n\t> ");
-    (void)fflush(stdout);
-    while (gets(buff) && buff[0]) {
-       d = get_date(buff, (struct timeb *)NULL);
-       if (d == -1)
-           (void)printf("Bad format - couldn't convert.\n");
-       else
-           (void)printf("%s", ctime(&d));
-       (void)printf("\t> ");
-       (void)fflush(stdout);
-    }
-    exit(0);
-    /* NOTREACHED */
-}
-#endif /* defined(TEST) */
-#line 1031 "y.tab.c"
-/* allocate initial stack or double stack size, up to YYMAXDEPTH */
-int yyparse __P((void));
-static int yygrowstack __P((void));
-static int yygrowstack()
-{
-    int newsize, i;
-    short *newss;
-    YYSTYPE *newvs;
-
-    if ((newsize = yystacksize) == 0)
-        newsize = YYINITSTACKSIZE;
-    else if (newsize >= YYMAXDEPTH)
-        return -1;
-    else if ((newsize *= 2) > YYMAXDEPTH)
-        newsize = YYMAXDEPTH;
-    i = yyssp - yyss;
-    if ((newss = (short *)realloc(yyss, newsize * sizeof *newss)) == NULL)
-        return -1;
-    yyss = newss;
-    yyssp = newss + i;
-    if ((newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs)) == NULL)
-        return -1;
-    yyvs = newvs;
-    yyvsp = newvs + i;
-    yystacksize = newsize;
-    yysslim = yyss + newsize - 1;
-    return 0;
-}
-
-#define YYABORT goto yyabort
-#define YYREJECT goto yyabort
-#define YYACCEPT goto yyaccept
-#define YYERROR goto yyerrlab
-int
-yyparse()
-{
-    int yym, yyn, yystate;
-#if YYDEBUG
-    char *yys;
-
-    if ((yys = getenv("YYDEBUG")) != NULL)
-    {
-        yyn = *yys;
-        if (yyn >= '0' && yyn <= '9')
-            yydebug = yyn - '0';
-    }
-#endif
-
-    yynerrs = 0;
-    yyerrflag = 0;
-    yychar = (-1);
-
-    if (yyss == NULL && yygrowstack()) goto yyoverflow;
-    yyssp = yyss;
-    yyvsp = yyvs;
-    *yyssp = yystate = 0;
-
-yyloop:
-    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
-    if (yychar < 0)
-    {
-        if ((yychar = yylex()) < 0) yychar = 0;
-#if YYDEBUG
-        if (yydebug)
-        {
-            yys = 0;
-            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
-            if (!yys) yys = "illegal-symbol";
-            printf("%sdebug: state %d, reading %d (%s)\n",
-                    YYPREFIX, yystate, yychar, yys);
-        }
-#endif
-    }
-    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
-    {
-#if YYDEBUG
-        if (yydebug)
-            printf("%sdebug: state %d, shifting to state %d\n",
-                    YYPREFIX, yystate, yytable[yyn]);
-#endif
-        if (yyssp >= yysslim && yygrowstack())
-        {
-            goto yyoverflow;
-        }
-        *++yyssp = yystate = yytable[yyn];
-        *++yyvsp = yylval;
-        yychar = (-1);
-        if (yyerrflag > 0)  --yyerrflag;
-        goto yyloop;
-    }
-    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
-    {
-        yyn = yytable[yyn];
-        goto yyreduce;
-    }
-    if (yyerrflag) goto yyinrecovery;
-    goto yynewerror;
-yynewerror:
-    yyerror("syntax error");
-    goto yyerrlab;
-yyerrlab:
-    ++yynerrs;
-yyinrecovery:
-    if (yyerrflag < 3)
-    {
-        yyerrflag = 3;
-        for (;;)
-        {
-            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
-                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
-            {
-#if YYDEBUG
-                if (yydebug)
-                    printf("%sdebug: state %d, error recovery shifting\
- to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
-#endif
-                if (yyssp >= yysslim && yygrowstack())
-                {
-                    goto yyoverflow;
-                }
-                *++yyssp = yystate = yytable[yyn];
-                *++yyvsp = yylval;
-                goto yyloop;
-            }
-            else
-            {
-#if YYDEBUG
-                if (yydebug)
-                    printf("%sdebug: error recovery discarding state %d\n",
-                            YYPREFIX, *yyssp);
-#endif
-                if (yyssp <= yyss) goto yyabort;
-                --yyssp;
-                --yyvsp;
-            }
-        }
-    }
-    else
-    {
-        if (yychar == 0) goto yyabort;
-#if YYDEBUG
-        if (yydebug)
-        {
-            yys = 0;
-            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
-            if (!yys) yys = "illegal-symbol";
-            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
-                    YYPREFIX, yystate, yychar, yys);
-        }
-#endif
-        yychar = (-1);
-        goto yyloop;
-    }
-yyreduce:
-#if YYDEBUG
-    if (yydebug)
-        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
-                YYPREFIX, yystate, yyn, yyrule[yyn]);
-#endif
-    yym = yylen[yyn];
-    yyval = yyvsp[1-yym];
-    switch (yyn)
-    {
-case 3:
-#line 168 "getdate.y"
-{
-           yyHaveTime++;
-       }
-break;
-case 4:
-#line 171 "getdate.y"
-{
-           yyHaveZone++;
-       }
-break;
-case 5:
-#line 174 "getdate.y"
-{
-           yyHaveDate++;
-       }
-break;
-case 6:
-#line 177 "getdate.y"
-{
-           yyHaveDay++;
-       }
-break;
-case 7:
-#line 180 "getdate.y"
-{
-           yyHaveRel++;
-       }
-break;
-case 9:
-#line 186 "getdate.y"
-{
-           yyHour = yyvsp[-1].Number;
-           yyMinutes = 0;
-           yySeconds = 0;
-           yyMeridian = yyvsp[0].Meridian;
-       }
-break;
-case 10:
-#line 192 "getdate.y"
-{
-           yyHour = yyvsp[-3].Number;
-           yyMinutes = yyvsp[-1].Number;
-           yySeconds = 0;
-           yyMeridian = yyvsp[0].Meridian;
-       }
-break;
-case 11:
-#line 198 "getdate.y"
-{
-           yyHour = yyvsp[-3].Number;
-           yyMinutes = yyvsp[-1].Number;
-           yyMeridian = MER24;
-           yyDSTmode = DSToff;
-           yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
-       }
-break;
-case 12:
-#line 205 "getdate.y"
-{
-           yyHour = yyvsp[-5].Number;
-           yyMinutes = yyvsp[-3].Number;
-           yySeconds = yyvsp[-1].Number;
-           yyMeridian = yyvsp[0].Meridian;
-       }
-break;
-case 13:
-#line 211 "getdate.y"
-{
-           yyHour = yyvsp[-5].Number;
-           yyMinutes = yyvsp[-3].Number;
-           yySeconds = yyvsp[-1].Number;
-           yyMeridian = MER24;
-           yyDSTmode = DSToff;
-           yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
-       }
-break;
-case 14:
-#line 221 "getdate.y"
-{
-           yyTimezone = yyvsp[0].Number;
-           yyDSTmode = DSToff;
-       }
-break;
-case 15:
-#line 225 "getdate.y"
-{
-           yyTimezone = yyvsp[0].Number;
-           yyDSTmode = DSTon;
-       }
-break;
-case 16:
-#line 230 "getdate.y"
-{
-           yyTimezone = yyvsp[-1].Number;
-           yyDSTmode = DSTon;
-       }
-break;
-case 17:
-#line 236 "getdate.y"
-{
-           yyDayOrdinal = 1;
-           yyDayNumber = yyvsp[0].Number;
-       }
-break;
-case 18:
-#line 240 "getdate.y"
-{
-           yyDayOrdinal = 1;
-           yyDayNumber = yyvsp[-1].Number;
-       }
-break;
-case 19:
-#line 244 "getdate.y"
-{
-           yyDayOrdinal = yyvsp[-1].Number;
-           yyDayNumber = yyvsp[0].Number;
-       }
-break;
-case 20:
-#line 250 "getdate.y"
-{
-           yyMonth = yyvsp[-2].Number;
-           yyDay = yyvsp[0].Number;
-       }
-break;
-case 21:
-#line 254 "getdate.y"
-{
-           if (yyvsp[-4].Number >= 100) {
-               yyYear = yyvsp[-4].Number;
-               yyMonth = yyvsp[-2].Number;
-               yyDay = yyvsp[0].Number;
-           } else {
-               yyMonth = yyvsp[-4].Number;
-               yyDay = yyvsp[-2].Number;
-               yyYear = yyvsp[0].Number;
-           }
-       }
-break;
-case 22:
-#line 265 "getdate.y"
-{
-           /* ISO 8601 format.  yyyy-mm-dd.  */
-           yyYear = yyvsp[-2].Number;
-           yyMonth = -yyvsp[-1].Number;
-           yyDay = -yyvsp[0].Number;
-       }
-break;
-case 23:
-#line 271 "getdate.y"
-{
-           /* e.g. 17-JUN-1992.  */
-           yyDay = yyvsp[-2].Number;
-           yyMonth = yyvsp[-1].Number;
-           yyYear = -yyvsp[0].Number;
-       }
-break;
-case 24:
-#line 277 "getdate.y"
-{
-           yyMonth = yyvsp[-1].Number;
-           yyDay = yyvsp[0].Number;
-       }
-break;
-case 25:
-#line 281 "getdate.y"
-{
-           yyMonth = yyvsp[-3].Number;
-           yyDay = yyvsp[-2].Number;
-           yyYear = yyvsp[0].Number;
-       }
-break;
-case 26:
-#line 286 "getdate.y"
-{
-           yyMonth = yyvsp[0].Number;
-           yyDay = yyvsp[-1].Number;
-       }
-break;
-case 27:
-#line 290 "getdate.y"
-{
-           yyMonth = yyvsp[-1].Number;
-           yyDay = yyvsp[-2].Number;
-           yyYear = yyvsp[0].Number;
-       }
-break;
-case 28:
-#line 297 "getdate.y"
-{
-           yyRelSeconds = -yyRelSeconds;
-           yyRelMonth = -yyRelMonth;
-       }
-break;
-case 30:
-#line 304 "getdate.y"
-{
-           yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
-       }
-break;
-case 31:
-#line 307 "getdate.y"
-{
-           yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
-       }
-break;
-case 32:
-#line 310 "getdate.y"
-{
-           yyRelSeconds += yyvsp[0].Number * 60L;
-       }
-break;
-case 33:
-#line 313 "getdate.y"
-{
-           yyRelSeconds += yyvsp[-1].Number;
-       }
-break;
-case 34:
-#line 316 "getdate.y"
-{
-           yyRelSeconds += yyvsp[-1].Number;
-       }
-break;
-case 35:
-#line 319 "getdate.y"
-{
-           yyRelSeconds++;
-       }
-break;
-case 36:
-#line 322 "getdate.y"
-{
-           yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
-       }
-break;
-case 37:
-#line 325 "getdate.y"
-{
-           yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
-       }
-break;
-case 38:
-#line 328 "getdate.y"
-{
-           yyRelMonth += yyvsp[0].Number;
-       }
-break;
-case 39:
-#line 333 "getdate.y"
-{
-           if (yyHaveTime && yyHaveDate && !yyHaveRel)
-               yyYear = yyvsp[0].Number;
-           else {
-               if(yyvsp[0].Number>10000) {
-                   yyHaveDate++;
-                   yyDay= (yyvsp[0].Number)%100;
-                   yyMonth= (yyvsp[0].Number/100)%100;
-                   yyYear = yyvsp[0].Number/10000;
-               }
-               else {
-                   yyHaveTime++;
-                   if (yyvsp[0].Number < 100) {
-                       yyHour = yyvsp[0].Number;
-                       yyMinutes = 0;
-                   }
-                   else {
-                       yyHour = yyvsp[0].Number / 100;
-                       yyMinutes = yyvsp[0].Number % 100;
-                   }
-                   yySeconds = 0;
-                   yyMeridian = MER24;
-               }
-           }
-       }
-break;
-case 40:
-#line 360 "getdate.y"
-{
-           yyval.Meridian = MER24;
-       }
-break;
-case 41:
-#line 363 "getdate.y"
-{
-           yyval.Meridian = yyvsp[0].Meridian;
-       }
-break;
-#line 1487 "y.tab.c"
-    }
-    yyssp -= yym;
-    yystate = *yyssp;
-    yyvsp -= yym;
-    yym = yylhs[yyn];
-    if (yystate == 0 && yym == 0)
-    {
-#if YYDEBUG
-        if (yydebug)
-            printf("%sdebug: after reduction, shifting from state 0 to\
- state %d\n", YYPREFIX, YYFINAL);
-#endif
-        yystate = YYFINAL;
-        *++yyssp = YYFINAL;
-        *++yyvsp = yyval;
-        if (yychar < 0)
-        {
-            if ((yychar = yylex()) < 0) yychar = 0;
-#if YYDEBUG
-            if (yydebug)
-            {
-                yys = 0;
-                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
-                if (!yys) yys = "illegal-symbol";
-                printf("%sdebug: state %d, reading %d (%s)\n",
-                        YYPREFIX, YYFINAL, yychar, yys);
-            }
-#endif
-        }
-        if (yychar == 0) goto yyaccept;
-        goto yyloop;
-    }
-    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
-            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
-        yystate = yytable[yyn];
-    else
-        yystate = yydgoto[yym];
-#if YYDEBUG
-    if (yydebug)
-        printf("%sdebug: after reduction, shifting from state %d \
-to state %d\n", YYPREFIX, *yyssp, yystate);
-#endif
-    if (yyssp >= yysslim && yygrowstack())
-    {
-        goto yyoverflow;
-    }
-    *++yyssp = yystate;
-    *++yyvsp = yyval;
-    goto yyloop;
-yyoverflow:
-    yyerror("yacc stack overflow");
-yyabort:
-    return (1);
-yyaccept:
-    return (0);
-}
index 0bbc53fd7b62f82156bee9b1e6f8bf06b74e5dd5..3257c7e4a43c98627a9e32cec63b53a03d15a3c1 100644 (file)
@@ -17,6 +17,7 @@ CFILES = id.c
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble groups.1\
             id.1 whoami.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID -DUSE_BSM_AUDIT
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index dfd36a0f958eb9756ad35108fcee704271081d6b..00c030ba8d2c2a69f69c7d24f4beebe279fec469 100644 (file)
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)groups.1    8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/id/groups.1,v 1.8 2001/08/15 09:09:41 ru Exp $
+.\" $FreeBSD: src/usr.bin/id/groups.1,v 1.10 2006/12/23 17:14:01 ru Exp $
 .\"
 .Dd June 6, 1993
 .Dt GROUPS 1
@@ -54,9 +54,10 @@ is suggested for normal interactive use.
 .Pp
 The
 .Nm
-utility displays the groups to which you (or the optionally specified user)
+utility displays the groups to which you (or the optionally specified
+.Ar user )
 belong.
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
 .Xr id 1
diff --git a/id/id.1 b/id/id.1
index c36c4f71164c271a33b5d5cbfe1c8e334db56271..c92c29a9c36610d1e299483b47dc1799d6f894fb 100644 (file)
--- a/id/id.1
+++ b/id/id.1
@@ -33,9 +33,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)id.1        8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/id/id.1,v 1.11 2001/08/15 09:09:41 ru Exp $
+.\" $FreeBSD: src/usr.bin/id/id.1,v 1.18 2006/09/26 22:28:12 ceri Exp $
 .\"
-.Dd June 6, 1993
+.Dd September 26, 2006
 .Dt ID 1
 .Os
 .Sh NAME
 .Nm
 .Op Ar user
 .Nm
+.Fl A
+.Nm
 .Fl G Op Fl n
 .Op Ar user
 .Nm
+.Fl M
+.Nm
 .Fl P
 .Op Ar user
 .Nm
@@ -75,11 +79,20 @@ In this case, the real and effective IDs are assumed to be the same.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl A
+Display the process audit user ID and other process audit properties, which
+requires privilege.
 .It Fl G
 Display the different group IDs (effective, real and supplementary)
 as white-space separated numbers, in no particular order.
+.It Fl M
+Display the MAC label of the current process.
 .It Fl P
 Display the id as a password file entry.
+.It Fl a
+Ignored for compatibility with other
+.Nm
+implementations.
 .It Fl g
 Display the effective group ID as a number.
 .It Fl n
@@ -121,7 +134,7 @@ options instead of the effective ID.
 .It Fl u
 Display the effective user ID as a number.
 .El
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
 .Xr who 1
diff --git a/id/id.c b/id/id.c
index e3957e691ed54c2e1f2ea4a174942ed73c1cdfc6..becc5912f1d40382d4d1a4efdb8529af7d465c3d 100644 (file)
--- a/id/id.c
+++ b/id/id.c
@@ -43,11 +43,19 @@ static char sccsid[] = "@(#)id.c    8.2 (Berkeley) 2/16/94";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/usr.bin/id/id.c,v 1.19 2002/09/04 23:29:02 dwmalone Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/id/id.c,v 1.33 2006/12/29 12:28:34 stefanf Exp $");
 
 #include <sys/param.h>
+#ifndef __APPLE__
+#include <sys/mac.h>
+#endif /* !__APPLE__ */
+
+#ifdef USE_BSM_AUDIT
+#include <bsm/audit.h>
+#endif
 
 #include <err.h>
+#include <errno.h>
 #include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
@@ -55,26 +63,33 @@ __RCSID("$FreeBSD: src/usr.bin/id/id.c,v 1.19 2002/09/04 23:29:02 dwmalone Exp $
 #include <string.h>
 #include <unistd.h>
 
-void   current(void);
+void   id_print(struct passwd *, int, int, int);
 void   pline(struct passwd *);
 void   pretty(struct passwd *);
+void   auditid(void);
 void   group(struct passwd *, int);
+void   maclabel(void);
 void   usage(void);
-void   user(struct passwd *);
-struct passwd *
-       who(char *);
+struct passwd *who(char *);
 
 int isgroups, iswhoami;
 
+#ifdef __APPLE__
+// SPI for 5235093
+int32_t getgrouplist_2(const char *, gid_t, gid_t **);
+#endif
+
 int
 main(int argc, char *argv[])
 {
        struct group *gr;
        struct passwd *pw;
-       int Gflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
+       int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
+       int Aflag;
        const char *myname;
 
-       Gflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
+       Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
+       Aflag = 0;
 
        myname = strrchr(argv[0], '/');
        myname = (myname != NULL) ? myname + 1 : argv[0];
@@ -88,14 +103,24 @@ main(int argc, char *argv[])
        }
 
        while ((ch = getopt(argc, argv,
-           (isgroups || iswhoami) ? "" : "PGgnpru")) != -1)
+           (isgroups || iswhoami) ? "" : "APGMagnpru")) != -1)
                switch(ch) {
+#ifdef USE_BSM_AUDIT
+               case 'A':
+                       Aflag = 1;
+                       break;
+#endif
                case 'G':
                        Gflag = 1;
                        break;
+               case 'M':
+                       Mflag = 1;
+                       break;
                case 'P':
                        Pflag = 1;
                        break;
+               case 'a':
+                       break;
                case 'g':
                        gflag = 1;
                        break;
@@ -121,7 +146,7 @@ main(int argc, char *argv[])
        if (iswhoami && argc > 0)
                usage();
 
-       switch(Gflag + Pflag + gflag + pflag + uflag) {
+       switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
        case 1:
                break;
        case 0:
@@ -134,6 +159,16 @@ main(int argc, char *argv[])
 
        pw = *argv ? who(*argv) : NULL;
 
+       if (Mflag && pw != NULL)
+               usage();
+
+#ifdef USE_BSM_AUDIT
+       if (Aflag) {
+               auditid();
+               exit(0);
+       }
+#endif
+
        if (gflag) {
                id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
                if (nflag && (gr = getgrgid(id)))
@@ -157,6 +192,11 @@ main(int argc, char *argv[])
                exit(0);
        }
 
+       if (Mflag) {
+               maclabel();
+               exit(0);
+       }
+
        if (Pflag) {
                pline(pw);
                exit(0);
@@ -167,10 +207,14 @@ main(int argc, char *argv[])
                exit(0);
        }
 
-       if (pw)
-               user(pw);
-       else
-               current();
+       if (pw) {
+               id_print(pw, 1, 0, 0);
+       }
+       else {
+               id = getuid();
+               pw = getpwuid(id);
+               id_print(pw, 0, 1, 1);
+       }
        exit(0);
 }
 
@@ -215,85 +259,131 @@ pretty(struct passwd *pw)
 }
 
 void
-current(void)
+id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
 {
        struct group *gr;
-       struct passwd *pw;
-       int cnt, id, eid, gid, egid, lastid, ngroups;
-       gid_t groups[NGROUPS];
+       gid_t gid, egid, lastgid;
+       uid_t uid, euid;
+       int cnt, ngroups;
+#ifdef __APPLE__
+       gid_t *groups;
+#else
+       gid_t groups[NGROUPS + 1];
+#endif
        const char *fmt;
 
-       id = getuid();
-       (void)printf("uid=%u", id);
-       if ((pw = getpwuid(id)))
-               (void)printf("(%s)", pw->pw_name);
-       gid = getgid();
-       (void)printf(" gid=%u", gid);
+#ifdef __APPLE__
+       if (pw == NULL) {
+               pw = getpwuid(getuid());
+       }
+
+       use_ggl = 1;
+#endif
+
+       if (pw != NULL) {
+               uid = pw->pw_uid;
+               gid = pw->pw_gid;
+       }
+       else {
+               uid = getuid();
+               gid = getgid();
+       }
+
+       if (use_ggl && pw != NULL) {
+#ifdef __APPLE__
+               // 5235093
+               ngroups = getgrouplist_2(pw->pw_name, gid, &groups);
+#else
+               ngroups = NGROUPS + 1;
+               getgrouplist(pw->pw_name, gid, groups, &ngroups);
+#endif
+       }
+       else {
+#ifdef __APPLE__
+               groups = malloc(NGROUPS + 1);
+#endif
+               ngroups = getgroups(NGROUPS + 1, groups);
+       }
+
+       if (pw != NULL)
+               printf("uid=%u(%s)", uid, pw->pw_name);
+       else 
+               printf("uid=%u", getuid());
+       printf(" gid=%u", gid);
        if ((gr = getgrgid(gid)))
                (void)printf("(%s)", gr->gr_name);
-       if ((eid = geteuid()) != id) {
-               (void)printf(" euid=%u", eid);
-               if ((pw = getpwuid(eid)))
+       if (p_euid && (euid = geteuid()) != uid) {
+               (void)printf(" euid=%u", euid);
+               if ((pw = getpwuid(euid)))
                        (void)printf("(%s)", pw->pw_name);
        }
-       if ((egid = getegid()) != gid) {
+       if (p_egid && (egid = getegid()) != gid) {
                (void)printf(" egid=%u", egid);
                if ((gr = getgrgid(egid)))
                        (void)printf("(%s)", gr->gr_name);
        }
-       if ((ngroups = getgroups(NGROUPS, groups))) {
-               for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups;
-                   fmt = ", %u", lastid = id) {
-                       id = groups[cnt++];
-                       if (lastid == id)
-                               continue;
-                       (void)printf(fmt, id);
-                       if ((gr = getgrgid(id)))
-                               (void)printf("(%s)", gr->gr_name);
-               }
-       }
-       (void)printf("\n");
-}
-
-void
-user(struct passwd *pw)
-{
-       struct group *gr;
-       const char *fmt;
-       int cnt, gid, lastgid, ngroups, groups[NGROUPS + 1];
-
-       (void)printf("uid=%u(%s)", pw->pw_uid, pw->pw_name);
-       gid = pw->pw_gid;
-       (void)printf(" gid=%u", gid);
-       if ((gr = getgrgid(gid)))
-               (void)printf("(%s)", gr->gr_name);
-       ngroups = NGROUPS + 1;
-       (void) getgrouplist(pw->pw_name, gid, groups, &ngroups);
        fmt = " groups=%u";
        for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
                if (lastgid == (gid = groups[cnt]))
                        continue;
-               (void)printf(fmt, gid);
-               fmt = ", %u";
+               printf(fmt, gid);
+               fmt = ",%u";
                if ((gr = getgrgid(gid)))
-                       (void)printf("(%s)", gr->gr_name);
+                       printf("(%s)", gr->gr_name);
                lastgid = gid;
        }
-       (void)printf("\n");
+       printf("\n");
+#ifdef __APPLE__
+       free(groups);
+#endif
 }
 
+#ifdef USE_BSM_AUDIT
+void
+auditid(void)
+{
+       auditinfo_t auditinfo;
+
+       if (getaudit(&auditinfo) < 0)
+               err(1, "getaudit");
+       printf("auid=%d\n", auditinfo.ai_auid);
+       printf("mask.success=0x%08x\n", auditinfo.ai_mask.am_success);
+       printf("mask.failure=0x%08x\n", auditinfo.ai_mask.am_failure);
+       printf("termid.port=0x%08x\n", auditinfo.ai_termid.port);
+       printf("asid=%d\n", auditinfo.ai_asid);
+}
+#endif
+
 void
 group(struct passwd *pw, int nflag)
 {
        struct group *gr;
        int cnt, id, lastid, ngroups;
+#ifdef __APPLE__
+       gid_t *groups;
+#else
        gid_t groups[NGROUPS + 1];
+#endif
        const char *fmt;
 
+#ifdef __APPLE__
+       if (pw == NULL) {
+               pw = getpwuid(getuid());
+       }
+#endif
+
        if (pw) {
+#ifdef __APPLE__
+               // 5235093
+               ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid, &groups);
+#else
                ngroups = NGROUPS + 1;
                (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+#endif
        } else {
+#ifdef __APPLE__
+               groups = malloc(NGROUPS + 1);
+#endif
                groups[0] = getgid();
                ngroups = getgroups(NGROUPS, groups + 1) + 1;
        }
@@ -315,6 +405,37 @@ group(struct passwd *pw, int nflag)
                lastid = id;
        }
        (void)printf("\n");
+#ifdef __APPLE__
+       free(groups);
+#endif
+}
+
+void
+maclabel(void)
+{
+#ifdef __APPLE__
+       errx(1, "-M unsupported");
+#else /* !__APPLE__ */
+       char *string;
+       mac_t label;
+       int error;
+
+       error = mac_prepare_process_label(&label);
+       if (error == -1)
+               errx(1, "mac_prepare_type: %s", strerror(errno));
+
+       error = mac_get_proc(label);
+       if (error == -1)
+               errx(1, "mac_get_proc: %s", strerror(errno));
+
+       error = mac_to_text(label, &string);
+       if (error == -1)
+               errx(1, "mac_to_text: %s", strerror(errno));
+
+       (void)printf("%s\n", string);
+       mac_free(label);
+       free(string);
+#endif /* __APPLE__ */
 }
 
 struct passwd *
@@ -340,10 +461,9 @@ who(char *u)
 void
 pline(struct passwd *pw)
 {
-       u_int rid;
 
        if (!pw) {
-               if ((pw = getpwuid(rid = getuid())) == NULL)
+               if ((pw = getpwuid(getuid())) == NULL)
                        err(1, "getpwuid");
        }
 
@@ -363,9 +483,15 @@ usage(void)
        else if (iswhoami)
                (void)fprintf(stderr, "usage: whoami\n");
        else
-               (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
+               (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n",
                    "usage: id [user]",
+#ifdef USE_BSM_AUDIT
+                   "       id -A\n",
+#else
+                   "",
+#endif
                    "       id -G [-n] [user]",
+                   "       id -M",
                    "       id -P [user]",
                    "       id -g [-nr] [user]",
                    "       id -p [user]",
index bf201d8f3c2fc58d41a3a8b62c0c1016998cb641..568fbaf147c176fb48d717f473d24d178f69fa99 100644 (file)
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)whoami.1    8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/id/whoami.1,v 1.8 2001/08/15 09:09:41 ru Exp $
+.\" $FreeBSD: src/usr.bin/id/whoami.1,v 1.9 2005/01/17 07:44:19 ru Exp $
 .\"
 .Dd June 6, 1993
 .Dt WHOAMI 1
@@ -54,7 +54,7 @@ is suggested for normal interactive use.
 The
 .Nm
 utility displays your effective user ID as a name.
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
 .Xr id 1
index 49907b5ca5e94c2a9aac029c71f3469e1090bb22..a2f09c0d23dc91ca3c99c61e62f420020077c4c8 100644 (file)
@@ -16,6 +16,7 @@ CFILES = killall.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble killall.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 69dbc05c541716a3be259d164c0ab4bca4ccce3a..da99668a569a22eb48499af8935b1bf02400e2b2 100644 (file)
@@ -22,9 +22,9 @@
 .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.bin/killall/killall.1,v 1.22 2001/11/30 00:30:28 bsd Exp $
+.\" $FreeBSD: src/usr.bin/killall/killall.1,v 1.34 2005/01/17 07:44:20 ru Exp $
 .\"
-.Dd June 25, 1995
+.Dd January 26, 2004
 .Os
 .Dt KILLALL 1
 .Sh NAME
 .Nd kill processes by name
 .Sh SYNOPSIS
 .Nm
-.Op Fl d | v
-.Op Fl h | ?\&
+.Op Fl delmsvz
 .Op Fl help
-.Op Fl l
-.Op Fl m
-.Op Fl s
 .Op Fl u Ar user
 .Op Fl t Ar tty
 .Op Fl c Ar procname
 .Op Fl SIGNAL
 .Op Ar procname ...
 .Sh DESCRIPTION
-.Nm Killall
-kills processes selected by name, as opposed to the selection by pid
+The
+.Nm
+utility kills processes selected by name, as opposed to the selection by pid
 as done by
 .Xr kill 1 .
 By default, it will send a
@@ -60,12 +57,17 @@ The super-user is allowed to kill any process.
 The options are as follows:
 .Bl -tag -width 10n -offset indent
 .It Fl d | v
-Be more verbose about what will be done.  For a single
+Be more verbose about what will be done.
+For a single
 .Fl d
 option, a list of the processes that will be sent the signal will be
 printed, or a message indicating that no matching processes have been
 found.
-.It Fl h | ?\&
+.It Fl e
+Use the effective user ID instead of the (default) real user ID for matching
+processes specified with the
+.Fl u
+option.
 .It Fl help
 Give a help on the command usage and exit.
 .It Fl l
@@ -74,9 +76,10 @@ List the names of the available signals and exit, like in
 .It Fl m
 Match the argument
 .Ar procname
-as a (case insensitive) regular expression against the names
+as a (case sensitive) regular expression against the names
 of processes found.
-CAUTION!  This is dangerous, a single dot will match any process
+CAUTION!
+This is dangerous, a single dot will match any process
 running under the real UID of the caller.
 .It Fl s
 Show only what would be done, but do not send any signal.
@@ -102,26 +105,32 @@ or
 .Fl t
 flags, limit potentially matching processes to those matching
 the specified
-.Ar progname .
+.Ar procname .
+.It Fl z
+Do not skip zombies.
+This should not have any effect except to print a few error messages
+if there are zombie processes that match the specified pattern.
 .El
 .Sh ALL PROCESSES
 Sending a signal to all processes with uid
-.Nm XYZ
+.Em XYZ
 is already supported by
 .Xr kill 1 .
 So use
 .Xr kill 1
-for this job (e.g. $ kill -TERM -1 or
+for this job (e.g.\& $ kill -TERM -1 or
 as root $ echo kill -TERM -1 | su -m <user>)
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 The
 .Nm
 command will respond with a short usage message and exit with a status
-of 2 in case of a command error.  A status of 1 will be returned if
+of 2 in case of a command error.
+A status of 1 will be returned if
 either no matching process has been found or not all processes have
-been signalled successfully.  Otherwise, a status of 0 will be
+been signalled successfully.
+Otherwise, a status of 0 will be
 returned.
-.Pp
+.Sh DIAGNOSTICS
 Diagnostic messages will only be printed if requested by
 .Fl d
 options.
index 25a2dedf80335e31e79f8bdc6651a4d212d8fc32..795df0424a3b1e9f281340a2aafcfa3d030a68a1 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.bin/killall/killall.c,v 1.15 2001/10/10 17:48:44 bde Exp $
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/killall/killall.c,v 1.31 2004/07/29 18:36:35 maxim Exp $");
+
 #include <sys/param.h>
+#ifndef __APPLE__
+#include <sys/jail.h>
+#endif /* !__APPLE__ */
 #include <sys/stat.h>
 #include <sys/user.h>
 #include <sys/sysctl.h>
 #include <err.h>
 #include <errno.h>
 #include <unistd.h>
+#include <locale.h>
 
-static char    *prog;
-
-static void 
+static void __dead2
 usage(void)
 {
 
-       fprintf(stderr, "usage: %s [-l] [-v] [-m] [-sig] [-u user] [-t tty] [-c cmd] [cmd]...\n", prog);
+#ifdef __APPLE__
+       fprintf(stderr, "usage: killall [-delmsvz] [-help]\n");
+#else /* !__APPLE__ */
+       fprintf(stderr, "usage: killall [-delmsvz] [-help] [-j jid]\n");
+#endif /* __APPLE__ */
+       fprintf(stderr,
+           "               [-u user] [-t tty] [-c cmd] [-SIGNAL] [cmd]...\n");
        fprintf(stderr, "At least one option or argument to specify processes must be given.\n");
        exit(1);
 }
@@ -65,7 +73,7 @@ upper(const char *str)
        strncpy(buf, str, sizeof(buf));
        buf[sizeof(buf) - 1] = '\0';
        for (s = buf; *s; s++)
-               *s = toupper(*s);
+               *s = toupper((unsigned char)*s);
        return buf;
 }
 
@@ -112,21 +120,32 @@ main(int ac, char **av)
        int             vflag = 0;
        int             sflag = 0;
        int             dflag = 0;
+       int             eflag = 0;
+#ifndef __APPLE__
+       int             jflag = 0;
+#endif /* !__APPLE__*/
        int             mflag = 0;
+       int             zflag = 0;
        uid_t           uid = 0;
        dev_t           tdev = 0;
-#ifdef OLD_STYLE
-       char            thiscmd[MAXCOMLEN+1];
-#else
+       pid_t           mypid;
+#ifdef __APPLE__
        char            *thiscmd;
-#endif
+#else /* !__APPLE__ */
+       char            thiscmd[MAXCOMLEN + 1];
+#endif /* __APPLE__ */
        pid_t           thispid;
+#ifndef __APPLE__
        uid_t           thisuid;
+#endif /* !__APPLE__ */
        dev_t           thistdev;
        int             sig = SIGTERM;
        const char *const *p;
        char            *ep;
        int             errors = 0;
+#ifndef __APPLE__
+       int             jid;
+#endif /* !__APPLE__ */
        int             mib[4];
        size_t          miblen;
        int             st, nprocs;
@@ -134,7 +153,8 @@ main(int ac, char **av)
        int             matched;
        int             killed = 0;
 
-       prog = av[0];
+       setlocale(LC_ALL, "");
+
        av++;
        ac--;
 
@@ -148,6 +168,22 @@ main(int ac, char **av)
                if (**av == '-') {
                        ++*av;
                        switch (**av) {
+#ifndef __APPLE__
+                       case 'j':
+                               ++*av;
+                               if (**av == '\0')
+                                       ++av;
+                               --ac;
+                               jflag++;
+                               if (!*av)
+                                       errx(1, "must specify jid");
+                               jid = strtol(*av, &ep, 10);
+                               if (!*av || *ep)
+                                       errx(1, "illegal jid: %s", *av);
+                               if (jail_attach(jid) == -1)
+                                       err(1, "jail_attach(): %d", jid);
+                               break;
+#endif /* !__APPLE__ */
                        case 'u':
                                ++*av;
                                if (**av == '\0')
@@ -178,11 +214,17 @@ main(int ac, char **av)
                        case 'd':
                                dflag++;
                                break;
+                       case 'e':
+                               eflag++;
+                               break;
                        case 'm':
                                mflag++;
                                break;
+                       case 'z':
+                               zflag++;
+                               break;
                        default:
-                               if (isalpha(**av)) {
+                               if (isalpha((unsigned char)**av)) {
                                        if (strncasecmp(*av, "sig", 3) == 0)
                                                *av += 3;
                                        for (sig = NSIG, p = sys_signame + 1;
@@ -193,11 +235,11 @@ main(int ac, char **av)
                                                }
                                        if (!sig)
                                                nosig(*av);
-                               } else if (isdigit(**av)) {
+                               } else if (isdigit((unsigned char)**av)) {
                                        sig = strtol(*av, &ep, 10);
                                        if (!*av || *ep)
                                                errx(1, "illegal signal number: %s", *av);
-                                       if (sig < 0 || sig > NSIG)
+                                       if (sig < 0 || sig >= NSIG)
                                                nosig(*av);
                                } else
                                        nosig(*av);
@@ -209,7 +251,11 @@ main(int ac, char **av)
                }
        }
 
+#ifdef __APPLE__
        if (user == NULL && tty == NULL && cmd == NULL && ac == 0)
+#else /* !__APPLE__*/
+       if (user == NULL && tty == NULL && cmd == NULL && !jflag && ac == 0)
+#endif /* __APPLE__ */
                usage();
 
        if (tty) {
@@ -229,7 +275,7 @@ main(int ac, char **av)
        }
        if (user) {
                uid = strtol(user, &ep, 10);
-               if ((ep - user) < strlen(user)) {
+               if (*user == '\0' || *ep != '\0') { /* was it a number? */
                        pw = getpwnam(user);
                        if (pw == NULL)
                                errx(1, "user %s does not exist", user);
@@ -250,16 +296,19 @@ main(int ac, char **av)
        size = 0;
        mib[0] = CTL_KERN;
        mib[1] = KERN_PROC;
+#ifdef __APPLE__
        mib[2] = KERN_PROC_ALL;
+#else /* !__APPLE__ */
+       mib[2] = KERN_PROC_PROC;
+#endif /* __APPLE__ */
        mib[3] = 0;
        miblen = 3;
 
-       if (user && mib[2] == KERN_PROC_ALL) {
-               mib[2] = KERN_PROC_RUID;
+       if (user) {
+               mib[2] = eflag ? KERN_PROC_UID : KERN_PROC_RUID;
                mib[3] = uid;
                miblen = 4;
-       }
-       if (tty && mib[2] == KERN_PROC_ALL) {
+       } else if (tty) {
                mib[2] = KERN_PROC_TTY;
                mib[3] = tdev;
                miblen = 4;
@@ -280,7 +329,7 @@ main(int ac, char **av)
        if (st == -1)
                err(1, "could not sysctl(KERN_PROC)");
        if (size % sizeof(struct kinfo_proc) != 0) {
-               fprintf(stderr, "proc size mismatch (%d total, %d chunks)\n",
+               fprintf(stderr, "proc size mismatch (%zu total, %zu chunks)\n",
                        size, sizeof(struct kinfo_proc));
                fprintf(stderr, "userland out of sync with kernel, recompile libkvm etc\n");
                exit(1);
@@ -288,9 +337,14 @@ main(int ac, char **av)
        nprocs = size / sizeof(struct kinfo_proc);
        if (dflag)
                printf("nprocs %d\n", nprocs);
+       mypid = getpid();
 
        for (i = 0; i < nprocs; i++) {
-#ifndef OLD_STYLE
+#ifdef __APPLE__
+               if ((procs[i].kp_proc.p_stat & SZOMB) == SZOMB && !zflag)
+                       continue;
+               thispid = procs[i].kp_proc.p_pid;
+
                int mib[3], argmax;
                size_t syssize;
                char *procargs, *cp;
@@ -299,7 +353,7 @@ main(int ac, char **av)
                mib[1] = KERN_ARGMAX;
 
                syssize = sizeof(argmax);
-               if (sysctl(mib, 2, &argmax, &syssize, NULL, 0) == -1) 
+               if (sysctl(mib, 2, &argmax, &syssize, NULL, 0) == -1)
                        continue;
 
                procargs = malloc(argmax);
@@ -308,8 +362,8 @@ main(int ac, char **av)
 
                mib[0] = CTL_KERN;
                mib[1] = KERN_PROCARGS;
-               mib[2] = procs[i].kp_proc.p_pid;
-               
+               mib[2] = thispid;
+
                syssize = (size_t)argmax;
                if (sysctl(mib, 3, procargs, &syssize, NULL, 0) == -1) {
                        free(procargs);
@@ -321,6 +375,7 @@ main(int ac, char **av)
                                break;
                        }
                }
+
                if (cp == &procargs[syssize]) {
                        free(procargs);
                        continue;
@@ -339,23 +394,40 @@ main(int ac, char **av)
 
                /* Strip off any path that was specified */
                for (thiscmd = cp; (cp < &procargs[syssize]) && (*cp != '\0'); cp++) {
-                       if( *cp == '/' ) {
-                               thiscmd = cp+1;
+                       if (*cp == '/') {
+                               thiscmd = cp + 1;
                        }
                }
-#else
-               thiscmd[MAXCOMLEN] = '\0';
-#endif
-               thispid = procs[i].kp_proc.p_pid;
 
                thistdev = procs[i].kp_eproc.e_tdev;
-               thisuid = procs[i].kp_eproc.e_pcred.p_ruid;     /* real uid */
+#else /* !__APPLE__ */
+               if ((procs[i].ki_stat & SZOMB) == SZOMB && !zflag)
+                       continue;
+               thispid = procs[i].ki_pid;
+               strncpy(thiscmd, procs[i].ki_comm, MAXCOMLEN);
+               thiscmd[MAXCOMLEN] = '\0';
+               thistdev = procs[i].ki_tdev;
+#endif /* __APPLE__ */
+#ifndef __APPLE__
+               if (eflag)
+                       thisuid = procs[i].ki_uid;      /* effective uid */
+               else
+                       thisuid = procs[i].ki_ruid;     /* real uid */
+#endif /* !__APPLE__ */
 
+               if (thispid == mypid) {
+#ifdef __APPLE__
+                       free(procargs);
+#endif /* __APPLE__ */
+                       continue;
+               }
                matched = 1;
+#ifndef __APPLE__
                if (user) {
                        if (thisuid != uid)
                                matched = 0;
                }
+#endif /* !__APPLE__ */
                if (tty) {
                        if (thistdev != tdev)
                                matched = 0;
@@ -380,10 +452,14 @@ main(int ac, char **av)
                                        matched = 0;
                        }
                }
+#ifndef __APPLE__
+               if (jflag && thispid == getpid())
+                       matched = 0;
+#endif /* !__APPLE__ */
                if (matched == 0) {
-#ifndef OLD_STYLE
+#ifdef __APPLE__
                        free(procargs);
-#endif
+#endif /* !__APPLE__ */
                        continue;
                }
                if (ac > 0)
@@ -411,14 +487,19 @@ main(int ac, char **av)
                                break;
                }
                if (matched == 0) {
-#ifndef OLD_STYLE
+#ifdef __APPLE__
                        free(procargs);
-#endif
+#endif /* __APPLE__ */
                        continue;
                }
                if (dflag)
+#ifdef __APPLE__
+                       printf("sig:%d, cmd:%s, pid:%d, dev:0x%x\n", sig,
+                           thiscmd, thispid, thistdev);
+#else /* !__APPLE__ */
                        printf("sig:%d, cmd:%s, pid:%d, dev:0x%x uid:%d\n", sig,
                            thiscmd, thispid, thistdev, thisuid);
+#endif /* __APPLE__ */
 
                if (vflag || sflag)
                        printf("kill -%s %d\n", upper(sys_signame[sig]),
@@ -427,11 +508,14 @@ main(int ac, char **av)
                killed++;
                if (!dflag && !sflag) {
                        if (kill(thispid, sig) < 0 /* && errno != ESRCH */ ) {
-                               warn("kill -%s %d", upper(sys_signame[sig]),
-                                   thispid);
+                               warn("warning: kill -%s %d",
+                                   upper(sys_signame[sig]), thispid);
                                errors = 1;
                        }
                }
+#ifdef __APPLE__
+               free(procargs);
+#endif /* __APPLE__ */
        }
        if (killed == 0) {
                fprintf(stderr, "No matching processes %swere found\n",
index 22f2f3324e5d31322808c111a510391bd500803d..7baaf62e12cecda9c198b9daaf4a719cd2a94e86 100644 (file)
@@ -51,7 +51,7 @@ PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
 : ${mklocatedb:=locate.mklocatedb}      # make locate database program
 : ${FCODES:=/var/db/locate.database}    # the database
 : ${SEARCHPATHS:="/"}          # directories to be put in the database
-: ${PRUNEPATHS:="/tmp /var/tmp"} # unwanted directories
+: ${PRUNEPATHS:="/tmp /var/tmp */Backups.backupdb"} # unwanted directories
 : ${FILESYSTEMS:="hfs ufs"}                     # allowed filesystems 
 : ${find:=find}
 
index 677ab9ece4627d6ab034528f779dae49c48507e7..cea00b77e400005a1acd0666b396881537d6f532 100644 (file)
@@ -1,8 +1,7 @@
-/*     $NetBSD: nohup.c,v 1.8 1997/12/23 18:21:34 ross Exp $   */
-
 /*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * Portions copyright (c) 2007 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+#if 0
 #ifndef lint
-__COPYRIGHT(
-    "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
All rights reserved.\n");
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-#if 0
-static char sccsid[] = "@(#)nohup.c    5.4 (Berkeley) 6/1/90";
-#endif
-__RCSID("$NetBSD: nohup.c,v 1.8 1997/12/23 18:21:34 ross Exp $");
+static char sccsid[] = "@(#)nohup.c    8.1 (Berkeley) 6/6/93";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+#ifndef __APPLE__
+__FBSDID("$FreeBSD: src/usr.bin/nohup/nohup.c,v 1.10 2003/05/03 19:44:46 obrien Exp $");
+#endif
 
 #include <sys/param.h>
-#include <sys/file.h>
 #include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
+#include <unistd.h>
+
+#ifdef __APPLE__
+#include <vproc.h>
+#include <vproc_priv.h>
+#endif
 
-static void dofile __P((void));
-static void usage __P((void));
-int main __P((int, char **));
+static void dofile(void);
+static void usage(void);
 
-/* nohup shall exit with one of the following values:
-   126 - The utility was found but could not be invoked.
-   127 - An error occured in the nohup utility, or the utility could
-         not be found. */
-#define EXIT_NOEXEC    126
-#define EXIT_NOTFOUND  127
-#define EXIT_MISC      127
+#define        FILENAME        "nohup.out"
+/*
+ * POSIX mandates that we exit with:
+ * 126 - If the utility was found, but failed to execute.
+ * 127 - If any other error occurred. 
+ */
+#define        EXIT_NOEXEC     126
+#define        EXIT_NOTFOUND   127
+#define        EXIT_MISC       127
 
 int
-main(argc, argv)
-       int argc;
-       char **argv;
+main(int argc, char *argv[])
 {
        int exit_status;
 
-       if (argc > 1 && !strcmp(argv[1], "--")) {
-               argv++;
-               argc--;
-       }
-       if (argc < 2)
+       while (getopt(argc, argv, "") != -1)
+               usage();
+       argc -= optind;
+       argv += optind;
+       if (argc < 1)
                usage();
 
        if (isatty(STDOUT_FILENO))
                dofile();
-       if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1) {
+       if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
                /* may have just closed stderr */
-               (void)fprintf(stdin, "nohup: %s\n", strerror(errno));
-               exit(EXIT_MISC);
-       }
+               err(EXIT_MISC, "%s", argv[0]);
 
-       /* The nohup utility shall take the standard action for all signals
-          except that SIGHUP shall be ignored. */
        (void)signal(SIGHUP, SIG_IGN);
 
-       execvp(argv[1], &argv[1]);
+#ifdef __APPLE__
+       if (_vprocmgr_move_subset_to_user(geteuid(), "Background") != NULL)
+               err(EXIT_MISC, "can't migrate to background session");
+#endif
+       execvp(*argv, argv);
        exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC;
-       (void)fprintf(stderr, "nohup: %s: %s\n", argv[1], strerror(errno));
-       exit(exit_status);
+       err(exit_status, "%s", argv[0]);
 }
 
 static void
-dofile()
+dofile(void)
 {
        int fd;
-       char *p, path[MAXPATHLEN];
-
-       /* If the standard output is a terminal, all output written to 
-          its standard output shall be appended to the end of the file
-          nohup.out in the current directory.  If nohup.out cannot be
-          created or opened for appending, the output shall be appended
-          to the end of the file nohup.out in the directory specified 
-          by the HOME environment variable.
-
-          If a file is created, the file's permission bits shall be
-          set to S_IRUSR | S_IWUSR. */
-#define        FILENAME        "nohup.out"
+       char path[MAXPATHLEN];
+       const char *p;
+
+       /*
+        * POSIX mandates if the standard output is a terminal, the standard
+        * output is appended to nohup.out in the working directory.  Failing
+        * that, it will be appended to nohup.out in the directory obtained
+        * from the HOME environment variable.  If file creation is required,
+        * the mode_t is set to S_IRUSR | S_IWUSR.
+        */
        p = FILENAME;
-       if ((fd = open(p, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR)) >= 0)
+       fd = open(p, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+       if (fd != -1)
                goto dupit;
-       if ((p = getenv("HOME")) != NULL) {
-               (void)strcpy(path, p);
-               (void)strcat(path, "/");
-               (void)strcat(path, FILENAME);
-               if ((fd = open(p = path, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR)) >= 0)
+       if ((p = getenv("HOME")) != NULL && *p != '\0' &&
+           (size_t)snprintf(path, sizeof(path), "%s/%s", p, FILENAME) <
+           sizeof(path)) {
+               fd = open(p = path, O_RDWR | O_CREAT | O_APPEND,
+                   S_IRUSR | S_IWUSR);
+               if (fd != -1)
                        goto dupit;
        }
-       (void)fprintf(stderr, "nohup: can't open a nohup.out file.\n");
-       exit(EXIT_MISC);
+       errx(EXIT_MISC, "can't open a nohup.out file");
 
-dupit: (void)lseek(fd, 0L, SEEK_END);
-       if (dup2(fd, STDOUT_FILENO) == -1) {
-               (void)fprintf(stderr, "nohup: %s\n", strerror(errno));
-               exit(EXIT_MISC);
-       }
-       (void)fprintf(stderr, "sending output to %s\n", p);
+dupit:
+#ifdef __APPLE__
+       (void)lseek(fd, 0L, SEEK_END);
+#endif
+       if (dup2(fd, STDOUT_FILENO) == -1)
+               err(EXIT_MISC, NULL);
+       (void)fprintf(stderr, "appending output to %s\n", p);
 }
 
 static void
-usage()
+usage(void)
 {
-       (void)fprintf(stderr, "usage: nohup command\n");
+       (void)fprintf(stderr, "usage: nohup [--] utility [arguments]\n");
        exit(EXIT_MISC);
 }
index 8db97381653fdc6011465627368a81e93555a693..6598d4e3d796ae44396fcc6bb9f7eea144f24db6 100644 (file)
@@ -47,8 +47,9 @@
 .Ar format
 .Op Ar arguments  ...
 .Sh DESCRIPTION
+The
 .Nm
-formats and prints its arguments, after the first, under control
+utility formats and prints its arguments, after the first, under control
 of the
 .Ar format  .
 The
index 377d63870a711cea11bc11e52e2c405e7950b269..895435e68921044dd42afe7330a3e10b2c1cc8fd 100644 (file)
@@ -16,6 +16,7 @@ CFILES = pwd.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble pwd.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 4b96209235647ea7b398872b5216d5d0150b5889..929c4b38a8578db7d95b1065e99b6f7892859ade 100644 (file)
--- a/pwd/pwd.1
+++ b/pwd/pwd.1
@@ -1,5 +1,4 @@
-.\"    $NetBSD: pwd.1,v 1.12 1997/09/14 08:51:38 lukem Exp $
-.\"
+.\"-
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)pwd.1      8.2 (Berkeley) 4/28/95
+.\" $FreeBSD: src/bin/pwd/pwd.1,v 1.26 2005/01/16 16:41:58 ru Exp $
 .\"
-.Dd November 2, 1998
+.Dd April 12, 2003
 .Dt PWD 1
-.Os BSD 4
+.Os
 .Sh NAME
 .Nm pwd
 .Nd return working directory name
 .Sh SYNOPSIS
 .Nm
-.Op Fl LP
+.Op Fl L | P
 .Sh DESCRIPTION
+The
 .Nm
-writes the absolute pathname of the current working directory to
+utility writes the absolute pathname of the current working directory to
 the standard output.
 .Pp
-The
+Some shells may provide a builtin
 .Nm
-utility exits 0 on success, and >0 if an error occurs.
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
 .Pp
-The following options are available:
+The options are as follows:
 .Bl -tag -width indent
 .It Fl L
-Print the logical path to the current working directory, as defined
-by the shell in the environment variable PWD.
+Display the logical current working directory.
 .It Fl P
-Print the physical path to the current working directory, with symbolic
-links in the path resolved. This is the default.
+Display the physical current working directory (all symbolic links resolved).
 .El
-.Sh STANDARDS
-The
-.Nm
-utility is expected to be
-.St -p1003.2
-compatible.
+.Pp
+If no options are specified, the
+.\" 4207130
+.Fl L
+option is assumed.
+.Sh ENVIRONMENT
+Environment variables used by
+.Nm :
+.Bl -tag -width ".Ev PWD"
+.It Ev PWD
+Logical current working directory.
+.El
+.Sh EXIT STATUS
+.Ex -std
 .Sh SEE ALSO
+.Xr builtin 1 ,
 .Xr cd 1 ,
 .Xr csh 1 ,
+.Xr sh 1 ,
 .Xr getcwd 3
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
 .Sh BUGS
 In
 .Xr csh 1
 the command
 .Ic dirs
-is always faster (although it can give a different answer in the rare case
+is always faster because it is built into that shell.
+However, it can give a different answer in the rare case
 that the current directory or a containing directory was moved after
-the shell descended into it).
+the shell descended into it.
+.Pp
+The
+.Fl L
+option does not work unless the
+.Ev PWD
+environment variable is exported by the shell.
index 1bf8c394198722f4291f333934633231fa18eae8..c5788b18e7ca4707034af5a63f818bac8d197816 100644 (file)
--- a/pwd/pwd.c
+++ b/pwd/pwd.c
@@ -1,6 +1,4 @@
-/*     $NetBSD: pwd.c,v 1.10 1998/07/28 05:31:26 mycroft Exp $ */
-
-/*
+/*-
  * Copyright (c) 1991, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+#if 0
 #ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\n\
-       The Regents of the University of California.  All rights reserved.\n");
+static char const copyright[] =
+"@(#) Copyright (c) 1991, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-#if 0
 static char sccsid[] = "@(#)pwd.c      8.3 (Berkeley) 4/1/94";
-#else
-__RCSID("$NetBSD: pwd.c,v 1.10 1998/07/28 05:31:26 mycroft Exp $");
-#endif
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/pwd/pwd.c,v 1.25 2005/02/09 17:37:38 ru Exp $");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include <err.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
 
-char *getcwd_logical __P((char *, size_t));
-void  usage __P((void));
-int   main __P((int, char *[]));
+static char *getcwd_logical(void);
+void usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char *argv[])
 {
+       int physical;
        int ch;
-       int lFlag=0;
-       char *p = NULL;
+       char *p;
 
+       // 4207130
+       physical = 0;
        while ((ch = getopt(argc, argv, "LP")) != -1)
                switch (ch) {
                case 'L':
-                       lFlag=1;
+                       physical = 0;
                        break;
                case 'P':
-                       lFlag=0;
+                       physical = 1;
                        break;
                case '?':
                default:
@@ -87,62 +81,47 @@ main(argc, argv)
        if (argc != 0)
                usage();
 
-       if (lFlag)
-               p = getcwd_logical(NULL, 0);
+       /*
+        * If we're trying to find the logical current directory and that
+        * fails, behave as if -P was specified.
+        *
+        * 4701537: Only fall back if $PWD was actually wrong. We want to
+        * fail if the path is too long (errno == ENAMETOOLONG).
+        */
+       if ((!physical && (p = getcwd_logical()) != NULL) ||
+           ((physical || errno == ENOENT) && (p = getcwd(NULL, 0)) != NULL))
+               printf("%s\n", p);
        else
-               p = getcwd(NULL, 0);
-
-       if (p == NULL) err(1, "%s", "");
-
-       (void)printf("%s\n", p);
+               err(1, ".");
 
        exit(0);
-       /* NOTREACHED */
 }
 
-char *
-getcwd_logical(pt, size)
-        char *pt;
-        size_t size;
+void
+usage(void)
 {
-        char *pwd;
-        size_t pwdlen;
-        dev_t dev;
-        ino_t ino;
-        struct stat s;
 
-        /* Check $PWD -- if it's right, it's fast. */
-        if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/' && stat(pwd, &s) != -1) {
-                dev = s.st_dev;
-                ino = s.st_ino;
-                if (stat(".", &s) != -1 && dev == s.st_dev && ino == s.st_ino) {
-                        pwdlen = strlen(pwd);
-                       if (pt) {
-                               if (!size) {
-                                        errno = EINVAL;
-                                        return (NULL);
-                               }
-                                if (pwdlen + 1 > size) {
-                                        errno = ERANGE;
-                                        return (NULL);
-                                }
-                        } else if ((pt = malloc(pwdlen + 1)) == NULL) {
-                               errno = ENOMEM;
-                                return (NULL);
-                       }
-                        memmove(pt, pwd, pwdlen);
-                        pt[pwdlen] = '\0';
-                        return (pt);
-                }
-        }
-
-        return (NULL);
+       (void)fprintf(stderr, "usage: pwd [-L | -P]\n");
+       exit(1);
 }
 
-void
-usage()
+static char *
+getcwd_logical(void)
 {
-       (void)fprintf(stderr, "usage: pwd [-LP]\n");
-       exit(1);
-       /* NOTREACHED */
+       struct stat lg, phy;
+       char *pwd;
+
+       /*
+        * Check that $PWD is an absolute logical pathname referring to
+        * the current working directory.
+        */
+       if ((pwd = getenv("PWD")) != NULL && *pwd == '/') {
+               if (stat(pwd, &lg) == -1 || stat(".", &phy) == -1)
+                       return (NULL);
+               if (lg.st_dev == phy.st_dev && lg.st_ino == phy.st_ino)
+                       return (pwd);
+       }
+
+       errno = ENOENT;
+       return (NULL);
 }
index d42123879b3ce135cc9dd6d4d8258817aa4eb90a..6d1b30bae5811d9f77da73558e9506028bd92d9a 100644 (file)
@@ -111,10 +111,9 @@ and set the priority to any value in the range
 to
 .Dv PRIO_MAX .
 Useful priorities are:
-20 (the affected processes will run only when nothing else
-in the system wants to),
+20 (the affected processes will run at the lowest priority),
 0 (the ``base'' scheduling priority),
-anything negative (to make things go very fast).
+anything negative (lower values cause more favorable scheduling).
 .Sh FILES
 .Bl -tag -width /etc/passwd -compact
 .It Pa /etc/passwd
index 08d1d7d365d369a7ad2660364c605354c3d87a92..6673f3772ef7ef16c799957e3dddff389f4ed2e3 100644 (file)
@@ -16,6 +16,7 @@ CFILES = script.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble script.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 485bf30a157fdbf0fdc32eb1d3dec44de26597df..8c0dae925069490114c79e45074b2f6c20ff52f3 100644 (file)
@@ -1,5 +1,3 @@
-.\"    $NetBSD: script.1,v 1.4 1997/10/19 22:57:47 lukem Exp $
-.\"
 .\" Copyright (c) 1980, 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)script.1    8.1 (Berkeley) 6/6/93
+.\" $FreeBSD: src/usr.bin/script/script.1,v 1.21 2004/07/03 00:24:43 ru Exp $
 .\"
-.Dd June 6, 1993
+.Dd January 22, 2004
 .Dt SCRIPT 1
-.Os BSD 4
+.Os
 .Sh NAME
 .Nm script
 .Nd make typescript of terminal session
 .Sh SYNOPSIS
 .Nm
-.Op Fl a
-.Op Ar file
+.Op Fl akq
+.Op Fl t Ar time
+.Op Ar file Op Ar command ...
 .Sh DESCRIPTION
+The
 .Nm
-makes a typescript of everything printed on your terminal.
+utility makes a typescript of everything printed on your terminal.
 It is useful for students who need a hardcopy record of an interactive
-session as proof of an assignment, as the typescript file 
+session as proof of an assignment, as the typescript file
 can be printed out later with
 .Xr lpr 1 .
 .Pp
@@ -58,28 +59,47 @@ is given,
 saves all dialogue in
 .Ar file .
 If no file name is given, the typescript is saved in the file
-.Pa typescript  .
+.Pa typescript .
 .Pp
-Option:
-.Bl -tag -width Ds
+If the argument
+.Ar command
+is given,
+.Nm
+will run the specified command with an optional argument vector
+instead of an interactive shell.
+.Pp
+The following options are available:
+.Bl -tag -width indent
 .It Fl a
 Append the output to
 .Ar file
 or
 .Pa typescript ,
 retaining the prior contents.
+.It Fl k
+Log keys sent to program as well as output.
+.It Fl q
+Run in quiet mode, omit the start and stop status messages.
+.It Fl t Ar time
+Specify time interval between flushing script output file.
+A value of 0
+causes
+.Nm
+to flush for every character I/O event.
+The default interval is
+30 seconds.
 .El
 .Pp
-The script ends when the forked shell exits (a
+The script ends when the forked shell (or command) exits (a
 .Em control-D
 to exit
 the Bourne shell
 .Pf ( Xr sh 1 ) ,
 and
-.Em exit , 
+.Em exit ,
 .Em logout
 or
-.Em control-d
+.Em control-D
 (if
 .Em ignoreeof
 is not set) for the
@@ -89,24 +109,25 @@ C-shell,
 Certain interactive commands, such as
 .Xr vi 1 ,
 create garbage in the typescript file.
+The
 .Nm
-works best with commands that do not manipulate the
-screen, the results are meant to emulate a hardcopy
-terminal.
+utility works best with commands that do not manipulate the screen.
+The results are meant to emulate a hardcopy terminal, not an addressable one.
 .Sh ENVIRONMENT
 The following environment variable is utilized by
-.Nm
-:
+.Nm :
 .Bl -tag -width SHELL
 .It Ev SHELL
 If the variable
 .Ev SHELL
 exists, the shell forked by
 .Nm
-will be that shell. If
+will be that shell.
+If
 .Ev SHELL
 is not set, the Bourne shell
-is assumed. (Most shells set this variable automatically).
+is assumed.
+(Most shells set this variable automatically).
 .El
 .Sh SEE ALSO
 .Xr csh 1
@@ -119,8 +140,20 @@ The
 command appeared in
 .Bx 3.0 .
 .Sh BUGS
+The
 .Nm
-places
+utility places
 .Sy everything
 in the log file, including linefeeds and backspaces.
 This is not what the naive user expects.
+.Pp
+It is not possible to specify a command without also naming the script file
+because of argument parsing compatibility issues.
+.Pp
+When running in
+.Fl k
+mode, echo cancelling is far from ideal.
+The slave terminal mode is checked
+for ECHO mode to check when to avoid manual echo logging.
+This does not
+work when in a raw mode where the program being run is doing manual echo.
index dc980ce928084c48740f77c2cc41848fa0b982bb..32d80f3d98fd2b5cca23be593d0ac4f76302b8b0 100644 (file)
@@ -1,5 +1,3 @@
-/*     $NetBSD: script.c,v 1.6 1998/04/02 11:08:34 kleink Exp $        */
-
 /*
  * Copyright (c) 1980, 1992, 1993
  *     The Regents of the University of California.  All rights reserved.
  */
 
 #include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD: src/usr.bin/script/script.c,v 1.24 2004/02/15 17:30:13 cperciva Exp $");
+
 #ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1980, 1992, 1993\n\
-       The Regents of the University of California.  All rights reserved.\n");
-#endif /* not lint */
+static const char copyright[] =
+"@(#) Copyright (c) 1980, 1992, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif
 
 #ifndef lint
-#if 0
-static char sccsid[] = "@(#)script.c   8.1 (Berkeley) 6/6/93";
+static const char sccsid[] = "@(#)script.c     8.1 (Berkeley) 6/6/93";
 #endif
-__RCSID("$NetBSD: script.c,v 1.6 1998/04/02 11:08:34 kleink Exp $");
-#endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -55,161 +54,201 @@ __RCSID("$NetBSD: script.c,v 1.6 1998/04/02 11:08:34 kleink Exp $");
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifndef __APPLE__
+#include <libutil.h>
+#endif /* !__APPLE__ */
 #include <paths.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <termios.h>
-#include <time.h>
-#include <tzfile.h>
 #include <unistd.h>
+#ifdef __APPLE__
 #include <util.h>
+#endif /* __APPLE__ */
 
 FILE   *fscript;
 int    master, slave;
-int    child, subchild;
-int    outcc;
-char   *fname;
+int    child;
+const char *fname;
+int    qflg, ttyflg;
 
 struct termios tt;
 
-void   done __P((void));
-void   dooutput __P((void));
-void   doshell __P((void));
-void   fail __P((void));
-void   finish __P((int));
-int    main __P((int, char **));
-void   scriptflush __P((int));
+void   done(int) __dead2;
+void   dooutput(void);
+void   doshell(char **);
+void   fail(void);
+void   finish(void);
+static void usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char *argv[])
 {
        int cc;
-       struct termios rtt;
+       struct termios rtt, stt;
        struct winsize win;
-       int aflg, ch;
+       int aflg, kflg, ch, n;
+       struct timeval tv, *tvp;
+       time_t tvec, start;
+       char obuf[BUFSIZ];
        char ibuf[BUFSIZ];
+       fd_set rfd;
+       int flushtime = 30;
 
-       aflg = 0;
-       while ((ch = getopt(argc, argv, "a")) != -1)
+       aflg = kflg = 0;
+       while ((ch = getopt(argc, argv, "aqkt:")) != -1)
                switch(ch) {
                case 'a':
                        aflg = 1;
                        break;
+               case 'q':
+                       qflg = 1;
+                       break;
+               case 'k':
+                       kflg = 1;
+                       break;
+               case 't':
+                       flushtime = atoi(optarg);
+                       if (flushtime < 0)
+                               err(1, "invalid flush time %d", flushtime);
+                       break;
                case '?':
                default:
-                       (void)fprintf(stderr, "usage: script [-a] [file]\n");
-                       exit(1);
+                       usage();
                }
        argc -= optind;
        argv += optind;
 
-       if (argc > 0)
+       if (argc > 0) {
                fname = argv[0];
-       else
+               argv++;
+               argc--;
+       } else
                fname = "typescript";
 
        if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
-               err(1, "fopen %s", fname);
+               err(1, "%s", fname);
 
-       (void)tcgetattr(STDIN_FILENO, &tt);
-       (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win);
-       if (openpty(&master, &slave, NULL, &tt, &win) == -1)
-               err(1, "openpty");
+       if (ttyflg = isatty(STDIN_FILENO)) {
+               if (tcgetattr(STDIN_FILENO, &tt) == -1)
+                       err(1, "tcgetattr");
+               if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1)
+                       err(1, "ioctl");
+               if (openpty(&master, &slave, NULL, &tt, &win) == -1)
+                       err(1, "openpty");
+       } else {
+               if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
+                       err(1, "openpty");
+       }
 
-       (void)printf("Script started, output file is %s\n", fname);
-       rtt = tt;
-       cfmakeraw(&rtt);
-       rtt.c_lflag &= ~ECHO;
-       (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+       if (!qflg) {
+               tvec = time(NULL);
+               (void)printf("Script started, output file is %s\n", fname);
+               (void)fprintf(fscript, "Script started on %s", ctime(&tvec));
+               fflush(fscript);
+       }
+       if (ttyflg) {
+               rtt = tt;
+               cfmakeraw(&rtt);
+               rtt.c_lflag &= ~ECHO;
+               (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+       }
 
-       (void)signal(SIGCHLD, finish);
        child = fork();
        if (child < 0) {
                warn("fork");
-               fail();
+               done(1);
        }
-       if (child == 0) {
-               subchild = child = fork();
-               if (child < 0) {
-                       warn("fork");
-                       fail();
+       if (child == 0)
+               doshell(argv);
+#ifdef __APPLE__
+       (void)close(slave);
+#endif /* __APPLE__ */
+
+       if (flushtime > 0)
+               tvp = &tv;
+       else
+               tvp = NULL;
+
+       start = time(0);
+       FD_ZERO(&rfd);
+       for (;;) {
+               FD_SET(master, &rfd);
+               FD_SET(STDIN_FILENO, &rfd);
+               if (flushtime > 0) {
+                       tv.tv_sec = flushtime;
+                       tv.tv_usec = 0;
+               }
+               n = select(master + 1, &rfd, 0, 0, tvp);
+               if (n < 0 && errno != EINTR)
+                       break;
+               if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
+                       cc = read(STDIN_FILENO, ibuf, BUFSIZ);
+                       if (cc < 0)
+                               break;
+                       if (cc == 0)
+                               (void)write(master, ibuf, 0);
+                       if (cc > 0) {
+                               (void)write(master, ibuf, cc);
+                               if (kflg && tcgetattr(master, &stt) >= 0 &&
+                                   ((stt.c_lflag & ECHO) == 0)) {
+                                       (void)fwrite(ibuf, 1, cc, fscript);
+                               }
+                       }
+               }
+               if (n > 0 && FD_ISSET(master, &rfd)) {
+                       cc = read(master, obuf, sizeof (obuf));
+                       if (cc <= 0)
+                               break;
+                       (void)write(STDOUT_FILENO, obuf, cc);
+                       (void)fwrite(obuf, 1, cc, fscript);
+               }
+               tvec = time(0);
+               if (tvec - start >= flushtime) {
+                       fflush(fscript);
+                       start = tvec;
                }
-               if (child)
-                       dooutput();
-               else
-                       doshell();
        }
-
-       (void)fclose(fscript);
-       while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0)
-               (void)write(master, ibuf, cc);
-       done();
-       /* NOTREACHED */
-       return (0);
+       finish();
+       done(0);
 }
 
-void
-finish(signo)
-       int signo;
+static void
+usage(void)
 {
-       int die, pid;
-       union wait status;
-
-       die = 0;
-       while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
-               if (pid == child)
-                       die = 1;
-
-       if (die)
-               done();
+       (void)fprintf(stderr,
+           "usage: script [-akq] [-t time] [file [command ...]]\n");
+       exit(1);
 }
 
 void
-dooutput()
+finish(void)
 {
-       struct itimerval value;
-       int cc;
-       time_t tvec;
-       char obuf[BUFSIZ];
-
-       (void)close(STDIN_FILENO);
-       tvec = time(NULL);
-       (void)fprintf(fscript, "Script started on %s", ctime(&tvec));
+       pid_t pid;
+       int die, e, status;
 
-       (void)signal(SIGALRM, scriptflush);
-       value.it_interval.tv_sec = SECSPERMIN / 2;
-       value.it_interval.tv_usec = 0;
-       value.it_value = value.it_interval;
-       (void)setitimer(ITIMER_REAL, &value, NULL);
-       for (;;) {
-               cc = read(master, obuf, sizeof (obuf));
-               if (cc <= 0)
-                       break;
-               (void)write(1, obuf, cc);
-               (void)fwrite(obuf, 1, cc, fscript);
-               outcc += cc;
-       }
-       done();
-}
+       die = e = 0;
+       while ((pid = wait3(&status, WNOHANG, 0)) > 0)
+               if (pid == child) {
+                       die = 1;
+                       if (WIFEXITED(status))
+                               e = WEXITSTATUS(status);
+                       else if (WIFSIGNALED(status))
+                               e = WTERMSIG(status);
+                       else /* can't happen */
+                               e = 1;
+               }
 
-void
-scriptflush(signo)
-       int signo;
-{
-       if (outcc) {
-               (void)fflush(fscript);
-               outcc = 0;
-       }
+       if (die)
+               done(e);
 }
 
 void
-doshell()
+doshell(char **av)
 {
-       char *shell;
+       const char *shell;
 
        shell = getenv("SHELL");
        if (shell == NULL)
@@ -218,32 +257,36 @@ doshell()
        (void)close(master);
        (void)fclose(fscript);
        login_tty(slave);
-       execl(shell, shell, "-i", NULL);
-       warn("execl %s", shell);
+       if (av[0]) {
+               execvp(av[0], av);
+               warn("%s", av[0]);
+       } else {
+               execl(shell, shell, "-i", (char *)NULL);
+               warn("%s", shell);
+       }
        fail();
 }
 
 void
-fail()
+fail(void)
 {
-
        (void)kill(0, SIGTERM);
-       done();
+       done(1);
 }
 
 void
-done()
+done(int eno)
 {
        time_t tvec;
 
-       if (subchild) {
-               tvec = time(NULL);
-               (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec));
-               (void)fclose(fscript);
-               (void)close(master);
-       } else {
+       if (ttyflg)
                (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
-               (void)printf("Script done, output file is %s\n", fname);
+       tvec = time(NULL);
+       if (!qflg) {
+               (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec));
+               (void)printf("\nScript done, output file is %s\n", fname);
        }
-       exit(0);
+       (void)fclose(fscript);
+       (void)close(master);
+       exit(eno);
 }
diff --git a/su/su.1 b/su/su.1
index f41431ff4e5145226e5b034a29e4621c13dd961f..906c9e58f8adeecd4be08c205e0da46b80687449 100644 (file)
--- a/su/su.1
+++ b/su/su.1
@@ -40,9 +40,9 @@
 .Nd substitute user identity
 .Sh SYNOPSIS
 .Nm
+.Op Fl
 .Op Fl flm
-.Op Ar login 
-.Op Ar -c shell arguments
+.Op Ar login Op Ar args
 .Sh DESCRIPTION
 .Nm
 requests the password for
@@ -60,8 +60,6 @@ with the appropriate user ID is executed.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
-.It Fl c
-Invoke the following command in a subshell as the specified user.
 .It Fl f
 If the invoked shell is
 .Xr csh 1 ,
diff --git a/su/su.c b/su/su.c
index fec3606d728bc841f136ffc3e0027a5308390495..a7197f5c5b994d93e04e25fc9040a2d1c62ecfa3 100644 (file)
--- a/su/su.c
+++ b/su/su.c
@@ -109,6 +109,7 @@ extern char **environ;
 int
 main(int argc, char *argv[])
 {
+       static char     *cleanenv;
        struct passwd   *pwd;
        struct pam_conv conv = {misc_conv, NULL};
        enum tristate   iscsh;
@@ -120,15 +121,21 @@ main(int argc, char *argv[])
        gid_t           gid;
        int             asme, ch, asthem, fastlogin, prio, i, setwhat, retcode,
                        statusp, child_pid, child_pgrp, ret_pid;
-       char            *username, *cleanenv, *class, shellbuf[MAXPATHLEN];
+       char            *username, *class, shellbuf[MAXPATHLEN];
        const char      *p, *user, *shell, *mytty, **nargv;
+       const char      *avshell;
+       char            avshellbuf[MAXPATHLEN];
 
        shell = class = cleanenv = NULL;
        asme = asthem = fastlogin = statusp = 0;
        user = "root";
        iscsh = UNSET;
 
+#ifdef __APPLE__
+       while ((ch = getopt(argc, argv, "-flm")) != -1)
+#else
        while ((ch = getopt(argc, argv, "-flmc:")) != -1)
+#endif /* __APPLE__ */
                switch ((char)ch) {
                case 'f':
                        fastlogin = 1;
@@ -142,9 +149,11 @@ main(int argc, char *argv[])
                        asme = 1;
                        asthem = 0;
                        break;
+#ifndef __APPLE__
                case 'c':
                        class = optarg;
                        break;
+#endif /* !__APPLE__ */
                case '?':
                default:
                        usage();
@@ -268,14 +277,14 @@ main(int argc, char *argv[])
                iscsh = NO;
        }
 
+       if ((p = strrchr(shell, '/')) != NULL)
+               avshell = p+1;
+       else
+               avshell = shell;
+
        /* if we're forking a csh, we want to slightly muck the args */
        if (iscsh == UNSET) {
-               p = strrchr(shell, '/');
-               if (p)
-                       ++p;
-               else
-                       p = shell;
-               iscsh = strcmp(p, "csh") ? (strcmp(p, "tcsh") ? NO : YES) : YES;
+               iscsh = strcmp(avshell, "csh") ? (strcmp(avshell, "tcsh") ? NO : YES) : YES;
        }
        setpriority(PRIO_PROCESS, 0, prio);
 
@@ -330,14 +339,24 @@ main(int argc, char *argv[])
        case 0:
                if( setgid(pwd->pw_gid) )
                        err(1, "setgid");
+               /* Call initgroups(2) after setgid(2) to re-establish memberd */
+               if( initgroups(user, pwd->pw_gid) )
+                       err(1, "initgroups");
                if( setuid(pwd->pw_uid) )
                        err(1, "setuid");
 
                if (!asme) {
                        if (asthem) {
                                p = getenv("TERM");
-                               *environ = NULL;
+                               environ = &cleanenv;
+                       }
 
+                       if (asthem || pwd->pw_uid)
+                               setenv("USER", pwd->pw_name, 1);
+                       setenv("HOME", pwd->pw_dir, 1);
+                       setenv("SHELL", shell, 1);
+
+                       if (asthem) {
                                /*
                                 * Add any environmental variables that the
                                 * PAM modules may have set.
@@ -346,15 +365,22 @@ main(int argc, char *argv[])
                                if (environ_pam)
                                        export_pam_environment();
 
+#ifdef __APPLE__
+                               /* 5276965: As documented, set $PATH. */
+                               setenv("PATH", "/bin:/usr/bin", 1);
+#else
+                               /* set the su'd user's environment & umask */
+                               setusercontext(lc, pwd, pwd->pw_uid,
+                                       LOGIN_SETPATH | LOGIN_SETUMASK |
+                                       LOGIN_SETENV);
+#endif
                                if (p)
                                        setenv("TERM", p, 1);
-                               if (chdir(pwd->pw_dir) < 0)
+
+                               p = pam_getenv(pamh, "HOME");
+                               if (chdir(p ? p : pwd->pw_dir) < 0)
                                        errx(1, "no directory");
                        }
-                       if (asthem || pwd->pw_uid)
-                               setenv("USER", pwd->pw_name, 1);
-                       setenv("HOME", pwd->pw_dir, 1);
-                       setenv("SHELL", shell, 1);
                }
 
                if (iscsh == YES) {
@@ -363,8 +389,15 @@ main(int argc, char *argv[])
                        if (asme)
                                *np.a-- = "-m";
                }
+
+               if (asthem) {
+                       avshellbuf[0] = '-';
+                       strlcpy(avshellbuf+1, avshell, sizeof(avshellbuf) - 1);
+                       avshell = avshellbuf;
+               }
+
                /* csh *no longer* strips the first character... */
-               *np.a = asthem ? "-su" : "su";
+               *np.a = avshell;
 
                if (ruid != 0)
                        syslog(LOG_NOTICE, "%s to %s%s", username, user,
@@ -421,7 +454,11 @@ static void
 usage(void)
 {
 
+#ifdef __APPLE__
+       fprintf(stderr, "usage: su [-] [-flm] [login [args]]\n");
+#else
        fprintf(stderr, "usage: su [-] [-flm] [-c class] [login [args]]\n");
+#endif /* __APPLE__ */
        exit(1);
 }
 
index 061189e71208ca5c85a2b38b423a15ef1673eb4f..44c5ff99d02d30c7251fb8c2a56d30eb699e20c7 100644 (file)
 .Os
 .Sh NAME
 .Nm test ,
-.Nm [
+.Nm \&[
 .Nd condition evaluation utility
 .Sh SYNOPSIS
-.Nm test
+.Nm
 .Ar expression
-.Nm [
+.Nm \&[
 .Ar expression Cm ]
 .Sh DESCRIPTION
 The
-.Nm test
+.Nm
 utility evaluates the expression and, if it evaluates
 to true, returns a zero (true) exit status; otherwise
 it returns 1 (false).
@@ -58,10 +58,10 @@ If there is no expression, test also
 returns 1 (false).
 .Pp
 All operators and flags are separate arguments to the
-.Nm test
+.Nm
 utility.
 .Pp
-The following primaries are used to construct expression:
+The following primaries are used to construct expressions:
 .Bl -tag -width Ar
 .It Fl b Ar file
 True if
@@ -214,11 +214,6 @@ True if string
 comes after
 .Ar \&s\&2
 based on the ASCII value of their characters.
-.It Ar \&s\&1
-True if
-.Ar \&s\&1
-is not the null
-string.
 .It Ar \&n\&1 Fl \&eq Ar \&n\&2 
 True if the integers
 .Ar \&n\&1
@@ -288,7 +283,7 @@ operator has higher precedence than the
 operator.
 .Sh GRAMMAR AMBIGUITY
 The 
-.Nm test
+.Nm
 grammar is inherently ambiguous.  In order to assure a degree of consistency,
 the cases described in 
 .St -p1003.2
@@ -298,7 +293,7 @@ standards document.  All other cases are subject to the ambiguity in the
 command semantics.
 .Sh RETURN VALUES
 The
-.Nm test
+.Nm
 utility exits with one of the following values:
 .Bl -tag -width Ds
 .It 0
@@ -311,7 +306,7 @@ An error occurred.
 .El
 .Sh STANDARDS
 The
-.Nm test
+.Nm
 utility implements a superset of the
 .St -p1003.2
 specification.
index 366ccda940ba66d55f82ef189f6179b4e4f0a02d..20df58a2e5255b30b3253f56c300484f93b02698 100644 (file)
@@ -164,7 +164,7 @@ main(argc, argv)
 {
        int     res;
 
-       if (strcmp(argv[0], "[") == 0) {
+       if (argv[0] && strcmp(argv[0], "[") == 0) {
                if (strcmp(argv[--argc], "]"))
                        errx(2, "missing ]");
                argv[argc] = NULL;
index 4ccc596ae1bbafd82890e2d4dbdcc30719ef94ba..8253ea99f89d97041fcb239c1abc5de632dc3284 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $NetBSD: uname.1,v 1.7 1997/10/20 02:16:38 lukem Exp $
+.\"    $NetBSD: uname.1,v 1.12 2005/03/27 18:41:22 peter Exp $
 .\"
 .\" Copyright (c) 1990 The Regents of the University of California.
 .\" All rights reserved.
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -32,9 +28,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     from: @(#)du.1 6.13 (Berkeley) 6/20/91
-.\"    $NetBSD: uname.1,v 1.7 1997/10/20 02:16:38 lukem Exp $
+.\"    $NetBSD: uname.1,v 1.12 2005/03/27 18:41:22 peter Exp $
 .\"
-.Dd January 26, 1994
+.Dd November 9, 1998
 .Dt UNAME 1
 .Os
 .Sh NAME
@@ -42,7 +38,7 @@
 .Nd Print operating system name
 .Sh SYNOPSIS
 .Nm
-.Op Fl amnpsrv
+.Op Fl amnprsv
 .Sh DESCRIPTION
 The
 .Nm
@@ -51,9 +47,9 @@ to the standard output.
 .Pp
 The following options are available:
 .Bl -tag -width indent
-.It Fl a 
+.It Fl a
 Behave as though all of the options
-.Fl mnrsv 
+.Fl mnrsv
 were specified.
 .It Fl m
 print the machine hardware name.
@@ -62,16 +58,16 @@ print the nodename (the nodename may be a name
 that the system is known by to a communications
 network).
 .It Fl p
-print the generic processor type.
-.It Fl s
-print the operating system name.
+print the machine processor architecture name.
 .It Fl r
 print the operating system release.
+.It Fl s
+print the operating system name.
 .It Fl v
 print the operating system version.
 .El
 .Pp
-If no options are specified, 
+If no options are specified,
 .Nm
 prints the operating system name as if the
 .Fl s
@@ -85,3 +81,6 @@ The
 .Nm
 utility conforms to
 .St -p1003.2-92 .
+The
+.Fl p
+option is an extension to the standard.
index 72a617860628331409d7f19f2d1b2644b12e0fa5..6c89b812a7b89e8395c3ae404965cf3643bb9f99 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: uname.c,v 1.9 1997/10/20 02:16:39 lukem Exp $  */
+/*     $NetBSD: uname.c,v 1.10 1998/11/09 13:24:05 kleink Exp $        */
 
 /*
  * Copyright (c) 1994 Winning Strategies, Inc.
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: uname.c,v 1.9 1997/10/20 02:16:39 lukem Exp $");
+__RCSID("$NetBSD: uname.c,v 1.10 1998/11/09 13:24:05 kleink Exp $");
 #endif /* not lint */
 
+#include <sys/param.h>
+#include <limits.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-#include <locale.h>
 #include <unistd.h>
-#include <sys/utsname.h>
 #include <err.h>
 
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+
+#ifdef __APPLE__
+#include <get_compat.h>
+#else  /* !__APPLE__ */
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
+
 int    main __P((int, char **));
 static void usage __P((void));
 
-#define        PRINT_SYSNAME   0x01
-#define        PRINT_NODENAME  0x02
-#define        PRINT_RELEASE   0x04
-#define        PRINT_VERSION   0x08
-#define        PRINT_MACHINE   0x10
-#define        PRINT_PROCESSOR 0x20
-#define        PRINT_ALL       0x3f
+/* Note that PRINT_MACHINE_ARCH is excluded from PRINT_ALL! */
+#define        PRINT_SYSNAME           0x01
+#define        PRINT_NODENAME          0x02
+#define        PRINT_RELEASE           0x04
+#define        PRINT_VERSION           0x08
+#define        PRINT_MACHINE           0x10
+#define        PRINT_MACHINE_ARCH      0x20
+#define        PRINT_ALL               \
+    (PRINT_SYSNAME|PRINT_NODENAME|PRINT_RELEASE|PRINT_VERSION|PRINT_MACHINE)
 
 int
 main(argc, argv) 
@@ -61,16 +72,24 @@ main(argc, argv)
        char **argv;
 {
        struct utsname u;
+#ifndef __APPLE__
+       char machine_arch[SYS_NMLN];
+#endif /* !__APPLE__ */
        int c;
        int space = 0;
        int print_mask = 0;
 
-       setlocale(LC_ALL, "");
+       (void)setlocale(LC_ALL, "");
 
-       while ((c = getopt(argc,argv,"amnprsv")) != -1 ) {
-               switch ( c ) {
+       while ((c = getopt(argc,argv,"amnprsv")) != -1) {
+               switch (c) {
                case 'a':
                        print_mask |= PRINT_ALL;
+#ifdef __APPLE__
+                       if (!COMPAT_MODE("bin/uname", "Unix2003")) {
+                               print_mask |= PRINT_MACHINE_ARCH;
+                       }
+#endif /* __APPLE__ */
                        break;
                case 'm':
                        print_mask |= PRINT_MACHINE;
@@ -78,8 +97,8 @@ main(argc, argv)
                case 'n':
                        print_mask |= PRINT_NODENAME;
                        break;
-               case 'p': 
-                       print_mask |= PRINT_PROCESSOR;
+               case 'p':
+                       print_mask |= PRINT_MACHINE_ARCH;
                        break;
                case 'r': 
                        print_mask |= PRINT_RELEASE;
@@ -105,11 +124,20 @@ main(argc, argv)
                print_mask = PRINT_SYSNAME;
        }
 
-       if (uname(&u)) {
-               err(1, "uname");
+       if (uname(&u) != 0) {
+               err(EXIT_FAILURE, "uname");
                /* NOTREACHED */
        }
+#ifndef __APPLE__
+       if (print_mask & PRINT_MACHINE_ARCH) {
+               int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
+               size_t len = sizeof (machine_arch);
 
+               if (sysctl(mib, sizeof (mib) / sizeof (mib[0]), machine_arch,
+                   &len, NULL, 0) < 0)
+                       err(EXIT_FAILURE, "sysctl");
+       }
+#else /* __APPLE__ */
        /*
         * Let's allow the user to override the output of uname via the shell environment.
         * This is a useful feature for cross-compiling (eg. during an OS bringup).
@@ -123,6 +151,7 @@ main(argc, argv)
                s = getenv ("UNAME_VERSION");  if (s) strncpy (u.version,  s, sizeof (u.version));
                s = getenv ("UNAME_MACHINE");  if (s) strncpy (u.machine,  s, sizeof (u.machine));
        }
+#endif /* !__APPLE__ */
 
        if (print_mask & PRINT_SYSNAME) {
                space++;
@@ -144,8 +173,11 @@ main(argc, argv)
                if (space++) putchar(' ');
                fputs(u.machine, stdout);
        }
-       if (print_mask & PRINT_PROCESSOR) {
+       if (print_mask & PRINT_MACHINE_ARCH) {
                if (space++) putchar(' ');
+#ifndef __APPLE__
+               fputs(machine_arch, stdout);
+#else
 #if   defined(__ppc__)
                fputs("powerpc", stdout);
 #elif defined(__i386__)
@@ -153,10 +185,11 @@ main(argc, argv)
 #else
                fputs("unknown", stdout);
 #endif
+#endif /* __APPLE__ */
        }
        putchar('\n');
 
-       exit(0);
+       exit(EXIT_SUCCESS);
        /* NOTREACHED */
 }
 
@@ -164,5 +197,5 @@ static void
 usage()
 {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
-       exit(1);
+       exit(EXIT_FAILURE);
 }
index 6629f57a836605579cae064607fd0f58396241e6..5c4f8726e3e9a7d9392ba093d9d4ec01155da7df 100644 (file)
 lists the login names of the users currently on the system,
 in sorted order, space separated, on a single line.
 .Sh FILES
-.Bl -tag -width /var/run/utmp
-.It Pa /var/run/utmp
+.Bl -tag -width /var/run/utmpx
+.It Pa /var/run/utmpx
 .El
 .Sh SEE ALSO
 .Xr finger 1 ,
 .Xr last 1 ,
 .Xr who 1 ,
-.Xr utmp 5
+.Xr utmpx 5
 .Sh HISTORY
 The
 .Nm
index 5e243cd420f25ee1c0b4a3b41825b40450f58183..ff24ecb9fcc7ae28d75ce09fcb1d8e5cbaa1ba81 100644 (file)
@@ -54,9 +54,9 @@ __RCSID("$NetBSD: users.c,v 1.7 1998/02/03 04:19:15 perry Exp $");
 #include <unistd.h>
 #include <string.h>
 #include <unistd.h>
-#include <utmp.h>
+#include <utmpx.h>
 
-typedef char   namebuf[UT_NAMESIZE];
+typedef char   namebuf[_UTX_USERSIZE];
 
 int    main __P((int, char **));
 int scmp __P((const void *, const void *));
@@ -70,7 +70,7 @@ main(argc, argv)
        int ncnt = 0;
        int nmax = 0;
        int cnt;
-       struct utmp utmp;
+       struct utmpx *ux;
        int ch;
 
        while ((ch = getopt(argc, argv, "")) != -1)
@@ -83,13 +83,11 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
-       if (!freopen(_PATH_UTMP, "r", stdin)) {
-               err(1, "can't open %s", _PATH_UTMP);
-               /* NOTREACHED */
-       }
+       setutxent();
 
-       while (fread((char *)&utmp, sizeof(utmp), 1, stdin) == 1) {
-               if (*utmp.ut_name) {
+       while ((ux = getutxent()) != NULL) {
+               if (*ux->ut_user && ux->ut_type == USER_PROCESS)
+               {
                        if (ncnt >= nmax) {
                                nmax += 32;
                                names = realloc(names, 
@@ -101,17 +99,17 @@ main(argc, argv)
                                }
                        }
 
-                       (void)strncpy(names[ncnt], utmp.ut_name, UT_NAMESIZE);
+                       (void)strncpy(names[ncnt], ux->ut_user, _UTX_USERSIZE);
                        ++ncnt;
                }
        }
 
        if (ncnt) {
-               qsort(names, ncnt, UT_NAMESIZE, scmp);
-               (void)printf("%.*s", UT_NAMESIZE, names[0]);
+               qsort(names, ncnt, _UTX_USERSIZE, scmp);
+               (void)printf("%.*s", _UTX_USERSIZE, names[0]);
                for (cnt = 1; cnt < ncnt; ++cnt)
-                       if (strncmp(names[cnt], names[cnt - 1], UT_NAMESIZE))
-                               (void)printf(" %.*s", UT_NAMESIZE, names[cnt]);
+                       if (strncmp(names[cnt], names[cnt - 1], _UTX_USERSIZE))
+                               (void)printf(" %.*s", _UTX_USERSIZE, names[cnt]);
                (void)printf("\n");
        }
        exit(0);
@@ -121,5 +119,5 @@ int
 scmp(p, q)
        const void *p, *q;
 {
-       return(strncmp((char *) p, (char *) q, UT_NAMESIZE));
+       return(strncmp((char *) p, (char *) q, _UTX_USERSIZE));
 }
index 66fdc32c33a892abb968bc91603ed33e95f5e941..b810f81afd3bfaf82ef7f525c85334bf98e90ac2 100644 (file)
@@ -28,7 +28,7 @@ DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
 
-NEXTSTEP_PB_CFLAGS = -no-cpp-precomp -Wno-error -DSUCKAGE=1000000000000
+NEXTSTEP_PB_CFLAGS = -no-cpp-precomp -Wno-error -DHAVE_KVM=0 -DHAVE_UTMPX=1
 
 
 NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(NAME)/Build
index ba7a1ade6a23c648237190313f41e9d42ef931a7..8fe24bb457f02b0720c013d776da2043932cb9a9 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 
 extern int use_ampm;
 
-struct extern_proc;
-void   pr_attime(time_t *, time_t *);
-int    pr_idle(time_t);
-int    proc_compare(struct extern_proc *, struct extern_proc *);
+struct kinfo_proc;
 
+#ifdef __APPLE__
 #define KI_PROC(ki) (&(ki)->kp->kp_proc)
+#endif
+
+void   pr_attime(time_t *, time_t *);
+int    pr_idle(time_t);
+int    proc_compare(struct kinfo_proc *, struct kinfo_proc *);
diff --git a/w/fmt.c b/w/fmt.c
index 5df1c8c981f7a46bf324af5bdf27722d6afa2c38..31a6e50a28c6d78d99b4e22c7db4aaae9b42dd2e 100644 (file)
--- a/w/fmt.c
+++ b/w/fmt.c
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
index 5027d9f303b53ef667acba44919344d9f43beafd..77d506d0ae88ed4a658461e8851eafc50b02a1af 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 
 #include <sys/cdefs.h>
 
+#ifndef __APPLE__
+__FBSDID("$FreeBSD: src/usr.bin/w/pr_time.c,v 1.19 2002/06/07 01:41:54 jmallett Exp $");
+#endif
+
 #ifndef lint
 static const char sccsid[] = "@(#)pr_time.c    8.2 (Berkeley) 4/4/94";
 #endif
@@ -50,8 +50,7 @@ static const char sccsid[] = "@(#)pr_time.c   8.2 (Berkeley) 4/4/94";
  *     Print the time since the user logged in.
  */
 void
-pr_attime(started, now)
-       time_t *started, *now;
+pr_attime(time_t *started, time_t *now)
 {
        static char buf[256];
        struct tm tp, tm;
@@ -90,8 +89,7 @@ pr_attime(started, now)
  *     Returns number of excess characters that were used for long idle time.
  */
 int
-pr_idle(idle)
-       time_t idle;
+pr_idle(time_t idle)
 {
        /* If idle more than 36 hours, print as a number of days. */
        if (idle >= 36 * 3600) {
index 94665dd423039f544e9368bac091b59e482b964d..806f57187602efe63e9a48e88f43a390f340a642 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
+#if 0
 #ifndef lint
-static const char sccsid[] = "@(#)proc_compare.c       8.2 (Berkeley) 9/23/93";
+static char sccsid[] = "@(#)proc_compare.c     8.2 (Berkeley) 9/23/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+#ifndef __APPLE__
+__FBSDID("$FreeBSD: src/usr.bin/w/proc_compare.c,v 1.9 2004/04/14 09:34:17 bde Exp $");
 #endif
 
 #include <sys/param.h>
+#ifdef __APPLE__
+#include <sys/time.h>
+#endif
+#include <sys/proc.h>
 #include <sys/time.h>
 #include <sys/user.h>
 
@@ -53,7 +58,7 @@ static const char sccsid[] = "@(#)proc_compare.c      8.2 (Berkeley) 9/23/93";
  *        with the highest cpu utilization is picked (p_estcpu).  Ties are
  *        broken by picking the highest pid.
  *     3) The sleeper with the shortest sleep time is next.  With ties,
- *        we pick out just "short-term" sleepers (PS_SINTR == 0).
+ *        we pick out just "short-term" sleepers (TDF_SINTR == 0).
  *     4) Further ties are broken by picking the highest pid.
  *
  * If you change this, be sure to consider making the change in the kernel
@@ -62,19 +67,31 @@ static const char sccsid[] = "@(#)proc_compare.c    8.2 (Berkeley) 9/23/93";
  * TODO - consider whether pctcpu should be used.
  */
 
-#include <sys/cdefs.h>
-
+#if !HAVE_KVM
+#define ki_estcpu      p_estcpu
+#define ki_pid         p_pid
+#define ki_slptime     p_slptime
+#define ki_stat                p_stat
+#define ki_tdflags     p_tdflags
+#endif
 
-#define ISRUN(p)        (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
+#define ISRUN(p)       (((p)->ki_stat == SRUN) || ((p)->ki_stat == SIDL))
 #define TESTAB(a, b)    ((a)<<1 | (b))
 #define ONLYA   2
 #define ONLYB   1
 #define BOTH    3
 
+#if HAVE_KVM
+int
+proc_compare(struct kinfo_proc *p1, struct kinfo_proc *p2)
+{
+#else
 int
-proc_compare(p1, p2)
-       struct extern_proc *p1, *p2;
+proc_compare(struct kinfo_proc *arg1, struct kinfo_proc *arg2)
 {
+       struct extern_proc* p1 = &arg1->kp_proc;
+       struct extern_proc* p2 = &arg2->kp_proc;
+#endif
 
        if (p1 == NULL)
                return (1);
@@ -90,29 +107,38 @@ proc_compare(p1, p2)
                /*
                 * tie - favor one with highest recent cpu utilization
                 */
-               if (p2->p_estcpu > p1->p_estcpu)
+               if (p2->ki_estcpu > p1->ki_estcpu)
                        return (1);
-               if (p1->p_estcpu > p2->p_estcpu)
+               if (p1->ki_estcpu > p2->ki_estcpu)
                        return (0);
-               return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
+               return (p2->ki_pid > p1->ki_pid); /* tie - return highest pid */
        }
        /*
         * weed out zombies
         */
-       switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
+       switch (TESTAB(p1->ki_stat == SZOMB, p2->ki_stat == SZOMB)) {
        case ONLYA:
                return (1);
        case ONLYB:
                return (0);
        case BOTH:
-               return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
+               return (p2->ki_pid > p1->ki_pid); /* tie - return highest pid */
        }
        /*
         * pick the one with the smallest sleep time
         */
-       if (p2->p_slptime > p1->p_slptime)
+       if (p2->ki_slptime > p1->ki_slptime)
                return (0);
-       if (p1->p_slptime > p2->p_slptime)
+       if (p1->ki_slptime > p2->ki_slptime)
                return (1);
-       return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
+#ifndef __APPLE__
+       /*
+        * favor one sleeping in a non-interruptible sleep
+        */
+       if (p1->ki_tdflags & TDF_SINTR && (p2->ki_tdflags & TDF_SINTR) == 0)
+               return (1);
+       if (p2->ki_tdflags & TDF_SINTR && (p1->ki_tdflags & TDF_SINTR) == 0)
+               return (0);
+#endif
+       return (p2->ki_pid > p1->ki_pid);       /* tie - return highest pid */
 }
index a7177a7493bfd343210145fadbdced47550fe701..a2c372acb9502a5694ec7c2275e4eb4f8661fc46 100644 (file)
@@ -9,11 +9,7 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
@@ -30,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)uptime.1   8.2 (Berkeley) 4/18/94
-.\" $FreeBSD: src/usr.bin/w/uptime.1,v 1.7 2001/07/15 08:01:40 dd Exp $
+.\" $FreeBSD: src/usr.bin/w/uptime.1,v 1.8 2002/05/09 11:47:40 joe Exp $
 .\"
 .Dd April 18, 1994
 .Dt UPTIME 1
@@ -47,11 +43,6 @@ utility displays the current time,
 the length of time the system has been up,
 the number of users, and the load average of the system over the last
 1, 5, and 15 minutes.
-.Sh FILES
-.Bl -tag -width /mach
-.It Pa /mach
-system name list
-.El
 .Sh SEE ALSO
 .Xr w 1
 .Sh HISTORY
diff --git a/w/w.1 b/w/w.1
index 5bea55776a6dde62d3f84d37909be7f02dbbae63..ba57bae98da2e120b539a4f82613b8d4a15e82f2 100644 (file)
--- a/w/w.1
+++ b/w/w.1
@@ -9,10 +9,6 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
@@ -30,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)w.1        8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/w/w.1,v 1.17 2001/07/26 19:20:13 brian Exp $
+.\" $FreeBSD: src/usr.bin/w/w.1,v 1.20 2005/02/13 22:25:25 ru Exp $
 .\"
 .Dd June 6, 1993
 .Dt W 1
@@ -40,9 +36,7 @@
 .Nd "display who is logged in and what they are doing"
 .Sh SYNOPSIS
 .Nm
-.Op Fl dhin
-.Op Fl M Ar core
-.Op Fl N Ar system
+.Op Fl hin
 .Op Ar user ...
 .Sh DESCRIPTION
 The
@@ -62,40 +56,37 @@ and the name and arguments of the current process.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
-.It Fl d
-dumps out the entire process list on a per controlling
-tty basis, instead of just the top level process.
 .It Fl h
 Suppress the heading.
 .It Fl i
 Output is sorted by idle time.
-.It Fl M
-Extract values associated with the name list from the specified
-core instead of the default
-.Dq /dev/kmem .
-.It Fl N
-Extract the name list from the specified system instead of the
-default
-.Dq /mach .
-.It Fl n
-Don't attempt to resolve network addresses (normally
-.Nm
-interprets addresses and attempts to display them as names).
 .El
 .Pp
 If one or more
 .Ar user
 names are specified, the output is restricted to those users.
-.Sh FILES
-.Bl -tag -width /var/run/utmp -compact
-.It Pa /var/run/utmp
-list of users on the system
-.El
+.Sh COMPATIBILITY
+The
+.Fl M ,
+.FL N ,
+.Fl d ,
+.Fl f ,
+.Fl l ,
+.Fl n ,
+.Fl s ,
+and
+.Fl w
+flags are no longer supported.
 .Sh SEE ALSO
 .Xr finger 1 ,
 .Xr ps 1 ,
 .Xr uptime 1 ,
 .Xr who 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
 .Sh BUGS
 The notion of the
 .Dq current process
@@ -130,16 +121,3 @@ The
 utility does not know about the new conventions for detection of background
 jobs.
 It will sometimes find a background job instead of the right one.
-.Sh COMPATIBILITY
-The
-.Fl f ,
-.Fl l ,
-.Fl s ,
-and
-.Fl w
-flags are no longer supported.
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 3.0 .
diff --git a/w/w.c b/w/w.c
index 0cda4e430fef25e9f1a181e7a913316befae51df..67d9835b1d6e382ac7304666223927624c58acee 100644 (file)
--- a/w/w.c
+++ b/w/w.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1980, 1991, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Portions copyright (c) 2007 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 
 #include <sys/cdefs.h>
 
+#ifndef __APPLE__
+__FBSDID("$FreeBSD: src/usr.bin/w/w.c,v 1.58 2005/06/04 23:40:09 gad Exp $");
+#endif
+
 #ifndef lint
 static const char copyright[] =
 "@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
@@ -59,6 +60,9 @@ static const char sccsid[] = "@(#)w.c 8.4 (Berkeley) 4/16/94";
 #include <sys/socket.h>
 #include <sys/tty.h>
 
+#ifndef __APPLE__
+#include <machine/cpu.h>
+#endif
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
@@ -67,7 +71,11 @@ static const char sccsid[] = "@(#)w.c        8.4 (Berkeley) 4/16/94";
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#if HAVE_KVM
 #include <kvm.h>
+#endif
+#include <langinfo.h>
+#include <libutil.h>
 #include <limits.h>
 #include <locale.h>
 #include <netdb.h>
@@ -77,22 +85,38 @@ static const char sccsid[] = "@(#)w.c       8.4 (Berkeley) 4/16/94";
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <timeconv.h>
 #include <unistd.h>
+#if HAVE_UTMPX
+#include <utmpx.h>
+/* use utmp values so formatting is the same */
+#define UT_NAMESIZE    8
+#define UT_LINESIZE    8
+#else /* HAVE_UTMPX */
 #include <utmp.h>
+#endif /* HAVE_UTMPX */
 #include <vis.h>
 
 #include "extern.h"
 
 struct timeval boottime;
+#if !HAVE_UTMPX
 struct utmp    utmp;
+#endif
 struct winsize ws;
+#if HAVE_KVM
 kvm_t         *kd;
+#endif
 time_t         now;            /* the current time of day */
 int            ttywidth;       /* width of tty */
 int            argwidth;       /* width of tty */
 int            header = 1;     /* true if -h flag: don't print heading */
+#if !HAVE_UTMPX
 int            nflag;          /* true if -n flag: don't convert addrs */
+#endif
+#ifndef __APPLE__
 int            dflag;          /* true if -d flag: output debug info */
+#endif
 int            sortidle;       /* sort by idle time */
 int            use_ampm;       /* use AM/PM time */
 int             use_comma;      /* use comma as floats separator */
@@ -103,7 +127,11 @@ char             **sel_users;      /* login array of particular users selected */
  */
 struct entry {
        struct  entry *next;
+#if HAVE_UTMPX
+       struct  utmpx utmp;
+#else
        struct  utmp utmp;
+#endif
        dev_t   tdev;                   /* dev_t of terminal */
        time_t  idle;                   /* idle time of terminal in seconds */
        struct  kinfo_proc *kp;         /* `most interesting' proc */
@@ -111,7 +139,11 @@ struct     entry {
        struct  kinfo_proc *dkp;        /* debug option proc list */
 } *ep, *ehead = NULL, **nextp = &ehead;
 
+#ifndef __APPLE__
+#define        debugproc(p) *((struct kinfo_proc **)&(p)->ki_udata)
+#else
 #define debugproc(p) *((struct kinfo_proc **)&(p)->ki_spare[0])
+#endif
 
 /* W_DISPHOSTSIZE should not be greater than UT_HOSTSIZE */
 #define        W_DISPHOSTSIZE  16
@@ -120,36 +152,52 @@ static void                pr_header(time_t *, int);
 static struct stat     *ttystat(char *, int);
 static void             usage(int);
 static int              this_is_uptime(const char *s);
+#if !HAVE_KVM
 static void             w_getargv(void);
+#endif
 
 char *fmt_argv(char **, char *, int);  /* ../../bin/ps/fmt.c */
 
 int
-main(argc, argv)
-       int argc;
-       char **argv;
+main(int argc, char *argv[])
 {
-       struct kinfo_proc *kp, *kprocbuf;
+       struct kinfo_proc *kp;
+       struct kinfo_proc *kprocbuf;
        struct kinfo_proc *dkp;
        struct stat *stp;
+#if HAVE_UTMPX
+       struct utmpx *ux;
+#else
        FILE *ut;
+#endif
        time_t touched;
+#if HAVE_KVM
        int ch, i, nentries, nusers, wcmd, longidle, dropgid;
        const char *memf, *nlistf, *p;
+#else
+       int ch, i, nentries, nusers, wcmd, longidle;
+       const char *p;
+#endif /* HAVE_KVM */
        char *x_suffix;
+#ifdef __APPLE__
+       char buf[MAXHOSTNAMELEN];
+#else
        char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];
        char fn[MAXHOSTNAMELEN];
+#endif /* __APPLE__ */
        char *dot;
+#if !HAVE_KVM
        int local_error = 0, retry_count = 0;
        size_t bufSize = 0;
        size_t orig_bufSize = 0;
        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
+#endif
 
        (void)setlocale(LC_ALL, "");
-       /*
+#ifndef __APPLE__
        use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
        use_comma = (*nl_langinfo(RADIXCHAR) != ',');
-       */
+#endif
 
        /* Are we w(1) or uptime(1)? */
        if (this_is_uptime(argv[0]) == 0) {
@@ -160,19 +208,24 @@ main(argc, argv)
                p = "dhiflM:N:nsuw";
        }
 
+#if HAVE_KVM
        dropgid = 0;
-       memf = nlistf = NULL;
+       memf = nlistf = _PATH_DEVNULL;
+#endif
        while ((ch = getopt(argc, argv, p)) != -1)
                switch (ch) {
+#ifndef __APPLE__
                case 'd':
                        dflag = 1;
                        break;
+#endif
                case 'h':
                        header = 0;
                        break;
                case 'i':
                        sortidle = 1;
                        break;
+#if HAVE_KVM
                case 'M':
                        header = 0;
                        memf = optarg;
@@ -182,11 +235,24 @@ main(argc, argv)
                        nlistf = optarg;
                        dropgid = 1;
                        break;
+#endif /* HAVE_KVM */
+#if !HAVE_UTMPX
                case 'n':
                        nflag = 1;
                        break;
+#else /* !HAVE_UTMPX */
+               case 'n':
+#endif /* !HAVE_UTMPX */
                case 'f': case 'l': case 's': case 'u': case 'w':
+#if !HAVE_KVM
+               case 'M': case 'N':
+#endif
+#ifdef __APPLE__
+               case 'd':
+                       warnx("[-MNdflnsuw] no longer supported");
+#else
                        warnx("[-flsuw] no longer supported");
+#endif
                        /* FALLTHROUGH */
                case '?':
                default:
@@ -200,6 +266,7 @@ main(argc, argv)
        _res.retrans = 2;       /* resolver timeout to 2 seconds per try */
        _res.retry = 1;         /* only try once.. */
 
+#if HAVE_KVM
        /*
         * Discard setgid privileges if not the running kernel so that bad
         * guys can't print interesting stuff from kernel memory.
@@ -207,23 +274,34 @@ main(argc, argv)
        if (dropgid)
                setgid(getgid());
 
-#ifdef OLD_PROC
        if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
                errx(1, "%s", errbuf);
 #endif
 
        (void)time(&now);
+#if HAVE_UTMPX
+       setutxent();
+#else
        if ((ut = fopen(_PATH_UTMP, "r")) == NULL)
                err(1, "%s", _PATH_UTMP);
+#endif
 
        if (*argv)
                sel_users = argv;
 
+#if HAVE_UTMPX
+       for (nusers = 0; (ux = getutxent());) {
+               if (ux->ut_user[0] == '\0' || ux->ut_type != USER_PROCESS)
+                       continue;
+               if (!(stp = ttystat(ux->ut_line, sizeof(ux->ut_line))))
+                       continue;       /* corrupted record */
+#else
        for (nusers = 0; fread(&utmp, sizeof(utmp), 1, ut);) {
                if (utmp.ut_name[0] == '\0')
                        continue;
                if (!(stp = ttystat(utmp.ut_line, UT_LINESIZE)))
                        continue;       /* corrupted record */
+#endif
                ++nusers;
                if (wcmd == 0)
                        continue;
@@ -233,7 +311,11 @@ main(argc, argv)
 
                        usermatch = 0;
                        for (user = sel_users; !usermatch && *user; user++)
+#if HAVE_UTMPX
+                               if (!strncmp(ux->ut_user, *user, sizeof(ux->ut_user)))
+#else
                                if (!strncmp(utmp.ut_name, *user, UT_NAMESIZE))
+#endif
                                        usermatch = 1;
                        if (!usermatch)
                                continue;
@@ -242,7 +324,11 @@ main(argc, argv)
                        errx(1, "calloc");
                *nextp = ep;
                nextp = &ep->next;
+#if HAVE_UTMPX
+               memmove(&ep->utmp, ux, sizeof(*ux));
+#else
                memmove(&ep->utmp, &utmp, sizeof(struct utmp));
+#endif
                ep->tdev = stp->st_rdev;
 #ifdef CPU_CONSDEV
                /*
@@ -260,19 +346,30 @@ main(argc, argv)
                }
 #endif
                touched = stp->st_atime;
+#ifdef __APPLE__
+               if (touched < ep->utmp.ut_tv.tv_sec) {
+                       /* tty untouched since before login */
+                       touched = ep->utmp.ut_tv.tv_sec;
+               }
+#else
                if (touched < ep->utmp.ut_time) {
                        /* tty untouched since before login */
                        touched = ep->utmp.ut_time;
                }
+#endif
                if ((ep->idle = now - touched) < 0)
                        ep->idle = 0;
        }
+#if HAVE_UTMPX
+       endutxent();
+#else
        (void)fclose(ut);
+#endif
 
        if (header || wcmd == 0) {
                pr_header(&now, nusers);
                if (wcmd == 0) {
-#ifdef OLD_PROC
+#if HAVE_KVM
                        (void)kvm_close(kd);
 #endif
                        exit(0);
@@ -292,7 +389,7 @@ main(argc, argv)
                                HEADER_LOGIN_IDLE HEADER_WHAT);
        }
 
-#ifdef OLD_PROC
+#if HAVE_KVM
        if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL)
                err(1, "%s", kvm_geterr(kd));
 #else
@@ -326,20 +423,27 @@ main(argc, argv)
                sleep(1);
        }
        nentries = bufSize / sizeof(struct kinfo_proc);
-#endif
+#endif /* !HAVE_KVM */
+
+#if !HAVE_KVM
+#define ki_stat                kp_proc.p_stat
+#define ki_pgid                kp_eproc.e_pgid
+#define ki_tpgid       kp_eproc.e_tpgid
+#define ki_tdev                kp_eproc.e_tdev
+#endif /* !HAVE_KVM */
        for (i = 0; i < nentries; i++, kp++) {
-               if (kp->kp_proc.p_stat == SIDL || kp->kp_proc.p_stat == SZOMB)
+               if (kp->ki_stat == SIDL || kp->ki_stat == SZOMB)
                        continue;
                for (ep = ehead; ep != NULL; ep = ep->next) {
-                       if (ep->tdev == kp->kp_eproc.e_tdev) {
+                       if (ep->tdev == kp->ki_tdev) {
                                /*
                                 * proc is associated with this terminal
                                 */
-                               if (ep->kp == NULL && kp->kp_eproc.e_pgid == kp->kp_eproc.e_tpgid) {
+                               if (ep->kp == NULL && kp->ki_pgid == kp->ki_tpgid) {
                                        /*
                                         * Proc is 'most interesting'
                                         */
-                                       if (proc_compare(&ep->kp->kp_proc, &kp->kp_proc))
+                                       if (proc_compare(ep->kp, kp))
                                                ep->kp = kp;
                                }
                                /*
@@ -350,9 +454,9 @@ main(argc, argv)
                                 */
                                dkp = ep->dkp;
                                ep->dkp = kp;
-/* --bbraun
+#ifndef __APPLE__
                                debugproc(kp) = dkp;
-*/
+#endif
                        }
                }
        }
@@ -370,12 +474,12 @@ main(argc, argv)
                        ep->args = strdup("-");
                        continue;
                }
-#ifdef OLD_PROC
+#if HAVE_KVM
                ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
-                   ep->kp->kp_proc.p_comm, MAXCOMLEN);
+                   ep->kp->ki_comm, MAXCOMLEN);
 #else
                w_getargv();
-#endif
+#endif /* HAVE_KVM */
                if (ep->args == NULL)
                        err(1, NULL);
        }
@@ -398,19 +502,21 @@ main(argc, argv)
        }
 
        for (ep = ehead; ep != NULL; ep = ep->next) {
+#if HAVE_UTMPX
+               char host_buf[sizeof(ep->utmp.ut_host) + 1];
+               strlcpy(host_buf, ep->utmp.ut_host, sizeof(host_buf));
+#else
                char host_buf[UT_HOSTSIZE + 1];
                struct sockaddr_storage ss;
                struct sockaddr *sa = (struct sockaddr *)&ss;
                struct sockaddr_in *lsin = (struct sockaddr_in *)&ss;
-#ifdef SUCKAGE
-               struct hostent *hp;
-#else
                struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)&ss;
-#endif
+               time_t t;
                int isaddr;
 
                host_buf[UT_HOSTSIZE] = '\0';
                strncpy(host_buf, ep->utmp.ut_host, UT_HOSTSIZE);
+#endif /* HAVE_UTMPX */
                p = *host_buf ? host_buf : "-";
                if ((x_suffix = strrchr(p, ':')) != NULL) {
                        if ((dot = strchr(x_suffix, '.')) != NULL &&
@@ -419,22 +525,11 @@ main(argc, argv)
                        else
                                x_suffix = NULL;
                }
+#if !HAVE_UTMPX
                if (!nflag) {
                        /* Attempt to change an IP address into a name */
                        isaddr = 0;
                        memset(&ss, '\0', sizeof(ss));
-#ifdef SUCKAGE
-                       if (inet_aton(p, &lsin->sin_addr) ) {
-                               lsin->sin_len = sizeof(*lsin);
-                               lsin->sin_family = AF_INET;
-                               isaddr = 1;
-                       }
-
-                       hp = gethostbyaddr((char *)&lsin->sin_addr, sizeof(lsin->sin_addr), AF_INET);
-                       if( hp ) {
-                               p = hp->h_name;
-                       }
-#else
                        if (inet_pton(AF_INET6, p, &lsin6->sin6_addr) == 1) {
                                lsin6->sin6_len = sizeof(*lsin6);
                                lsin6->sin6_family = AF_INET6;
@@ -447,13 +542,13 @@ main(argc, argv)
                        if (isaddr && realhostname_sa(fn, sizeof(fn), sa,
                            sa->sa_len) == HOSTNAME_FOUND)
                                p = fn;
-#endif
                }
+#endif /* !HAVE_UTMPX */
                if (x_suffix) {
                        (void)snprintf(buf, sizeof(buf), "%s:%s", p, x_suffix);
                        p = buf;
                }
-#ifndef SUCKAGE
+#ifndef __APPLE__
                if (dflag) {
                        for (dkp = ep->dkp; dkp != NULL; dkp = debugproc(dkp)) {
                                const char *ptr;
@@ -466,33 +561,41 @@ main(argc, argv)
                                    dkp->ki_pid, ptr);
                        }
                }
-#endif
+#endif /* !__APPLE__ */
                (void)printf("%-*.*s %-*.*s %-*.*s ",
+#if HAVE_UTMPX
+                   UT_NAMESIZE, (int)sizeof(ep->utmp.ut_user), ep->utmp.ut_user,
+                   UT_LINESIZE, (int)sizeof(ep->utmp.ut_line),
+#else
                    UT_NAMESIZE, UT_NAMESIZE, ep->utmp.ut_name,
                    UT_LINESIZE, UT_LINESIZE,
+#endif
                    strncmp(ep->utmp.ut_line, "tty", 3) &&
                    strncmp(ep->utmp.ut_line, "cua", 3) ?
                    ep->utmp.ut_line : ep->utmp.ut_line + 3,
                    W_DISPHOSTSIZE, W_DISPHOSTSIZE, *p ? p : "-");
-               pr_attime(&ep->utmp.ut_time, &now);
+#ifdef __APPLE__
+               pr_attime(&ep->utmp.ut_tv.tv_sec, &now);
+#else
+               t = _time_to_time32(ep->utmp.ut_time);
+               pr_attime(&t, &now);
+#endif
                longidle = pr_idle(ep->idle);
                (void)printf("%.*s\n", argwidth - longidle, ep->args);
-#ifndef OLD_PROC
+#ifdef __APPLE__
                free(ep->args);
 #endif
        }
-#ifdef OLD_PROC
+#if HAVE_KVM
        (void)kvm_close(kd);
 #else
        free(kprocbuf);
-#endif
+#endif /* HAVE_KVM */
        exit(0);
 }
 
 static void
-pr_header(nowp, nusers)
-       time_t *nowp;
-       int nusers;
+pr_header(time_t *nowp, int nusers)
 {
        double avenrun[3];
        time_t uptime;
@@ -504,11 +607,9 @@ pr_header(nowp, nusers)
        /*
         * Print time of day.
         */
-       (void)strftime(buf, sizeof(buf) - 1,
-                      use_ampm ? "%l:%M%p" : "%k:%M", localtime(nowp));
-       buf[sizeof(buf) - 1] = '\0';
-       (void)printf("%s ", buf);
-
+       if (strftime(buf, sizeof(buf),
+           use_ampm ? "%l:%M%p" : "%k:%M", localtime(nowp)) != 0)
+               (void)printf("%s ", buf);
        /*
         * Print how long system has been up.
         * (Found by looking getting "boottime" from the kernel)
@@ -560,36 +661,33 @@ pr_header(nowp, nusers)
 }
 
 static struct stat *
-ttystat(line, sz)
-       char *line;
-       int sz;
+ttystat(char *line, int sz)
 {
        static struct stat sb;
        char ttybuf[MAXPATHLEN];
 
        (void)snprintf(ttybuf, sizeof(ttybuf), "%s%.*s", _PATH_DEV, sz, line);
-       if (stat(ttybuf, &sb)) {
+       if (stat(ttybuf, &sb) == 0) {
+               return (&sb);
+       } else {
                warn("%s", ttybuf);
                return (NULL);
        }
-       return (&sb);
 }
 
 static void
-usage(wcmd)
-       int wcmd;
+usage(int wcmd)
 {
        if (wcmd)
                (void)fprintf(stderr,
-                   "usage: w [-dhin] [-M core] [-N system] [user ...]\n");
+                   "usage: w [hi] [user ...]\n");
        else
                (void)fprintf(stderr, "usage: uptime\n");
        exit(1);
 }
 
 static int 
-this_is_uptime(s)
-       const char *s;
+this_is_uptime(const char *s)
 {
        const char *u;
 
@@ -602,6 +700,7 @@ this_is_uptime(s)
        return (-1);
 }
 
+#if !HAVE_KVM
 static void
 w_getargv(void)
 {
@@ -670,3 +769,4 @@ ERROR:
        asprintf(&ep->args, "%s", KI_PROC(ep)->p_comm);
        return;
 }
+#endif /* HAVE_KVM */
index 21a2a4a3d7a2b3bc5f5cf918cc7724af2bd463f1..a425a8a8e0514d4039dc9f6f7cff40144891ce9c 100644 (file)
@@ -12,11 +12,11 @@ NAME = which
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Tool
 
-OTHERLINKED = which.csh
+CFILES = which.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble which.1
 
-OTHERLINKEDOFILES = which.o
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index ec3a5ea73bace030b18bff080b5329634cd49732..9e10e90bb6746d84796f702e9cf6b6039454678d 100644 (file)
@@ -1,3 +1 @@
-SHELLTOOL = which.csh
-
 include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Preamble.Common
index 908f7d37ed3370f7b42cb722b1efcfa20f0eb44a..f889e0980141d01801e078841500d52d43dc5aa6 100644 (file)
@@ -1,7 +1,4 @@
-.\"    $NetBSD: which.1,v 1.4 1997/10/20 03:19:23 lukem Exp $
-.\"
-.\" Copyright (c) 1980, 1991 Regents of the University of California.
-.\" All rights reserved.
+.\" Manpage Copyright (c) 1995, Jordan Hubbard <jkh@FreeBSD.org>
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\"    documentation and/or other materials provided with the distribution.
 .\" 3. All advertising materials mentioning features or use of this software
 .\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\"      This product includes software developed by the FreeBSD Project
+.\"      its contributors.
+.\" 4. Neither the name of the FreeBSD Project nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
+.\" THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\"     from: @(#)which.1      6.3 (Berkeley) 4/23/91
-.\"    $NetBSD: which.1,v 1.4 1997/10/20 03:19:23 lukem Exp $
+.\" $FreeBSD: src/usr.bin/which/which.1,v 1.25 2005/02/10 16:04:22 ru Exp $
 .\"
-.Dd April 23, 1991
+.Dd June 21, 2002
 .Dt WHICH 1
-.Os BSD 3
+.Os
 .Sh NAME
 .Nm which
 .Nd "locate a program file in the user's path"
 .Sh SYNOPSIS
 .Nm
-.Op Ar name
-.Ar ...
+.Op Fl as
+.Ar program ...
 .Sh DESCRIPTION
+The
 .Nm
-takes a list of names and looks for the files which would be
-executed had these names been given as commands.
-Each argument is expanded if it is aliased,
-and searched for along the user's path.
-Both aliases and path are taken from the user's
-.Pa \&.cshrc
-file.
-.Sh FILES
-.Bl -tag -width ~/\&.cshrc
-.It Pa ~/\&.cshrc
-source of aliases and path values
+utility
+takes a list of command names and searches the path for each executable
+file that would be run had these commands actually been invoked.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+List all instances of executables found (instead of just the first one
+of each).
+.It Fl s
+No output, just return 0 if any of the executables are found, or 1 if
+none are found.
 .El
-.Sh DIAGNOSTICS
-A diagnostic is given for names which are aliased to more than a single
-word,
-or if an executable file with the argument name was not found in the path.
-.Sh BUGS
-Must be executed by a
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh SEE ALSO
+.Xr builtin 1 ,
 .Xr csh 1 ,
-or some other shell which knows about aliases.
+.Xr find 1 ,
+.Xr locate 1 ,
+.Xr whereis 1
 .Sh HISTORY
 The
 .Nm
-command appeared in
-.Bx 3.0 .
+command first appeared in
+.Fx 2.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was originally written in Perl and was contributed by
+.An Wolfram Schneider Aq wosch@FreeBSD.org .
+The current version of
+.Nm
+was rewritten in C by
+.An Daniel Papasian Aq dpapasia@andrew.cmu.edu .
diff --git a/which/which.c b/which/which.c
new file mode 100644 (file)
index 0000000..e8ecea2
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2000 Dan Papasian.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD: src/usr.bin/which/which.c,v 1.6 2005/02/10 16:04:22 ru Exp $");
+
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void     usage(void);
+static int      print_matches(char *, char *);
+       
+int    silent;
+int    allpaths;
+
+int
+main(int argc, char **argv)
+{
+       char *p, *path;
+       ssize_t pathlen;
+       int opt, status;
+
+       status = EXIT_SUCCESS;
+
+       while ((opt = getopt(argc, argv, "as")) != -1) {
+               switch (opt) {
+               case 'a':
+                       allpaths = 1;
+                       break;
+               case 's':
+                       silent = 1;
+                       break;
+               default:
+                       usage();
+                       break;
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       if (argc == 0)
+               usage();
+
+       if ((p = getenv("PATH")) == NULL)
+               exit(EXIT_FAILURE);
+       pathlen = strlen(p) + 1;
+       path = malloc(pathlen);
+       if (path == NULL)
+               err(EXIT_FAILURE, NULL);
+
+       while (argc > 0) {
+               memcpy(path, p, pathlen);
+       
+               if (strlen(*argv) >= FILENAME_MAX ||
+                   print_matches(path, *argv) == -1)
+                       status = EXIT_FAILURE;
+
+               argv++;
+               argc--;
+       }
+
+       exit(status);
+}
+
+static void
+usage(void)
+{
+
+       (void)fprintf(stderr, "usage: which [-as] program ...\n");
+       exit(EXIT_FAILURE);
+}
+
+static int
+is_there(char *candidate)
+{
+       struct stat fin;
+
+       /* XXX work around access(2) false positives for superuser */
+       if (access(candidate, X_OK) == 0 &&
+           stat(candidate, &fin) == 0 &&
+           S_ISREG(fin.st_mode) &&
+           (getuid() != 0 ||
+           (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+               if (!silent)
+                       printf("%s\n", candidate);
+               return (1);
+       }
+       return (0);
+}
+
+static int
+print_matches(char *path, char *filename)
+{
+       char candidate[PATH_MAX];
+       const char *d;
+       int found;
+
+       if (strchr(filename, '/') != NULL)
+               return (is_there(filename) ? 0 : -1);
+       found = 0;
+       while ((d = strsep(&path, ":")) != NULL) {
+               if (*d == '\0')
+                       d = ".";
+               if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
+                   filename) >= (int)sizeof(candidate))
+                       continue;
+               if (is_there(candidate)) {
+                       found = 1;
+                       if (!allpaths)
+                               break;
+               }
+       }
+       return (found ? 0 : -1);
+}
+
diff --git a/which/which.csh b/which/which.csh
deleted file mode 100644 (file)
index 5295deb..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/csh
-#
-# DO NOT USE "csh -f"
-#
-# Copyright (c) 1983 The Regents of the University of California.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#      This product includes software developed by the University of
-#      California, Berkeley and its contributors.
-# 4. Neither the name of the University nor the names of its contributors
-#    may be used to endorse or promote products derived from this software
-#    without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-#      @(#)which.csh   5.5 (Berkeley) 4/18/91
-#
-
-#      which : tells you which program you get
-#
-set prompt = "% "
-set noglob
-foreach arg ( $argv )
-    set alius = `alias $arg`
-    switch ( $#alius )
-       case 0 :
-           breaksw
-       case 1 :
-           set arg = $alius[1]
-           breaksw
-        default :
-           echo ${arg}: "      " aliased to $alius
-           continue
-    endsw
-    unset found
-    if ( $arg:h != $arg:t ) then
-       if ( -e $arg ) then
-           echo $arg
-       else
-           echo $arg not found
-       endif
-       continue
-    else
-       foreach i ( $path )
-           if ( -x $i/$arg && ! -d $i/$arg ) then
-               echo $i/$arg
-               set found
-               break
-           endif
-       end
-    endif
-    if ( ! $?found ) then
-       echo no $arg in $path
-    endif
-end
index 333d180d5d349db58bd0c578084824c5ffe69252..f80a0f47c4aa2709d3ac6415df81c0ad517735e0 100644 (file)
--- a/who/who.1
+++ b/who/who.1
@@ -79,9 +79,10 @@ An error occurred.
 Show idle time for each user in hours and minutes as
 .Ar hh Ns : Ns Ar mm ,
 .Ql \&.
-if the user has been idle less that a minute, and
+if the user has been idle less than a minute, and
 .Dq Li old
 if the user has been idle more than 24 hours.
+Additionally, display the PID of the user's login process.
 .It Cm am I
 Equivalent to
 .Fl m .
@@ -90,36 +91,14 @@ Equivalent to
 By default,
 .Nm
 gathers information from the file
-.Pa /var/run/utmp .
+.Pa /var/run/utmpx .
 An alternate
 .Ar file
-may be specified which is usually
-.Pa /var/log/wtmp
-(or
-.Pa /var/log/wtmp.[0-6]
-depending on site policy as
-.Pa wtmp
-can grow quite large and daily versions may or may not
-be kept around after compression by
-.Xr ac 8 ) .
-The
-.Pa wtmp
-file contains a record of every login, logout,
-crash, shutdown and date change
-since
-.Pa wtmp
-was last truncated or
-created.
-.Pp
-If
-.Pa /var/log/wtmp
-is being used as the file, the user name may be empty
-or one of the special characters '|', '}' and '~'.
-Logouts produce
-an output line without any user name.
-For more information on the
-special characters, see
-.Xr utmp 5 .
+may be specified.
+.Sh LEGACY DESCRIPTION
+In legacy mode,
+.Fl u
+does not display the PID of the user's login process.
 .Sh ENVIRONMENT
 The
 .Ev COLUMNS , LANG , LC_ALL
@@ -130,10 +109,8 @@ environment variables affect the execution of
 as described in
 .Xr environ 7 .
 .Sh FILES
-.Bl -tag -width /var/log/wtmp.[0-6] -compact
-.It Pa /var/run/utmp
-.It Pa /var/log/wtmp
-.It Pa /var/log/wtmp.[0-6]
+.Bl -tag -width /var/log/utmpx -compact
+.It Pa /var/run/utmpx
 .El
 .Sh DIAGNOSTICS
 .Ex -std
@@ -141,7 +118,8 @@ as described in
 .Xr last 1 ,
 .Xr users 1 ,
 .Xr w 1 ,
-.Xr utmp 5
+.Xr compat 5 ,
+.Xr utmpx 5
 .Sh STANDARDS
 The
 .Nm
index b700264473e9aa4ef5685e1f073c590589a47d26..da46ad77d9e4349d83f99c873ed6fdd6356d1cec 100644 (file)
--- a/who/who.c
+++ b/who/who.c
@@ -46,17 +46,21 @@ __FBSDID("$FreeBSD: src/usr.bin/who/who.c,v 1.20 2003/10/26 05:05:48 peter Exp $
 #include <time.h>
 #include <timeconv.h>
 #include <unistd.h>
-#include <utmp.h>
 #include <utmpx.h>
 
+/* from utmp.h; used only for print formatting */
+#define        UT_NAMESIZE     8
+#define        UT_LINESIZE     8
+#define        UT_HOSTSIZE     16
+
 static void    heading(void);
-static void    process_utmp(FILE *);
-static void    process_wtmp(FILE *);
-static void    quick(FILE *);
-static void    row(struct utmp *);
+static void    process_utmp(void);
+static void    process_wtmp();
+static void    quick(void);
+static void    row(const struct utmpx *);
 static int     ttywidth(void);
 static void    usage(void);
-static void    whoami(FILE *);
+static void    whoami(void);
 
 static int     bflag;                  /* date & time of last reboot */
 static int     dflag;                  /* dead processes */
@@ -76,15 +80,11 @@ static int  uflag;                  /* Show idle time */
 #define COMPAT_MODE(a,b) (1)
 #endif /* __APPLE__ */
 static int     unix2003_std;
-static struct utmpx *utx_db = NULL;
 
 int
 main(int argc, char *argv[])
 {
        int ch;
-       const char *file;
-       FILE *fp;
-       FILE *wtmp_fp;
 
        setlocale(LC_TIME, "");
 
@@ -151,45 +151,33 @@ main(int argc, char *argv[])
        if (argc > 1)
                usage();
 
-       if (*argv != NULL)
-               file = *argv;
-       else
-               file = _PATH_UTMP;
-       if ((fp = fopen(file, "r")) == NULL)
-               err(1, "%s", file);
+       if (*argv != NULL) {
+               if (!utmpxname(*argv) || !wtmpxname(*argv))
+                   usage();
+       }
 
        if (qflag)
-               quick(fp);
+               quick();
        else {
                if (sflag)
                        Tflag = uflag = 0;
                if (Hflag)
                        heading();
                if (mflag)
-                       whoami(fp);
+                       whoami();
                else
-                       /* read and process utmp file for relevant options */
+                       /* read and process utmpx file for relevant options */
                        if( Tflag || uflag || !(bflag || dflag || lflag || pflag || rflag) )
-                               process_utmp(fp);
+                               process_utmp();
        }
 
-       fclose(fp);
-
        /* read and process wtmp file for relevant options */
        if (bflag || dflag || lflag || pflag || rflag ) {
 
-               /* Open the wtmp file */
-               if ((wtmp_fp = fopen(_PATH_WTMP, "r")) == NULL)
-                       err(1, "%s", _PATH_WTMP);
-               else {
-                       process_wtmp(wtmp_fp);
-                       fclose(wtmp_fp);
-               }
+               process_wtmp();
        }
 
-       if (utx_db) {
-               endutxent();    /* close db */
-       }
+       endutxent();
        exit(0);
 }
 
@@ -219,9 +207,9 @@ heading(void)
 }
 
 static void
-row(struct utmp *ut)
+row(const struct utmpx *ut)
 {
-       char buf[80], tty[sizeof(_PATH_DEV) + UT_LINESIZE];
+       char buf[80], tty[sizeof(_PATH_DEV) + _UTX_LINESIZE];
        struct stat sb;
        time_t idle, t;
        static int d_first = -1;
@@ -234,7 +222,7 @@ row(struct utmp *ut)
 
        if (Tflag || uflag) {
                snprintf(tty, sizeof(tty), "%s%.*s", _PATH_DEV,
-                       UT_LINESIZE, ut->ut_line);
+                       _UTX_LINESIZE, ut->ut_line);
                state = '?';
                idle = 0;
                if (stat(tty, &sb) == 0) {
@@ -244,34 +232,20 @@ row(struct utmp *ut)
                }
                if (unix2003_std && !Tflag) {
                        /* uflag without Tflag */
-                       struct utmpx * utx = NULL;
-                       if (!utx_db) {
-                               utx_db = getutxent(); /* just to open db */
-                       }
-                       if (utx_db) {
-                               struct utmpx this_line;
-                               setutxent();    /* reset db */
-                               memset(&this_line, 0, sizeof(this_line));
-/*
-                               strcpy(this_line.ut_user, ut->ut_name);
-*/
-                               strcpy(this_line.ut_line, ut->ut_line);
-                               utx = getutxline(&this_line);
-                       }
-                       if (utx) {
+                       if (ut->ut_pid) {
                                snprintf(login_pidstr,sizeof(login_pidstr),
-                                               "%8d",utx->ut_pid);
+                                               "%8d",ut->ut_pid);
                        } else {
                                strcpy(login_pidstr,"       ?");
                        }
                }
        }
 
-       printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, ut->ut_name);
+       printf("%-*.*s ", UT_NAMESIZE, _UTX_USERSIZE, ut->ut_user);
        if (Tflag)
                printf("%c ", state);
-       printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, ut->ut_line);
-       t = _time32_to_time(ut->ut_time);
+       printf("%-*.*s ", UT_LINESIZE, _UTX_LINESIZE, ut->ut_line);
+       t = _time32_to_time(ut->ut_tv.tv_sec);
        tm = localtime(&t);
        strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm);
        printf("%-*s ", 12, buf);
@@ -288,40 +262,50 @@ row(struct utmp *ut)
                }
        }
        if (*ut->ut_host != '\0')
-               printf("(%.*s)", UT_HOSTSIZE, ut->ut_host);
+               printf("(%.*s)", _UTX_HOSTSIZE, ut->ut_host);
        putchar('\n');
 
 }
 
 static void
-process_utmp(FILE *fp)
+process_utmp(void)
 {
-       struct utmp ut;
+       struct utmpx *ut;
 
-       while (fread(&ut, sizeof(ut), 1, fp) == 1)
-               if (*ut.ut_name != '\0') {
-                       row(&ut);
+       while ((ut = getutxent()) != NULL)
+               if (*ut->ut_user != '\0' && ut->ut_type == USER_PROCESS) {
+                       row(ut);
                }
 }
 
 /* For some options, process the wtmp file to generate output */
 static void
-process_wtmp(FILE *fp)
+process_wtmp(void)
 {
-       struct utmp ut;
-       struct utmp lboot_ut = { "", "", "", 0 };
+       struct utmpx *ut;
+       struct utmpx lboot_ut;
        int num = 0;    /* count of user entries */
 
-       while (fread(&ut, sizeof(ut), 1, fp) == 1)
-               if (*ut.ut_name != '\0') {
-                       if (bflag && (!strcmp(ut.ut_name, "reboot"))) {
-                               memcpy(&lboot_ut, &ut, sizeof(ut));
-                       }
-                       else
-                               num++;
-               };
+       setutxent_wtmp(0);      /* zero means reverse chronological */
+       lboot_ut.ut_type = 0;
+       while (!lboot_ut.ut_type && (ut = getutxent_wtmp()) != NULL) {
+               switch(ut->ut_type) {
+               case BOOT_TIME:
+                       lboot_ut = *ut;
+                       strcpy(lboot_ut.ut_user, "reboot");
+                       strcpy(lboot_ut.ut_line, "~");
+                       break;
+               case INIT_PROCESS:
+               case LOGIN_PROCESS:
+               case USER_PROCESS:
+               case DEAD_PROCESS:
+                       num++;
+                       break;
+               }
+       }
+       endutxent_wtmp();
 
-       if (bflag && (!strcmp(lboot_ut.ut_name, "reboot")))
+       if (bflag && lboot_ut.ut_type)
                row(&lboot_ut);
 
        /* run level of the init process is unknown in BSD system. If multi
@@ -332,17 +316,17 @@ process_wtmp(FILE *fp)
 }
 
 static void
-quick(FILE *fp)
+quick(void)
 {
-       struct utmp ut;
+       struct utmpx *ut;
        int col, ncols, num;
 
        ncols = ttywidth();
        col = num = 0;
-       while (fread(&ut, sizeof(ut), 1, fp) == 1) {
-               if (*ut.ut_name == '\0')
+       while ((ut = getutxent()) != NULL) {
+               if (*ut->ut_user == '\0' || ut->ut_type != USER_PROCESS)
                        continue;
-               printf("%-*.*s", UT_NAMESIZE, UT_NAMESIZE, ut.ut_name);
+               printf("%-*.*s", UT_NAMESIZE, _UTX_USERSIZE, ut->ut_user);
                if (++col < ncols / (UT_NAMESIZE + 1))
                        putchar(' ');
                else {
@@ -358,9 +342,10 @@ quick(FILE *fp)
 }
 
 static void
-whoami(FILE *fp)
+whoami(void)
 {
-       struct utmp ut;
+       struct utmpx ut;
+       struct utmpx *u;
        struct passwd *pwd;
        const char *name, *p, *tty;
 
@@ -369,23 +354,24 @@ whoami(FILE *fp)
        else if ((p = strrchr(tty, '/')) != NULL)
                tty = p + 1;
 
+       memset(&ut, 0, sizeof(ut));
+       strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
+       memcpy(ut.ut_id, tty + (strlen(tty) - sizeof(ut.ut_id)), sizeof(ut.ut_id));
+       ut.ut_type = USER_PROCESS;
        /* Search utmp for our tty, dump first matching record. */
-       while (fread(&ut, sizeof(ut), 1, fp) == 1)
-               if (*ut.ut_name != '\0' && strncmp(ut.ut_line, tty,
-                   UT_LINESIZE) == 0) {
-                       row(&ut);
-                       return;
-               }
+       u = getutxid(&ut);
+       if (u) {
+               row(u);
+               return;
+       }
 
-       /* Not found; fill the utmp structure with the information we have. */
-       memset(&ut, 0, sizeof(ut));
+       /* Not found; fill the utmpx structure with the information we have. */
        if ((pwd = getpwuid(getuid())) != NULL)
                name = pwd->pw_name;
        else
                name = "?";
-       strncpy(ut.ut_name, name, UT_NAMESIZE);
-       strncpy(ut.ut_line, tty, UT_LINESIZE);
-       ut.ut_time = _time_to_time32(time(NULL));
+       strncpy(ut.ut_user, name, _UTX_USERSIZE);
+       ut.ut_tv.tv_sec = _time_to_time32(time(NULL));
        row(&ut);
 }
 
index 174730e220c4cabd44e6fe14f38658f4c7474a89..62f9db71e58843f732153fc9cb351629c3a171c6 100644 (file)
@@ -18,6 +18,7 @@ CFILES = xargs.c strnsubst.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble xargs.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index ed4337b0c722d8ce9c8bd7c1ba2848d59610b23b..3f05b3dcc2d172772650814ab952dfab55d29716 100644 (file)
@@ -1,5 +1,3 @@
-/*     $NetBSD: pathnames.h,v 1.4 1995/11/15 16:11:17 thorpej Exp $    */
-
 /*-
  * Copyright (c) 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
index fa8d93375bc19c856eef63b8bfc5277392eae9c5..4b3f9b64d74ebe947d5c5fa395a999cf35286a71 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/usr.bin/xargs/strnsubst.c,v 1.6 2002/06/22 12:58:42 jmallett Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/xargs/strnsubst.c,v 1.7 2004/10/18 15:40:47 cperciva Exp $");
 
 #include <err.h>
 #include <stdlib.h>
@@ -44,8 +44,7 @@ strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
                replstr = "";
 
        if (match == NULL || replstr == NULL || maxsize == strlen(s1)) {
-               strncpy(s2, s1, maxsize);
-               s2[maxsize - 1] = '\0';
+               strlcpy(s2, s1, maxsize);
                goto done;
        }
 
@@ -53,10 +52,9 @@ strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
                this = strstr(s1, match);
                if (this == NULL)
                        break;
-               if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) +
-                   (strlen(replstr) - 1)) > maxsize && *replstr != '\0') {
-                       strncat(s2, s1, maxsize);
-                       s2[maxsize - 1] = '\0';
+               if ((strlen(s2) + strlen(s1) + strlen(replstr) -
+                   strlen(match) + 1) > maxsize) {
+                       strlcat(s2, s1, maxsize);
                        goto done;
                }
                strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1);
index 9db9a3f2f381fc29aaf35d4173693a012fe94404..f8a8592e8adbbe77539d20ef0645bcccd7e7e0a8 100644 (file)
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)xargs.1     8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/xargs/xargs.1,v 1.23 2002/06/22 12:47:56 jmallett Exp $
+.\" $FreeBSD: src/usr.bin/xargs/xargs.1,v 1.34 2005/05/21 09:55:09 ru Exp $
 .\" $xMach: xargs.1,v 1.2 2002/02/23 05:23:37 tim Exp $
 .\"
-.Dd May 7, 2001
+.Dd August 2, 2004
 .Dt XARGS 1
 .Os
 .Sh NAME
@@ -45,7 +45,7 @@
 .Nd "construct argument list(s) and execute utility"
 .Sh SYNOPSIS
 .Nm
-.Op Fl 0pt
+.Op Fl 0opt
 .Op Fl E Ar eofstr
 .Oo
 .Fl I Ar replstr
 .Fl n Ar number
 .Op Fl x
 .Oc
+.Op Fl P Ar maxprocs
 .Op Fl s Ar size
 .Op Ar utility Op Ar argument ...
 .Sh DESCRIPTION
 The
 .Nm
-utility reads space, tab, newline and end-of-file delimited arguments
-from the standard input and executes the specified
+utility reads space, tab, newline and end-of-file delimited strings
+from the standard input and executes
 .Ar utility
-with them as
+with the strings as
 arguments.
 .Pp
-The utility and any arguments specified on the command line are given
-to the
+Any arguments specified on the command line are given to
 .Ar utility
 upon each invocation, followed by some number of the arguments read
-from standard input.
-The
-.Ar utility
+from the standard input of
+.Nm .
+The utility
 is repeatedly executed until standard input is exhausted.
 .Pp
 Spaces, tabs and newlines may be embedded in arguments using single
@@ -105,7 +105,7 @@ as a logical EOF marker.
 .It Fl I Ar replstr
 Execute
 .Ar utility
-for each input line, replacing one or more occurences of
+for each input line, replacing one or more occurrences of
 .Ar replstr
 in up to
 .Ar replacements
@@ -136,7 +136,7 @@ If this option is specified,
 will use the data read from standard input to replace the first occurrence of
 .Ar replstr
 instead of appending that data after all other arguments.
-This option will not effect how many arguments will be read from input
+This option will not affect how many arguments will be read from input
 .Pq Fl n ,
 or the size of the command(s)
 .Nm
@@ -167,15 +167,22 @@ Call
 .Ar utility
 for every
 .Ar number
-lines read.
+non-empty lines read.
+A line ending with a space continues to the next non-empty line.
 If EOF is reached and fewer lines have been read than
 .Ar number
 then
 .Ar utility
 will be called with the available lines.
+The
+.Fl L
+and
+.Fl n
+options are mutually-exclusive; the last one given will be used.
 .It Fl n Ar number
 Set the maximum number of arguments taken from standard input for each
-invocation of the utility.
+invocation of
+.Ar utility .
 An invocation of
 .Ar utility
 will use less than
@@ -191,6 +198,19 @@ arguments remaining for the last invocation of
 The current default value for
 .Ar number
 is 5000.
+.It Fl o
+Reopen stdin as
+.Pa /dev/tty
+in the child process before executing the command.
+This is useful if you want
+.Nm
+to run an interactive application.
+.It Fl P Ar maxprocs
+Parallel mode: run at most
+.Ar maxprocs
+invocations of
+.Ar utility
+at once.
 .It Fl p
 Echo each command to be executed and ask the user whether it should be
 executed.
@@ -204,6 +224,9 @@ No commands are executed if the process is not attached to a terminal.
 Specify the maximum number of arguments that
 .Fl I
 will do replacement in.
+If
+.Ar replacements
+is negative, the number of arguments in which to replace is unbounded.
 .It Fl s Ar size
 Set the maximum number of bytes for the command line length provided to
 .Ar utility .
@@ -229,9 +252,9 @@ to terminate immediately if a command line containing
 arguments will not fit in the specified (or default) command line length.
 .El
 .Pp
-If no
+If
 .Ar utility
-is specified,
+is omitted,
 .Xr echo 1
 is used.
 .Pp
@@ -244,9 +267,23 @@ The
 utility exits immediately (without processing any further input) if a
 command line cannot be assembled,
 .Ar utility
-cannot be invoked, an invocation of the utility is terminated by a signal
-or an invocation of the utility exits with a value of 255.
-.Sh DIAGNOSTICS
+cannot be invoked, an invocation of
+.Ar utility
+is terminated by a signal,
+or an invocation of
+.Ar utility
+exits with a value of 255.
+.Sh LEGACY DESCRIPTION
+In legacy mode, the
+.Fl L
+option treats all newlines as end-of-line, regardless of whether
+the line is empty or ends with a space.
+In addition, the
+.Fl L
+and
+.Fl n
+options are not mutually-exclusive.
+.Sh EXIT STATUS
 The
 .Nm
 utility exits with a value of 0 if no error occurs.
@@ -265,7 +302,8 @@ exits with a value of 1.
 .Sh SEE ALSO
 .Xr echo 1 ,
 .Xr find 1 ,
-.Xr execvp 3
+.Xr execvp 3 ,
+.Xr compat 5
 .Sh STANDARDS
 The
 .Nm
@@ -273,7 +311,7 @@ utility is expected to be
 .St -p1003.2
 compliant.
 The
-.Fl J
+.Fl J , o , P
 and
 .Fl R
 options are non-standard
@@ -291,3 +329,12 @@ size of the environment is increased, it risks
 .Xr execvp 3
 failing with
 .Er E2BIG .
+.Pp
+The
+.Nm
+utility does not take multibyte characters into account when performing
+string comparisons for the
+.Fl I
+and
+.Fl J
+options, which may lead to incorrect results in some locales.
index a54326152b2965bcc5a8c21efbbd377aa09497bb..8f71d99a1c84633b59e69f2e3476b43a3bf6769a 100644 (file)
  * $xMach: xargs.c,v 1.6 2002/02/23 05:27:47 tim Exp $
  */
 
+#if 0
 #ifndef lint
 static const char copyright[] =
 "@(#) Copyright (c) 1990, 1993\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
-#if 0
 #ifndef lint
 static char sccsid[] = "@(#)xargs.c    8.1 (Berkeley) 6/6/93";
 #endif /* not lint */
 #endif
-
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/usr.bin/xargs/xargs.c,v 1.41 2002/07/01 03:21:05 tjr Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/xargs/xargs.c,v 1.57 2005/02/27 02:01:31 gad Exp $");
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/wait.h>
 
 #include <err.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <langinfo.h>
 #include <locale.h>
 #include <paths.h>
 #include <regex.h>
@@ -78,15 +79,20 @@ static int  prompt(void);
 static void    run(char **);
 static void    usage(void);
 void           strnsubst(char **, const char *, const char *, size_t);
+static void    waitchildren(const char *, int);
+
+static int last_was_newline = 1;
+static int last_was_blank = 0;
 
 static char echo[] = _PATH_ECHO;
-static char **av, **bxp, **ep, **exp, **xp;
+static char **av, **bxp, **ep, **endxp, **xp;
 static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
 static const char *eofstr;
-static int count, insingle, indouble, pflag, tflag, Rflag, rval, zflag;
+static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag;
 static int cnt, Iflag, jfound, Lflag, wasquoted, xflag;
-static int last_was_newline = 1;
-static int last_was_blank = 0;
+static int curprocs, maxprocs;
+
+static volatile int childerr;
 
 extern char **environ;
 
@@ -96,12 +102,15 @@ main(int argc, char *argv[])
        long arg_max;
        int ch, Jflag, nargs, nflag, nline;
        size_t linelen;
+       char *endptr;
 
        inpline = replstr = NULL;
        ep = environ;
        eofstr = "";
        Jflag = nflag = 0;
 
+       (void)setlocale(LC_ALL, "");
+
        /*
         * POSIX.2 limits the exec line length to ARG_MAX - 2K.  Running that
         * caused some E2BIG errors, so it was changed to ARG_MAX - 4K.  Given
@@ -123,7 +132,8 @@ main(int argc, char *argv[])
                /* 1 byte for each '\0' */
                nline -= strlen(*ep++) + 1 + sizeof(*ep);
        }
-       while ((ch = getopt(argc, argv, "0E:I:J:L:n:pR:s:tx")) != -1)
+       maxprocs = 1;
+       while ((ch = getopt(argc, argv, "0E:I:J:L:n:oP:pR:s:tx")) != -1)
                switch(ch) {
                case 'E':
                        eofstr = optarg;
@@ -148,18 +158,26 @@ main(int argc, char *argv[])
                        break;
                case 'n':
                        nflag = 1;
+                       if ((nargs = atoi(optarg)) <= 0)
+                               errx(1, "illegal argument count");
                        if (COMPAT_MODE("bin/xargs", "Unix2003")) {
                                Lflag = 0; /* Override */
                        }
-                       if ((nargs = atoi(optarg)) <= 0)
-                               errx(1, "illegal argument count");
+                       break;
+               case 'o':
+                       oflag = 1;
+                       break;
+               case 'P':
+                       if ((maxprocs = atoi(optarg)) <= 0)
+                               errx(1, "max. processes must be >0");
                        break;
                case 'p':
                        pflag = 1;
                        break;
                case 'R':
-                       if ((Rflag = atoi(optarg)) <= 0)
-                               errx(1, "illegal number of replacements");
+                       Rflag = strtol(optarg, &endptr, 10);
+                       if (*endptr != '\0')
+                               errx(1, "replacements must be a number");
                        break;
                case 's':
                        nline = atoi(optarg);
@@ -226,7 +244,7 @@ main(int argc, char *argv[])
         * count doesn't include the trailing NULL pointer, so the malloc
         * added in an extra slot.
         */
-       exp = (xp = bxp) + nargs;
+       endxp = (xp = bxp) + nargs;
 
        /*
         * Allocate buffer space for the arguments read from stdin and the
@@ -259,8 +277,10 @@ parse_input(int argc, char *argv[])
        switch(ch = getchar()) {
        case EOF:
                /* No arguments since last exec. */
-               if (p == bbp)
+               if (p == bbp) {
+                       waitchildren(*argv, 1);
                        exit(rval);
+               }
                goto arg1;
        case ' ':
                last_was_blank = 1;
@@ -270,10 +290,19 @@ parse_input(int argc, char *argv[])
                        goto addch;
                goto arg2;
        case '\0':
-               if (zflag)
+               if (zflag) {
+                       /*
+                        * Increment 'count', so that nulls will be treated
+                        * as end-of-line, as well as end-of-argument.  This
+                        * is needed so -0 works properly with -I and -L.
+                        */
+                       count++;
                        goto arg2;
+               }
                goto addch;
        case '\n':
+               if (zflag)
+                       goto addch;
                if (COMPAT_MODE("bin/xargs", "Unix2003")) {
                        if (last_was_newline) {
                                /* don't count empty line */
@@ -287,8 +316,6 @@ parse_input(int argc, char *argv[])
                        count++;
                }
                last_was_newline = 1;
-               if (zflag)
-                       goto addch;
 
                /* Quotes do not escape newlines. */
 arg1:          if (insingle || indouble)
@@ -310,7 +337,7 @@ arg2:
                                        /*
                                         * If this string is not zero
                                         * length, append a space for
-                                        * seperation before the next
+                                        * separation before the next
                                         * argument.
                                         */
                                        if ((curlen = strlen(inpline)))
@@ -341,17 +368,19 @@ arg2:
                 * of input lines, as specified by -L is the same as
                 * maxing out on arguments.
                 */
-               if (xp == exp || p > ebp || ch == EOF ||
+               if (xp == endxp || p > ebp || ch == EOF ||
                    (Lflag <= count && xflag) || foundeof) {
-                       if (xflag && xp != exp && p > ebp)
+                       if (xflag && xp != endxp && p > ebp)
                                errx(1, "insufficient space for arguments");
                        if (jfound) {
                                for (avj = argv; *avj; avj++)
                                        *xp++ = *avj;
                        }
                        prerun(argc, av);
-                       if (ch == EOF || foundeof)
+                       if (ch == EOF || foundeof) {
+                               waitchildren(*argv, 1);
                                exit(rval);
+                       }
                        p = bbp;
                        xp = bxp;
                        count = 0;
@@ -408,7 +437,6 @@ addch:              if (p < ebp) {
                last_was_blank = 0;
        if (ch != '\n' || last_was_backslashed)
                last_was_newline = 0;
-       return;
 }
 
 /*
@@ -450,7 +478,7 @@ prerun(int argc, char *argv[])
        /*
         * For each argument to utility, if we have not used up
         * the number of replacements we are allowed to do, and
-        * if the argument contains at least one occurance of
+        * if the argument contains at least one occurrence of
         * replstr, call strnsubst(), else just save the string.
         * Iterations over elements of avj and tmp are done
         * where appropriate.
@@ -459,7 +487,8 @@ prerun(int argc, char *argv[])
                *tmp = *avj++;
                if (repls && strstr(*tmp, replstr) != NULL) {
                        strnsubst(tmp++, replstr, inpline, (size_t)255);
-                       repls--;
+                       if (repls > 0)
+                               repls--;
                } else {
                        if ((*tmp = strdup(*tmp)) == NULL)
                                errx(1, "strdup failed");
@@ -495,10 +524,9 @@ prerun(int argc, char *argv[])
 static void
 run(char **argv)
 {
-       volatile int childerr;
-       char **avec;
        pid_t pid;
-       int status;
+       int fd;
+       char **avec;
 
        /*
         * If the user wants to be notified of each command before it is
@@ -536,21 +564,50 @@ exec:
        case -1:
                err(1, "vfork");
        case 0:
+               if (oflag) {
+                       if ((fd = open(_PATH_TTY, O_RDONLY)) == -1)
+                               err(1, "can't open /dev/tty");
+               } else {
+                       fd = open(_PATH_DEVNULL, O_RDONLY);
+               }
+               if (fd > STDIN_FILENO) {
+                       if (dup2(fd, STDIN_FILENO) != 0)
+                               err(1, "can't dup2 to stdin");
+                       close(fd);
+               }
                execvp(argv[0], argv);
                childerr = errno;
                _exit(1);
        }
-       pid = waitpid(pid, &status, 0);
-       if (pid == -1)
-               err(1, "waitpid");
-       /* If we couldn't invoke the utility, exit. */
-       if (childerr != 0)
-               err(childerr == ENOENT ? 127 : 126, "%s", *argv);
-       /* If utility signaled or exited with a value of 255, exit 1-125. */
-       if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
-               exit(1);
-       if (WEXITSTATUS(status))
-               rval = 1;
+       curprocs++;
+       waitchildren(*argv, 0);
+}
+
+static void
+waitchildren(const char *name, int waitall)
+{
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, !waitall && curprocs < maxprocs ?
+           WNOHANG : 0)) > 0) {
+               curprocs--;
+               /* If we couldn't invoke the utility, exit. */
+               if (childerr != 0) {
+                       errno = childerr;
+                       err(errno == ENOENT ? 127 : 126, "%s", name);
+               }
+               /*
+                * If utility signaled or exited with a value of 255,
+                * exit 1-125.
+                */
+               if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
+                       exit(1);
+               if (WEXITSTATUS(status))
+                       rval = 1;
+       }
+       if (pid == -1 && errno != ECHILD)
+               err(1, "wait3");
 }
 
 /*
@@ -570,9 +627,7 @@ prompt(void)
        (void)fprintf(stderr, "?...");
        (void)fflush(stderr);
        if ((response = fgetln(ttyfp, &rsize)) == NULL ||
-           regcomp(&cre,
-               "^[yY]",
-               REG_BASIC) != 0) {
+           regcomp(&cre, nl_langinfo(YESEXPR), REG_BASIC) != 0) {
                (void)fclose(ttyfp);
                return (0);
        }
@@ -586,7 +641,8 @@ static void
 usage(void)
 {
        fprintf(stderr,
-"usage: xargs [-0pt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]\n"
-"             [-L number] [-n number [-x] [-s size] [utility [argument ...]]\n");
+"usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]\n"
+"             [-L number] [-n number [-x]] [-P maxprocs] [-s size]\n"
+"             [utility [argument ...]]\n");
        exit(1);
 }