From e1a085bab7df5bb0af9b495e350271357a7cd388 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 17 Sep 2007 22:07:53 +0000 Subject: [PATCH] shell_cmds-116.tar.gz --- Makefile | 4 +- Makefile.postamble | 92 ++- Manpages/alloc.1 | 1 - Manpages/bindkey.1 | 1 - Manpages/break.1 | 1 - Manpages/breaksw.1 | 1 - Manpages/builtin.1 | 83 +- Manpages/builtins.1 | 1 - Manpages/case.1 | 1 - Manpages/chdir.1 | 1 - Manpages/complete.1 | 1 - Manpages/continue.1 | 1 - Manpages/default.1 | 1 - Manpages/dirs.1 | 1 - Manpages/do.1 | 1 - Manpages/done.1 | 1 - Manpages/echotc.1 | 1 - Manpages/elif.1 | 1 - Manpages/else.1 | 1 - Manpages/end.1 | 1 - Manpages/endif.1 | 1 - Manpages/endsw.1 | 1 - Manpages/esac.1 | 1 - Manpages/eval.1 | 1 - Manpages/exec.1 | 1 - Manpages/exit.1 | 1 - Manpages/export.1 | 1 - Manpages/fi.1 | 1 - Manpages/filetest.1 | 1 - Manpages/foreach.1 | 1 - Manpages/glob.1 | 1 - Manpages/goto.1 | 1 - Manpages/hashstat.1 | 1 - Manpages/history.1 | 1 - Manpages/hup.1 | 1 - Manpages/if.1 | 1 - Manpages/jobid.1 | 1 - Manpages/limit.1 | 1 - Manpages/log.1 | 1 - Manpages/logout.1 | 1 - Manpages/ls-F.1 | 1 - Manpages/notify.1 | 1 - Manpages/onintr.1 | 1 - Manpages/popd.1 | 1 - Manpages/pushd.1 | 1 - Manpages/readonly.1 | 1 - Manpages/rehash.1 | 1 - Manpages/repeat.1 | 1 - Manpages/sched.1 | 1 - Manpages/set.1 | 1 - Manpages/setenv.1 | 1 - Manpages/settc.1 | 1 - Manpages/setty.1 | 1 - Manpages/setvar.1 | 1 - Manpages/shift.1 | 1 - Manpages/source.1 | 1 - Manpages/stop.1 | 1 - Manpages/suspend.1 | 1 - Manpages/switch.1 | 1 - Manpages/telltc.1 | 1 - Manpages/then.1 | 1 - Manpages/trap.1 | 1 - Manpages/uncomplete.1 | 1 - Manpages/unhash.1 | 1 - Manpages/unlimit.1 | 1 - Manpages/unset.1 | 1 - Manpages/unsetenv.1 | 1 - Manpages/until.1 | 1 - Manpages/where.1 | 1 - Manpages/while.1 | 1 - alias/Makefile.postamble | 2 +- alias/generic.sh | 4 +- date/Makefile | 5 +- date/date.1 | 410 +++++++--- date/date.c | 396 +++++----- date/extern.h | 9 +- date/netdate.c | 78 +- date/vary.c | 506 ++++++++++++ date/vary.h | 36 + echo/Makefile | 1 + echo/echo.1 | 39 +- echo/echo.c | 86 ++- expr/expr.c | 70 +- find/Makefile | 6 +- find/extern.h | 34 +- find/find.1 | 381 ++++++--- find/find.c | 69 +- find/find.h | 29 +- find/function.c | 816 +++++++++++--------- find/getdate.y | 970 +++++++++++++++++++++++ find/ls.c | 71 +- find/main.c | 16 +- find/misc.c | 59 +- find/operator.c | 47 +- find/option.c | 47 +- find/y.tab.c | 1542 ------------------------------------- id/Makefile | 1 + id/groups.1 | 7 +- id/id.1 | 19 +- id/id.c | 250 ++++-- id/whoami.1 | 4 +- killall/Makefile | 1 + killall/killall.1 | 49 +- killall/killall.c | 160 +++- locate/locate/updatedb.sh | 2 +- nohup/nohup.c | 153 ++-- printf/printf.1 | 3 +- pwd/Makefile | 1 + pwd/pwd.1 | 70 +- pwd/pwd.c | 131 ++-- renice/renice.8 | 5 +- script/Makefile | 1 + script/script.1 | 77 +- script/script.c | 285 ++++--- su/su.1 | 6 +- su/su.c | 65 +- test/test.1 | 23 +- test/test.c | 2 +- uname/uname.1 | 29 +- uname/uname.c | 77 +- users/users.1 | 6 +- users/users.c | 28 +- w/Makefile | 2 +- w/extern.h | 17 +- w/fmt.c | 6 +- w/pr_time.c | 16 +- w/proc_compare.c | 70 +- w/uptime.1 | 13 +- w/w.1 | 60 +- w/w.c | 232 ++++-- which/Makefile | 4 +- which/Makefile.preamble | 2 - which/which.1 | 100 +-- which/which.c | 146 ++++ which/which.csh | 75 -- who/who.1 | 46 +- who/who.c | 166 ++-- xargs/Makefile | 1 + xargs/pathnames.h | 2 - xargs/strnsubst.c | 12 +- xargs/xargs.1 | 91 ++- xargs/xargs.c | 144 ++-- 142 files changed, 4983 insertions(+), 3652 deletions(-) delete mode 100644 Manpages/alloc.1 delete mode 100644 Manpages/bindkey.1 delete mode 100644 Manpages/break.1 delete mode 100644 Manpages/breaksw.1 delete mode 100644 Manpages/builtins.1 delete mode 100644 Manpages/case.1 delete mode 100644 Manpages/chdir.1 delete mode 100644 Manpages/complete.1 delete mode 100644 Manpages/continue.1 delete mode 100644 Manpages/default.1 delete mode 100644 Manpages/dirs.1 delete mode 100644 Manpages/do.1 delete mode 100644 Manpages/done.1 delete mode 100644 Manpages/echotc.1 delete mode 100644 Manpages/elif.1 delete mode 100644 Manpages/else.1 delete mode 100644 Manpages/end.1 delete mode 100644 Manpages/endif.1 delete mode 100644 Manpages/endsw.1 delete mode 100644 Manpages/esac.1 delete mode 100644 Manpages/eval.1 delete mode 100644 Manpages/exec.1 delete mode 100644 Manpages/exit.1 delete mode 100644 Manpages/export.1 delete mode 100644 Manpages/fi.1 delete mode 100644 Manpages/filetest.1 delete mode 100644 Manpages/foreach.1 delete mode 100644 Manpages/glob.1 delete mode 100644 Manpages/goto.1 delete mode 100644 Manpages/hashstat.1 delete mode 100644 Manpages/history.1 delete mode 100644 Manpages/hup.1 delete mode 100644 Manpages/if.1 delete mode 100644 Manpages/jobid.1 delete mode 100644 Manpages/limit.1 delete mode 100644 Manpages/log.1 delete mode 100644 Manpages/logout.1 delete mode 100644 Manpages/ls-F.1 delete mode 100644 Manpages/notify.1 delete mode 100644 Manpages/onintr.1 delete mode 100644 Manpages/popd.1 delete mode 100644 Manpages/pushd.1 delete mode 100644 Manpages/readonly.1 delete mode 100644 Manpages/rehash.1 delete mode 100644 Manpages/repeat.1 delete mode 100644 Manpages/sched.1 delete mode 100644 Manpages/set.1 delete mode 100644 Manpages/setenv.1 delete mode 100644 Manpages/settc.1 delete mode 100644 Manpages/setty.1 delete mode 100644 Manpages/setvar.1 delete mode 100644 Manpages/shift.1 delete mode 100644 Manpages/source.1 delete mode 100644 Manpages/stop.1 delete mode 100644 Manpages/suspend.1 delete mode 100644 Manpages/switch.1 delete mode 100644 Manpages/telltc.1 delete mode 100644 Manpages/then.1 delete mode 100644 Manpages/trap.1 delete mode 100644 Manpages/uncomplete.1 delete mode 100644 Manpages/unhash.1 delete mode 100644 Manpages/unlimit.1 delete mode 100644 Manpages/unset.1 delete mode 100644 Manpages/unsetenv.1 delete mode 100644 Manpages/until.1 delete mode 100644 Manpages/where.1 delete mode 100644 Manpages/while.1 create mode 100644 date/vary.c create mode 100644 date/vary.h create mode 100644 find/getdate.y delete mode 100644 find/y.tab.c create mode 100644 which/which.c delete mode 100644 which/which.csh diff --git a/Makefile b/Makefile index e9fc42f..936206b 100644 --- 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 diff --git a/Makefile.postamble b/Makefile.postamble index f2fd4e9..b60b7ed 100644 --- a/Makefile.postamble +++ b/Makefile.postamble @@ -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 index 5a811f4..0000000 --- a/Manpages/alloc.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/bindkey.1 b/Manpages/bindkey.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/bindkey.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/break.1 b/Manpages/break.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/break.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/breaksw.1 b/Manpages/breaksw.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/breaksw.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/builtin.1 b/Manpages/builtin.1 index bc53b39..f452c91 100644 --- a/Manpages/builtin.1 +++ b/Manpages/builtin.1 @@ -24,13 +24,20 @@ .\" 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 , @@ -96,6 +104,7 @@ .Nm readonly , .Nm rehash , .Nm repeat , +.Nm return , .Nm sched , .Nm set , .Nm setenv , @@ -111,6 +120,7 @@ .Nm test , .Nm then , .Nm time , +.Nm times , .Nm trap , .Nm true , .Nm type , @@ -127,7 +137,7 @@ .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 index 5a811f4..0000000 --- a/Manpages/builtins.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/case.1 b/Manpages/case.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/case.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/chdir.1 b/Manpages/chdir.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/chdir.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/complete.1 b/Manpages/complete.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/complete.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/continue.1 b/Manpages/continue.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/continue.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/default.1 b/Manpages/default.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/default.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/dirs.1 b/Manpages/dirs.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/dirs.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/do.1 b/Manpages/do.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/do.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/done.1 b/Manpages/done.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/done.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/echotc.1 b/Manpages/echotc.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/echotc.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/elif.1 b/Manpages/elif.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/elif.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/else.1 b/Manpages/else.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/else.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/end.1 b/Manpages/end.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/end.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/endif.1 b/Manpages/endif.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/endif.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/endsw.1 b/Manpages/endsw.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/endsw.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/esac.1 b/Manpages/esac.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/esac.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/eval.1 b/Manpages/eval.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/eval.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/exec.1 b/Manpages/exec.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/exec.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/exit.1 b/Manpages/exit.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/exit.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/export.1 b/Manpages/export.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/export.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/fi.1 b/Manpages/fi.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/fi.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/filetest.1 b/Manpages/filetest.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/filetest.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/foreach.1 b/Manpages/foreach.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/foreach.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/glob.1 b/Manpages/glob.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/glob.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/goto.1 b/Manpages/goto.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/goto.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/hashstat.1 b/Manpages/hashstat.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/hashstat.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/history.1 b/Manpages/history.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/history.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/hup.1 b/Manpages/hup.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/hup.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/if.1 b/Manpages/if.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/if.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/jobid.1 b/Manpages/jobid.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/jobid.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/limit.1 b/Manpages/limit.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/limit.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/log.1 b/Manpages/log.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/log.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/logout.1 b/Manpages/logout.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/logout.1 +++ /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 index 5a811f4..0000000 --- a/Manpages/ls-F.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/notify.1 b/Manpages/notify.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/notify.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/onintr.1 b/Manpages/onintr.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/onintr.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/popd.1 b/Manpages/popd.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/popd.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/pushd.1 b/Manpages/pushd.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/pushd.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/readonly.1 b/Manpages/readonly.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/readonly.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/rehash.1 b/Manpages/rehash.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/rehash.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/repeat.1 b/Manpages/repeat.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/repeat.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/sched.1 b/Manpages/sched.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/sched.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/set.1 b/Manpages/set.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/set.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/setenv.1 b/Manpages/setenv.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/setenv.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/settc.1 b/Manpages/settc.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/settc.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/setty.1 b/Manpages/setty.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/setty.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/setvar.1 b/Manpages/setvar.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/setvar.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/shift.1 b/Manpages/shift.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/shift.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/source.1 b/Manpages/source.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/source.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/stop.1 b/Manpages/stop.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/stop.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/suspend.1 b/Manpages/suspend.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/suspend.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/switch.1 b/Manpages/switch.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/switch.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/telltc.1 b/Manpages/telltc.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/telltc.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/then.1 b/Manpages/then.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/then.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/trap.1 b/Manpages/trap.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/trap.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/uncomplete.1 b/Manpages/uncomplete.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/uncomplete.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/unhash.1 b/Manpages/unhash.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/unhash.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/unlimit.1 b/Manpages/unlimit.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/unlimit.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/unset.1 b/Manpages/unset.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/unset.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/unsetenv.1 b/Manpages/unsetenv.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/unsetenv.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/until.1 b/Manpages/until.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/until.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/where.1 b/Manpages/where.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/where.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/Manpages/while.1 b/Manpages/while.1 deleted file mode 100644 index 5a811f4..0000000 --- a/Manpages/while.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/builtin.1 diff --git a/alias/Makefile.postamble b/alias/Makefile.postamble index 25b1a3a..0e72ad2 100644 --- a/alias/Makefile.postamble +++ b/alias/Makefile.postamble @@ -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 diff --git a/alias/generic.sh b/alias/generic.sh index ebc2b85..b47956d 100644 --- a/alias/generic.sh +++ b/alias/generic.sh @@ -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+"$@"} diff --git a/date/Makefile b/date/Makefile index a7632ac..5fb3ba6 100644 --- a/date/Makefile +++ b/date/Makefile @@ -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 diff --git a/date/date.1 b/date/date.1 index e5962fe..e176c35 100644 --- a/date/date.1 +++ b/date/date.1 @@ -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. .\" @@ -14,10 +13,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. @@ -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 @@ -44,56 +40,220 @@ .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 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 . diff --git a/date/date.c b/date/date.c index fc456f8..64b4496 100644 --- a/date/date.c +++ b/date/date.c @@ -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. * @@ -12,10 +10,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. @@ -33,81 +27,118 @@ * SUCH DAMAGE. */ -#include #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 +__FBSDID("$FreeBSD: src/bin/date/date.c,v 1.47 2005/01/10 08:39:21 imp Exp $"); #include #include #include #include -#include +#include +#ifndef __APPLE__ +#include +#endif /* !__APPLE__ */ #include #include #include -#include #include -#include -#include #include -#include +#include -#include "get_compat.h" +#ifdef __APPLE__ +#include +#include +#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, <); + 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, <); (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 */ } diff --git a/date/extern.h b/date/extern.h index c0d7fbe..fe2baee 100644 --- a/date/extern.h +++ b/date/extern.h @@ -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. @@ -12,10 +10,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. @@ -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); diff --git a/date/netdate.c b/date/netdate.c index ee7b8ff..4f7852a 100644 --- a/date/netdate.c +++ b/date/netdate.c @@ -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. @@ -12,10 +10,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. @@ -33,14 +27,14 @@ * SUCH DAMAGE. */ -#include -#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 +__FBSDID("$FreeBSD: src/bin/date/netdate.c,v 1.18 2004/04/06 20:06:45 markm Exp $"); #include #include @@ -53,7 +47,6 @@ __RCSID("$NetBSD: netdate.c,v 1.16 1998/07/28 03:47:15 mycroft Exp $"); #include #include -#include #include #include @@ -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 index 0000000..82a6cea --- /dev/null +++ b/date/vary.c @@ -0,0 +1,506 @@ +/*- + * Copyright (c) 1997 Brian Somers + * 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 +__FBSDID("$FreeBSD: src/bin/date/vary.c,v 1.16 2004/08/09 13:43:39 yar Exp $"); + +#include +#include +#include +#include +#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 index 0000000..27eddf7 --- /dev/null +++ b/date/vary.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1997 Brian Somers + * 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); diff --git a/echo/Makefile b/echo/Makefile index f2346d3..bd0e437 100644 --- a/echo/Makefile +++ b/echo/Makefile @@ -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 diff --git a/echo/echo.1 b/echo/echo.1 index 9e08e23..87bcc34 100644 --- a/echo/echo.1 +++ b/echo/echo.1 @@ -1,3 +1,4 @@ +.\"- .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -12,10 +13,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. @@ -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. diff --git a/echo/echo.c b/echo/echo.c index bbb0539..629e22f 100644 --- a/echo/echo.c +++ b/echo/echo.c @@ -1,4 +1,4 @@ -/* +/*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -10,10 +10,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. @@ -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 -__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 +#include +#include + +#include +#include +#include #include #include +#include -/* 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; } diff --git a/expr/expr.c b/expr/expr.c index 36b998f..590608c 100644 --- a/expr/expr.c +++ b/expr/expr.c @@ -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(); diff --git a/find/Makefile b/find/Makefile index c0cb276..4e13a44 100644 --- a/find/Makefile +++ b/find/Makefile @@ -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 diff --git a/find/extern.h b/find/extern.h index d909f1e..945b557 100644 --- a/find/extern.h +++ b/find/extern.h @@ -31,26 +31,29 @@ * 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 -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; diff --git a/find/find.1 b/find/find.1 index 5a3ad96..a20f450 100644 --- a/find/find.1 +++ b/find/find.1 @@ -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 @@ -45,11 +46,18 @@ .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. diff --git a/find/find.c b/find/find.c index 9f5db7d..35f8006 100644 --- a/find/find.c +++ b/find/find.c @@ -38,11 +38,12 @@ #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 +__FBSDID("$FreeBSD: src/usr.bin/find/find.c,v 1.18 2006/05/14 20:23:00 krion Exp $"); + #include #include @@ -51,19 +52,19 @@ static const char rcsid[] = #include #include #include -#include #include -#include +#include #ifdef __APPLE__ -#include "get_compat.h" +#include +#include #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); } diff --git a/find/find.h b/find/find.h index 24eaa55..6a8bc43 100644 --- a/find/find.h +++ b/find/find.h @@ -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 @@ -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; diff --git a/find/function.c b/find/function.c index eb2c65a..0e6028e 100644 --- a/find/function.c +++ b/find/function.c @@ -36,21 +36,21 @@ #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 +__FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.58 2006/05/27 18:27:41 krion Exp $"); + #include #include #include +#include +#include #include #include #include -#include -#include #include #include @@ -58,24 +58,34 @@ static const char rcsid[] = #include #include #include +#include #include #include #include #include #include #include +#include #include "find.h" #ifdef __APPLE__ -#include "get_compat.h" +#include +#include #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 index 0000000..c68de33 --- /dev/null +++ b/find/getdate.y @@ -0,0 +1,970 @@ +%{ +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets 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 +__FBSDID("$FreeBSD: src/usr.bin/find/getdate.y,v 1.4 2005/08/25 13:44:02 roberto Exp $"); + +#include +#include + +/* 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 if that will be used. */ + +#if defined(vms) +# include +#else /* defined(vms) */ +# include +# include +# include +#endif /* !defined(vms) */ + +#if defined (__STDC__) || defined (USG) +#include +#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 +#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 + +#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 tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT +%type tSEC_UNIT tSNUMBER tUNUMBER tZONE +%type 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 } +}; + + + + +/* 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) */ diff --git a/find/ls.c b/find/ls.c index d050029..5a42be2 100644 --- a/find/ls.c +++ b/find/ls.c @@ -34,47 +34,58 @@ #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 +__FBSDID("$FreeBSD: src/usr.bin/find/ls.c,v 1.17 2004/01/20 09:27:03 des Exp $"); + #include #include #include #include +#include +#include +#include +#include +#include #include #include #include #include +#ifdef __APPLE__ #include +#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); diff --git a/find/main.c b/find/main.c index bad04a2..b1f2233 100644 --- a/find/main.c +++ b/find/main.c @@ -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 +__FBSDID("$FreeBSD: src/usr.bin/find/main.c,v 1.15 2003/06/14 13:00:21 markm Exp $"); + #include #include @@ -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"); diff --git a/find/misc.c b/find/misc.c index 2ad2ace..ced8cfb 100644 --- a/find/misc.c +++ b/find/misc.c @@ -38,11 +38,12 @@ #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 +__FBSDID("$FreeBSD: src/usr.bin/find/misc.c,v 1.8 2005/04/02 07:44:12 tjr Exp $"); + #include #include @@ -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 } diff --git a/find/operator.c b/find/operator.c index a8feb8e..f04d12a 100644 --- a/find/operator.c +++ b/find/operator.c @@ -32,14 +32,17 @@ * 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 +__FBSDID("$FreeBSD: src/usr.bin/find/operator.c,v 1.14 2003/06/14 13:00:21 markm Exp $"); + #include #include @@ -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; diff --git a/find/option.c b/find/option.c index a0abc8b..004d550 100644 --- a/find/option.c +++ b/find/option.c @@ -38,10 +38,11 @@ /* 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 +__FBSDID("$FreeBSD: src/usr.bin/find/option.c,v 1.25 2006/04/05 23:06:11 ceri Exp $"); + #include #include @@ -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 index 573e775..0000000 --- a/find/y.tab.c +++ /dev/null @@ -1,1542 +0,0 @@ -#include -#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 -#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 while -** at the University of North Carolina at Chapel Hill. Later tweaked by -** a couple of people on Usenet. Completely overhauled by Rich $alz -** and Jim Berets 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 -#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 -#include -#include - -/* 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 if that will be used. */ - -#if defined(vms) -# include -#else /* defined(vms) */ -# include -/* don't need xtime.h */ -# include -# include -#endif /* !defined(vms) */ - -#include - -#if defined (STDC_HEADERS) || defined (USG) -#include -#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 -#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 } -}; - - - - -/* 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); -} diff --git a/id/Makefile b/id/Makefile index 0bbc53f..3257c7e 100644 --- a/id/Makefile +++ b/id/Makefile @@ -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 diff --git a/id/groups.1 b/id/groups.1 index dfd36a0..00c030b 100644 --- a/id/groups.1 +++ b/id/groups.1 @@ -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 c36c4f7..c92c29a 100644 --- 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 @@ -45,9 +45,13 @@ .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 e3957e6..becc591 100644 --- 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 -__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 +#ifndef __APPLE__ +#include +#endif /* !__APPLE__ */ + +#ifdef USE_BSM_AUDIT +#include +#endif #include +#include #include #include #include @@ -55,26 +63,33 @@ __RCSID("$FreeBSD: src/usr.bin/id/id.c,v 1.19 2002/09/04 23:29:02 dwmalone Exp $ #include #include -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]", diff --git a/id/whoami.1 b/id/whoami.1 index bf201d8..568fbaf 100644 --- a/id/whoami.1 +++ b/id/whoami.1 @@ -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 diff --git a/killall/Makefile b/killall/Makefile index 49907b5..a2f09c0 100644 --- a/killall/Makefile +++ b/killall/Makefile @@ -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 diff --git a/killall/killall.1 b/killall/killall.1 index 69dbc05..da99668 100644 --- a/killall/killall.1 +++ b/killall/killall.1 @@ -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 @@ -32,20 +32,17 @@ .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 ) -.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. diff --git a/killall/killall.c b/killall/killall.c index 25a2ded..795df04 100644 --- a/killall/killall.c +++ b/killall/killall.c @@ -23,12 +23,15 @@ * 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 +__FBSDID("$FreeBSD: src/usr.bin/killall/killall.c,v 1.31 2004/07/29 18:36:35 maxim Exp $"); + #include +#ifndef __APPLE__ +#include +#endif /* !__APPLE__ */ #include #include #include @@ -44,14 +47,19 @@ #include #include #include +#include -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", diff --git a/locate/locate/updatedb.sh b/locate/locate/updatedb.sh index 22f2f33..7baaf62 100644 --- a/locate/locate/updatedb.sh +++ b/locate/locate/updatedb.sh @@ -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} diff --git a/nohup/nohup.c b/nohup/nohup.c index 677ab9e..cea00b7 100644 --- a/nohup/nohup.c +++ b/nohup/nohup.c @@ -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 @@ -12,11 +11,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. * @@ -33,115 +28,121 @@ * SUCH DAMAGE. */ -#include +#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 +#ifndef __APPLE__ +__FBSDID("$FreeBSD: src/usr.bin/nohup/nohup.c,v 1.10 2003/05/03 19:44:46 obrien Exp $"); +#endif #include -#include #include + +#include +#include #include -#include #include #include #include #include -#include +#include + +#ifdef __APPLE__ +#include +#include +#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); } diff --git a/printf/printf.1 b/printf/printf.1 index 8db9738..6598d4e 100644 --- a/printf/printf.1 +++ b/printf/printf.1 @@ -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 diff --git a/pwd/Makefile b/pwd/Makefile index 377d638..895435e 100644 --- a/pwd/Makefile +++ b/pwd/Makefile @@ -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 diff --git a/pwd/pwd.1 b/pwd/pwd.1 index 4b96209..929c4b3 100644 --- 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. .\" @@ -14,10 +13,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. @@ -35,49 +30,74 @@ .\" 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. diff --git a/pwd/pwd.c b/pwd/pwd.c index 1bf8c39..c5788b1 100644 --- 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. * @@ -12,10 +10,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. @@ -33,49 +27,49 @@ * SUCH DAMAGE. */ -#include +#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 +__FBSDID("$FreeBSD: src/bin/pwd/pwd.c,v 1.25 2005/02/09 17:37:38 ru Exp $"); + +#include +#include +#include #include +#include #include #include #include -#include -#include -#include -#include -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); } diff --git a/renice/renice.8 b/renice/renice.8 index d421238..6d1b30b 100644 --- a/renice/renice.8 +++ b/renice/renice.8 @@ -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 diff --git a/script/Makefile b/script/Makefile index 08d1d7d..6673f37 100644 --- a/script/Makefile +++ b/script/Makefile @@ -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 diff --git a/script/script.1 b/script/script.1 index 485bf30..8c0dae9 100644 --- a/script/script.1 +++ b/script/script.1 @@ -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. .\" @@ -32,22 +30,25 @@ .\" 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. diff --git a/script/script.c b/script/script.c index dc980ce..32d80f3 100644 --- a/script/script.c +++ b/script/script.c @@ -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. @@ -34,17 +32,18 @@ */ #include + +__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 #include @@ -55,161 +54,201 @@ __RCSID("$NetBSD: script.c,v 1.6 1998/04/02 11:08:34 kleink Exp $"); #include #include #include +#ifndef __APPLE__ +#include +#endif /* !__APPLE__ */ #include #include #include #include #include #include -#include -#include #include +#ifdef __APPLE__ #include +#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 f41431f..906c9e5 100644 --- 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 fec3606..a7197f5 100644 --- 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); } diff --git a/test/test.1 b/test/test.1 index 061189e..44c5ff9 100644 --- a/test/test.1 +++ b/test/test.1 @@ -41,16 +41,16 @@ .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. diff --git a/test/test.c b/test/test.c index 366ccda..20df58a 100644 --- a/test/test.c +++ b/test/test.c @@ -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; diff --git a/uname/uname.1 b/uname/uname.1 index 4ccc596..8253ea9 100644 --- a/uname/uname.1 +++ b/uname/uname.1 @@ -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. @@ -11,11 +11,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. .\" @@ -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. diff --git a/uname/uname.c b/uname/uname.c index 72a6178..6c89b81 100644 --- a/uname/uname.c +++ b/uname/uname.c @@ -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. @@ -33,27 +33,38 @@ #include #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 +#include +#include #include #include -#include -#include #include -#include #include +#include +#include + +#ifdef __APPLE__ +#include +#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); } diff --git a/users/users.1 b/users/users.1 index 6629f57..5c4f872 100644 --- a/users/users.1 +++ b/users/users.1 @@ -46,14 +46,14 @@ 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 diff --git a/users/users.c b/users/users.c index 5e243cd..ff24ecb 100644 --- a/users/users.c +++ b/users/users.c @@ -54,9 +54,9 @@ __RCSID("$NetBSD: users.c,v 1.7 1998/02/03 04:19:15 perry Exp $"); #include #include #include -#include +#include -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)); } diff --git a/w/Makefile b/w/Makefile index 66fdc32..b810f81 100644 --- a/w/Makefile +++ b/w/Makefile @@ -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 diff --git a/w/extern.h b/w/extern.h index ba7a1ad..8fe24bb 100644 --- a/w/extern.h +++ b/w/extern.h @@ -10,11 +10,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. * @@ -37,9 +33,12 @@ 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 5df1c8c..31a6e50 100644 --- a/w/fmt.c +++ b/w/fmt.c @@ -10,11 +10,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. * diff --git a/w/pr_time.c b/w/pr_time.c index 5027d9f..77d506d 100644 --- a/w/pr_time.c +++ b/w/pr_time.c @@ -10,11 +10,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. * @@ -33,6 +29,10 @@ #include +#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) { diff --git a/w/proc_compare.c b/w/proc_compare.c index 94665dd..806f571 100644 --- a/w/proc_compare.c +++ b/w/proc_compare.c @@ -10,11 +10,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. * @@ -31,13 +27,22 @@ * SUCH DAMAGE. */ -#include - +#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 +#ifndef __APPLE__ +__FBSDID("$FreeBSD: src/usr.bin/w/proc_compare.c,v 1.9 2004/04/14 09:34:17 bde Exp $"); #endif #include +#ifdef __APPLE__ +#include +#endif +#include #include #include @@ -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 - +#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 */ } diff --git a/w/uptime.1 b/w/uptime.1 index a7177a7..a2c372a 100644 --- a/w/uptime.1 +++ b/w/uptime.1 @@ -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 5bea557..ba57bae 100644 --- 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 0cda4e4..67d9835 100644 --- 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 @@ -10,11 +11,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. * @@ -33,6 +30,10 @@ #include +#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 #include +#ifndef __APPLE__ +#include +#endif #include #include #include @@ -67,7 +71,11 @@ static const char sccsid[] = "@(#)w.c 8.4 (Berkeley) 4/16/94"; #include #include #include +#if HAVE_KVM #include +#endif +#include +#include #include #include #include @@ -77,22 +85,38 @@ static const char sccsid[] = "@(#)w.c 8.4 (Berkeley) 4/16/94"; #include #include #include +#include #include +#if HAVE_UTMPX +#include +/* use utmp values so formatting is the same */ +#define UT_NAMESIZE 8 +#define UT_LINESIZE 8 +#else /* HAVE_UTMPX */ #include +#endif /* HAVE_UTMPX */ #include #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 */ diff --git a/which/Makefile b/which/Makefile index 21a2a4a..a425a8a 100644 --- a/which/Makefile +++ b/which/Makefile @@ -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 diff --git a/which/Makefile.preamble b/which/Makefile.preamble index ec3a5ea..9e10e90 100644 --- a/which/Makefile.preamble +++ b/which/Makefile.preamble @@ -1,3 +1 @@ -SHELLTOOL = which.csh - include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Preamble.Common diff --git a/which/which.1 b/which/which.1 index 908f7d3..f889e09 100644 --- a/which/which.1 +++ b/which/which.1 @@ -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 .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -13,61 +10,76 @@ .\" 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 index 0000000..e8ecea2 --- /dev/null +++ b/which/which.c @@ -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 + +__FBSDID("$FreeBSD: src/usr.bin/which/which.c,v 1.6 2005/02/10 16:04:22 ru Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +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 index 5295deb..0000000 --- a/which/which.csh +++ /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 diff --git a/who/who.1 b/who/who.1 index 333d180..f80a0f4 100644 --- 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 diff --git a/who/who.c b/who/who.c index b700264..da46ad7 100644 --- 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 #include #include -#include #include +/* 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); } diff --git a/xargs/Makefile b/xargs/Makefile index 174730e..62f9db7 100644 --- a/xargs/Makefile +++ b/xargs/Makefile @@ -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 diff --git a/xargs/pathnames.h b/xargs/pathnames.h index ed4337b..3f05b3d 100644 --- a/xargs/pathnames.h +++ b/xargs/pathnames.h @@ -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. diff --git a/xargs/strnsubst.c b/xargs/strnsubst.c index fa8d933..4b3f9b6 100644 --- a/xargs/strnsubst.c +++ b/xargs/strnsubst.c @@ -9,7 +9,7 @@ */ #include -__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 #include @@ -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); diff --git a/xargs/xargs.1 b/xargs/xargs.1 index 9db9a3f..f8a8592 100644 --- a/xargs/xargs.1 +++ b/xargs/xargs.1 @@ -34,10 +34,10 @@ .\" 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 @@ -57,24 +57,24 @@ .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. diff --git a/xargs/xargs.c b/xargs/xargs.c index a543261..8f71d99 100644 --- a/xargs/xargs.c +++ b/xargs/xargs.c @@ -36,26 +36,27 @@ * $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 -__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 +#include #include #include #include +#include +#include #include #include #include @@ -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); } -- 2.45.2